diff --git a/TMessagesProj/jni/CMakeLists.txt b/TMessagesProj/jni/CMakeLists.txt index 137d17f21..45abbb692 100644 --- a/TMessagesProj/jni/CMakeLists.txt +++ b/TMessagesProj/jni/CMakeLists.txt @@ -435,7 +435,7 @@ target_include_directories(breakpad PUBLIC #voip include(${CMAKE_HOME_DIRECTORY}/voip/CMakeLists.txt) -set(NATIVE_LIB "tmessages.46") +set(NATIVE_LIB "tmessages.47") #tmessages add_library(${NATIVE_LIB} SHARED diff --git a/TMessagesProj/jni/TgNetWrapper.cpp b/TMessagesProj/jni/TgNetWrapper.cpp index 3d108e2e9..7ee850d7c 100644 --- a/TMessagesProj/jni/TgNetWrapper.cpp +++ b/TMessagesProj/jni/TgNetWrapper.cpp @@ -202,6 +202,10 @@ void setUserId(JNIEnv *env, jclass c, jint instanceNum, int64_t id) { ConnectionsManager::getInstance(instanceNum).setUserId(id); } +void setUserPremium(JNIEnv *env, jclass c, jint instanceNum, bool premium) { + ConnectionsManager::getInstance(instanceNum).setUserPremium(premium); +} + void switchBackend(JNIEnv *env, jclass c, jint instanceNum, jboolean restart) { ConnectionsManager::getInstance(instanceNum).switchBackend(restart); } @@ -384,7 +388,7 @@ void setSystemLangCode(JNIEnv *env, jclass c, jint instanceNum, jstring langCode } } -void init(JNIEnv *env, jclass c, jint instanceNum, jint version, jint layer, jint apiId, jstring deviceModel, jstring systemVersion, jstring appVersion, jstring langCode, jstring systemLangCode, jstring configPath, jstring logPath, jstring regId, jstring cFingerprint, jstring installerId, jstring packageId, jint timezoneOffset, jlong userId, jboolean enablePushConnection, jboolean hasNetwork, jint networkType, jint performanceClass) { +void init(JNIEnv *env, jclass c, jint instanceNum, jint version, jint layer, jint apiId, jstring deviceModel, jstring systemVersion, jstring appVersion, jstring langCode, jstring systemLangCode, jstring configPath, jstring logPath, jstring regId, jstring cFingerprint, jstring installerId, jstring packageId, jint timezoneOffset, jlong userId, jboolean userPremium, jboolean enablePushConnection, jboolean hasNetwork, jint networkType, jint performanceClass) { const char *deviceModelStr = env->GetStringUTFChars(deviceModel, 0); const char *systemVersionStr = env->GetStringUTFChars(systemVersion, 0); const char *appVersionStr = env->GetStringUTFChars(appVersion, 0); @@ -397,7 +401,7 @@ void init(JNIEnv *env, jclass c, jint instanceNum, jint version, jint layer, jin const char *installerIdStr = env->GetStringUTFChars(installerId, 0); const char *packageIdStr = env->GetStringUTFChars(packageId, 0); - ConnectionsManager::getInstance(instanceNum).init((uint32_t) version, layer, apiId, std::string(deviceModelStr), std::string(systemVersionStr), std::string(appVersionStr), std::string(langCodeStr), std::string(systemLangCodeStr), std::string(configPathStr), std::string(logPathStr), std::string(regIdStr), std::string(cFingerprintStr), std::string(installerIdStr), std::string(packageIdStr), timezoneOffset, userId, true, enablePushConnection, hasNetwork, networkType, performanceClass); + ConnectionsManager::getInstance(instanceNum).init((uint32_t) version, layer, apiId, std::string(deviceModelStr), std::string(systemVersionStr), std::string(appVersionStr), std::string(langCodeStr), std::string(systemLangCodeStr), std::string(configPathStr), std::string(logPathStr), std::string(regIdStr), std::string(cFingerprintStr), std::string(installerIdStr), std::string(packageIdStr), timezoneOffset, userId, userPremium, true, enablePushConnection, hasNetwork, networkType, performanceClass); if (deviceModelStr != 0) { env->ReleaseStringUTFChars(deviceModel, deviceModelStr); @@ -457,7 +461,7 @@ static JNINativeMethod ConnectionsManagerMethods[] = { {"native_setProxySettings", "(ILjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", (void *) setProxySettings}, {"native_getConnectionState", "(I)I", (void *) getConnectionState}, {"native_setUserId", "(IJ)V", (void *) setUserId}, - {"native_init", "(IIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJZZII)V", (void *) init}, + {"native_init", "(IIIILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJZZZII)V", (void *) init}, {"native_setLangCode", "(ILjava/lang/String;)V", (void *) setLangCode}, {"native_setRegId", "(ILjava/lang/String;)V", (void *) setRegId}, {"native_setSystemLangCode", "(ILjava/lang/String;)V", (void *) setSystemLangCode}, diff --git a/TMessagesProj/jni/tgnet/ApiScheme.cpp b/TMessagesProj/jni/tgnet/ApiScheme.cpp index 9e61cfb0f..5ab7064f9 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.cpp +++ b/TMessagesProj/jni/tgnet/ApiScheme.cpp @@ -483,19 +483,19 @@ void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er lang_code = stream->readString(&error); } if ((flags & 1073741824) != 0) { - uint32_t magic = stream->readUint32(&error); - if (magic == 0x2de11aae) { + emojiStatusMagic = stream->readUint32(&error); + if (emojiStatusMagic == 0x2de11aae) { // emojiStatusEmpty - } else if (magic == 0x929b619d) { + } else if (emojiStatusMagic == 0x929b619d) { // emojiStatus - int64_t document_id = stream->readInt64(&error); - } else if (magic == 0xfa30a8c7) { + emojiStatusDocumentId = stream->readInt64(&error); + } else if (emojiStatusMagic == 0xfa30a8c7) { // emojiStatusUntil - int64_t document_id = stream->readInt64(&error); - int until = stream->readInt32(&error); + emojiStatusDocumentId = stream->readInt64(&error); + emojiStatusUntil = stream->readInt32(&error); } else { error = true; - if (LOGS_ENABLED) DEBUG_FATAL("wrong EmojiStatus magic, got %x", magic); + if (LOGS_ENABLED) DEBUG_FATAL("wrong EmojiStatus magic, got %x", emojiStatusMagic); return; } } @@ -518,6 +518,12 @@ void TL_user::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &er if ((flags2 & 32) != 0) { stories_max_id = stream->readInt32(&error); } + if ((flags2 & 128) != 0) { + color = stream->readInt32(&error); + } + if ((flags2 & 64) != 0) { + background_emoji_id = stream->readInt64(&error); + } } void TL_user::serializeToStream(NativeByteBuffer *stream) { @@ -563,6 +569,34 @@ void TL_user::serializeToStream(NativeByteBuffer *stream) { if ((flags & 4194304) != 0) { stream->writeString(lang_code); } + if ((flags & 1073741824) != 0) { + stream->writeInt32(emojiStatusMagic); + if (emojiStatusMagic == 0x929b619d) { + // emojiStatus + stream->writeInt64(emojiStatusDocumentId); + } else if (emojiStatusMagic == 0xfa30a8c7) { + // emojiStatusUntil + stream->writeInt64(emojiStatusDocumentId); + stream->writeInt32(emojiStatusUntil); + } + } + if ((flags2 & 1) != 0) { + stream->writeInt32(0x1cb5c415); + int32_t count = (int32_t) usernames.size(); + stream->writeInt32(count); + for (int a = 0; a < count; a++) { + usernames[a]->serializeToStream(stream); + } + } + if ((flags2 & 32) != 0) { + stream->writeInt32(stories_max_id); + } + if ((flags2 & 128) != 0) { + stream->writeInt32(color); + } + if ((flags2 & 64) != 0) { + stream->writeInt64(background_emoji_id); + } } InputPeer *InputPeer::TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error) { diff --git a/TMessagesProj/jni/tgnet/ApiScheme.h b/TMessagesProj/jni/tgnet/ApiScheme.h index 17926c7cf..0318c1a64 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.h +++ b/TMessagesProj/jni/tgnet/ApiScheme.h @@ -336,6 +336,11 @@ public: std::string lang_code; std::vector> usernames; int32_t stories_max_id; + int32_t emojiStatusMagic; + int64_t emojiStatusDocumentId; + int32_t emojiStatusUntil; + int32_t color; + int64_t background_emoji_id; static User *TLdeserialize(NativeByteBuffer *stream, uint32_t constructor, int32_t instanceNum, bool &error); }; @@ -352,7 +357,7 @@ public: class TL_user : public User { public: - static const uint32_t constructor = 0xabb5f120; + static const uint32_t constructor = 0xeb602f25; void readParams(NativeByteBuffer *stream, int32_t instanceNum, bool &error); void serializeToStream(NativeByteBuffer *stream); diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index 0dae96967..8c6974ef9 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -741,6 +741,7 @@ void ConnectionsManager::cleanUp(bool resetKeys, int32_t datacenterId) { if (datacenterId == -1) { sessionsToDestroy.clear(); currentUserId = 0; + currentUserPremium = false; registeredForInternalPush = false; } saveConfig(); @@ -1464,6 +1465,7 @@ void ConnectionsManager::processServerResponse(TLObject *message, int64_t messag } else if (datacenter->getDatacenterId() == currentDatacenterId || datacenter->getDatacenterId() == movingToDatacenterId) { if (request->connectionType & ConnectionTypeGeneric && currentUserId) { currentUserId = 0; + currentUserPremium = false; if (delegate != nullptr) { delegate->onLogout(instanceNum); } @@ -1964,6 +1966,12 @@ void ConnectionsManager::bindRequestToGuid(int32_t requestToken, int32_t guid) { }); } +void ConnectionsManager::setUserPremium(bool premium) { + scheduleTask([&, premium] { + currentUserPremium = premium; + }); +} + void ConnectionsManager::setUserId(int64_t userId) { scheduleTask([&, userId] { int32_t oldUserId = currentUserId; @@ -2064,7 +2072,7 @@ bool ConnectionsManager::cancelRequestInternal(int32_t token, int64_t messageId, if (notifyServer) { auto dropAnswer = new TL_rpc_drop_answer(); dropAnswer->req_msg_id = request->messageId; - sendRequest(dropAnswer, nullptr, nullptr, RequestFlagEnableUnauthorized | RequestFlagWithoutLogin | RequestFlagFailOnServerErrors, request->datacenterId, request->connectionType, true); + sendRequest(dropAnswer, nullptr, nullptr, RequestFlagEnableUnauthorized | RequestFlagWithoutLogin | RequestFlagFailOnServerErrors | RequestFlagIsCancel, request->datacenterId, request->connectionType, true); } request->cancelled = true; if (LOGS_ENABLED) DEBUG_D("cancelled running rpc request %p - %s", request->rawRequest, typeid(*request->rawRequest).name()); @@ -2289,6 +2297,7 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t neededDatacenters.clear(); unauthorizedDatacenters.clear(); downloadRunningRequestCount.clear(); + downloadCancelRunningRequestCount.clear(); int64_t currentTimeMillis = getCurrentTimeMonotonicMillis(); auto currentTime = (int32_t) (currentTimeMillis / 1000); @@ -2325,14 +2334,15 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t genericRunningRequestCount++; break; case ConnectionTypeDownload: { + auto map = request->isCancelRequest() ? downloadCancelRunningRequestCount : downloadRunningRequestCount; uint32_t currentCount; - auto dcIter = downloadRunningRequestCount.find(datacenterId); - if (dcIter != downloadRunningRequestCount.end()) { + auto dcIter = map.find(datacenterId); + if (dcIter != map.end()) { currentCount = dcIter->second; } else { currentCount = 0; } - downloadRunningRequestCount[datacenterId] = currentCount + 1; + map[datacenterId] = currentCount + 1; break; } case ConnectionTypeUpload: @@ -2548,6 +2558,8 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t Request *request = iter->get(); if (request->cancelled) { iter = requestsQueue.erase(iter); + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: cancelled", request->requestToken); continue; } if (hasInvokeWaitMessage && (request->requestFlags & RequestFlagInvokeAfter) != 0 && (request->requestFlags & RequestFlagResendAfter) == 0) { @@ -2565,6 +2577,8 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t if (datacenterId == DEFAULT_DATACENTER_ID) { if (movingToDatacenterId != DEFAULT_DATACENTER_ID) { iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: moving dc", request->requestToken); continue; } datacenterId = currentDatacenterId; @@ -2610,6 +2624,8 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t if (std::find(unknownDatacenterIds.begin(), unknownDatacenterIds.end(), datacenterId) == unknownDatacenterIds.end()) { unknownDatacenterIds.push_back(datacenterId); } + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: unknown dc", request->requestToken); iter++; continue; } else { @@ -2623,12 +2639,16 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t if (std::find(neededDatacenters.begin(), neededDatacenters.end(), pair) == neededDatacenters.end()) { neededDatacenters.push_back(pair); } + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: no authkey for dc", request->requestToken); iter++; continue; } else if (!(request->requestFlags & RequestFlagEnableUnauthorized) && !requestDatacenter->authorized && request->datacenterId != DEFAULT_DATACENTER_ID && request->datacenterId != currentDatacenterId) { if (std::find(unauthorizedDatacenters.begin(), unauthorizedDatacenters.end(), requestDatacenter) == unauthorizedDatacenters.end()) { unauthorizedDatacenters.push_back(requestDatacenter); } + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: dc is unauthorized", request->requestToken); iter++; continue; } @@ -2638,6 +2658,8 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t if (request->connectionType & ConnectionTypeGeneric && connection->getConnectionToken() == 0) { iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: generic && connectionToken == 0", request->requestToken); continue; } @@ -2646,20 +2668,38 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t case ConnectionTypeGenericMedia: if (!canUseUnboundKey && genericRunningRequestCount >= 60) { iter++; + DEBUG_D("skip queue, token = %d: generic type: running generic requests >= 60", request->requestToken); continue; } genericRunningRequestCount++; break; case ConnectionTypeDownload: { uint32_t currentCount; - auto dcIter = downloadRunningRequestCount.find(datacenterId); - if (dcIter != downloadRunningRequestCount.end()) { + auto map = request->isCancelRequest() ? downloadCancelRunningRequestCount : downloadRunningRequestCount; + auto dcIter = map.find(datacenterId); + if (dcIter != map.end()) { currentCount = dcIter->second; } else { currentCount = 0; } - if (!networkAvailable || currentCount >= 16) { + if (!networkAvailable) { iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: download type: network unavailable", request->requestToken); + continue; + } + int max; + if (request->isCancelRequest()) { + max = 24; + } else if (currentUserPremium) { + max = 32; + } else { + max = 16; + } + if (currentCount >= max) { + iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: download type: running download requests >= %d", request->requestToken, max); continue; } downloadRunningRequestCount[datacenterId] = currentCount + 1; @@ -2669,12 +2709,22 @@ void ConnectionsManager::processRequestQueue(uint32_t connectionTypes, uint32_t case ConnectionTypeTemp: if (!networkAvailable) { iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: proxy/temp type: network unavailable", request->requestToken); continue; } break; case ConnectionTypeUpload: - if (!networkAvailable || uploadRunningRequestCount >= 10) { + if (!networkAvailable) { iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: upload type: network unavailable", request->requestToken); + continue; + } + if (uploadRunningRequestCount >= 10) { + iter++; + if (LOGS_ENABLED) + DEBUG_D("skip queue, token = %d: upload type: running upload requests >= 10", request->requestToken); continue; } uploadRunningRequestCount++; @@ -3132,14 +3182,13 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround, bool if ((!workaround && !updatingDcSettings) || (workaround && !updatingDcSettingsWorkaround)) { return; } - if (!workaround && updatingDcSettingsAgain && updatingDcSettingsAgainDcNum == dcNum) { + if (!workaround && updatingDcSettingsAgain) { + updatingDcSettings = false; updatingDcSettingsAgain = false; for (auto & datacenter : datacenters) { - if (datacenter.first == dcNum) { - datacenter.second->resetInitVersion(); - } + datacenter.second->resetInitVersion(); } - updateDcSettings(updatingDcSettingsAgainDcNum, false, false); + updateDcSettings(0, false, false); return; } @@ -3437,7 +3486,7 @@ void ConnectionsManager::applyDnsConfig(NativeByteBuffer *buffer, std::string ph }); } -void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string systemLangCode, std::string configPath, std::string logPath, std::string regId, std::string cFingerpting, std::string installerId, std::string packageId, int32_t timezoneOffset, int64_t userId, bool isPaused, bool enablePushConnection, bool hasNetwork, int32_t networkType, int32_t performanceClass) { +void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string systemLangCode, std::string configPath, std::string logPath, std::string regId, std::string cFingerpting, std::string installerId, std::string packageId, int32_t timezoneOffset, int64_t userId, bool userPremium, bool isPaused, bool enablePushConnection, bool hasNetwork, int32_t networkType, int32_t performanceClass) { currentVersion = version; currentLayer = layer; currentApiId = apiId; @@ -3453,6 +3502,7 @@ void ConnectionsManager::init(uint32_t version, int32_t layer, int32_t apiId, st currentDeviceTimezone = timezoneOffset; currentSystemLangCode = systemLangCode; currentUserId = userId; + currentUserPremium = userPremium; currentLogPath = logPath; pushConnectionEnabled = enablePushConnection; currentNetworkType = networkType; @@ -3750,9 +3800,8 @@ void ConnectionsManager::reconnect(int32_t dcId, int32_t connectionType) { Connection *connection = datacenter->getConnectionByType(connectionType, false, 0); if (connection != nullptr) { - if (LOGS_ENABLED) - DEBUG_D("discard connection dcId=%d connectionType=%d", dcId, - connectionType); + DEBUG_D("discard connection dcId=%d connectionType=%d", dcId, + connectionType); connection->suspendConnection(true); } } diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.h b/TMessagesProj/jni/tgnet/ConnectionsManager.h index 9bceda77e..765e9db35 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.h +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.h @@ -59,12 +59,13 @@ public: void setDelegate(ConnectiosManagerDelegate *connectiosManagerDelegate); ConnectionState getConnectionState(); void setUserId(int64_t userId); + void setUserPremium(bool premium); void switchBackend(bool restart); void resumeNetwork(bool partial); void pauseNetwork(); void setNetworkAvailable(bool value, int32_t type, bool slow); void setIpStrategy(uint8_t value); - void init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string systemLangCode, std::string configPath, std::string logPath, std::string regId, std::string cFingerprint, std::string installerId, std::string packageId, int32_t timezoneOffset, int64_t userId, bool isPaused, bool enablePushConnection, bool hasNetwork, int32_t networkType, int32_t performanceClass); + void init(uint32_t version, int32_t layer, int32_t apiId, std::string deviceModel, std::string systemVersion, std::string appVersion, std::string langCode, std::string systemLangCode, std::string configPath, std::string logPath, std::string regId, std::string cFingerprint, std::string installerId, std::string packageId, int32_t timezoneOffset, int64_t userId, bool userPremium, bool isPaused, bool enablePushConnection, bool hasNetwork, int32_t networkType, int32_t performanceClass); void setProxySettings(std::string address, uint16_t port, std::string username, std::string password, std::string secret); void setLangCode(std::string langCode); void setRegId(std::string regId); @@ -231,6 +232,7 @@ private: std::string currentConfigPath; std::string currentLogPath; int64_t currentUserId = 0; + bool currentUserPremium = false; bool registeredForInternalPush = false; bool pushConnectionEnabled = true; int32_t currentPerformanceClass = -1; @@ -241,6 +243,7 @@ private: std::vector unknownDatacenterIds; std::vector> neededDatacenters; std::map downloadRunningRequestCount; + std::map downloadCancelRunningRequestCount; std::vector unauthorizedDatacenters; NativeByteBuffer *sizeCalculator; diff --git a/TMessagesProj/jni/tgnet/Defines.h b/TMessagesProj/jni/tgnet/Defines.h index 7d72184e8..68b745a62 100644 --- a/TMessagesProj/jni/tgnet/Defines.h +++ b/TMessagesProj/jni/tgnet/Defines.h @@ -170,7 +170,8 @@ enum RequestFlag { RequestFlagNeedQuickAck = 128, RequestFlagUseUnboundKey = 256, RequestFlagResendAfter = 512, - RequestFlagIgnoreFloodWait = 1024 + RequestFlagIgnoreFloodWait = 1024, + RequestFlagIsCancel = 32768 }; inline std::string to_string_int32(int32_t value) { diff --git a/TMessagesProj/jni/tgnet/Request.cpp b/TMessagesProj/jni/tgnet/Request.cpp index 14667314b..9aec8bfc4 100644 --- a/TMessagesProj/jni/tgnet/Request.cpp +++ b/TMessagesProj/jni/tgnet/Request.cpp @@ -85,6 +85,10 @@ bool Request::isMediaRequest() { return Connection::isMediaConnectionType(connectionType); } +bool Request::isCancelRequest() { + return (requestFlags & RequestFlagIsCancel) != 0; +} + bool Request::needInitRequest(Datacenter *datacenter, uint32_t currentVersion) { bool media = PFS_ENABLED && datacenter != nullptr && isMediaRequest() && datacenter->hasMediaAddress(); return !media && datacenter->lastInitVersion != currentVersion || media && datacenter->lastInitMediaVersion != currentVersion; diff --git a/TMessagesProj/jni/tgnet/Request.h b/TMessagesProj/jni/tgnet/Request.h index 5298f6a8d..2013a6526 100644 --- a/TMessagesProj/jni/tgnet/Request.h +++ b/TMessagesProj/jni/tgnet/Request.h @@ -63,6 +63,7 @@ public: void onQuickAck(); void onWriteToSocket(); bool isMediaRequest(); + bool isCancelRequest(); bool hasInitFlag(); bool needInitRequest(Datacenter *datacenter, uint32_t currentVersion); TLObject *getRpcRequest(); diff --git a/TMessagesProj/jni/voip/tgcalls/DirectConnectionChannel.h b/TMessagesProj/jni/voip/tgcalls/DirectConnectionChannel.h new file mode 100644 index 000000000..50a41fcb1 --- /dev/null +++ b/TMessagesProj/jni/voip/tgcalls/DirectConnectionChannel.h @@ -0,0 +1,21 @@ +#ifndef TGCALLS_DIRECT_CONNECTION_CHANNEL_H +#define TGCALLS_DIRECT_CONNECTION_CHANNEL_H + +#include +#include +#include + +namespace tgcalls { + +class DirectConnectionChannel { +public: + virtual ~DirectConnectionChannel() = default; + + virtual std::vector addOnIncomingPacket(std::function>)> &&) = 0; + virtual void removeOnIncomingPacket(std::vector &token) = 0; + virtual void sendPacket(std::unique_ptr> &&packet) = 0; +}; + +} // namespace tgcalls + +#endif diff --git a/TMessagesProj/jni/voip/tgcalls/Instance.h b/TMessagesProj/jni/voip/tgcalls/Instance.h index 3a43c2990..9cc6b515f 100644 --- a/TMessagesProj/jni/voip/tgcalls/Instance.h +++ b/TMessagesProj/jni/voip/tgcalls/Instance.h @@ -8,6 +8,7 @@ #include #include "Stats.h" +#include "DirectConnectionChannel.h" namespace rtc { template @@ -186,7 +187,7 @@ public: virtual void setEchoCancellationStrength(int strength) = 0; virtual bool supportsVideo() = 0; - virtual void setIncomingVideoOutput(std::shared_ptr> sink) = 0; + virtual void setIncomingVideoOutput(std::weak_ptr> sink) = 0; virtual void setAudioInputDevice(std::string id) = 0; virtual void setAudioOutputDevice(std::string id) = 0; @@ -237,6 +238,7 @@ struct Descriptor { std::function(webrtc::TaskQueueFactory*)> createAudioDeviceModule; std::string initialInputDeviceId; std::string initialOutputDeviceId; + std::shared_ptr directConnectionChannel; std::shared_ptr platformContext; }; diff --git a/TMessagesProj/jni/voip/tgcalls/InstanceImpl.cpp b/TMessagesProj/jni/voip/tgcalls/InstanceImpl.cpp index bec896334..c0350a5a7 100644 --- a/TMessagesProj/jni/voip/tgcalls/InstanceImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/InstanceImpl.cpp @@ -93,7 +93,7 @@ void InstanceImpl::setMuteMicrophone(bool muteMicrophone) { }); } -void InstanceImpl::setIncomingVideoOutput(std::shared_ptr> sink) { +void InstanceImpl::setIncomingVideoOutput(std::weak_ptr> sink) { _manager->perform([sink](Manager *manager) { manager->setIncomingVideoOutput(sink); }); @@ -166,6 +166,8 @@ PersistentState InstanceImpl::getPersistentState() { } void InstanceImpl::stop(std::function completion) { + RTC_LOG(LS_INFO) << "Stopping InstanceImpl"; + std::string debugLog = _logSink->result(); _manager->perform([completion, debugLog = std::move(debugLog)](Manager *manager) { diff --git a/TMessagesProj/jni/voip/tgcalls/InstanceImpl.h b/TMessagesProj/jni/voip/tgcalls/InstanceImpl.h index 89103f3b5..0eb0e6761 100644 --- a/TMessagesProj/jni/voip/tgcalls/InstanceImpl.h +++ b/TMessagesProj/jni/voip/tgcalls/InstanceImpl.h @@ -28,7 +28,7 @@ public: bool supportsVideo() override { return true; } - void setIncomingVideoOutput(std::shared_ptr> sink) override; + void setIncomingVideoOutput(std::weak_ptr> sink) override; void setAudioOutputGainControlEnabled(bool enabled) override; void setEchoCancellationStrength(int strength) override; void setAudioInputDevice(std::string id) override; diff --git a/TMessagesProj/jni/voip/tgcalls/Manager.cpp b/TMessagesProj/jni/voip/tgcalls/Manager.cpp index 9ba5794bc..dd528bd49 100644 --- a/TMessagesProj/jni/voip/tgcalls/Manager.cpp +++ b/TMessagesProj/jni/voip/tgcalls/Manager.cpp @@ -98,7 +98,7 @@ _remoteBatteryLevelIsLowUpdated(std::move(descriptor.remoteBatteryLevelIsLowUpda _remotePrefferedAspectRatioUpdated(std::move(descriptor.remotePrefferedAspectRatioUpdated)), _signalingDataEmitted(std::move(descriptor.signalingDataEmitted)), _signalBarsUpdated(std::move(descriptor.signalBarsUpdated)), -_audioLevelsUpdated(std::move(descriptor.audioLevelsUpdated)), +_audioLevelUpdated(std::move(descriptor.audioLevelsUpdated)), _createAudioDeviceModule(std::move(descriptor.createAudioDeviceModule)), _enableHighBitrateVideo(descriptor.config.enableHighBitrateVideo), _dataSaving(descriptor.config.dataSaving), @@ -223,7 +223,7 @@ void Manager::start() { }); })); bool isOutgoing = _encryptionKey.isOutgoing; - _mediaManager.reset(new ThreadLocalObject(StaticThreads::getMediaThread(), [weak, isOutgoing, protocolVersion = _protocolVersion, thread, sendSignalingMessage, videoCapture = _videoCapture, mediaDevicesConfig = _mediaDevicesConfig, enableHighBitrateVideo = _enableHighBitrateVideo, signalBarsUpdated = _signalBarsUpdated, audioLevelsUpdated = _audioLevelsUpdated, preferredCodecs = _preferredCodecs, createAudioDeviceModule = _createAudioDeviceModule, platformContext = _platformContext]() { + _mediaManager.reset(new ThreadLocalObject(StaticThreads::getMediaThread(), [weak, isOutgoing, protocolVersion = _protocolVersion, thread, sendSignalingMessage, videoCapture = _videoCapture, mediaDevicesConfig = _mediaDevicesConfig, enableHighBitrateVideo = _enableHighBitrateVideo, signalBarsUpdated = _signalBarsUpdated, audioLevelsUpdated = _audioLevelUpdated, preferredCodecs = _preferredCodecs, createAudioDeviceModule = _createAudioDeviceModule, platformContext = _platformContext]() { return new MediaManager( StaticThreads::getMediaThread(), isOutgoing, diff --git a/TMessagesProj/jni/voip/tgcalls/Manager.h b/TMessagesProj/jni/voip/tgcalls/Manager.h index bf449d519..23ae34557 100644 --- a/TMessagesProj/jni/voip/tgcalls/Manager.h +++ b/TMessagesProj/jni/voip/tgcalls/Manager.h @@ -69,7 +69,7 @@ private: std::function _remotePrefferedAspectRatioUpdated; std::function &)> _signalingDataEmitted; std::function _signalBarsUpdated; - std::function _audioLevelsUpdated; + std::function _audioLevelUpdated; std::function(webrtc::TaskQueueFactory*)> _createAudioDeviceModule; std::function _sendSignalingMessage; std::function _sendTransportMessage; diff --git a/TMessagesProj/jni/voip/tgcalls/MediaManager.cpp b/TMessagesProj/jni/voip/tgcalls/MediaManager.cpp index 3aa19ae85..f2ecc5680 100644 --- a/TMessagesProj/jni/voip/tgcalls/MediaManager.cpp +++ b/TMessagesProj/jni/voip/tgcalls/MediaManager.cpp @@ -256,7 +256,7 @@ _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()), _sendSignalingMessage(std::move(sendSignalingMessage)), _sendTransportMessage(std::move(sendTransportMessage)), _signalBarsUpdated(std::move(signalBarsUpdated)), -_audioLevelsUpdated(std::move(audioLevelsUpdated)), +_audioLevelUpdated(std::move(audioLevelsUpdated)), _createAudioDeviceModule(std::move(createAudioDeviceModule)), _protocolVersion(protocolVersion), _outgoingVideoState(videoCapture ? VideoState::Active : VideoState::Inactive), @@ -467,7 +467,7 @@ void MediaManager::start() { } beginStatsTimer(3000); - if (_audioLevelsUpdated != nullptr) { + if (_audioLevelUpdated != nullptr) { beginLevelsTimer(100); } } @@ -595,7 +595,7 @@ void MediaManager::beginLevelsTimer(int timeoutMs) { return; } - strong->_audioLevelsUpdated(strong->_currentMyAudioLevel, strong->_currentAudioLevel); + strong->_audioLevelUpdated(strong->_currentMyAudioLevel, strong->_currentAudioLevel); strong->beginLevelsTimer(100); }, webrtc::TimeDelta::Millis(timeoutMs)); @@ -689,7 +689,7 @@ void MediaManager::setSendVideo(std::shared_ptr videoCapt const auto object = GetVideoCaptureAssumingSameThread(_videoCapture.get()); _isScreenCapture = object->isScreenCapture(); _videoCaptureGuard = std::make_shared(true); - const auto guard = std::weak_ptr{_videoCaptureGuard}; + const auto guard = std::weak_ptr{ _videoCaptureGuard }; object->setStateUpdated([=](VideoState state) { thread->PostTask([=] { // Checking this special guard instead of weak_ptr(this) @@ -1040,7 +1040,7 @@ void MediaManager::fillCallStats(CallStats &callStats) { if (_videoCodecOut.has_value()) { callStats.outgoingCodec = _videoCodecOut->name; } - callStats.bitrateRecords = std::move(_bitrateRecords); + callStats.bitrateRecords = _bitrateRecords; } void MediaManager::setAudioInputDevice(std::string id) { diff --git a/TMessagesProj/jni/voip/tgcalls/MediaManager.h b/TMessagesProj/jni/voip/tgcalls/MediaManager.h index 6eb9a1367..eb3f06e13 100644 --- a/TMessagesProj/jni/voip/tgcalls/MediaManager.h +++ b/TMessagesProj/jni/voip/tgcalls/MediaManager.h @@ -47,7 +47,7 @@ public: std::function sendSignalingMessage, std::function sendTransportMessage, std::function signalBarsUpdated, - std::function audioLevelsUpdated, + std::function audioLevelUpdated, std::function(webrtc::TaskQueueFactory*)> createAudioDeviceModule, bool enableHighBitrateVideo, std::vector preferredCodecs, @@ -130,7 +130,7 @@ private: std::function _sendSignalingMessage; std::function _sendTransportMessage; std::function _signalBarsUpdated; - std::function _audioLevelsUpdated; + std::function _audioLevelUpdated; std::function(webrtc::TaskQueueFactory*)> _createAudioDeviceModule; SSRC _ssrcAudio; diff --git a/TMessagesProj/jni/voip/tgcalls/NetworkManager.cpp b/TMessagesProj/jni/voip/tgcalls/NetworkManager.cpp index dd74752ef..8facd7a74 100644 --- a/TMessagesProj/jni/voip/tgcalls/NetworkManager.cpp +++ b/TMessagesProj/jni/voip/tgcalls/NetworkManager.cpp @@ -269,7 +269,7 @@ TrafficStats NetworkManager::getNetworkStats() { } void NetworkManager::fillCallStats(CallStats &callStats) { - callStats.networkRecords = std::move(_networkRecords); + callStats.networkRecords = _networkRecords; } void NetworkManager::logCurrentNetworkState() { diff --git a/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp b/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp index 7ac3cc6f7..3f4c545fe 100644 --- a/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.cpp @@ -7,7 +7,7 @@ namespace tgcalls { SctpDataChannelProviderInterfaceImpl::SctpDataChannelProviderInterfaceImpl( - cricket::DtlsTransport *transportChannel, + rtc::PacketTransportInternal *transportChannel, bool isOutgoing, std::function onStateChanged, std::function onTerminated, diff --git a/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.h b/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.h index 5da150a29..67034ffe4 100644 --- a/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.h +++ b/TMessagesProj/jni/voip/tgcalls/SctpDataChannelProviderInterfaceImpl.h @@ -19,7 +19,7 @@ namespace tgcalls { class SctpDataChannelProviderInterfaceImpl : public sigslot::has_slots<>, public webrtc::SctpDataChannelControllerInterface, public webrtc::DataChannelObserver, public webrtc::DataChannelSink { public: SctpDataChannelProviderInterfaceImpl( - cricket::DtlsTransport *transportChannel, + rtc::PacketTransportInternal *transportChannel, bool isOutgoing, std::function onStateChanged, std::function onTerminated, diff --git a/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartInternal.cpp b/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartInternal.cpp index 178091618..747738167 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartInternal.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartInternal.cpp @@ -199,7 +199,7 @@ _avIoContext(std::move(fileData)) { AudioStreamingPartInternal::~AudioStreamingPartInternal() { if (_frame) { - av_frame_unref(_frame); + av_frame_free(&_frame); } if (_inputFormatContext) { avformat_close_input(&_inputFormatContext); diff --git a/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartPersistentDecoder.cpp b/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartPersistentDecoder.cpp index 63ef4755f..2bcfb1e66 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartPersistentDecoder.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/AudioStreamingPartPersistentDecoder.cpp @@ -55,6 +55,7 @@ public: ~AudioStreamingPartPersistentDecoderState() { if (_codecContext) { + avcodec_close(_codecContext); avcodec_free_context(&_codecContext); } } @@ -85,6 +86,10 @@ AudioStreamingPartPersistentDecoder::AudioStreamingPartPersistentDecoder() { } AudioStreamingPartPersistentDecoder::~AudioStreamingPartPersistentDecoder() { + if (_state) { + delete _state; + _state = nullptr; + } } void AudioStreamingPartPersistentDecoder::maybeReset(AVCodecParameters const *codecParameters, AVRational timeBase) { diff --git a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp index 1e9ed3d60..6de6f0c35 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/GroupInstanceCustomImpl.cpp @@ -103,15 +103,11 @@ static int stringToInt(std::string const &string) { } static std::string intToString(int value) { - std::ostringstream stringStream; - stringStream << value; - return stringStream.str(); + return std::to_string(value); } static std::string uint32ToString(uint32_t value) { - std::ostringstream stringStream; - stringStream << value; - return stringStream.str(); + return std::to_string(value); } static uint32_t stringToUInt32(std::string const &string) { @@ -130,6 +126,7 @@ static uint16_t stringToUInt16(std::string const &string) { static std::string formatTimestampMillis(int64_t timestamp) { std::ostringstream stringStream; + stringStream.imbue(std::locale::classic()); stringStream << std::fixed << std::setprecision(3) << (double)timestamp / 1000.0; return stringStream.str(); } @@ -2845,9 +2842,9 @@ public: void setAudioInputDevice(const std::string &id) { #if not defined(WEBRTC_IOS) && not defined(WEBRTC_ANDROID) - _threads->getWorkerThread()->BlockingCall([&] { + _threads->getWorkerThread()->BlockingCall([&] { SetAudioInputDeviceById(_audioDeviceModule.get(), id); - }); + }); #endif // WEBRTC_IOS } diff --git a/TMessagesProj/jni/voip/tgcalls/group/StreamingMediaContext.cpp b/TMessagesProj/jni/voip/tgcalls/group/StreamingMediaContext.cpp index 6d8f74361..a0ffdae2c 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/StreamingMediaContext.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/StreamingMediaContext.cpp @@ -302,8 +302,20 @@ public: for (auto &videoSegment : segment->video) { videoSegment->isPlaying = true; cancelPendingVideoQualityUpdate(videoSegment); - - auto frame = videoSegment->part->getFrameAtRelativeTimestamp(relativeTimestamp); + + std::shared_ptr sharedVideoState; + auto endpointId = videoSegment->part->getActiveEndpointId(); + if (endpointId.has_value()) { + auto it = _sharedVideoStateByEndpointId.find(endpointId.value()); + if (it != _sharedVideoStateByEndpointId.end()) { + sharedVideoState = it->second; + } else { + sharedVideoState = std::make_shared(); + _sharedVideoStateByEndpointId.insert(std::make_pair(endpointId.value(), sharedVideoState)); + } + } + + auto frame = videoSegment->part->getFrameAtRelativeTimestamp(sharedVideoState.get(), relativeTimestamp); if (frame) { if (videoSegment->lastFramePts != frame->pts) { videoSegment->lastFramePts = frame->pts; @@ -324,8 +336,20 @@ public: for (auto &videoSegment : segment->unified) { videoSegment->isPlaying = true; + + absl::optional endpointId = "unified"; + std::shared_ptr sharedVideoState; + if (endpointId.has_value()) { + auto it = _sharedVideoStateByEndpointId.find(endpointId.value()); + if (it != _sharedVideoStateByEndpointId.end()) { + sharedVideoState = it->second; + } else { + sharedVideoState = std::make_shared(); + _sharedVideoStateByEndpointId.insert(std::make_pair(endpointId.value(), sharedVideoState)); + } + } - auto frame = videoSegment->videoPart->getFrameAtRelativeTimestamp(relativeTimestamp); + auto frame = videoSegment->videoPart->getFrameAtRelativeTimestamp(sharedVideoState.get(), relativeTimestamp); if (frame) { if (videoSegment->lastFramePts != frame->pts) { videoSegment->lastFramePts = frame->pts; @@ -1039,6 +1063,7 @@ private: std::map _volumeBySsrc; std::vector _activeVideoChannels; + std::map> _sharedVideoStateByEndpointId; std::map>>> _videoSinks; std::map _currentEndpointMapping; diff --git a/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.cpp b/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.cpp index 4a3441d5c..5129f12b2 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.cpp +++ b/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.cpp @@ -5,6 +5,7 @@ #include "api/video/i420_buffer.h" #include "AVIOContextImpl.h" +#include "platform/PlatformInterface.h" #include #include @@ -79,7 +80,7 @@ public: ~Frame() { if (_frame) { - av_frame_unref(_frame); + av_frame_free(&_frame); } } @@ -265,6 +266,214 @@ absl::optional consumeVideoStreamInfo(std::vector &dat return info; } +bool areCodecParametersEqual(AVCodecParameters const &lhs, AVCodecParameters const &rhs) { + if (lhs.codec_id != rhs.codec_id) { + return false; + } + if (lhs.extradata_size != rhs.extradata_size) { + return false; + } + if (lhs.extradata_size != 0) { + if (memcmp(lhs.extradata, rhs.extradata, lhs.extradata_size)) { + return false; + } + } + if (lhs.format != rhs.format) { + return false; + } + if (lhs.profile != rhs.profile) { + return false; + } + if (lhs.level != rhs.level) { + return false; + } + if (lhs.width != rhs.width) { + return false; + } + if (lhs.height != rhs.height) { + return false; + } + if (lhs.sample_aspect_ratio.num != rhs.sample_aspect_ratio.num) { + return false; + } + if (lhs.sample_aspect_ratio.den != rhs.sample_aspect_ratio.den) { + return false; + } + if (lhs.field_order != rhs.field_order) { + return false; + } + if (lhs.color_range != rhs.color_range) { + return false; + } + if (lhs.color_primaries != rhs.color_primaries) { + return false; + } + if (lhs.color_trc != rhs.color_trc) { + return false; + } + if (lhs.color_space != rhs.color_space) { + return false; + } + if (lhs.chroma_location != rhs.chroma_location) { + return false; + } + + return true; +} + +class VideoStreamingDecoderState { +public: + static std::unique_ptr create( + AVCodecParameters const *codecParameters, + AVRational pktTimebase + ) { + AVCodec const *codec = nullptr; + if (!codec) { + codec = avcodec_find_decoder(codecParameters->codec_id); + } + if (!codec) { + return nullptr; + } + AVCodecContext *codecContext = avcodec_alloc_context3(codec); + int ret = avcodec_parameters_to_context(codecContext, codecParameters); + if (ret < 0) { + avcodec_free_context(&codecContext); + return nullptr; + } else { + codecContext->pkt_timebase = pktTimebase; + + PlatformInterface::SharedInstance()->setupVideoDecoding(codecContext); + + ret = avcodec_open2(codecContext, codec, nullptr); + if (ret < 0) { + avcodec_free_context(&codecContext); + return nullptr; + } + } + + return std::make_unique( + codecContext, + codecParameters, + pktTimebase + ); + } + +public: + VideoStreamingDecoderState( + AVCodecContext *codecContext, + AVCodecParameters const *codecParameters, + AVRational pktTimebase + ) { + _codecContext = codecContext; + _codecParameters = avcodec_parameters_alloc(); + avcodec_parameters_copy(_codecParameters, codecParameters); + _pktTimebase = pktTimebase; + } + + ~VideoStreamingDecoderState() { + if (_codecContext) { + avcodec_close(_codecContext); + avcodec_free_context(&_codecContext); + } + if (_codecParameters) { + avcodec_parameters_free(&_codecParameters); + } + } + + bool supportsDecoding( + AVCodecParameters const *codecParameters, + AVRational pktTimebase + ) const { + if (!areCodecParametersEqual(*_codecParameters, *codecParameters)) { + return false; + } + if (_pktTimebase.num != pktTimebase.num) { + return false; + } + if (_pktTimebase.den != pktTimebase.den) { + return false; + } + return true; + } + + int sendFrame(std::shared_ptr frame) { + if (frame) { + int status = avcodec_send_packet(_codecContext, frame->packet().packet()); + return status; + } else { + int status = avcodec_send_packet(_codecContext, nullptr); + return status; + } + } + + int receiveFrame(Frame &frame) { + int status = avcodec_receive_frame(_codecContext, frame.frame()); + return status; + } + + void reset() { + avcodec_flush_buffers(_codecContext); + } + +private: + AVCodecContext *_codecContext = nullptr; + AVCodecParameters *_codecParameters = nullptr; + AVRational _pktTimebase; +}; + +} + +class VideoStreamingSharedStateInternal { +public: + VideoStreamingSharedStateInternal() { + } + + ~VideoStreamingSharedStateInternal() { + } + + void updateDecoderState( + AVCodecParameters const *codecParameters, + AVRational pktTimebase + ) { + if (_decoderState && _decoderState->supportsDecoding(codecParameters, pktTimebase)) { + return; + } + + _decoderState.reset(); + _decoderState = VideoStreamingDecoderState::create(codecParameters, pktTimebase); + } + + int sendFrame(std::shared_ptr frame) { + if (!_decoderState) { + return AVERROR(EIO); + } + return _decoderState->sendFrame(frame); + } + + int receiveFrame(Frame &frame) { + if (!_decoderState) { + return AVERROR(EIO); + } + return _decoderState->receiveFrame(frame); + } + + void reset() { + if (!_decoderState) { + return; + } + _decoderState->reset(); + } + +private: + std::unique_ptr _decoderState; +}; + +VideoStreamingSharedState::VideoStreamingSharedState() { + _impl = new VideoStreamingSharedStateInternal(); +} + +VideoStreamingSharedState::~VideoStreamingSharedState() { + delete _impl; } class VideoStreamingPartInternal { @@ -322,7 +531,11 @@ public: } if (videoCodecParameters && videoStream) { - const AVCodec *codec = avcodec_find_decoder(videoCodecParameters->codec_id); + _videoCodecParameters = avcodec_parameters_alloc(); + avcodec_parameters_copy(_videoCodecParameters, videoCodecParameters); + _videoStream = videoStream; + + /*const AVCodec *codec = avcodec_find_decoder(videoCodecParameters->codec_id); if (codec) { _codecContext = avcodec_alloc_context3(codec); ret = avcodec_parameters_to_context(_codecContext, videoCodecParameters); @@ -344,14 +557,13 @@ public: _videoStream = videoStream; } } - } + }*/ } } ~VideoStreamingPartInternal() { - if (_codecContext) { - avcodec_close(_codecContext); - avcodec_free_context(&_codecContext); + if (_videoCodecParameters) { + avcodec_parameters_free(&_videoCodecParameters); } if (_inputFormatContext) { avformat_close_input(&_inputFormatContext); @@ -393,32 +605,47 @@ public: } absl::optional convertCurrentFrame() { - rtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Copy( - _frame.frame()->width, - _frame.frame()->height, - _frame.frame()->data[0], - _frame.frame()->linesize[0], - _frame.frame()->data[1], - _frame.frame()->linesize[1], - _frame.frame()->data[2], - _frame.frame()->linesize[2] - ); - if (i420Buffer) { + auto platformFrameBuffer = PlatformInterface::SharedInstance()->createPlatformFrameFromData(_frame.frame()); + if (platformFrameBuffer) { auto videoFrame = webrtc::VideoFrame::Builder() - .set_video_frame_buffer(i420Buffer) + .set_video_frame_buffer(platformFrameBuffer) .set_rotation(_rotation) .build(); return VideoStreamingPartFrame(_endpointId, videoFrame, _frame.pts(_videoStream, _firstFramePts), _frameIndex); } else { - return absl::nullopt; + rtc::scoped_refptr i420Buffer = webrtc::I420Buffer::Copy( + _frame.frame()->width, + _frame.frame()->height, + _frame.frame()->data[0], + _frame.frame()->linesize[0], + _frame.frame()->data[1], + _frame.frame()->linesize[1], + _frame.frame()->data[2], + _frame.frame()->linesize[2] + ); + if (i420Buffer) { + auto videoFrame = webrtc::VideoFrame::Builder() + .set_video_frame_buffer(i420Buffer) + .set_rotation(_rotation) + .build(); + + return VideoStreamingPartFrame(_endpointId, videoFrame, _frame.pts(_videoStream, _firstFramePts), _frameIndex); + } else { + return absl::nullopt; + } } } - absl::optional getNextFrame() { - if (!_codecContext) { + absl::optional getNextFrame(VideoStreamingSharedState const *sharedState) { + if (!_videoStream) { return {}; } + if (!_videoCodecParameters) { + return {}; + } + + sharedState->impl()->updateDecoderState(_videoCodecParameters, _videoStream->time_base); while (true) { if (_didReadToEnd) { @@ -432,42 +659,50 @@ public: } else { const auto frame = readNextDecodableFrame(); if (frame) { - auto status = avcodec_send_packet(_codecContext, frame->packet().packet()); - if (status == 0) { - auto status = avcodec_receive_frame(_codecContext, _frame.frame()); - if (status == 0) { + int sendStatus = sharedState->impl()->sendFrame(frame); + if (sendStatus == 0) { + int receiveStatus = sharedState->impl()->receiveFrame(_frame); + if (receiveStatus == 0) { auto convertedFrame = convertCurrentFrame(); if (convertedFrame) { _frameIndex++; return convertedFrame; } - } else if (status == AVERROR(EAGAIN)) { + } else if (receiveStatus == AVERROR(EAGAIN)) { // more data needed } else { + RTC_LOG(LS_ERROR) << "avcodec_receive_frame failed with result: " << receiveStatus; _didReadToEnd = true; break; } } else { + RTC_LOG(LS_ERROR) << "avcodec_send_packet failed with result: " << sendStatus; _didReadToEnd = true; return {}; } } else { _didReadToEnd = true; - int status = avcodec_send_packet(_codecContext, nullptr); - if (status == 0) { + int sendStatus = sharedState->impl()->sendFrame(nullptr); + if (sendStatus == 0) { while (true) { - auto status = avcodec_receive_frame(_codecContext, _frame.frame()); - if (status == 0) { + int receiveStatus = sharedState->impl()->receiveFrame(_frame); + if (receiveStatus == 0) { auto convertedFrame = convertCurrentFrame(); if (convertedFrame) { _frameIndex++; _finalFrames.push_back(convertedFrame.value()); } } else { + if (receiveStatus != AVERROR_EOF) { + RTC_LOG(LS_ERROR) << "avcodec_receive_frame (drain) failed with result: " << receiveStatus; + } break; } } + } else { + RTC_LOG(LS_ERROR) << "avcodec_send_packet (drain) failed with result: " << sendStatus; } + sharedState->impl()->reset(); } } } @@ -482,10 +717,11 @@ private: std::unique_ptr _avIoContext; AVFormatContext *_inputFormatContext = nullptr; - AVCodecContext *_codecContext = nullptr; AVStream *_videoStream = nullptr; Frame _frame; + AVCodecParameters *_videoCodecParameters = nullptr; + std::vector _finalFrames; int _frameIndex = 0; @@ -564,7 +800,7 @@ public: ~VideoStreamingPartState() { } - absl::optional getFrameAtRelativeTimestamp(double timestamp) { + absl::optional getFrameAtRelativeTimestamp(VideoStreamingSharedState const *sharedState, double timestamp) { while (true) { while (_availableFrames.size() >= 2) { if (timestamp >= _availableFrames[1].pts) { @@ -576,7 +812,7 @@ public: if (_availableFrames.size() < 2) { if (!_parsedVideoParts.empty()) { - auto result = _parsedVideoParts[0]->getNextFrame(); + auto result = _parsedVideoParts[0]->getNextFrame(sharedState); if (result) { _availableFrames.push_back(result.value()); } else { @@ -622,7 +858,7 @@ public: } return 0; } - + std::vector getAudio10msPerChannel(AudioStreamingPartPersistentDecoder &persistentDecoder) { while (!_parsedAudioParts.empty()) { auto firstPartResult = _parsedAudioParts[0]->get10msPerChannel(persistentDecoder); @@ -655,9 +891,9 @@ VideoStreamingPart::~VideoStreamingPart() { } } -absl::optional VideoStreamingPart::getFrameAtRelativeTimestamp(double timestamp) { +absl::optional VideoStreamingPart::getFrameAtRelativeTimestamp(VideoStreamingSharedState const *sharedState, double timestamp) { return _state - ? _state->getFrameAtRelativeTimestamp(timestamp) + ? _state->getFrameAtRelativeTimestamp(sharedState, timestamp) : absl::nullopt; } diff --git a/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.h b/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.h index 16bc0ab4b..cdcf21e7a 100644 --- a/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.h +++ b/TMessagesProj/jni/voip/tgcalls/group/VideoStreamingPart.h @@ -14,6 +14,7 @@ namespace tgcalls { class VideoStreamingPartState; +class VideoStreamingSharedStateInternal; struct VideoStreamingPartFrame { std::string endpointId; @@ -29,6 +30,19 @@ struct VideoStreamingPartFrame { } }; +class VideoStreamingSharedState { +public: + VideoStreamingSharedState(); + ~VideoStreamingSharedState(); + + VideoStreamingSharedStateInternal *impl() const { + return _impl; + } + +private: + VideoStreamingSharedStateInternal *_impl = nullptr; +}; + class VideoStreamingPart { public: enum class ContentType { @@ -48,7 +62,7 @@ public: VideoStreamingPart& operator=(const VideoStreamingPart&) = delete; VideoStreamingPart& operator=(VideoStreamingPart&&) = delete; - absl::optional getFrameAtRelativeTimestamp(double timestamp); + absl::optional getFrameAtRelativeTimestamp(VideoStreamingSharedState const *sharedState, double timestamp); absl::optional getActiveEndpointId() const; bool hasRemainingFrames() const; diff --git a/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.cpp b/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.cpp index bf9bd35db..b1e532c9c 100644 --- a/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.cpp +++ b/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.cpp @@ -215,7 +215,7 @@ void InstanceImplLegacy::sendVideoDeviceUpdated() { void InstanceImplLegacy::setRequestedVideoAspect(float aspect) { } -void InstanceImplLegacy::setIncomingVideoOutput(std::shared_ptr> sink) { +void InstanceImplLegacy::setIncomingVideoOutput(std::weak_ptr> sink) { } void InstanceImplLegacy::setAudioOutputGainControlEnabled(bool enabled) { diff --git a/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.h b/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.h index 3a3a6647e..6eca4c588 100644 --- a/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.h +++ b/TMessagesProj/jni/voip/tgcalls/legacy/InstanceImplLegacy.h @@ -25,7 +25,7 @@ public: bool supportsVideo() override { return false; } - void setIncomingVideoOutput(std::shared_ptr> sink) override; + void setIncomingVideoOutput(std::weak_ptr> sink) override; void setAudioOutputGainControlEnabled(bool enabled) override; void setEchoCancellationStrength(int strength) override; void setAudioInputDevice(std::string id) override; diff --git a/TMessagesProj/jni/voip/tgcalls/platform/PlatformInterface.h b/TMessagesProj/jni/voip/tgcalls/platform/PlatformInterface.h index 2f6e11ea2..7f0bb367d 100644 --- a/TMessagesProj/jni/voip/tgcalls/platform/PlatformInterface.h +++ b/TMessagesProj/jni/voip/tgcalls/platform/PlatformInterface.h @@ -10,6 +10,9 @@ #include "rtc_base/ref_counted_object.h" #include +struct AVFrame; +struct AVCodecContext; + namespace tgcalls { enum class VideoState; @@ -292,6 +295,14 @@ private: rtc::scoped_refptr _impl; }; +class PlatformVideoFrame { +public: + PlatformVideoFrame() { + } + + virtual ~PlatformVideoFrame() = default; +}; + class PlatformInterface { public: static PlatformInterface *SharedInstance(); @@ -313,6 +324,11 @@ public: virtual rtc::scoped_refptr wrapAudioDeviceModule(rtc::scoped_refptr module) { return rtc::make_ref_counted(module); } + virtual void setupVideoDecoding(AVCodecContext *codecContext) { + } + virtual rtc::scoped_refptr createPlatformFrameFromData(AVFrame const *frame) { + return nullptr; + } public: bool preferX264 = false; diff --git a/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp b/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp index 3feb47ee7..7cf031dc8 100644 --- a/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp +++ b/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp @@ -6,12 +6,9 @@ namespace tgcalls { AndroidContext::AndroidContext(JNIEnv *env, jobject instance, bool screencast) { - DEBUG_REF("VideoCapturerDevice"); VideoCapturerDeviceClass = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/VideoCapturerDevice")); jmethodID initMethodId = env->GetMethodID(VideoCapturerDeviceClass, "", "(Z)V"); - DEBUG_REF("VideoCapturerDevice javaCapturer"); javaCapturer = env->NewGlobalRef(env->NewObject(VideoCapturerDeviceClass, initMethodId, screencast)); - DEBUG_REF("VideoCapturerDevice javaInstance"); javaInstance = env->NewGlobalRef(instance); } @@ -20,21 +17,17 @@ AndroidContext::~AndroidContext() { jmethodID onDestroyMethodId = env->GetMethodID(VideoCapturerDeviceClass, "onDestroy", "()V"); env->CallVoidMethod(javaCapturer, onDestroyMethodId); - DEBUG_DELREF("javaCapturer"); env->DeleteGlobalRef(javaCapturer); javaCapturer = nullptr; - DEBUG_DELREF("VideoCapturerDeviceClass"); env->DeleteGlobalRef(VideoCapturerDeviceClass); if (javaInstance) { - DEBUG_DELREF("javaInstance"); env->DeleteGlobalRef(javaInstance); } } void AndroidContext::setJavaInstance(JNIEnv *env, jobject instance) { - DEBUG_REF("setJavaInstance"); javaInstance = env->NewGlobalRef(instance); } diff --git a/TMessagesProj/jni/voip/tgcalls/v2/ContentNegotiation.cpp b/TMessagesProj/jni/voip/tgcalls/v2/ContentNegotiation.cpp index 726b1fbfa..3d5e12588 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/ContentNegotiation.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2/ContentNegotiation.cpp @@ -11,60 +11,60 @@ namespace { signaling::MediaContent convertContentInfoToSingalingContent(cricket::ContentInfo const &content) { signaling::MediaContent mappedContent; - + switch (content.media_description()->type()) { case cricket::MediaType::MEDIA_TYPE_AUDIO: { mappedContent.type = signaling::MediaContent::Type::Audio; - + for (const auto &codec : content.media_description()->as_audio()->codecs()) { signaling::PayloadType mappedPayloadType; mappedPayloadType.id = codec.id; mappedPayloadType.name = codec.name; mappedPayloadType.clockrate = codec.clockrate; mappedPayloadType.channels = (uint32_t)codec.channels; - + for (const auto &feedbackType : codec.feedback_params.params()) { signaling::FeedbackType mappedFeedbackType; mappedFeedbackType.type = feedbackType.id(); mappedFeedbackType.subtype = feedbackType.param(); mappedPayloadType.feedbackTypes.push_back(std::move(mappedFeedbackType)); } - + for (const auto ¶meter : codec.params) { mappedPayloadType.parameters.push_back(std::make_pair(parameter.first, parameter.second)); } std::sort(mappedPayloadType.parameters.begin(), mappedPayloadType.parameters.end(), [](std::pair const &lhs, std::pair const &rhs) -> bool { return lhs.first < rhs.first; }); - + mappedContent.payloadTypes.push_back(std::move(mappedPayloadType)); } break; } case cricket::MediaType::MEDIA_TYPE_VIDEO: { mappedContent.type = signaling::MediaContent::Type::Video; - + for (const auto &codec : content.media_description()->as_video()->codecs()) { signaling::PayloadType mappedPayloadType; mappedPayloadType.id = codec.id; mappedPayloadType.name = codec.name; mappedPayloadType.clockrate = codec.clockrate; mappedPayloadType.channels = 0; - + for (const auto &feedbackType : codec.feedback_params.params()) { signaling::FeedbackType mappedFeedbackType; mappedFeedbackType.type = feedbackType.id(); mappedFeedbackType.subtype = feedbackType.param(); mappedPayloadType.feedbackTypes.push_back(std::move(mappedFeedbackType)); } - + for (const auto ¶meter : codec.params) { mappedPayloadType.parameters.push_back(std::make_pair(parameter.first, parameter.second)); } std::sort(mappedPayloadType.parameters.begin(), mappedPayloadType.parameters.end(), [](std::pair const &lhs, std::pair const &rhs) -> bool { return lhs.first < rhs.first; }); - + mappedContent.payloadTypes.push_back(std::move(mappedPayloadType)); } break; @@ -74,7 +74,7 @@ signaling::MediaContent convertContentInfoToSingalingContent(cricket::ContentInf break; } } - + if (!content.media_description()->streams().empty()) { mappedContent.ssrc = content.media_description()->streams()[0].first_ssrc(); for (const auto &ssrcGroup : content.media_description()->streams()[0].ssrc_groups) { @@ -84,21 +84,21 @@ signaling::MediaContent convertContentInfoToSingalingContent(cricket::ContentInf mappedContent.ssrcGroups.push_back(std::move(mappedSsrcGroup)); } } - + for (const auto &extension : content.media_description()->rtp_header_extensions()) { mappedContent.rtpExtensions.push_back(extension); } - + return mappedContent; } cricket::ContentInfo convertSingalingContentToContentInfo(std::string const &contentId, signaling::MediaContent const &content, webrtc::RtpTransceiverDirection direction) { std::unique_ptr contentDescription; - + switch (content.type) { case signaling::MediaContent::Type::Audio: { auto audioDescription = std::make_unique(); - + for (const auto &payloadType : content.payloadTypes) { cricket::AudioCodec mappedCodec((int)payloadType.id, payloadType.name, (int)payloadType.clockrate, 0, payloadType.channels); for (const auto ¶meter : payloadType.parameters) { @@ -109,14 +109,14 @@ cricket::ContentInfo convertSingalingContentToContentInfo(std::string const &con } audioDescription->AddCodec(mappedCodec); } - + contentDescription = std::move(audioDescription); - + break; } case signaling::MediaContent::Type::Video: { auto videoDescription = std::make_unique(); - + for (const auto &payloadType : content.payloadTypes) { cricket::VideoCodec mappedCodec((int)payloadType.id, payloadType.name); for (const auto ¶meter : payloadType.parameters) { @@ -127,9 +127,9 @@ cricket::ContentInfo convertSingalingContentToContentInfo(std::string const &con } videoDescription->AddCodec(mappedCodec); } - + contentDescription = std::move(videoDescription); - + break; } default: { @@ -137,7 +137,7 @@ cricket::ContentInfo convertSingalingContentToContentInfo(std::string const &con break; } } - + cricket::StreamParams streamParams; streamParams.id = contentId; streamParams.set_stream_ids({ contentId }); @@ -151,47 +151,43 @@ cricket::ContentInfo convertSingalingContentToContentInfo(std::string const &con } } contentDescription->AddStream(streamParams); - + for (const auto &extension : content.rtpExtensions) { contentDescription->AddRtpHeaderExtension(extension); } - + contentDescription->set_direction(direction); contentDescription->set_rtcp_mux(true); - + cricket::ContentInfo mappedContentInfo(cricket::MediaProtocolType::kRtp); mappedContentInfo.name = contentId; mappedContentInfo.rejected = false; mappedContentInfo.bundle_only = false; mappedContentInfo.set_media_description(std::move(contentDescription)); - + return mappedContentInfo; } cricket::ContentInfo createInactiveContentInfo(std::string const &contentId) { std::unique_ptr contentDescription; - + auto audioDescription = std::make_unique(); contentDescription = std::move(audioDescription); - + contentDescription->set_direction(webrtc::RtpTransceiverDirection::kInactive); contentDescription->set_rtcp_mux(true); - + cricket::ContentInfo mappedContentInfo(cricket::MediaProtocolType::kRtp); mappedContentInfo.name = contentId; mappedContentInfo.rejected = false; mappedContentInfo.bundle_only = false; mappedContentInfo.set_media_description(std::move(contentDescription)); - + return mappedContentInfo; } std::string contentIdBySsrc(uint32_t ssrc) { - std::ostringstream contentIdString; - - contentIdString << ssrc; - - return contentIdString.str(); + return std::to_string(ssrc); } } @@ -200,19 +196,19 @@ ContentNegotiationContext::ContentNegotiationContext(const webrtc::WebRtcKeyValu _isOutgoing(isOutgoing), _uniqueRandomIdGenerator(uniqueRandomIdGenerator) { _transportDescriptionFactory = std::make_unique(fieldTrials); - + // tempCertificate is only used to fill in the local SDP auto tempCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt); _transportDescriptionFactory->set_secure(cricket::SecurePolicy::SEC_REQUIRED); _transportDescriptionFactory->set_certificate(tempCertificate); - + _sessionDescriptionFactory = std::make_unique(_transportDescriptionFactory.get(), uniqueRandomIdGenerator); - + _needNegotiation = true; } ContentNegotiationContext::~ContentNegotiationContext() { - + } void ContentNegotiationContext::copyCodecsFromChannelManager(cricket::MediaEngineInterface *mediaEngine, bool randomize) { @@ -220,7 +216,7 @@ void ContentNegotiationContext::copyCodecsFromChannelManager(cricket::MediaEngin cricket::AudioCodecs audioRecvCodecs = mediaEngine->voice().recv_codecs(); cricket::VideoCodecs videoSendCodecs = mediaEngine->video().send_codecs(); cricket::VideoCodecs videoRecvCodecs = mediaEngine->video().recv_codecs(); - + for (const auto &codec : audioSendCodecs) { if (codec.name == "opus") { audioSendCodecs = { codec }; @@ -228,7 +224,7 @@ void ContentNegotiationContext::copyCodecsFromChannelManager(cricket::MediaEngin break; } } - + if (randomize) { for (auto &codec : audioSendCodecs) { codec.id += 3; @@ -243,23 +239,23 @@ void ContentNegotiationContext::copyCodecsFromChannelManager(cricket::MediaEngin codec.id += 3; } } - + _sessionDescriptionFactory->set_audio_codecs(audioSendCodecs, audioRecvCodecs); _sessionDescriptionFactory->set_video_codecs(videoSendCodecs, videoRecvCodecs); - + int absSendTimeUriId = 2; int transportSequenceNumberUriId = 3; int videoRotationUri = 13; - + if (randomize) { absSendTimeUriId = 3; transportSequenceNumberUriId = 2; videoRotationUri = 4; } - + _rtpAudioExtensions.emplace_back(webrtc::RtpExtension::kAbsSendTimeUri, absSendTimeUriId); _rtpAudioExtensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, transportSequenceNumberUriId); - + _rtpVideoExtensions.emplace_back(webrtc::RtpExtension::kAbsSendTimeUri, absSendTimeUriId); _rtpVideoExtensions.emplace_back(webrtc::RtpExtension::kTransportSequenceNumberUri, transportSequenceNumberUriId); _rtpVideoExtensions.emplace_back(webrtc::RtpExtension::kVideoRotationUri, videoRotationUri); @@ -267,7 +263,7 @@ void ContentNegotiationContext::copyCodecsFromChannelManager(cricket::MediaEngin std::string ContentNegotiationContext::addOutgoingChannel(signaling::MediaContent::Type mediaType) { std::string channelId = takeNextOutgoingChannelId(); - + cricket::MediaType mappedMediaType; std::vector rtpExtensions; switch (mediaType) { @@ -288,7 +284,7 @@ std::string ContentNegotiationContext::addOutgoingChannel(signaling::MediaConten } cricket::MediaDescriptionOptions offerDescription(mappedMediaType, channelId, webrtc::RtpTransceiverDirection::kSendOnly, false); offerDescription.header_extensions = rtpExtensions; - + switch (mediaType) { case signaling::MediaContent::Type::Audio: { offerDescription.AddAudioSender(channelId, { channelId }); @@ -304,10 +300,10 @@ std::string ContentNegotiationContext::addOutgoingChannel(signaling::MediaConten break; } } - + _outgoingChannelDescriptions.emplace_back(std::move(offerDescription)); _needNegotiation = true; - + return channelId; } @@ -315,9 +311,9 @@ void ContentNegotiationContext::removeOutgoingChannel(std::string const &id) { for (size_t i = 0; i < _outgoingChannels.size(); i++) { if (_outgoingChannelDescriptions[i].description.mid == id) { _outgoingChannelDescriptions.erase(_outgoingChannelDescriptions.begin() + i); - + _needNegotiation = true; - + break; } } @@ -327,66 +323,66 @@ std::unique_ptr ContentNegotiationContext::currentS if (_channelIdOrder.empty()) { return nullptr; } - + auto sessionDescription = std::make_unique(); - + for (const auto &id : _channelIdOrder) { bool found = false; - + for (const auto &channel : _incomingChannels) { if (contentIdBySsrc(channel.ssrc) == id) { found = true; - + auto mappedContent = convertSingalingContentToContentInfo(contentIdBySsrc(channel.ssrc), channel, webrtc::RtpTransceiverDirection::kRecvOnly); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(contentIdBySsrc(channel.ssrc), transportDescription); sessionDescription->AddTransportInfo(transportInfo); - + sessionDescription->AddContent(std::move(mappedContent)); - + break; } } - + for (const auto &channel : _outgoingChannels) { if (channel.id == id) { found = true; - + auto mappedContent = convertSingalingContentToContentInfo(channel.id, channel.content, webrtc::RtpTransceiverDirection::kSendOnly); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(mappedContent.name, transportDescription); sessionDescription->AddTransportInfo(transportInfo); - + sessionDescription->AddContent(std::move(mappedContent)); - + break; } } - + if (!found) { auto mappedContent = createInactiveContentInfo("_" + id); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(mappedContent.name, transportDescription); sessionDescription->AddTransportInfo(transportInfo); - + sessionDescription->AddContent(std::move(mappedContent)); } } - + return sessionDescription; } static cricket::MediaDescriptionOptions getIncomingContentDescription(signaling::MediaContent const &content) { auto mappedContent = convertSingalingContentToContentInfo(contentIdBySsrc(content.ssrc), content, webrtc::RtpTransceiverDirection::kSendOnly); - + cricket::MediaDescriptionOptions contentDescription(mappedContent.media_description()->type(), mappedContent.name, webrtc::RtpTransceiverDirection::kRecvOnly, false); for (const auto &extension : mappedContent.media_description()->rtp_header_extensions()) { contentDescription.header_extensions.emplace_back(extension.uri, extension.id); } - + return contentDescription; } @@ -397,71 +393,73 @@ std::unique_ptr ContentNegotiati if (_pendingOutgoingOffer) { return nullptr; } - + + _needNegotiation = false; + _pendingOutgoingOffer = std::make_unique(); _pendingOutgoingOffer->exchangeId = _uniqueRandomIdGenerator->GenerateId(); - + auto currentSessionDescription = currentSessionDescriptionFromCoordinatedState(); - + cricket::MediaSessionOptions offerOptions; offerOptions.offer_extmap_allow_mixed = true; offerOptions.bundle_enabled = true; - + for (const auto &id : _channelIdOrder) { bool found = false; - + for (const auto &channel : _outgoingChannelDescriptions) { if (channel.description.mid == id) { found = true; offerOptions.media_description_options.push_back(channel.description); - + break; } } - + for (const auto &content : _incomingChannels) { if (contentIdBySsrc(content.ssrc) == id) { found = true; offerOptions.media_description_options.push_back(getIncomingContentDescription(content)); - + break; } } - + if (!found) { cricket::MediaDescriptionOptions contentDescription(cricket::MediaType::MEDIA_TYPE_AUDIO, "_" + id, webrtc::RtpTransceiverDirection::kInactive, false); offerOptions.media_description_options.push_back(contentDescription); } } - + for (const auto &channel : _outgoingChannelDescriptions) { if (std::find(_channelIdOrder.begin(), _channelIdOrder.end(), channel.description.mid) == _channelIdOrder.end()) { _channelIdOrder.push_back(channel.description.mid); - + offerOptions.media_description_options.push_back(channel.description); } - + for (const auto &content : _incomingChannels) { if (std::find(_channelIdOrder.begin(), _channelIdOrder.end(), contentIdBySsrc(content.ssrc)) == _channelIdOrder.end()) { _channelIdOrder.push_back(contentIdBySsrc(content.ssrc)); - + offerOptions.media_description_options.push_back(getIncomingContentDescription(content)); } } } - + std::unique_ptr offer = _sessionDescriptionFactory->CreateOffer(offerOptions, currentSessionDescription.get()); - + auto mappedOffer = std::make_unique(); - + mappedOffer->exchangeId = _pendingOutgoingOffer->exchangeId; - + for (const auto &content : offer->contents()) { auto mappedContent = convertContentInfoToSingalingContent(content); - + if (content.media_description()->direction() == webrtc::RtpTransceiverDirection::kSendOnly) { mappedOffer->contents.push_back(std::move(mappedContent)); - + for (auto &channel : _outgoingChannelDescriptions) { if (channel.description.mid == content.mid()) { channel.ssrc = mappedContent.ssrc; @@ -470,7 +468,7 @@ std::unique_ptr ContentNegotiati } } } - + return mappedOffer; } @@ -478,7 +476,7 @@ std::unique_ptr ContentNegotiati if (!remoteNegotiationContent) { return nullptr; } - + if (_pendingOutgoingOffer) { if (remoteNegotiationContent->exchangeId == _pendingOutgoingOffer->exchangeId) { setAnswer(std::move(remoteNegotiationContent)); @@ -499,118 +497,118 @@ std::unique_ptr ContentNegotiati std::unique_ptr ContentNegotiationContext::getAnswer(std::unique_ptr &&offer) { auto currentSessionDescription = currentSessionDescriptionFromCoordinatedState(); - + auto mappedOffer = std::make_unique(); - + cricket::MediaSessionOptions answerOptions; answerOptions.offer_extmap_allow_mixed = true; answerOptions.bundle_enabled = true; - + for (const auto &id : _channelIdOrder) { bool found = false; - + for (const auto &channel : _outgoingChannels) { if (channel.id == id) { found = true; - + auto mappedContent = convertSingalingContentToContentInfo(channel.id, channel.content, webrtc::RtpTransceiverDirection::kRecvOnly); - + cricket::MediaDescriptionOptions contentDescription(mappedContent.media_description()->type(), mappedContent.name, webrtc::RtpTransceiverDirection::kSendOnly, false); for (const auto &extension : mappedContent.media_description()->rtp_header_extensions()) { contentDescription.header_extensions.emplace_back(extension.uri, extension.id); } answerOptions.media_description_options.push_back(contentDescription); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(channel.id, transportDescription); mappedOffer->AddTransportInfo(transportInfo); - + mappedOffer->AddContent(std::move(mappedContent)); - + break; } } - + for (const auto &content : offer->contents) { if (contentIdBySsrc(content.ssrc) == id) { found = true; - + auto mappedContent = convertSingalingContentToContentInfo(contentIdBySsrc(content.ssrc), content, webrtc::RtpTransceiverDirection::kSendOnly); - + cricket::MediaDescriptionOptions contentDescription(mappedContent.media_description()->type(), mappedContent.name, webrtc::RtpTransceiverDirection::kRecvOnly, false); for (const auto &extension : mappedContent.media_description()->rtp_header_extensions()) { contentDescription.header_extensions.emplace_back(extension.uri, extension.id); } answerOptions.media_description_options.push_back(contentDescription); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(mappedContent.mid(), transportDescription); mappedOffer->AddTransportInfo(transportInfo); - + mappedOffer->AddContent(std::move(mappedContent)); - + break; } } - + if (!found) { auto mappedContent = createInactiveContentInfo("_" + id); - + cricket::MediaDescriptionOptions contentDescription(cricket::MediaType::MEDIA_TYPE_AUDIO, "_" + id, webrtc::RtpTransceiverDirection::kInactive, false); answerOptions.media_description_options.push_back(contentDescription); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(mappedContent.mid(), transportDescription); mappedOffer->AddTransportInfo(transportInfo); - + mappedOffer->AddContent(std::move(mappedContent)); } } - + for (const auto &content : offer->contents) { if (std::find(_channelIdOrder.begin(), _channelIdOrder.end(), contentIdBySsrc(content.ssrc)) == _channelIdOrder.end()) { _channelIdOrder.push_back(contentIdBySsrc(content.ssrc)); - + answerOptions.media_description_options.push_back(getIncomingContentDescription(content)); - + auto mappedContent = convertSingalingContentToContentInfo(contentIdBySsrc(content.ssrc), content, webrtc::RtpTransceiverDirection::kSendOnly); - + cricket::TransportDescription transportDescription; cricket::TransportInfo transportInfo(mappedContent.mid(), transportDescription); mappedOffer->AddTransportInfo(transportInfo); - + mappedOffer->AddContent(std::move(mappedContent)); } } - + std::unique_ptr answer = _sessionDescriptionFactory->CreateAnswer(mappedOffer.get(), answerOptions, currentSessionDescription.get()); - + auto mappedAnswer = std::make_unique(); - + mappedAnswer->exchangeId = offer->exchangeId; - + std::vector incomingChannels; - + for (const auto &content : answer->contents()) { auto mappedContent = convertContentInfoToSingalingContent(content); - + if (content.media_description()->direction() == webrtc::RtpTransceiverDirection::kRecvOnly) { for (const auto &offerContent : offer->contents) { if (contentIdBySsrc(offerContent.ssrc) == content.mid()) { mappedContent.ssrc = offerContent.ssrc; mappedContent.ssrcGroups = offerContent.ssrcGroups; - + break; } } - + incomingChannels.push_back(mappedContent); mappedAnswer->contents.push_back(std::move(mappedContent)); } } - + _incomingChannels = incomingChannels; - + return mappedAnswer; } @@ -621,17 +619,16 @@ void ContentNegotiationContext::setAnswer(std::unique_ptrexchangeId != answer->exchangeId) { return; } - + _pendingOutgoingOffer.reset(); - _needNegotiation = false; - + _outgoingChannels.clear(); - + for (const auto &content : answer->contents) { for (const auto &pendingChannel : _outgoingChannelDescriptions) { if (pendingChannel.ssrc != 0 && content.ssrc == pendingChannel.ssrc) { _outgoingChannels.emplace_back(pendingChannel.description.mid, content); - + break; } } @@ -639,53 +636,52 @@ void ContentNegotiationContext::setAnswer(std::unique_ptr ContentNegotiationContext::coordinatedState() const { auto result = std::make_unique(); - + result->incomingContents = _incomingChannels; for (const auto &channel : _outgoingChannels) { bool found = false; - + for (const auto &channelDescription : _outgoingChannelDescriptions) { if (channelDescription.description.mid == channel.id) { found = true; break; } } - + if (found) { result->outgoingContents.push_back(channel.content); } } - + return result; } absl::optional ContentNegotiationContext::outgoingChannelSsrc(std::string const &id) const { for (const auto &channel : _outgoingChannels) { bool found = false; - + for (const auto &channelDescription : _outgoingChannelDescriptions) { if (channelDescription.description.mid == channel.id) { found = true; break; } } - + if (found && channel.id == id) { if (channel.content.ssrc != 0) { return channel.content.ssrc; } } } - + return absl::nullopt; } diff --git a/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.cpp b/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.cpp new file mode 100644 index 000000000..ba07d08f8 --- /dev/null +++ b/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.cpp @@ -0,0 +1,597 @@ +#include "v2/DirectNetworkingImpl.h" + +#include "p2p/base/basic_packet_socket_factory.h" +#include "p2p/client/basic_port_allocator.h" +#include "p2p/base/p2p_transport_channel.h" +#include "p2p/base/basic_async_resolver_factory.h" +#include "api/packet_socket_factory.h" +#include "rtc_base/rtc_certificate_generator.h" +#include "p2p/base/ice_credentials_iterator.h" +#include "api/jsep_ice_candidate.h" +#include "p2p/base/dtls_transport.h" +#include "p2p/base/dtls_transport_factory.h" +#include "pc/dtls_srtp_transport.h" +#include "pc/dtls_transport.h" +#include "pc/jsep_transport_controller.h" +#include "api/async_dns_resolver.h" + +#include "TurnCustomizerImpl.h" +#include "ReflectorRelayPortFactory.h" +#include "SctpDataChannelProviderInterfaceImpl.h" +#include "StaticThreads.h" +#include "platform/PlatformInterface.h" +#include "p2p/base/turn_port.h" + +#include "ReflectorPort.h" +#include "FieldTrialsConfig.h" + +namespace tgcalls { + +namespace { + +} + +class DirectPacketTransport : public rtc::PacketTransportInternal, public std::enable_shared_from_this { +public: + DirectPacketTransport( + rtc::Thread *thread, + EncryptionKey const &encryptionKey, + std::shared_ptr channel, std::function &&isConnectedUpdated + ) : + _isConnectedUpdated(std::move(isConnectedUpdated)), + _thread(thread), + _encryption( + EncryptedConnection::Type::Transport, + encryptionKey, + [=](int delayMs, int cause) { + assert(false); + }), + _channel(channel) { + assert(_thread->IsCurrent()); + } + + virtual ~DirectPacketTransport() { + } + + void start() { + auto weakSelf = std::weak_ptr(shared_from_this()); + _onIncomingPacketToken = _channel->addOnIncomingPacket([weakSelf, thread = _thread](std::shared_ptr> packet) { + thread->PostTask([weakSelf, packet] { + auto strongSelf = weakSelf.lock(); + if (!strongSelf) { + return; + } + strongSelf->processIncomingPacket(packet); + }); + }); + + updateState(); + runStateTimer(); + } + + void stop() { + if (!_onIncomingPacketToken.empty()) { + _channel->removeOnIncomingPacket(_onIncomingPacketToken); + _onIncomingPacketToken.resize(0); + } + } + +public: + virtual const std::string &transport_name() const override { + return name; + } + + // The transport has been established. + virtual bool writable() const override { + return _isConnected; + } + + // The transport has received a packet in the last X milliseconds, here X is + // configured by each implementation. + virtual bool receiving() const override { + return _isConnected; + } + + // Attempts to send the given packet. + // The return value is < 0 on failure. The return value in failure case is not + // descriptive. Depending on failure cause and implementation details + // GetError() returns an descriptive errno.h error value. + // This mimics posix socket send() or sendto() behavior. + // TODO(johan): Reliable, meaningful, consistent error codes for all + // implementations would be nice. + // TODO(johan): Remove the default argument once channel code is updated. + virtual int SendPacket(const char *data, + size_t len, + const rtc::PacketOptions& options, + int flags = 0) override { + if (!_isConnected) { + _lastError = ENOTCONN; + return -1; + } + + rtc::CopyOnWriteBuffer buffer; + buffer.AppendData(data, len); + + Message message = flags == 0 ? Message { AudioDataMessage { buffer } } : Message { VideoDataMessage { buffer } }; + + if (const auto prepared = _encryption.prepareForSending(message)) { + rtc::PacketOptions packetOptions; + + rtc::ByteBufferWriter bufferWriter; + bufferWriter.WriteUInt32((uint32_t)prepared->bytes.size()); + bufferWriter.WriteBytes(reinterpret_cast(prepared->bytes.data()), prepared->bytes.size()); + while (bufferWriter.Length() % 4 != 0) { + bufferWriter.WriteUInt8(0); + } + + auto packet = std::make_unique>(bufferWriter.Data(), bufferWriter.Data() + bufferWriter.Length()); + _channel->sendPacket(std::move(packet)); + } + + rtc::SentPacket sentPacket; + sentPacket.packet_id = options.packet_id; + sentPacket.send_time_ms = rtc::TimeMillis(); + SignalSentPacket(this, sentPacket); + + return 0; + } + + // Sets a socket option. Note that not all options are + // supported by all transport types. + virtual int SetOption(rtc::Socket::Option opt, int value) override { + return 0; + } + + // TODO(pthatcher): Once Chrome's MockPacketTransportInterface implements + // this, remove the default implementation. + virtual bool GetOption(rtc::Socket::Option opt, int *value) override { + return false; + } + + // Returns the most recent error that occurred on this channel. + virtual int GetError() override { + return _lastError; + } + + // Returns the current network route with transport overhead. + // TODO(zhihuang): Make it pure virtual once the Chrome/remoting is updated. + virtual absl::optional network_route() const override { + return absl::nullopt; + } + + /*sigslot::signal1 SignalWritableState; + + // Emitted when the PacketTransportInternal is ready to send packets. "Ready + // to send" is more sensitive than the writable state; a transport may be + // writable, but temporarily not able to send packets. For example, the + // underlying transport's socket buffer may be full, as indicated by + // SendPacket's return code and/or GetError. + sigslot::signal1 SignalReadyToSend; + + // Emitted when receiving state changes to true. + sigslot::signal1 SignalReceivingState; + + // Signalled each time a packet is received on this channel. + sigslot::signal5 + SignalReadPacket; + + // Signalled each time a packet is sent on this channel. + sigslot::signal2 + SignalSentPacket; + + // Signalled when the current network route has changed. + sigslot::signal1> SignalNetworkRouteChanged; + + // Signalled when the transport is closed. + sigslot::signal1 SignalClosed;*/ + +private: + void runStateTimer() { + const auto weakSelf = std::weak_ptr(shared_from_this()); + _thread->PostDelayedTask([weakSelf]() { + auto strongSelf = weakSelf.lock(); + if (!strongSelf) { + return; + } + + strongSelf->updateState(); + strongSelf->runStateTimer(); + }, webrtc::TimeDelta::Millis(100)); + } + + std::unique_ptr> makeServerHelloPacket() { + rtc::ByteBufferWriter bufferWriter; + for (int i = 0; i < 12; i++) { + bufferWriter.WriteUInt8(0xffu); + } + bufferWriter.WriteUInt8(0xfeu); + for (int i = 0; i < 3; i++) { + bufferWriter.WriteUInt8(0xffu); + } + bufferWriter.WriteUInt64(123); + + while (bufferWriter.Length() % 4 != 0) { + bufferWriter.WriteUInt8(0); + } + + return std::make_unique>(bufferWriter.Data(), bufferWriter.Data() + bufferWriter.Length()); + } + + std::unique_ptr> makePingPacket() { + rtc::ByteBufferWriter bufferWriter; + bufferWriter.WriteUInt32(_pingMarker); + + return std::make_unique>(bufferWriter.Data(), bufferWriter.Data() + bufferWriter.Length()); + } + + void updateState() { + auto timestamp = rtc::TimeMillis(); + + if (_isConnected && _lastDataReceivedTimestamp < timestamp - _keepalivePingInterval * 2) { + _isConnected = false; + SignalWritableState(this); + + if (_isConnectedUpdated) { + _isConnectedUpdated(_isConnected); + } + } + + if (_isConnected) { + if (_lastPingSentTimestamp < timestamp - _initialPingInterval) { + _lastPingSentTimestamp = timestamp; + + auto packet = makePingPacket(); + _channel->sendPacket(std::move(packet)); + } + } else { + if (_lastPingSentTimestamp < timestamp - _keepalivePingInterval) { + _lastPingSentTimestamp = timestamp; + + if (_hasCompletedHello) { + auto packet = makePingPacket(); + _channel->sendPacket(std::move(packet)); + } else { + auto packet = makeServerHelloPacket(); + _channel->sendPacket(std::move(packet)); + } + } + } + } + + void processIncomingPacket(std::shared_ptr> const &packet) { + rtc::ByteBufferReader reader(reinterpret_cast(packet->data()), packet->size()); + + uint32_t header = 0; + if (!reader.ReadUInt32(&header)) { + return; + } + + _lastDataReceivedTimestamp = rtc::TimeMillis(); + if (!_isConnected) { + _isConnected = true; + SignalWritableState(this); + SignalReadyToSend(this); + SignalReceivingState(this); + + if (_isConnectedUpdated) { + _isConnectedUpdated(_isConnected); + } + } + + if (header == _pingMarker) { + } else { + bool isSpecialPacket = false; + if (packet->size() >= 12) { + uint8_t specialTag[12]; + memcpy(specialTag, packet->data(), 12); + + uint8_t expectedSpecialTag[12]; + memset(expectedSpecialTag, 0xff, 12); + + if (memcmp(specialTag, expectedSpecialTag, 12) == 0) { + isSpecialPacket = true; + } + } + + if (!isSpecialPacket) { + rtc::ByteBufferReader dataPacketReader(reinterpret_cast(packet->data()), packet->size()); + uint32_t dataSize = 0; + if (!dataPacketReader.ReadUInt32(&dataSize)) { + return; + } + if (dataSize > packet->size() - 4) { + return; + } + + if (auto decrypted = _encryption.handleIncomingPacket(reinterpret_cast(packet->data()) + 4, dataSize)) { + handleIncomingMessage(decrypted->main); + for (auto &message : decrypted->additional) { + handleIncomingMessage(message); + } + + /*if (_transportMessageReceived) { + _transportMessageReceived(std::move(decrypted->main)); + for (auto &message : decrypted->additional) { + _transportMessageReceived(std::move(message)); + } + }*/ + } else { + RTC_LOG(LS_ERROR) << "DirectPacketTransport: could not decrypt incoming packet"; + } + + /*uint32_t dataSize = 0; + memcpy(&dataSize, packet->data(), 4); + dataSize = be32toh(dataSize); + if (dataSize > packet->size() - 4) { + RTC_LOG(LS_WARNING) << "DirectPacketTransport: Received data packet with invalid size tag"; + } else { + SignalReadPacket(this, reinterpret_cast(packet->data() + 4), dataSize, rtc::TimeMicros(), 0); + }*/ + } + } + } + + void handleIncomingMessage(DecryptedMessage const &message) { + const auto data = &message.message.data; + if (const auto dataMessage = absl::get_if(data)) { + SignalReadPacket(this, reinterpret_cast(dataMessage->data.data()), dataMessage->data.size(), rtc::TimeMicros(), 0); + } else if (const auto dataMessage = absl::get_if(data)) { + SignalReadPacket(this, reinterpret_cast(dataMessage->data.data()), dataMessage->data.size(), rtc::TimeMicros(), 1); + } else { + RTC_LOG(LS_INFO) << "DirectPacketTransport: unknown incoming message"; + } + } + +private: + std::string name = "DirectPacketTransport"; + + std::function _isConnectedUpdated; + + rtc::Thread *_thread = nullptr; + EncryptedConnection _encryption; + std::shared_ptr _channel; + + std::vector _onIncomingPacketToken; + + int _lastError = 0; + + int64_t _lastPingSentTimestamp = 0; + int64_t _lastDataReceivedTimestamp = 0; + bool _isConnected = false; + + bool _hasCompletedHello = false; + + uint32_t _pingMarker = 0xabcd0102; + int64_t _initialPingInterval = 100; + int64_t _keepalivePingInterval = 1000; +}; + +class DirectRtpTransport : public webrtc::RtpTransport { +public: + explicit DirectRtpTransport() : + webrtc::RtpTransport(true) { + } + + virtual bool IsSrtpActive() const override { + return true; + } +}; + +DirectNetworkingImpl::DirectNetworkingImpl(Configuration &&configuration) : +_threads(std::move(configuration.threads)), +_isOutgoing(configuration.isOutgoing), +_rtcServers(configuration.rtcServers), +_stateUpdated(std::move(configuration.stateUpdated)), +_transportMessageReceived(std::move(configuration.transportMessageReceived)), +_rtcpPacketReceived(std::move(configuration.rtcpPacketReceived)), +_dataChannelStateUpdated(configuration.dataChannelStateUpdated), +_dataChannelMessageReceived(configuration.dataChannelMessageReceived) { + assert(_threads->getNetworkThread()->IsCurrent()); + + _localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true); + + _localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt); + + _rtpTransport = std::make_unique(); + + _rtpTransport->SignalReadyToSend.connect(this, &DirectNetworkingImpl::DtlsReadyToSend); + _rtpTransport->SignalRtcpPacketReceived.connect(this, &DirectNetworkingImpl::OnRtcpPacketReceived_n); + + _directConnectionChannel = configuration.directConnectionChannel; + _packetTransport = std::make_shared( + _threads->getNetworkThread(), + configuration.encryptionKey, + _directConnectionChannel, + [this](bool isConnected) { + this->_transportIsConnected = isConnected; + this->UpdateAggregateStates_n(); + } + ); + + resetDtlsSrtpTransport(); +} + +DirectNetworkingImpl::~DirectNetworkingImpl() { + assert(_threads->getNetworkThread()->IsCurrent()); + + RTC_LOG(LS_INFO) << "DirectNetworkingImpl::~DirectNetworkingImpl()"; + + _rtpTransport.reset(); + _dataChannelInterface.reset(); + _packetTransport.reset(); +} + +void DirectNetworkingImpl::resetDtlsSrtpTransport() { + _rtpTransport->SetRtpPacketTransport(_packetTransport.get()); +} + +void DirectNetworkingImpl::start() { + const auto weak = std::weak_ptr(shared_from_this()); + _dataChannelInterface.reset(new SctpDataChannelProviderInterfaceImpl( + _packetTransport.get(), + _isOutgoing, + [weak, threads = _threads](bool state) { + assert(threads->getNetworkThread()->IsCurrent()); + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->_dataChannelStateUpdated(state); + }, + [weak, threads = _threads]() { + assert(threads->getNetworkThread()->IsCurrent()); + const auto strong = weak.lock(); + if (!strong) { + return; + } + //strong->restartDataChannel(); + }, + [weak, threads = _threads](std::string const &message) { + assert(threads->getNetworkThread()->IsCurrent()); + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->_dataChannelMessageReceived(message); + }, + _threads + )); + + _lastDisconnectedTimestamp = rtc::TimeMillis(); + checkConnectionTimeout(); + + _packetTransport->start(); +} + +void DirectNetworkingImpl::stop() { + _rtpTransport->SignalWritableState.disconnect(this); + //_rtpTransport->SignalReceivingState.disconnect(this); + + _dataChannelInterface.reset(); + _rtpTransport.reset(); + + _packetTransport->stop(); + + _localIceParameters = PeerIceParameters(rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH), rtc::CreateRandomString(cricket::ICE_PWD_LENGTH), true); + + _localCertificate = rtc::RTCCertificateGenerator::GenerateCertificate(rtc::KeyParams(rtc::KT_ECDSA), absl::nullopt); +} + +PeerIceParameters DirectNetworkingImpl::getLocalIceParameters() { + return _localIceParameters; +} + +std::unique_ptr DirectNetworkingImpl::getLocalFingerprint() { + auto certificate = _localCertificate; + if (!certificate) { + return nullptr; + } + return rtc::SSLFingerprint::CreateFromCertificate(*certificate); +} + +void DirectNetworkingImpl::setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup) { +} + +void DirectNetworkingImpl::addCandidates(std::vector const &candidates) { +} + +void DirectNetworkingImpl::sendDataChannelMessage(std::string const &message) { + if (_dataChannelInterface) { + _dataChannelInterface->sendDataChannelMessage(message); + } +} + +webrtc::RtpTransport *DirectNetworkingImpl::getRtpTransport() { + return _rtpTransport.get(); +} + +void DirectNetworkingImpl::checkConnectionTimeout() { + const auto weak = std::weak_ptr(shared_from_this()); + _threads->getNetworkThread()->PostDelayedTask([weak]() { + auto strong = weak.lock(); + if (!strong) { + return; + } + + int64_t currentTimestamp = rtc::TimeMillis(); + const int64_t maxTimeout = 20000; + + if (!strong->_isConnected && strong->_lastDisconnectedTimestamp + maxTimeout < currentTimestamp) { + RTC_LOG(LS_INFO) << "DirectNetworkingImpl timeout " << (currentTimestamp - strong->_lastDisconnectedTimestamp) << " ms"; + + strong->_isFailed = true; + strong->notifyStateUpdated(); + } + + strong->checkConnectionTimeout(); + }, webrtc::TimeDelta::Millis(1000)); +} + +void DirectNetworkingImpl::OnTransportWritableState_n(rtc::PacketTransportInternal *transport) { + assert(_threads->getNetworkThread()->IsCurrent()); + + UpdateAggregateStates_n(); +} +void DirectNetworkingImpl::OnTransportReceivingState_n(rtc::PacketTransportInternal *transport) { + assert(_threads->getNetworkThread()->IsCurrent()); + + UpdateAggregateStates_n(); +} + +void DirectNetworkingImpl::DtlsReadyToSend(bool isReadyToSend) { + UpdateAggregateStates_n(); + + if (isReadyToSend) { + const auto weak = std::weak_ptr(shared_from_this()); + _threads->getNetworkThread()->PostTask([weak]() { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->UpdateAggregateStates_n(); + }); + } +} + +void DirectNetworkingImpl::OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer *packet, int64_t packet_time_us) { + if (_rtcpPacketReceived) { + _rtcpPacketReceived(*packet, packet_time_us); + } +} + +void DirectNetworkingImpl::UpdateAggregateStates_n() { + assert(_threads->getNetworkThread()->IsCurrent()); + + bool isConnected = _transportIsConnected; + + if (_isConnected != isConnected) { + _isConnected = isConnected; + + if (!isConnected) { + _lastDisconnectedTimestamp = rtc::TimeMillis(); + } + + notifyStateUpdated(); + + if (_dataChannelInterface) { + _dataChannelInterface->updateIsConnected(isConnected); + } + } +} + +void DirectNetworkingImpl::notifyStateUpdated() { + DirectNetworkingImpl::State emitState; + emitState.isReadyToSendData = _isConnected; + emitState.route = _currentRouteDescription; + emitState.connection = _currentConnectionDescription; + emitState.isFailed = _isFailed; + _stateUpdated(emitState); +} + +} // namespace tgcalls diff --git a/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.h b/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.h new file mode 100644 index 000000000..b2c91b1dc --- /dev/null +++ b/TMessagesProj/jni/voip/tgcalls/v2/DirectNetworkingImpl.h @@ -0,0 +1,119 @@ +#ifndef TGCALLS_DIRECT_NETWORKING_IMPL_H +#define TGCALLS_DIRECT_NETWORKING_IMPL_H + +#ifdef WEBRTC_WIN +// Compiler errors in conflicting Windows headers if not included here. +#include +#endif // WEBRTC_WIN + +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "api/candidate.h" +#include "media/base/media_channel.h" +#include "rtc_base/ssl_fingerprint.h" +#include "pc/sctp_data_channel.h" +#include "p2p/base/port.h" +#include "api/transport/field_trial_based_config.h" + +#include +#include + +#include "InstanceNetworking.h" +#include "Message.h" +#include "ThreadLocalObject.h" +#include "Instance.h" +#include "EncryptedConnection.h" + +namespace rtc { +class BasicPacketSocketFactory; +class BasicNetworkManager; +class PacketTransportInternal; +struct NetworkRoute; +} // namespace rtc + +namespace cricket { +class BasicPortAllocator; +class P2PTransportChannel; +class IceTransportInternal; +class DtlsTransport; +class RelayPortFactoryInterface; +} // namespace cricket + +namespace webrtc { +class TurnCustomizer; +class DtlsSrtpTransport; +class RtpTransport; +class AsyncDnsResolverFactoryInterface; +} // namespace webrtc + +namespace tgcalls { + +struct Message; +class SctpDataChannelProviderInterfaceImpl; +class Threads; +class DirectPacketTransport; +class DirectRtpTransport; + +class DirectNetworkingImpl : public InstanceNetworking, public sigslot::has_slots<>, public std::enable_shared_from_this { +public: + static webrtc::CryptoOptions getDefaulCryptoOptions(); + + DirectNetworkingImpl(Configuration &&configuration); + ~DirectNetworkingImpl(); + + void start(); + void stop(); + + PeerIceParameters getLocalIceParameters(); + std::unique_ptr getLocalFingerprint(); + void setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup); + void addCandidates(std::vector const &candidates); + + void sendDataChannelMessage(std::string const &message); + + webrtc::RtpTransport *getRtpTransport(); + +private: + void checkConnectionTimeout(); + void notifyStateUpdated(); + + void resetDtlsSrtpTransport(); + + void DtlsReadyToSend(bool DtlsReadyToSend); + void UpdateAggregateStates_n(); + void OnRtcpPacketReceived_n(rtc::CopyOnWriteBuffer *packet, int64_t packet_time_us); + void OnTransportWritableState_n(rtc::PacketTransportInternal *transport); + void OnTransportReceivingState_n(rtc::PacketTransportInternal *transport); + +private: + std::shared_ptr _threads; + bool _isOutgoing = false; + + rtc::scoped_refptr _localCertificate; + std::vector _rtcServers; + PeerIceParameters _localIceParameters; + + std::unique_ptr _channel; + + std::shared_ptr _directConnectionChannel; + std::shared_ptr _packetTransport; + std::unique_ptr _rtpTransport; + std::unique_ptr _dataChannelInterface; + + std::function _stateUpdated; + std::function _transportMessageReceived; + std::function _rtcpPacketReceived; + std::function _dataChannelStateUpdated; + std::function _dataChannelMessageReceived; + + bool _transportIsConnected = false; + bool _isConnected = false; + bool _isFailed = false; + int64_t _lastDisconnectedTimestamp = 0; + absl::optional _currentRouteDescription; + absl::optional _currentConnectionDescription; +}; + +} // namespace tgcalls + +#endif diff --git a/TMessagesProj/jni/voip/tgcalls/v2/InstanceNetworking.h b/TMessagesProj/jni/voip/tgcalls/v2/InstanceNetworking.h new file mode 100644 index 000000000..94a6907a1 --- /dev/null +++ b/TMessagesProj/jni/voip/tgcalls/v2/InstanceNetworking.h @@ -0,0 +1,169 @@ +#ifndef TGCALLS_INSTANCE_NETWORKING_H +#define TGCALLS_INSTANCE_NETWORKING_H + +#ifdef WEBRTC_WIN +// Compiler errors in conflicting Windows headers if not included here. +#include +#endif // WEBRTC_WIN + +#include "rtc_base/copy_on_write_buffer.h" +#include "rtc_base/third_party/sigslot/sigslot.h" +#include "api/candidate.h" +#include "media/base/media_channel.h" +#include "rtc_base/ssl_fingerprint.h" +#include "pc/sctp_data_channel.h" +#include "p2p/base/port.h" +#include "api/transport/field_trial_based_config.h" + +#include +#include + +#include "Message.h" +#include "ThreadLocalObject.h" +#include "Instance.h" + +namespace rtc { +class BasicPacketSocketFactory; +class BasicNetworkManager; +class PacketTransportInternal; +struct NetworkRoute; +} // namespace rtc + +namespace cricket { +class BasicPortAllocator; +class P2PTransportChannel; +class IceTransportInternal; +class DtlsTransport; +class RelayPortFactoryInterface; +} // namespace cricket + +namespace webrtc { +class TurnCustomizer; +class DtlsSrtpTransport; +class RtpTransport; +class AsyncDnsResolverFactoryInterface; +} // namespace webrtc + +namespace tgcalls { + +struct Message; +class SctpDataChannelProviderInterfaceImpl; +class Threads; + +class InstanceNetworking { +public: + struct RouteDescription { + explicit RouteDescription(std::string const &localDescription_, std::string const &remoteDescription_) : + localDescription(localDescription_), + remoteDescription(remoteDescription_) { + } + + std::string localDescription; + std::string remoteDescription; + + bool operator==(RouteDescription const &rhs) const { + if (localDescription != rhs.localDescription) { + return false; + } + if (remoteDescription != rhs.remoteDescription) { + return false; + } + + return true; + } + + bool operator!=(const RouteDescription& rhs) const { + return !(*this == rhs); + } + }; + + struct ConnectionDescription { + struct CandidateDescription { + std::string protocol; + std::string type; + std::string address; + + bool operator==(CandidateDescription const &rhs) const { + if (protocol != rhs.protocol) { + return false; + } + if (type != rhs.type) { + return false; + } + if (address != rhs.address) { + return false; + } + + return true; + } + + bool operator!=(const CandidateDescription& rhs) const { + return !(*this == rhs); + } + }; + + CandidateDescription local; + CandidateDescription remote; + + bool operator==(ConnectionDescription const &rhs) const { + if (local != rhs.local) { + return false; + } + if (remote != rhs.remote) { + return false; + } + + return true; + } + + bool operator!=(const ConnectionDescription& rhs) const { + return !(*this == rhs); + } + }; + + struct State { + bool isReadyToSendData = false; + bool isFailed = false; + absl::optional route; + absl::optional connection; + }; + + struct Configuration { + EncryptionKey encryptionKey; + bool isOutgoing = false; + bool enableStunMarking = false; + bool enableTCP = false; + bool enableP2P = false; + std::vector rtcServers; + absl::optional proxy; + std::function stateUpdated; + std::function candidateGathered; + std::function transportMessageReceived; + std::function rtcpPacketReceived; + std::function dataChannelStateUpdated; + std::function dataChannelMessageReceived; + std::shared_ptr threads; + std::shared_ptr directConnectionChannel; + }; + + static webrtc::CryptoOptions getDefaulCryptoOptions(); + static ConnectionDescription::CandidateDescription connectionDescriptionFromCandidate(cricket::Candidate const &candidate); + + virtual ~InstanceNetworking() = default; + + virtual void start() = 0; + virtual void stop() = 0; + + virtual PeerIceParameters getLocalIceParameters() = 0; + virtual std::unique_ptr getLocalFingerprint() = 0; + virtual void setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup) = 0; + virtual void addCandidates(std::vector const &candidates) = 0; + + virtual void sendDataChannelMessage(std::string const &message) = 0; + + virtual webrtc::RtpTransport *getRtpTransport() = 0; +}; + +} // namespace tgcalls + +#endif diff --git a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.cpp b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.cpp index 59170a4b4..c3913cd4d 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.cpp @@ -4,6 +4,7 @@ #include "VideoCaptureInterfaceImpl.h" #include "VideoCapturerInterface.h" #include "v2/NativeNetworkingImpl.h" +#include "v2/DirectNetworkingImpl.h" #include "v2/Signaling.h" #include "v2/ContentNegotiation.h" @@ -77,7 +78,7 @@ SignalingProtocolVersion signalingProtocolVersion(std::string const &version) { } else if (version == "8.0.0") { return SignalingProtocolVersion::V2; } else if (version == "9.0.0") { - return SignalingProtocolVersion::V3; + return SignalingProtocolVersion::V2; } else { RTC_LOG(LS_ERROR) << "signalingProtocolVersion: unknown version " << version; @@ -136,13 +137,12 @@ public: audioOptions.noise_suppression = true; } - std::ostringstream contentId; - contentId << _ssrc; + const auto contentId = std::to_string(_ssrc); std::vector streamIds; - streamIds.push_back(contentId.str()); + streamIds.push_back(contentId); - _outgoingAudioChannel = _channelManager->CreateVoiceChannel(call, cricket::MediaConfig(), contentId.str(), false, NativeNetworkingImpl::getDefaulCryptoOptions(), audioOptions); + _outgoingAudioChannel = _channelManager->CreateVoiceChannel(call, cricket::MediaConfig(), contentId, false, NativeNetworkingImpl::getDefaulCryptoOptions(), audioOptions); _threads->getNetworkThread()->BlockingCall([&]() { _outgoingAudioChannel->SetRtpTransport(rtpTransport); }); @@ -272,12 +272,9 @@ public: audioOptions.audio_jitter_buffer_fast_accelerate = true; audioOptions.audio_jitter_buffer_min_delay_ms = 50; - std::ostringstream contentId; - contentId << _ssrc; + const auto streamId = std::to_string(_ssrc); - std::string streamId = contentId.str(); - - _audioChannel = _channelManager->CreateVoiceChannel(call, cricket::MediaConfig(), contentId.str(), false, NativeNetworkingImpl::getDefaulCryptoOptions(), audioOptions); + _audioChannel = _channelManager->CreateVoiceChannel(call, cricket::MediaConfig(), streamId, false, NativeNetworkingImpl::getDefaulCryptoOptions(), audioOptions); _threads->getNetworkThread()->BlockingCall([&]() { _audioChannel->SetRtpTransport(rtpTransport); }); @@ -401,10 +398,7 @@ public: cricket::VideoOptions videoOptions; videoOptions.is_screencast = isScreencast; - std::ostringstream contentId; - contentId << mediaContent.ssrc; - - _outgoingVideoChannel = _channelManager->CreateVideoChannel(call, cricket::MediaConfig(), contentId.str(), false, NativeNetworkingImpl::getDefaulCryptoOptions(), videoOptions, videoBitrateAllocatorFactory); + _outgoingVideoChannel = _channelManager->CreateVideoChannel(call, cricket::MediaConfig(), std::to_string(mediaContent.ssrc), false, NativeNetworkingImpl::getDefaulCryptoOptions(), videoOptions, videoBitrateAllocatorFactory); _threads->getNetworkThread()->BlockingCall([&]() { _outgoingVideoChannel->SetRtpTransport(rtpTransport); }); @@ -702,10 +696,9 @@ public: _videoBitrateAllocatorFactory = webrtc::CreateBuiltinVideoBitrateAllocatorFactory(); - std::ostringstream contentId; - contentId << mediaContent.ssrc; + const auto contentId = std::to_string(mediaContent.ssrc); - _videoChannel = _channelManager->CreateVideoChannel(call, cricket::MediaConfig(), contentId.str(), false, NativeNetworkingImpl::getDefaulCryptoOptions(), cricket::VideoOptions(), _videoBitrateAllocatorFactory.get()); + _videoChannel = _channelManager->CreateVideoChannel(call, cricket::MediaConfig(), contentId, false, NativeNetworkingImpl::getDefaulCryptoOptions(), cricket::VideoOptions(), _videoBitrateAllocatorFactory.get()); _threads->getNetworkThread()->BlockingCall([&]() { _videoChannel->SetRtpTransport(rtpTransport); }); @@ -750,7 +743,7 @@ public: videoRecvStreamParams.ssrcs = allSsrcs; videoRecvStreamParams.cname = "cname"; - videoRecvStreamParams.set_stream_ids({ contentId.str() }); + videoRecvStreamParams.set_stream_ids({ contentId }); auto incomingVideoDescription = std::make_unique(); for (const auto &rtpExtension : mediaContent.rtpExtensions) { @@ -824,8 +817,8 @@ struct StateLogRecord { struct NetworkStateLogRecord { bool isConnected = false; bool isFailed = false; - absl::optional route; - absl::optional connection; + absl::optional route; + absl::optional connection; bool operator==(NetworkStateLogRecord const &rhs) const { if (isConnected != rhs.isConnected) { @@ -858,23 +851,25 @@ public: _threads(threads), _rtcServers(descriptor.rtcServers), _proxy(std::move(descriptor.proxy)), + _directConnectionChannel(descriptor.directConnectionChannel), _enableP2P(descriptor.config.enableP2P), _encryptionKey(std::move(descriptor.encryptionKey)), _stateUpdated(descriptor.stateUpdated), _signalBarsUpdated(descriptor.signalBarsUpdated), - _audioLevelsUpdated(descriptor.audioLevelsUpdated), + _audioLevelUpdated(descriptor.audioLevelsUpdated), _remoteBatteryLevelIsLowUpdated(descriptor.remoteBatteryLevelIsLowUpdated), _remoteMediaStateUpdated(descriptor.remoteMediaStateUpdated), _remotePrefferedAspectRatioUpdated(descriptor.remotePrefferedAspectRatioUpdated), _signalingDataEmitted(descriptor.signalingDataEmitted), _createAudioDeviceModule(descriptor.createAudioDeviceModule), + _devicesConfig(descriptor.mediaDevicesConfig), _statsLogPath(descriptor.config.statsLogPath), _eventLog(std::make_unique()), _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()), _initialInputDeviceId(std::move(descriptor.initialInputDeviceId)), _initialOutputDeviceId(std::move(descriptor.initialOutputDeviceId)), _videoCapture(descriptor.videoCapture), - _platformContext(descriptor.platformContext) { + _platformContext(descriptor.platformContext) { webrtc::field_trial::InitFieldTrialsFromString( "WebRTC-DataChannel-Dcsctp/Enabled/" "WebRTC-Audio-MinimizeResamplingOnMobile/Enabled/" @@ -901,7 +896,7 @@ public: _contentNegotiationContext.reset(); - _networking->perform([](NativeNetworkingImpl *networking) { + _networking->perform([](InstanceNetworking *networking) { networking->stop(); }); @@ -957,68 +952,136 @@ public: proxy = *(_proxy.get()); } - _networking.reset(new ThreadLocalObject(_threads->getNetworkThread(), [weak, threads = _threads, isOutgoing = _encryptionKey.isOutgoing, rtcServers = _rtcServers, proxy, enableP2P = _enableP2P]() { - return new NativeNetworkingImpl(NativeNetworkingImpl::Configuration{ - .isOutgoing = isOutgoing, - .enableStunMarking = false, - .enableTCP = false, - .enableP2P = enableP2P, - .rtcServers = rtcServers, - .proxy = proxy, - .stateUpdated = [threads, weak](const NativeNetworkingImpl::State &state) { - threads->getMediaThread()->PostTask([=] { - const auto strong = weak.lock(); - if (!strong) { - return; - } - strong->onNetworkStateUpdated(state); - }); - }, - .candidateGathered = [threads, weak](const cricket::Candidate &candidate) { - threads->getMediaThread()->PostTask([=] { - const auto strong = weak.lock(); - if (!strong) { - return; - } + _networking.reset(new ThreadLocalObject(_threads->getNetworkThread(), [weak, threads = _threads, encryptionKey = _encryptionKey, isOutgoing = _encryptionKey.isOutgoing, rtcServers = _rtcServers, proxy, enableP2P = _enableP2P, directConnectionChannel = _directConnectionChannel]() { + if (directConnectionChannel) { + return new NativeNetworkingImpl(InstanceNetworking::Configuration { + .encryptionKey = encryptionKey, + .isOutgoing = isOutgoing, + .enableStunMarking = false, + .enableTCP = false, + .enableP2P = enableP2P, + .rtcServers = rtcServers, + .proxy = proxy, + .stateUpdated = [threads, weak](const InstanceNetworking::State &state) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onNetworkStateUpdated(state); + }); + }, + .candidateGathered = [threads, weak](const cricket::Candidate &candidate) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } - strong->sendCandidate(candidate); - }); - }, - .transportMessageReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, bool isMissing) { - threads->getMediaThread()->PostTask([=] { + strong->sendCandidate(candidate); + }); + }, + .transportMessageReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, bool isMissing) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + }); + }, + .rtcpPacketReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, int64_t timestamp) { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->_call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet, timestamp); + }, + .dataChannelStateUpdated = [threads, weak](bool isDataChannelOpen) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onDataChannelStateUpdated(isDataChannelOpen); + }); + }, + .dataChannelMessageReceived = [threads, weak](std::string const &message) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onDataChannelMessage(message); + }); + }, + .threads = threads, + .directConnectionChannel = directConnectionChannel, + }); + } else { + return new NativeNetworkingImpl(InstanceNetworking::Configuration{ + .encryptionKey = encryptionKey, + .isOutgoing = isOutgoing, + .enableStunMarking = false, + .enableTCP = false, + .enableP2P = enableP2P, + .rtcServers = rtcServers, + .proxy = proxy, + .stateUpdated = [threads, weak](const InstanceNetworking::State &state) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onNetworkStateUpdated(state); + }); + }, + .candidateGathered = [threads, weak](const cricket::Candidate &candidate) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + + strong->sendCandidate(candidate); + }); + }, + .transportMessageReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, bool isMissing) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + }); + }, + .rtcpPacketReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, int64_t timestamp) { const auto strong = weak.lock(); if (!strong) { return; } - }); - }, - .rtcpPacketReceived = [threads, weak](rtc::CopyOnWriteBuffer const &packet, int64_t timestamp) { - const auto strong = weak.lock(); - if (!strong) { - return; - } - strong->_call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet, timestamp); - }, - .dataChannelStateUpdated = [threads, weak](bool isDataChannelOpen) { - threads->getMediaThread()->PostTask([=] { - const auto strong = weak.lock(); - if (!strong) { - return; - } - strong->onDataChannelStateUpdated(isDataChannelOpen); - }); - }, - .dataChannelMessageReceived = [threads, weak](std::string const &message) { - threads->getMediaThread()->PostTask([=] { - const auto strong = weak.lock(); - if (!strong) { - return; - } - strong->onDataChannelMessage(message); - }); - }, - .threads = threads - }); + strong->_call->Receiver()->DeliverPacket(webrtc::MediaType::ANY, packet, timestamp); + }, + .dataChannelStateUpdated = [threads, weak](bool isDataChannelOpen) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onDataChannelStateUpdated(isDataChannelOpen); + }); + }, + .dataChannelMessageReceived = [threads, weak](std::string const &message) { + threads->getMediaThread()->PostTask([=] { + const auto strong = weak.lock(); + if (!strong) { + return; + } + strong->onDataChannelMessage(message); + }); + }, + .threads = threads, + .directConnectionChannel = directConnectionChannel, + }); + } })); PlatformInterface::SharedInstance()->configurePlatformAudio(); @@ -1033,12 +1096,13 @@ public: mediaDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory(); mediaDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory(); - mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext, true); - mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext); + mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext, true); + mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext); mediaDeps.adm = _audioDeviceModule; - + webrtc:: AudioProcessingBuilder builder; + mediaDeps.audio_processing = builder.Create(); _availableVideoFormats = mediaDeps.video_encoder_factory->GetSupportedFormats(); @@ -1061,6 +1125,9 @@ public: _threads->getWorkerThread()->BlockingCall([&]() { callConfig.audio_state = _channelManager->media_engine()->voice().GetAudioState(); _call.reset(webrtc::Call::Create(callConfig)); + +// SetAudioInputDeviceById(_audioDeviceModule.get(), _devicesConfig.audioInputId); +// SetAudioOutputDeviceById(_audioDeviceModule.get(), _devicesConfig.audioOutputId); }); _uniqueRandomIdGenerator.reset(new rtc::UniqueRandomIdGenerator()); @@ -1072,7 +1139,7 @@ public: _videoBitrateAllocatorFactory = webrtc::CreateBuiltinVideoBitrateAllocatorFactory(); - _networking->perform([](NativeNetworkingImpl *networking) { + _networking->perform([](InstanceNetworking *networking) { networking->start(); }); @@ -1087,7 +1154,7 @@ public: beginQualityTimer(0); beginLogTimer(0); - NativeNetworkingImpl::State initialNetworkState; + InstanceNetworking::State initialNetworkState; initialNetworkState.isReadyToSendData = false; onNetworkStateUpdated(initialNetworkState); } @@ -1287,6 +1354,7 @@ public: outgoingAudioContent.value(), _threads )); + _outgoingAudioChannel->setIsMuted(_isMicrophoneMuted); } } } @@ -1481,10 +1549,16 @@ public: void sendInitialSetup() { const auto weak = std::weak_ptr(shared_from_this()); - _networking->perform([weak, threads = _threads, isOutgoing = _encryptionKey.isOutgoing](NativeNetworkingImpl *networking) { + _networking->perform([weak, threads = _threads, isOutgoing = _encryptionKey.isOutgoing](InstanceNetworking *networking) { auto localFingerprint = networking->getLocalFingerprint(); - std::string hash = localFingerprint->algorithm; - std::string fingerprint = localFingerprint->GetRfc4572Fingerprint(); + std::string hash; + std::string fingerprint; + + if (localFingerprint) { + hash = localFingerprint->algorithm; + fingerprint = localFingerprint->GetRfc4572Fingerprint(); + } + std::string setup; if (isOutgoing) { setup = "actpass"; @@ -1497,7 +1571,7 @@ public: std::string pwd = localIceParams.pwd; bool supportsRenomination = localIceParams.supportsRenomination; - threads->getMediaThread()->PostTask([weak, ufrag, pwd, supportsRenomination, hash, fingerprint, setup, localIceParams]() { + threads->getMediaThread()->PostTask([weak, ufrag, pwd, supportsRenomination, hash, fingerprint, setup]() { const auto strong = weak.lock(); if (!strong) { return; @@ -1614,7 +1688,7 @@ public: sslSetup = initialSetup->fingerprints[0].setup; } - _networking->perform([threads = _threads, remoteIceParameters = std::move(remoteIceParameters), fingerprint = std::move(fingerprint), sslSetup = std::move(sslSetup)](NativeNetworkingImpl *networking) { + _networking->perform([threads = _threads, remoteIceParameters = std::move(remoteIceParameters), fingerprint = std::move(fingerprint), sslSetup = std::move(sslSetup)](InstanceNetworking *networking) { networking->setRemoteParams(remoteIceParameters, fingerprint.get(), sslSetup); }); @@ -1726,13 +1800,13 @@ public: if (_pendingIceCandidates.size() == 0) { return; } - _networking->perform([threads = _threads, parsedCandidates = _pendingIceCandidates](NativeNetworkingImpl *networking) { + _networking->perform([threads = _threads, parsedCandidates = _pendingIceCandidates](InstanceNetworking *networking) { networking->addCandidates(parsedCandidates); }); _pendingIceCandidates.clear(); } - void onNetworkStateUpdated(NativeNetworkingImpl::State const &state) { + void onNetworkStateUpdated(InstanceNetworking::State const &state) { State mappedState; if (state.isFailed) { mappedState = State::Failed; @@ -1775,7 +1849,7 @@ public: auto data = message.serialize(); std::string stringData(data.begin(), data.end()); RTC_LOG(LS_INFO) << "sendDataChannelMessage: " << stringData; - _networking->perform([stringData = std::move(stringData)](NativeNetworkingImpl *networking) { + _networking->perform([stringData = std::move(stringData)](InstanceNetworking *networking) { networking->sendDataChannelMessage(stringData); }); } @@ -1932,7 +2006,7 @@ public: } } - void setIncomingVideoOutput(std::shared_ptr> sink) { + void setIncomingVideoOutput(std::weak_ptr> sink) { _currentSink = sink; if (_incomingVideoChannel) { _incomingVideoChannel->addSink(sink); @@ -1978,14 +2052,10 @@ public: for (const auto &record : _networkStateLogRecords) { json11::Json::object jsonRecord; - std::ostringstream timestampString; - if (baseTimestamp == 0) { baseTimestamp = record.timestamp; } - timestampString << (record.timestamp - baseTimestamp); - - jsonRecord.insert(std::make_pair("t", json11::Json(timestampString.str()))); + jsonRecord.insert(std::make_pair("t", json11::Json(std::to_string(record.timestamp - baseTimestamp)))); jsonRecord.insert(std::make_pair("c", json11::Json(record.record.isConnected ? 1 : 0))); if (record.record.route) { jsonRecord.insert(std::make_pair("local", json11::Json(record.record.route->localDescription))); @@ -1994,7 +2064,7 @@ public: if (record.record.connection) { json11::Json::object jsonConnection; - auto serializeCandidate = [](NativeNetworkingImpl::ConnectionDescription::CandidateDescription const &candidate) -> json11::Json::object { + auto serializeCandidate = [](InstanceNetworking::ConnectionDescription::CandidateDescription const &candidate) -> json11::Json::object { json11::Json::object jsonCandidate; jsonCandidate.insert(std::make_pair("type", json11::Json(candidate.type))); @@ -2077,16 +2147,18 @@ private: std::shared_ptr _threads; std::vector _rtcServers; std::unique_ptr _proxy; + std::shared_ptr _directConnectionChannel; bool _enableP2P = false; EncryptionKey _encryptionKey; std::function _stateUpdated; std::function _signalBarsUpdated; - std::function _audioLevelsUpdated; + std::function _audioLevelUpdated; std::function _remoteBatteryLevelIsLowUpdated; std::function _remoteMediaStateUpdated; std::function _remotePrefferedAspectRatioUpdated; std::function &)> _signalingDataEmitted; std::function(webrtc::TaskQueueFactory*)> _createAudioDeviceModule; + MediaDevicesConfig _devicesConfig; FilePath _statsLogPath; std::unique_ptr _signalingConnection; @@ -2098,7 +2170,7 @@ private: std::vector> _networkStateLogRecords; std::vector> _networkBitrateLogRecords; - absl::optional _networkState; + absl::optional _networkState; bool _handshakeCompleted = false; std::vector _pendingIceCandidates; @@ -2202,7 +2274,7 @@ void InstanceV2Impl::setMuteMicrophone(bool muteMicrophone) { }); } -void InstanceV2Impl::setIncomingVideoOutput(std::shared_ptr> sink) { +void InstanceV2Impl::setIncomingVideoOutput(std::weak_ptr> sink) { _internal->perform([sink](InstanceV2ImplInternal *internal) { internal->setIncomingVideoOutput(sink); }); diff --git a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.h b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.h index 690a17353..541f09bb2 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.h +++ b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2Impl.h @@ -27,7 +27,7 @@ public: bool supportsVideo() override { return true; } - void setIncomingVideoOutput(std::shared_ptr> sink) override; + void setIncomingVideoOutput(std::weak_ptr> sink) override; void setAudioOutputGainControlEnabled(bool enabled) override; void setEchoCancellationStrength(int strength) override; void setAudioInputDevice(std::string id) override; diff --git a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.cpp b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.cpp index 82455c644..e2ee369ab 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.cpp @@ -325,8 +325,8 @@ struct StateLogRecord { struct NetworkStateLogRecord { bool isConnected = false; bool isFailed = false; - absl::optional route; - absl::optional connection; + absl::optional route; + absl::optional connection; bool operator==(NetworkStateLogRecord const &rhs) const { if (isConnected != rhs.isConnected) { @@ -363,7 +363,7 @@ public: _encryptionKey(std::move(descriptor.encryptionKey)), _stateUpdated(descriptor.stateUpdated), _signalBarsUpdated(descriptor.signalBarsUpdated), - _audioLevelsUpdated(descriptor.audioLevelsUpdated), + _audioLevelUpdated(descriptor.audioLevelsUpdated), _remoteBatteryLevelIsLowUpdated(descriptor.remoteBatteryLevelIsLowUpdated), _remoteMediaStateUpdated(descriptor.remoteMediaStateUpdated), _remotePrefferedAspectRatioUpdated(descriptor.remotePrefferedAspectRatioUpdated), @@ -373,7 +373,7 @@ public: _eventLog(std::make_unique()), _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()), _videoCapture(descriptor.videoCapture), - _platformContext(descriptor.platformContext) { + _platformContext(descriptor.platformContext) { webrtc::field_trial::InitFieldTrialsFromString( "WebRTC-DataChannel-Dcsctp/Enabled/" "WebRTC-Audio-iOS-Holding/Enabled/" @@ -459,6 +459,11 @@ public: cricket::MediaEngineDependencies mediaDeps; mediaDeps.adm = _audioDeviceModule; + + webrtc:: AudioProcessingBuilder builder; + mediaDeps.audio_processing = builder.Create(); + + mediaDeps.task_queue_factory = peerConnectionFactoryDependencies.task_queue_factory.get(); mediaDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory(); mediaDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory(); @@ -607,10 +612,10 @@ public: return; } - NativeNetworkingImpl::ConnectionDescription connectionDescription; + InstanceNetworking::ConnectionDescription connectionDescription; - connectionDescription.local = NativeNetworkingImpl::connectionDescriptionFromCandidate(event.selected_candidate_pair.local); - connectionDescription.remote = NativeNetworkingImpl::connectionDescriptionFromCandidate(event.selected_candidate_pair.remote); + connectionDescription.local = InstanceNetworking::connectionDescriptionFromCandidate(event.selected_candidate_pair.local); + connectionDescription.remote = InstanceNetworking::connectionDescriptionFromCandidate(event.selected_candidate_pair.remote); if (!strong->_currentConnectionDescription || strong->_currentConnectionDescription.value() != connectionDescription) { strong->_currentConnectionDescription = std::move(connectionDescription); @@ -649,10 +654,8 @@ public: if (server.isTurn) { webrtc::PeerConnectionInterface::IceServer mappedServer; - std::ostringstream uri; - uri << "turn:" << address.HostAsURIString() << ":" << server.port; - - mappedServer.urls.push_back(uri.str()); + mappedServer.urls.push_back( + "turn:" + address.HostAsURIString() + ":" + std::to_string(server.port)); mappedServer.username = server.login; mappedServer.password = server.password; @@ -660,10 +663,8 @@ public: } else { webrtc::PeerConnectionInterface::IceServer mappedServer; - std::ostringstream uri; - uri << "stun:" << address.HostAsURIString() << ":" << server.port; - - mappedServer.urls.push_back(uri.str()); + mappedServer.urls.push_back( + "stun:" + address.HostAsURIString() + ":" + std::to_string(server.port)); peerConnectionConfiguration.servers.push_back(mappedServer); } @@ -704,7 +705,7 @@ public: parameters.encodings[0].max_bitrate_bps = 32 * 1024; _outgoingAudioTransceiver->sender()->SetParameters(parameters); - _outgoingAudioTrack->set_enabled(true); + _outgoingAudioTrack->set_enabled(!_isMicrophoneMuted); } } @@ -1451,14 +1452,10 @@ public: for (const auto &record : _networkStateLogRecords) { json11::Json::object jsonRecord; - std::ostringstream timestampString; - if (baseTimestamp == 0) { baseTimestamp = record.timestamp; } - timestampString << (record.timestamp - baseTimestamp); - - jsonRecord.insert(std::make_pair("t", json11::Json(timestampString.str()))); + jsonRecord.insert(std::make_pair("t", json11::Json(std::to_string(record.timestamp - baseTimestamp)))); jsonRecord.insert(std::make_pair("c", json11::Json(record.record.isConnected ? 1 : 0))); if (record.record.route) { jsonRecord.insert(std::make_pair("local", json11::Json(record.record.route->localDescription))); @@ -1467,7 +1464,7 @@ public: if (record.record.connection) { json11::Json::object jsonConnection; - auto serializeCandidate = [](NativeNetworkingImpl::ConnectionDescription::CandidateDescription const &candidate) -> json11::Json::object { + auto serializeCandidate = [](InstanceNetworking::ConnectionDescription::CandidateDescription const &candidate) -> json11::Json::object { json11::Json::object jsonCandidate; jsonCandidate.insert(std::make_pair("type", json11::Json(candidate.type))); @@ -1554,7 +1551,7 @@ private: EncryptionKey _encryptionKey; std::function _stateUpdated; std::function _signalBarsUpdated; - std::function _audioLevelsUpdated; + std::function _audioLevelUpdated; std::function _remoteBatteryLevelIsLowUpdated; std::function _remoteMediaStateUpdated; std::function _remotePrefferedAspectRatioUpdated; @@ -1567,7 +1564,7 @@ private: bool _isConnected = false; bool _isFailed = false; - absl::optional _currentConnectionDescription; + absl::optional _currentConnectionDescription; absl::optional _currentNetworkStateLogRecord; std::vector> _networkStateLogRecords; @@ -1665,7 +1662,7 @@ void InstanceV2ReferenceImpl::setMuteMicrophone(bool muteMicrophone) { }); } -void InstanceV2ReferenceImpl::setIncomingVideoOutput(std::shared_ptr> sink) { +void InstanceV2ReferenceImpl::setIncomingVideoOutput(std::weak_ptr> sink) { _internal->perform([sink](InstanceV2ReferenceImplInternal *internal) { internal->setIncomingVideoOutput(sink); }); diff --git a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.h b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.h index 44b0a9587..b3f9db032 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.h +++ b/TMessagesProj/jni/voip/tgcalls/v2/InstanceV2ReferenceImpl.h @@ -27,7 +27,7 @@ public: bool supportsVideo() override { return true; } - void setIncomingVideoOutput(std::shared_ptr> sink) override; + void setIncomingVideoOutput(std::weak_ptr> sink) override; void setAudioOutputGainControlEnabled(bool enabled) override; void setEchoCancellationStrength(int strength) override; void setAudioInputDevice(std::string id) override; diff --git a/TMessagesProj/jni/voip/tgcalls/v2/NativeNetworkingImpl.cpp b/TMessagesProj/jni/voip/tgcalls/v2/NativeNetworkingImpl.cpp index 7398a0611..843e0d95c 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/NativeNetworkingImpl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2/NativeNetworkingImpl.cpp @@ -186,8 +186,8 @@ private: } -NativeNetworkingImpl::ConnectionDescription::CandidateDescription NativeNetworkingImpl::connectionDescriptionFromCandidate(cricket::Candidate const &candidate) { - NativeNetworkingImpl::ConnectionDescription::CandidateDescription result; +InstanceNetworking::ConnectionDescription::CandidateDescription InstanceNetworking::connectionDescriptionFromCandidate(cricket::Candidate const &candidate) { + InstanceNetworking::ConnectionDescription::CandidateDescription result; result.type = candidate.type(); result.protocol = candidate.protocol(); @@ -569,8 +569,8 @@ void NativeNetworkingImpl::transportRouteChanged(absl::optional #include +#include "InstanceNetworking.h" #include "Message.h" #include "ThreadLocalObject.h" #include "Instance.h" @@ -50,117 +51,24 @@ struct Message; class SctpDataChannelProviderInterfaceImpl; class Threads; -class NativeNetworkingImpl : public sigslot::has_slots<>, public std::enable_shared_from_this { +class NativeNetworkingImpl : public InstanceNetworking, public sigslot::has_slots<>, public std::enable_shared_from_this { public: - struct RouteDescription { - explicit RouteDescription(std::string const &localDescription_, std::string const &remoteDescription_) : - localDescription(localDescription_), - remoteDescription(remoteDescription_) { - } - - std::string localDescription; - std::string remoteDescription; - - bool operator==(RouteDescription const &rhs) const { - if (localDescription != rhs.localDescription) { - return false; - } - if (remoteDescription != rhs.remoteDescription) { - return false; - } - - return true; - } - - bool operator!=(const RouteDescription& rhs) const { - return !(*this == rhs); - } - }; - - struct ConnectionDescription { - struct CandidateDescription { - std::string protocol; - std::string type; - std::string address; - - bool operator==(CandidateDescription const &rhs) const { - if (protocol != rhs.protocol) { - return false; - } - if (type != rhs.type) { - return false; - } - if (address != rhs.address) { - return false; - } - - return true; - } - - bool operator!=(const CandidateDescription& rhs) const { - return !(*this == rhs); - } - }; - - CandidateDescription local; - CandidateDescription remote; - - bool operator==(ConnectionDescription const &rhs) const { - if (local != rhs.local) { - return false; - } - if (remote != rhs.remote) { - return false; - } - - return true; - } - - bool operator!=(const ConnectionDescription& rhs) const { - return !(*this == rhs); - } - }; - - struct State { - bool isReadyToSendData = false; - bool isFailed = false; - absl::optional route; - absl::optional connection; - }; - - struct Configuration { - bool isOutgoing = false; - bool enableStunMarking = false; - bool enableTCP = false; - bool enableP2P = false; - std::vector rtcServers; - absl::optional proxy; - std::function stateUpdated; - std::function candidateGathered; - std::function transportMessageReceived; - std::function rtcpPacketReceived; - std::function dataChannelStateUpdated; - std::function dataChannelMessageReceived; - std::shared_ptr threads; - }; - static webrtc::CryptoOptions getDefaulCryptoOptions(); - static ConnectionDescription::CandidateDescription connectionDescriptionFromCandidate(cricket::Candidate const &candidate); NativeNetworkingImpl(Configuration &&configuration); - ~NativeNetworkingImpl(); + virtual ~NativeNetworkingImpl(); - void start(); - void stop(); + virtual void start() override; + virtual void stop() override; - PeerIceParameters getLocalIceParameters(); - std::unique_ptr getLocalFingerprint(); - void setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup); - void addCandidates(std::vector const &candidates); + virtual PeerIceParameters getLocalIceParameters() override; + virtual std::unique_ptr getLocalFingerprint() override; + virtual void setRemoteParams(PeerIceParameters const &remoteIceParameters, rtc::SSLFingerprint *fingerprint, std::string const &sslSetup) override; + virtual void addCandidates(std::vector const &candidates) override; - void sendDataChannelMessage(std::string const &message); + virtual void sendDataChannelMessage(std::string const &message) override; - webrtc::RtpTransport *getRtpTransport(); + virtual webrtc::RtpTransport *getRtpTransport() override; private: void resetDtlsSrtpTransport(); @@ -191,7 +99,7 @@ private: std::vector _rtcServers; absl::optional _proxy; - std::function _stateUpdated; + std::function _stateUpdated; std::function _candidateGathered; std::function _transportMessageReceived; std::function _rtcpPacketReceived; diff --git a/TMessagesProj/jni/voip/tgcalls/v2/Signaling.cpp b/TMessagesProj/jni/voip/tgcalls/v2/Signaling.cpp index 20893fac3..c64205366 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2/Signaling.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2/Signaling.cpp @@ -11,9 +11,7 @@ namespace tgcalls { namespace signaling { static std::string uint32ToString(uint32_t value) { - std::ostringstream stringStream; - stringStream << value; - return stringStream.str(); + return std::to_string(value); } static uint32_t stringToUInt32(std::string const &string) { @@ -221,7 +219,7 @@ absl::optional PayloadType_parse(json11::Json::object const &object json11::Json::object MediaContent_serialize(MediaContent const &mediaContent) { json11::Json::object object; - + std::string mappedType; switch (mediaContent.type) { case MediaContent::Type::Audio: { @@ -268,7 +266,7 @@ json11::Json::object MediaContent_serialize(MediaContent const &mediaContent) { absl::optional MediaContent_parse(json11::Json::object const &object) { MediaContent result; - + const auto type = object.find("type"); if (type == object.end() || !type->second.is_string()) { RTC_LOG(LS_ERROR) << "Signaling: type must be a string"; @@ -362,7 +360,7 @@ absl::optional MediaContent_parse(json11::Json::object const &obje std::vector InitialSetupMessage_serialize(const InitialSetupMessage * const message) { json11::Json::object object; - + object.insert(std::make_pair("@type", json11::Json("InitialSetup"))); object.insert(std::make_pair("ufrag", json11::Json(message->ufrag))); object.insert(std::make_pair("pwd", json11::Json(message->pwd))); @@ -425,7 +423,7 @@ absl::optional InitialSetupMessage_parse(json11::Json::obje RTC_LOG(LS_ERROR) << "Signaling: fingerprint must be a string"; return absl::nullopt; } - + DtlsFingerprint parsedFingerprint; parsedFingerprint.hash = hash->second.string_value(); parsedFingerprint.setup = setup->second.string_value(); @@ -445,11 +443,11 @@ absl::optional InitialSetupMessage_parse(json11::Json::obje std::vector NegotiateChannelsMessage_serialize(const NegotiateChannelsMessage * const message) { json11::Json::object object; - + object.insert(std::make_pair("@type", json11::Json("NegotiateChannels"))); - + object.insert(std::make_pair("exchangeId", json11::Json(uint32ToString(message->exchangeId)))); - + json11::Json::array contents; for (const auto &content : message->contents) { contents.push_back(json11::Json(MediaContent_serialize(content))); @@ -463,9 +461,9 @@ std::vector NegotiateChannelsMessage_serialize(const NegotiateChannelsM absl::optional NegotiateChannelsMessage_parse(json11::Json::object const &object) { NegotiateChannelsMessage message; - + const auto exchangeId = object.find("exchangeId"); - + if (exchangeId == object.end()) { RTC_LOG(LS_ERROR) << "Signaling: exchangeId must be present"; return absl::nullopt; diff --git a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.cpp b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.cpp index 3e9c3cead..a0b792ed0 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.cpp @@ -57,9 +57,7 @@ namespace tgcalls { namespace { static std::string intToString(int value) { - std::ostringstream stringStream; - stringStream << value; - return stringStream.str(); + return std::to_string(value); } static VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(VideoCaptureInterface *videoCapture) { @@ -1214,7 +1212,7 @@ public: _encryptionKey(std::move(descriptor.encryptionKey)), _stateUpdated(descriptor.stateUpdated), _signalBarsUpdated(descriptor.signalBarsUpdated), - _audioLevelsUpdated(descriptor.audioLevelsUpdated), + _audioLevelUpdated(descriptor.audioLevelsUpdated), _remoteBatteryLevelIsLowUpdated(descriptor.remoteBatteryLevelIsLowUpdated), _remoteMediaStateUpdated(descriptor.remoteMediaStateUpdated), _remotePrefferedAspectRatioUpdated(descriptor.remotePrefferedAspectRatioUpdated), @@ -1253,14 +1251,15 @@ public: void start() { const auto weak = std::weak_ptr(shared_from_this()); - _networking.reset(new ThreadLocalObject(_threads->getNetworkThread(), [weak, threads = _threads, isOutgoing = _encryptionKey.isOutgoing, rtcServers = _rtcServers, enableP2P = _enableP2P]() { - return new NativeNetworkingImpl(NativeNetworkingImpl::Configuration{ + _networking.reset(new ThreadLocalObject(_threads->getNetworkThread(), [weak, threads = _threads, encryptionKey = _encryptionKey, isOutgoing = _encryptionKey.isOutgoing, rtcServers = _rtcServers, enableP2P = _enableP2P]() { + return new NativeNetworkingImpl(InstanceNetworking::Configuration{ + .encryptionKey = encryptionKey, .isOutgoing = isOutgoing, .enableStunMarking = false, .enableTCP = false, .enableP2P = enableP2P, .rtcServers = rtcServers, - .stateUpdated = [threads, weak](const NativeNetworkingImpl::State &state) { + .stateUpdated = [threads, weak](const InstanceNetworking::State &state) { threads->getMediaThread()->PostTask([=] { const auto strong = weak.lock(); if (!strong) { @@ -1335,6 +1334,10 @@ public: mediaDeps.adm = _audioDeviceModule; + webrtc:: AudioProcessingBuilder builder; + mediaDeps.audio_processing = builder.Create(); + + _availableVideoFormats = mediaDeps.video_encoder_factory->GetSupportedFormats(); std::unique_ptr mediaEngine = cricket::CreateMediaEngine(std::move(mediaDeps)); @@ -1474,6 +1477,7 @@ public: _negotiatedOutgoingAudioContent.value(), _threads )); + _outgoingAudioChannel->setIsMuted(_isMicrophoneMuted); } adjustBitratePreferences(true); @@ -1838,7 +1842,7 @@ public: _pendingIceCandidates.clear(); } - void onNetworkStateUpdated(NativeNetworkingImpl::State const &state) { + void onNetworkStateUpdated(InstanceNetworking::State const &state) { State mappedState; if (state.isReadyToSendData) { mappedState = State::Established; @@ -2078,7 +2082,7 @@ private: EncryptionKey _encryptionKey; std::function _stateUpdated; std::function _signalBarsUpdated; - std::function _audioLevelsUpdated; + std::function _audioLevelUpdated; std::function _remoteBatteryLevelIsLowUpdated; std::function _remoteMediaStateUpdated; std::function _remotePrefferedAspectRatioUpdated; @@ -2187,7 +2191,7 @@ void InstanceV2_4_0_0Impl::setMuteMicrophone(bool muteMicrophone) { }); } -void InstanceV2_4_0_0Impl::setIncomingVideoOutput(std::shared_ptr> sink) { +void InstanceV2_4_0_0Impl::setIncomingVideoOutput(std::weak_ptr> sink) { _internal->perform([sink](InstanceV2_4_0_0ImplInternal *internal) { internal->setIncomingVideoOutput(sink); }); diff --git a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.h b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.h index 1a892de4b..2fca29e74 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.h +++ b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/InstanceV2_4_0_0Impl.h @@ -27,7 +27,7 @@ public: bool supportsVideo() override { return true; } - void setIncomingVideoOutput(std::shared_ptr> sink) override; + void setIncomingVideoOutput(std::weak_ptr> sink) override; void setAudioOutputGainControlEnabled(bool enabled) override; void setEchoCancellationStrength(int strength) override; void setAudioInputDevice(std::string id) override; diff --git a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/Signaling_4_0_0.cpp b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/Signaling_4_0_0.cpp index 7d80f022c..127c8eaa9 100644 --- a/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/Signaling_4_0_0.cpp +++ b/TMessagesProj/jni/voip/tgcalls/v2_4_0_0/Signaling_4_0_0.cpp @@ -10,9 +10,7 @@ namespace tgcalls { namespace signaling_4_0_0 { static std::string uint32ToString(uint32_t value) { - std::ostringstream stringStream; - stringStream << value; - return stringStream.str(); + return std::to_string(value); } static uint32_t stringToUInt32(std::string const &string) { diff --git a/TMessagesProj/src/main/assets/arctic.attheme b/TMessagesProj/src/main/assets/arctic.attheme index 955d1070c..a385f6148 100644 --- a/TMessagesProj/src/main/assets/arctic.attheme +++ b/TMessagesProj/src/main/assets/arctic.attheme @@ -1,3 +1,4 @@ +chat_BlurAlpha=-1056964608 chat_unreadMessagesStartText=-14512671 chat_inFileBackgroundSelected=-2823172 radioBackgroundChecked=-14638337 @@ -74,6 +75,7 @@ chat_inBubbleShadow=1981626195 chat_outAudioProgress=-10907938 player_progress=-14441474 chat_inReplyLine=-12478487 +chat_inQuote=-12478487 dialogLineProgressBackground=-3152133 chat_inReplyNameText=-13464859 chat_outAudioPerfomerSelectedText=-1 diff --git a/TMessagesProj/src/main/assets/bluebubbles.attheme b/TMessagesProj/src/main/assets/bluebubbles.attheme index ebff93f9a..6e29f76c9 100644 --- a/TMessagesProj/src/main/assets/bluebubbles.attheme +++ b/TMessagesProj/src/main/assets/bluebubbles.attheme @@ -43,6 +43,7 @@ chat_inLoaderSelected=-12277262 chat_outLocationIcon=-2105761599 chat_outAudioProgress=-6239505 chat_inReplyLine=-348807706 +chat_inQuote=-348807706 dialogLineProgressBackground=-2035723 chat_inReplyNameText=-14643754 chats_onlineCircle=-13192972 diff --git a/TMessagesProj/src/main/assets/codelng.gzip b/TMessagesProj/src/main/assets/codelng.gzip new file mode 100644 index 000000000..847881eb5 Binary files /dev/null and b/TMessagesProj/src/main/assets/codelng.gzip differ diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index e1b88a0e8..c533d7471 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -22,7 +22,7 @@ chat_attachAudioBackground=-626837 location_sendLocationBackground=-9919529 actionBarDefaultSubmenuBackground=-14075831 switchTrackBlueThumb=-14866637 -avatar_nameInMessageViolet=-6643205 +avatar_nameInMessageViolet=-7565846 emptyListPlaceholder=-8549479 chat_inAudioSelectedProgress=-1 chats_nameMessage=-1446156 @@ -118,6 +118,7 @@ chat_outAudioProgress=-1 stickers_menu=-10719105 player_progress=-10177041 chat_inReplyLine=-8796932 +chat_inQuote=-8796932 chat_inAudioPerfomerSelectedText=-7490861 dialogBackground=-14602949 dialogLineProgressBackground=-13548718 @@ -138,10 +139,10 @@ chat_messagePanelSend=-10177041 passport_authorizeBackground=-12352582 chat_inSentClock=-10653824 chats_menuTopShadow=789516 -avatar_nameInMessageRed=-21124 +avatar_nameInMessageRed=-1537928 chat_botSwitchToInlineText=-8796932 chats_nameMessageArchived=-8549479 -avatar_nameInMessageOrange=-13984 +avatar_nameInMessageOrange=-1528998 chats_pinnedIcon=-10982016 chat_attachActiveTab=-9781249 chat_replyPanelLine=1578572317 @@ -166,12 +167,12 @@ avatar_background2Red=-2013369 chat_emojiPanelBadgeBackground=-11291403 chat_inForwardedNameText=-8796932 chats_actionBackground=-10509346 -avatar_nameInMessageGreen=-7018619 +avatar_nameInMessageGreen=-8531855 chat_outContactNameText=-1 chat_inSiteNameText=-8796932 chat_linkSelectBackground=1516415459 windowBackgroundWhiteBlueText=-10177041 -avatar_nameInMessageCyan=-10623523 +avatar_nameInMessageCyan=-11285306 chat_inLocationBackground=-13417903 radioBackground=-1635939431 profile_tabText=2027746559 @@ -278,12 +279,12 @@ key_chat_messagePanelVoiceLockBackground=-13548712 chat_outFileNameText=-1 picker_enabledButton=-9781249 inappPlayerBackground=-14602949 -avatar_nameInMessagePink=-624741 +avatar_nameInMessagePink=-1543014 windowBackgroundWhiteGrayText=-8549479 statisticChartSignature=-1214008894 actionBarDefaultSubmenuItemIcon=1859974399 chat_attachPollBackground=-2183099 -avatar_nameInMessageBlue=-8796932 +avatar_nameInMessageBlue=-10703382 dialogTextBlack=-592138 actionBarDefault=-14406343 location_placeLocationBackground=-9919529 @@ -425,4 +426,7 @@ chat_topPanelBackground=-14602949 chat_outSentClock=-8213557 dialogBackgroundGray=-14932431 chat_searchPanelText=-8796932 -chat_inContactIcon=-1 \ No newline at end of file +chat_inContactIcon=-1 +code_comment=-2130706433 +chat_outCodeBackground=857487708 +chat_inCodeBackground=856033549 \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/day.attheme b/TMessagesProj/src/main/assets/day.attheme index 6944f3d31..861fbd3ae 100644 --- a/TMessagesProj/src/main/assets/day.attheme +++ b/TMessagesProj/src/main/assets/day.attheme @@ -79,6 +79,7 @@ chat_outAudioProgress=-12155183 player_progress=-14574092 chat_stickerReplyMessageText=-7565679 chat_inReplyLine=-12676640 +chat_inQuote=-12676640 dialogLineProgressBackground=-3348999 chat_inReplyNameText=-13531425 chat_outAudioPerfomerSelectedText=-1 diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index 28941bb69..252f7771c 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -22,7 +22,7 @@ chat_attachAudioBackground=-626837 location_sendLocationBackground=-9919529 actionBarDefaultSubmenuBackground=-14145495 switchTrackBlueThumb=-14803424 -avatar_nameInMessageViolet=-6643205 +avatar_nameInMessageViolet=-7565846 emptyListPlaceholder=-8553091 chat_inAudioSelectedProgress=-1 chats_nameMessage=-1315861 @@ -121,6 +121,7 @@ chat_outAudioProgress=-1 stickers_menu=-10724260 player_progress=-11292689 chat_inReplyLine=-8796932 +chat_inQuote=-8796932 chat_inAudioPerfomerSelectedText=-7490861 dialogBackground=-14803426 dialogLineProgressBackground=-12303292 @@ -146,10 +147,10 @@ chats_sentReadCheck=-12145165 passport_authorizeBackground=-12352582 chat_inSentClock=-11050909 chats_menuTopShadow=789516 -avatar_nameInMessageRed=-21124 +avatar_nameInMessageRed=-1537928 chat_botSwitchToInlineText=-8796932 chats_nameMessageArchived=-8553091 -avatar_nameInMessageOrange=-13984 +avatar_nameInMessageOrange=-1528998 chats_pinnedIcon=-10197916 chat_attachActiveTab=-9781249 chat_replyPanelLine=838860800 @@ -176,14 +177,14 @@ avatar_background2Red=-2530993 chat_emojiPanelBadgeBackground=-11291403 chat_inForwardedNameText=-8930052 chats_actionBackground=-10575653 -avatar_nameInMessageGreen=-7018619 +avatar_nameInMessageGreen=-8531855 chat_outContactNameText=-1 chat_TextSelectionCursor=-11028499 chat_inSiteNameText=-8796932 chat_linkSelectBackground=1516415459 chats_archivePullDownBackground=-14145496 windowBackgroundWhiteBlueText=-10177041 -avatar_nameInMessageCyan=-10623523 +avatar_nameInMessageCyan=-11285306 chat_inLocationBackground=-12829636 radioBackground=-10461088 profile_tabText=2030043135 @@ -296,12 +297,12 @@ key_chat_messagePanelVoiceLockBackground=-14606046 chat_outFileNameText=-1 picker_enabledButton=-9781249 inappPlayerBackground=-15066597 -avatar_nameInMessagePink=-624741 +avatar_nameInMessagePink=-1543014 windowBackgroundWhiteGrayText=1862270975 statisticChartSignature=-1214008894 actionBarDefaultSubmenuItemIcon=2029911551 chat_attachPollBackground=-2183099 -avatar_nameInMessageBlue=-8796932 +avatar_nameInMessageBlue=-10703382 dialogTextBlack=-592138 actionBarDefault=-14474458 location_placeLocationBackground=-9919529 @@ -451,3 +452,6 @@ chat_outSentClock=-6698513 dialogBackgroundGray=-14013910 chat_searchPanelText=-10767620 chat_inContactIcon=-1 +code_comment=-2130706433 +chat_outCodeBackground=859062986 +chat_inCodeBackground=855638016 \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java index cd543eb7e..c93178c22 100644 --- a/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java +++ b/TMessagesProj/src/main/java/org/telegram/PhoneFormat/PhoneFormat.java @@ -24,6 +24,8 @@ package org.telegram.PhoneFormat; +import androidx.annotation.NonNull; + import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; @@ -181,6 +183,7 @@ public class PhoneFormat { return res; } + @NonNull public String format(String orig) { if (!initialzed) { return orig; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index ad347727a..b3ed1614e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -211,6 +211,7 @@ public class AndroidUtilities { public final static int REPLACING_TAG_TYPE_LINK = 0; public final static int REPLACING_TAG_TYPE_BOLD = 1; + public final static int REPLACING_TAG_TYPE_LINKBOLD = 2; public final static String TYPEFACE_ROBOTO_MEDIUM = "fonts/rmedium.ttf"; public final static String TYPEFACE_ROBOTO_MEDIUM_ITALIC = "fonts/rmediumitalic.ttf"; @@ -455,6 +456,10 @@ public class AndroidUtilities { return null; } + public static CharSequence premiumText(String str, Runnable runnable) { + return replaceSingleTag(str, -1, REPLACING_TAG_TYPE_LINKBOLD, runnable); + } + public static CharSequence replaceSingleTag(String str, Runnable runnable) { return replaceSingleTag(str, -1, 0, runnable); } @@ -475,7 +480,7 @@ public class AndroidUtilities { } SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(str); if (index >= 0) { - if (type == REPLACING_TAG_TYPE_LINK) { + if (type == REPLACING_TAG_TYPE_LINK || type == REPLACING_TAG_TYPE_LINKBOLD) { spannableStringBuilder.setSpan(new ClickableSpan() { @Override @@ -485,6 +490,9 @@ public class AndroidUtilities { if (colorKey >= 0) { ds.setColor(Theme.getColor(colorKey, resourcesProvider)); } + if (type == REPLACING_TAG_TYPE_LINKBOLD) { + ds.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + } } @Override @@ -595,8 +603,11 @@ public class AndroidUtilities { if (child.getVisibility() != View.VISIBLE || child instanceof PeerStoriesView && child != onlyThisView) { continue; } - if (child instanceof StoryMediaAreasView.AreaView && !((StoryMediaAreasView) container).hasSelected() && (x < dp(60) || x > container.getWidth() - dp(60))) { - continue; + if (child instanceof StoryMediaAreasView.AreaView) { + StoryMediaAreasView areasView = (StoryMediaAreasView) container; + if (!(areasView.hasSelected() && (x < dp(60) || x > container.getWidth() - dp(60))) && !areasView.hasAreaAboveAt(x, y)) { + continue; + } } child.getHitRect(AndroidUtilities.rectTmp2); if (AndroidUtilities.rectTmp2.contains((int) x, (int) y) && child.isClickable()) { @@ -3457,7 +3468,7 @@ public class AndroidUtilities { return stringBuilder.toString(); } - public static final String[] numbersSignatureArray = {"", "K", "M", "G", "T", "P"}; + public static final String[] numbersSignatureArray = {"", "K", "M", "B", "T", "P"}; public static String formatWholeNumber(int v, int dif) { if (v == 0) { @@ -4635,6 +4646,20 @@ public class AndroidUtilities { } } + public static void setLightStatusBar(View view, boolean enable) { + if (view != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + int flags = view.getSystemUiVisibility(); + if (((flags & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) > 0) != enable) { + if (enable) { + flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } + view.setSystemUiVisibility(flags); + } + } + } + public static void setLightNavigationBar(Window window, boolean enable) { if (window != null) { setLightNavigationBar(window.getDecorView(), enable); @@ -5288,6 +5313,10 @@ public class AndroidUtilities { return Math.max(x1, x2) > Math.min(y1, y2) && Math.max(y1, y2) > Math.min(x1, x2); } + public static boolean intersect1dInclusive(int x1, int x2, int y1, int y2) { + return Math.max(x1, x2) >= Math.min(y1, y2) && Math.max(y1, y2) >= Math.min(x1, x2); + } + public static String getSysInfoString(String path) { RandomAccessFile reader = null; try { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 79e287a0d..ca95b237d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -28,6 +28,7 @@ import android.os.Handler; import android.os.PowerManager; import android.os.SystemClock; import android.telephony.TelephonyManager; +import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.multidex.MultiDex; @@ -41,6 +42,8 @@ import org.telegram.messenger.voip.VideoCapturerDevice; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.ForegroundDetector; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.IUpdateLayout; import org.telegram.ui.LauncherIconController; import java.io.BufferedWriter; @@ -132,10 +135,18 @@ public class ApplicationLoader extends Application { return applicationLoaderInstance.isHuaweiBuild(); } + public static boolean isStandaloneBuild() { + return applicationLoaderInstance.isStandalone(); + } + protected boolean isHuaweiBuild() { return false; } + protected boolean isStandalone() { + return false; + } + public static File getFilesDirFixed() { for (int a = 0; a < 10; a++) { File path = ApplicationLoader.applicationContext.getFilesDir(); @@ -637,4 +648,13 @@ public class ApplicationLoader extends Application { public boolean openApkInstall(Activity activity, TLRPC.Document document) { return false; } + + public boolean showUpdateAppPopup(Context context, TLRPC.TL_help_appUpdate update, int account) { + return false; + } + + public IUpdateLayout takeUpdateLayout(Activity activity, ViewGroup sideMenu, ViewGroup sideMenuContainer) { + return null; + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java index 5c0219936..a56ad537c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java @@ -59,6 +59,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien private String lastPremiumTransaction; private String lastPremiumToken; private boolean isDisconnected; + private Runnable onCanceled; public static BillingController getInstance() { if (instance == null) { @@ -74,6 +75,10 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien .build(); } + public void setOnCanceled(Runnable onCanceled) { + this.onCanceled = onCanceled; + } + public String getLastPremiumTransaction() { return lastPremiumTransaction; } @@ -177,7 +182,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien if (purchase.getProducts().contains(productId)) { productsToBeConsumed.incrementAndGet(); billingClient.consumeAsync(ConsumeParams.newBuilder() - .setPurchaseToken(purchase.getPurchaseToken()) + .setPurchaseToken(purchase.getPurchaseToken()) .build(), (billingResult1, s) -> { if (billingResult1.getResponseCode() == BillingClient.BillingResponseCode.OK) { productsConsumed.add(productId); @@ -228,6 +233,10 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien if (billing.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) { PremiumPreviewFragment.sentPremiumBuyCanceled(); } + if (onCanceled != null) { + onCanceled.run(); + onCanceled = null; + } return; } if (list == null || list.isEmpty()) { @@ -269,7 +278,10 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien consumeGiftPurchase(purchase, req.purpose); } else if (error != null) { - FileLog.d("Billing: Confirmation Error: " + error.code + " " + error.text); + if (onCanceled != null) { + onCanceled.run(); + onCanceled = null; + } NotificationCenter.getGlobalInstance().postNotificationNameOnUIThread(NotificationCenter.billingConfirmPurchaseError, req, error); } }, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagInvokeAfter); @@ -285,7 +297,9 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien * Without confirmation the user will not be able to buy the product again. */ private void consumeGiftPurchase(Purchase purchase, TLRPC.InputStorePaymentPurpose purpose) { - if (purpose instanceof TLRPC.TL_inputStorePaymentGiftPremium) { + if (purpose instanceof TLRPC.TL_inputStorePaymentGiftPremium + || purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode + || purpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway) { billingClient.consumeAsync( ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 1378350ec..bb37a24f1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -24,14 +24,13 @@ public class BuildVars { public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29; - public static int BUILD_VERSION = 3926; - public static String BUILD_VERSION_STRING = "10.1.1"; + public static int BUILD_VERSION = 4056; + public static String BUILD_VERSION_STRING = "10.2.0"; public static int APP_ID = 12652123; // set you own APP_ID public static String APP_HASH = "bb81fa5b3c3f80706ac142c9b72ce9ef"; // set you own APP_HASH // SafetyNet key for Google Identity SDK, set it to empty to disable public static String SAFETYNET_KEY = "AIzaSyDqt8P-7F7CPCseMkOiVRgb1LY8RN1bvH8"; - public static String SMS_HASH = isStandaloneApp() ? "w0lkcmTZkKh" : (DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT"); public static String PLAYSTORE_APP_URL = "https://play.google.com/store/apps/details?id=org.telegram.messenger"; public static String HUAWEI_STORE_URL = "https://appgallery.huawei.com/app/C101184875"; public static String GOOGLE_AUTH_CLIENT_ID = "760348033671-81kmi3pi84p11ub8hp9a1funsv0rn2p9.apps.googleusercontent.com"; @@ -52,7 +51,7 @@ public class BuildVars { } public static boolean useInvoiceBilling() { - return true;//BillingController.billingClientEmpty || DEBUG_VERSION || isStandaloneApp() || isBetaApp() || isHuaweiStoreApp() || hasDirectCurrency(); + return true;//BillingController.billingClientEmpty || DEBUG_VERSION || ApplicationLoader.isStandaloneBuild() || isBetaApp() || isHuaweiStoreApp() || hasDirectCurrency(); } private static boolean hasDirectCurrency() { @@ -71,17 +70,6 @@ public class BuildVars { return false; } - private static Boolean standaloneApp; - public static boolean isStandaloneApp() { - if (SharedConfig.fakePasscodeActivatedIndex == -1) { - return true; - } - if (standaloneApp == null) { - standaloneApp = ApplicationLoader.applicationContext != null && ("org.telegram.messenger.web".equals(ApplicationLoader.applicationContext.getPackageName()) || "org.telegram.messenger.alpha".equals(ApplicationLoader.applicationContext.getPackageName())); - } - return standaloneApp; - } - private static Boolean betaApp; public static boolean isBetaApp() { if (betaApp == null) { @@ -94,11 +82,7 @@ public class BuildVars { return ApplicationLoader.isHuaweiStoreBuild(); } - private static Boolean alphaApp; - public static boolean isAlphaApp() { - if (alphaApp == null) { - alphaApp = ApplicationLoader.applicationContext != null && "org.telegram.messenger.alpha".equals(ApplicationLoader.applicationContext.getPackageName()); - } - return alphaApp; + public static String getSmsHash() { + return ApplicationLoader.isStandaloneBuild() ? "w0lkcmTZkKh" : (DEBUG_VERSION ? "O2P2z+/jBpJ" : "oLeq9AcOZkT"); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChannelBoostsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChannelBoostsController.java index 4fdc97a67..695079473 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChannelBoostsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChannelBoostsController.java @@ -4,8 +4,13 @@ import com.google.android.exoplayer2.util.Consumer; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.Components.Bulletin; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; public class ChannelBoostsController { @@ -23,86 +28,123 @@ public class ChannelBoostsController { } - public void getBoostsStats(long dialogId, Consumer consumer) { - TLRPC.TL_stories_getBoostsStatus req = new TLRPC.TL_stories_getBoostsStatus(); + public void getBoostsStats(long dialogId, Consumer consumer) { + TL_stories.TL_premium_getBoostsStatus req = new TL_stories.TL_premium_getBoostsStatus(); req.peer = messagesController.getInputPeer(dialogId); connectionsManager.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response != null) { - consumer.accept((TLRPC.TL_stories_boostsStatus) response); + consumer.accept((TL_stories.TL_premium_boostsStatus) response); } else { BulletinFactory.showForError(error); consumer.accept(null); } })); - } - public void userCanBoostChannel(long dialogId, Consumer consumer) { - TLRPC.TL_stories_canApplyBoost req = new TLRPC.TL_stories_canApplyBoost(); - req.peer = messagesController.getInputPeer(dialogId); - connectionsManager.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - CanApplyBoost canApplyBoost = new CanApplyBoost(); - if (response != null) { - canApplyBoost.canApply = true; - if (response instanceof TLRPC.TL_stories_canApplyBoostReplace) { - TLRPC.TL_stories_canApplyBoostReplace canApplyBoostReplace = (TLRPC.TL_stories_canApplyBoostReplace) response; - messagesController.putChats(canApplyBoostReplace.chats, false); - canApplyBoost.replaceDialogId = DialogObject.getPeerDialogId(canApplyBoostReplace.current_boost); - if (canApplyBoost.replaceDialogId == 0 && canApplyBoostReplace.chats.size() > 0) { - canApplyBoost.replaceDialogId = -canApplyBoostReplace.chats.get(0).id; - } - } - } else { - if (error != null) { - if (error.text.equals("SAME_BOOST_ALREADY_ACTIVE") || error.text.equals("BOOST_NOT_MODIFIED")) { - canApplyBoost.alreadyActive = true; - } else if (error.text.equals("PREMIUM_GIFTED_NOT_ALLOWED")) { - canApplyBoost.giftedPremium = true; - } else if (error.text.startsWith("FLOOD_WAIT")) { - canApplyBoost.floodWait = Utilities.parseInt(error.text); - canApplyBoost.lastCheckTime = System.currentTimeMillis(); - } - } - } + public void userCanBoostChannel(long dialogId, TL_stories.TL_premium_boostsStatus boostsStatus, Consumer consumer) { + CanApplyBoost canApplyBoost = new CanApplyBoost(); + canApplyBoost.currentPeer = messagesController.getPeer(dialogId); + canApplyBoost.currentDialogId = dialogId; + canApplyBoost.currentChat = messagesController.getChat(-dialogId); + BoostRepository.getMyBoosts(myBoosts -> { + canApplyBoost.isMaxLvl = boostsStatus.next_level_boosts <= 0; + canApplyBoost.setMyBoosts(myBoosts); + consumer.accept(canApplyBoost); + }, error -> { + if (error.text.startsWith("FLOOD_WAIT")) { + canApplyBoost.floodWait = Utilities.parseInt(error.text); + } else if (error.text.startsWith("BOOSTS_EMPTY")) { + canApplyBoost.empty = true; + } + canApplyBoost.canApply = false; consumer.accept(canApplyBoost); - }), ConnectionsManager.RequestFlagDoNotWaitFloodWait); - } - - public void applyBoost(long dialogId) { - TLRPC.TL_stories_applyBoost req = new TLRPC.TL_stories_applyBoost(); - req.peer = messagesController.getInputPeer(dialogId); - connectionsManager.sendRequest(req, (response, error) -> { - }); } - public int getTotalBooststToLevel(int level) { - int count = 0; - if (level >= 1) { - count += BOOSTS_FOR_LEVEL_1; - } - if (level >= 2) { - count += BOOSTS_FOR_LEVEL_2; - } - return count; + public void applyBoost(long dialogId, int slot, Utilities.Callback onDone, Utilities.Callback onError) { + BoostRepository.applyBoost(-dialogId, Arrays.asList(slot), onDone, onError); } public static class CanApplyBoost { public boolean canApply; + public boolean empty; public long replaceDialogId; public boolean alreadyActive; + public boolean needSelector; public int floodWait; - public boolean giftedPremium; - private long lastCheckTime; + public int slot; + public TL_stories.TL_premium_myBoosts myBoosts; + public int boostCount = 0; + public TLRPC.Peer currentPeer; + public long currentDialogId; + public TLRPC.Chat currentChat; + public boolean boostedNow; + public boolean isMaxLvl; - public void checkTime() { - floodWait -= (System.currentTimeMillis() - lastCheckTime) / 1000; - lastCheckTime = System.currentTimeMillis(); - if (floodWait < 0) { - floodWait = 0; + public void setMyBoosts(TL_stories.TL_premium_myBoosts myBoosts) { + this.myBoosts = myBoosts; + boostCount = 0; + slot = 0; + alreadyActive = false; + canApply = false; + needSelector = false; + replaceDialogId = 0; + + if (myBoosts.my_boosts.isEmpty()) { + empty = true; + } + + //search boosted count + for (TL_stories.TL_myBoost myBoost : myBoosts.my_boosts) { + if (currentDialogId == DialogObject.getPeerDialogId(myBoost.peer)) { + boostCount++; + } + } + + if (boostCount > 0) { + alreadyActive = true; + } + + //search free slot + for (TL_stories.TL_myBoost myBoost : myBoosts.my_boosts) { + if (myBoost.peer == null) { + slot = myBoost.slot; + break; + } + } + boolean noFreeSlot = slot == 0; + if (noFreeSlot) { + //only replacement + List replaceBoost = new ArrayList<>(); + for (TL_stories.TL_myBoost myBoost : myBoosts.my_boosts) { + if (myBoost.peer != null && DialogObject.getPeerDialogId(myBoost.peer) != -currentChat.id) { + replaceBoost.add(myBoost); + } + } + + if (replaceBoost.size() == 1) { + TL_stories.TL_myBoost myBoost = replaceBoost.get(0); + replaceDialogId = DialogObject.getPeerDialogId(myBoost.peer); + slot = myBoost.slot; + canApply = true; + } else if (replaceBoost.size() > 1) { + needSelector = true; + if (!BoostRepository.isMultiBoostsAvailable()) { + TL_stories.TL_myBoost myBoost = replaceBoost.get(0); + replaceDialogId = DialogObject.getPeerDialogId(myBoost.peer); + slot = myBoost.slot; + } + canApply = true; + } else { + canApply = false; + } + } else { canApply = true; } + if (isMaxLvl) { + canApply = false; + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java index a13d21515..96bd6aec0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatMessagesMetadataController.java @@ -1,17 +1,11 @@ package org.telegram.messenger; -import com.google.android.exoplayer2.util.Log; - -import org.checkerframework.checker.units.qual.A; -import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.RequestDelegate; -import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ChatActivity; import org.telegram.ui.Stories.StoriesStorage; import java.util.ArrayList; -import java.util.Collections; public class ChatMessagesMetadataController { @@ -53,8 +47,8 @@ public class ChatMessagesMetadataController { extendedMediaToCheck.add(messageObject); } if (messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION || messageObject.messageOwner.replyStory != null) { - TLRPC.StoryItem storyItem = messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION ? messageObject.messageOwner.media.storyItem : messageObject.messageOwner.replyStory; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION ? messageObject.messageOwner.media.storyItem : messageObject.messageOwner.replyStory; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } if (currentTime - storyItem.lastUpdateTime > 1000 * 5 * 60) { @@ -74,9 +68,9 @@ public class ChatMessagesMetadataController { return; } for (int i = 0; i < visibleObjects.size(); i++) { - TLRPC.TL_stories_getStoriesByID req = new TLRPC.TL_stories_getStoriesByID(); + TL_stories.TL_stories_getStoriesByID req = new TL_stories.TL_stories_getStoriesByID(); MessageObject messageObject = visibleObjects.get(i); - TLRPC.StoryItem storyItem = new TLRPC.TL_storyItem(); + TL_stories.StoryItem storyItem = new TL_stories.TL_storyItem(); if (messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION) { storyItem = messageObject.messageOwner.media.storyItem; storyItem.dialogId = messageObject.messageOwner.media.user_id; @@ -91,18 +85,18 @@ public class ChatMessagesMetadataController { req.id.add(storyItem.id); int storyId = storyItem.id; int reqId = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> { - TLRPC.StoryItem newStoryItem = null; + TL_stories.StoryItem newStoryItem = null; if (response != null) { - TLRPC.TL_stories_stories stories = (TLRPC.TL_stories_stories) response; + TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; if (stories.stories.size() > 0) { newStoryItem = stories.stories.get(0); } if (newStoryItem == null) { - newStoryItem = new TLRPC.TL_storyItemDeleted(); + newStoryItem = new TL_stories.TL_storyItemDeleted(); } newStoryItem.lastUpdateTime = System.currentTimeMillis(); newStoryItem.id = storyId; - TLRPC.StoryItem finalNewStoryItem = newStoryItem; + TL_stories.StoryItem finalNewStoryItem = newStoryItem; AndroidUtilities.runOnUIThread(() -> { boolean wasExpired = messageObject.isExpiredStory(); StoriesStorage.applyStory(chatActivity.getCurrentAccount(), storyDialogId, messageObject, finalNewStoryItem); @@ -137,7 +131,8 @@ public class ChatMessagesMetadataController { MessageObject messageObject = visibleObjects.get(i); req.id.add(messageObject.getId()); } - int reqId = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> { + final int[] reqId = new int[1]; + reqId[0] = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { TLRPC.Updates updates = (TLRPC.Updates) response; for (int i = 0; i < updates.updates.size(); i++) { @@ -147,9 +142,12 @@ public class ChatMessagesMetadataController { } chatActivity.getMessagesController().processUpdates(updates, false); } + AndroidUtilities.runOnUIThread(() -> { + reactionsRequests.remove((Object) reqId[0]); + }); }); - reactionsRequests.add(reqId); - if (reactionsRequests.size() > 5) { + reactionsRequests.add(reqId[0]); + while (reactionsRequests.size() > 4) { chatActivity.getConnectionsManager().cancelRequest(reactionsRequests.remove(0), false); } } @@ -164,13 +162,17 @@ public class ChatMessagesMetadataController { MessageObject messageObject = visibleObjects.get(i); req.id.add(messageObject.getId()); } - int reqId = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> { + final int[] reqId = new int[1]; + reqId[0] = chatActivity.getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { chatActivity.getMessagesController().processUpdates((TLRPC.Updates) response, false); } + AndroidUtilities.runOnUIThread(() -> { + extendedMediaRequests.remove((Object) reqId[0]); + }); }); - extendedMediaRequests.add(reqId); - if (extendedMediaRequests.size() > 10) { + extendedMediaRequests.add(reqId[0]); + while (extendedMediaRequests.size() > 10) { chatActivity.getConnectionsManager().cancelRequest(extendedMediaRequests.remove(0), false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java b/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java new file mode 100644 index 000000000..084b1eac6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/CodeHighlighting.java @@ -0,0 +1,754 @@ +package org.telegram.messenger; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.SpannedString; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.text.style.LineHeightSpan; +import android.text.style.MetricAffectingSpan; +import android.util.Log; + +import androidx.annotation.NonNull; + +import org.telegram.tgnet.AbstractSerializedData; +import org.telegram.tgnet.SerializedData; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.TextStyleSpan; + +import java.io.BufferedInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Array; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class CodeHighlighting { + + public static final int MATCH_NONE = 0; + public static final int MATCH_KEYWORD = 1; + public static final int MATCH_OPERATOR = 2; + public static final int MATCH_CONSTANT = 3; + public static final int MATCH_STRING = 4; + public static final int MATCH_NUMBER = 5; + public static final int MATCH_COMMENT = 6; + public static final int MATCH_FUNCTION = 7; + + public static class Span extends MetricAffectingSpan { + + public final String lng; + public final String code; + public final int currentType; + public final TextStyleSpan.TextStyleRun style; + public final float decrementSize; + + public final boolean smallerSize; + + public Span(boolean smallerSize, int type, TextStyleSpan.TextStyleRun style, String lng, String code) { + this.smallerSize = smallerSize; + + this.lng = lng; + this.code = code; + if (code == null) { + this.decrementSize = 2; + } else if (code.length() > 120) { + this.decrementSize = 5; + } else if (code.length() > 50) { + this.decrementSize = 3; + } else { + this.decrementSize = 2; + } + this.currentType = type; + this.style = style; + } + + @Override + public void updateMeasureState(TextPaint p) { + if (smallerSize) { + p.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize - decrementSize)); + } + p.setFlags(p.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); + if (style != null) { + style.applyStyle(p); + } else { + p.setTypeface(Typeface.MONOSPACE); + } + } + + @Override + public void updateDrawState(TextPaint p) { + if (smallerSize) { + p.setTextSize(AndroidUtilities.dp(SharedConfig.fontSize - decrementSize)); + } + if (currentType == 2) { + p.setColor(0xffffffff); + } else if (currentType == 1) { + p.setColor(Theme.getColor(Theme.key_chat_messageTextOut)); + } else { + p.setColor(Theme.getColor(Theme.key_chat_messageTextIn)); + } + if (style != null) { + style.applyStyle(p); + } else { + p.setTypeface(Typeface.MONOSPACE); + p.setUnderlineText(false); + } + } + } + + public static class ColorSpan extends CharacterStyle { + public int group; + public ColorSpan(int match) { + this.group = match; + } + + public int getColorKey() { + switch (this.group) { + case MATCH_KEYWORD: return Theme.key_code_keyword; + case MATCH_OPERATOR: return Theme.key_code_operator; + case MATCH_CONSTANT: return Theme.key_code_constant; + case MATCH_STRING: return Theme.key_code_string; + case MATCH_NUMBER: return Theme.key_code_number; + case MATCH_COMMENT: return Theme.key_code_comment; + case MATCH_FUNCTION: return Theme.key_code_function; + default: return -1; + } + } + + @Override + public void updateDrawState(TextPaint tp) { + tp.setColor(Theme.getColor(getColorKey())); + } + } + + // setting 100-300 spans is hard + // fast way to fix this is to do it on another thread, and not give access to data until it's finished processing + public static class LockedSpannableString extends SpannableString { + public LockedSpannableString(CharSequence text) { + super(text); + } + + private boolean ready; + public void unlock() { + this.ready = true; + } + + @Override + public T[] getSpans(int queryStart, int queryEnd, Class kind) { + if (!ready) return (T[]) Array.newInstance(kind, 0); + return super.getSpans(queryStart, queryEnd, kind); + } + + @Override + public int nextSpanTransition(int start, int limit, Class kind) { + if (!ready) return limit; + return super.nextSpanTransition(start, limit, kind); + } + + @Override + public int getSpanStart(Object what) { + if (!ready) return -1; + return super.getSpanStart(what); + } + + @Override + public int getSpanEnd(Object what) { + if (!ready) return -1; + return super.getSpanEnd(what); + } + + @Override + public int getSpanFlags(Object what) { + if (!ready) return 0; + return super.getSpanFlags(what); + } + } + + private static final HashMap processedHighlighting = new HashMap<>(); + private static class Highlighting { + String text, language; + SpannableString result; + } + + public static SpannableString getHighlighted(String text, String language) { + if (TextUtils.isEmpty(language)) { + return new SpannableString(text); + } + final String key = language + "`" + text; + Highlighting process = processedHighlighting.get(key); + if (process == null) { + process = new Highlighting(); + process.text = text; + process.language = language; + process.result = new LockedSpannableString(text); + + highlight(process.result, 0, process.result.length(), language, 0, null, true); + + Iterator keys = processedHighlighting.keySet().iterator(); + while (keys.hasNext() && processedHighlighting.size() > 8) { + keys.next(); + keys.remove(); + } + + processedHighlighting.put(key, process); + } + return process.result; + } + + public static void highlight(Spannable text, int start, int end, String lng, int type, TextStyleSpan.TextStyleRun style, boolean smallerSize) { + if (text == null) { + return; + } +// text.setSpan(new Span(smallerSize, type, style, lng, text.subSequence(start, end).toString(), start <= 0, end >= text.length() - 1, start, end), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + Utilities.searchQueue.postRunnable(() -> { + if (compiledPatterns == null) + parse(); + long S = System.currentTimeMillis(); + final StringToken[][] tokens = new StringToken[1][]; + try { + tokens[0] = tokenize(text.subSequence(start, end).toString(), compiledPatterns == null ? null : compiledPatterns.get(lng)).toArray(); + } catch (Exception e) { + FileLog.e(e); + } + FileLog.d("[CodeHighlighter] tokenize took " + (System.currentTimeMillis() - S) + "ms"); + + long S2 = System.currentTimeMillis(); + ArrayList spans = new ArrayList<>(); + colorize(text, start, end, tokens[0], -1, spans); + FileLog.d("[CodeHighlighter] colorize took " + (System.currentTimeMillis() - S2) + "ms"); + + if (!spans.isEmpty()) { + if (text instanceof LockedSpannableString) { + long S3 = System.currentTimeMillis(); + for (int i = 0; i < spans.size(); ++i) { + CachedToSpan span = spans.get(i); + text.setSpan(new ColorSpan(span.group), span.start, span.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + FileLog.d("[CodeHighlighter] applying " + spans.size() + " colorize spans took " + (System.currentTimeMillis() - S3) + "ms in another thread"); + AndroidUtilities.runOnUIThread(() -> { + ((LockedSpannableString) text).unlock(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiLoaded); + }); + } else { + AndroidUtilities.runOnUIThread(() -> { + long S3 = System.currentTimeMillis(); + for (int i = 0; i < spans.size(); ++i) { + CachedToSpan span = spans.get(i); + text.setSpan(new ColorSpan(span.group), span.start, span.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + FileLog.d("[CodeHighlighter] applying " + spans.size() + " colorize spans took " + (System.currentTimeMillis() - S3) + "ms"); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiLoaded); + }); + } + } + }); + } + + private static void colorize(Spannable text, int start, int end, StringToken[] tokens, int defGroup, ArrayList result) { + if (tokens == null) { + return; + } + int p = start; + for (int i = 0; i < tokens.length && p < end; ++i) { + StringToken t = tokens[i]; + if (t == null) continue; + if (t.string != null) { + int group = t.group; + if (defGroup != -1) { + group = defGroup; + } + if (group == -1) { + p += t.length(); + continue; + } + + result.add(new CachedToSpan(group, p, p + t.length())); +// text.setSpan(new ColorSpan(group), p, p + t.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (t.inside != null) { + colorize(text, p, p + t.length(), t.inside.toArray(), t.group, result); + } + p += t.length(); + } + } + + private static class CachedToSpan { + public int group; + public int start, end; + public CachedToSpan(int group, int start, int end) { + this.group = group; + this.start = start; + this.end = end; + } + } + + private static LinkedList tokenize(String text, TokenPattern[] grammar) { + return tokenize(text, grammar, null); + } + + private static LinkedList tokenize(String text, TokenPattern[] grammar, TokenPattern ignorePattern) { + LinkedList list = new LinkedList(); + list.addAfter(list.head, new StringToken(text)); + grammar = flatRest(grammar); + matchGrammar(text, list, grammar, list.head, 0, null, ignorePattern); + return list; + } + + private static TokenPattern[] flatRest(TokenPattern[] patterns) { + if (patterns == null) { + return null; + } + ArrayList result = null; + for (int i = 0; i < patterns.length; ++i) { + if (patterns[i].pattern != null && "REST".equals(patterns[i].pattern.patternSource)) { + if (result == null) { + result = new ArrayList<>(); + Collections.addAll(result, patterns); + } + result.remove(patterns[i]); + if (!TextUtils.isEmpty(patterns[i].insideLanguage) && compiledPatterns != null) { + TokenPattern[] grammar = compiledPatterns.get(patterns[i].insideLanguage); + if (grammar != null) { + Collections.addAll(result, grammar); + } + } + } + } + if (result != null) { + return result.toArray(new TokenPattern[0]); + } + return patterns; + } + + private static void matchGrammar(String text, LinkedList tokenList, TokenPattern[] grammar, Node startNode, int startPos, RematchOptions rematch, TokenPattern ignorePattern) { + if (grammar == null) { + return; + } + for (TokenPattern pattern : grammar) { + if (pattern == ignorePattern || rematch != null && rematch.cause == pattern) { + return; + } + + + Node currentNode = startNode.next; + int pos = startPos; + for (; + currentNode != tokenList.tail; + pos += currentNode.value.length(), currentNode = currentNode.next + ) { + if (rematch != null && pos >= rematch.reach) { + return; + } + + if (tokenList.length > text.length()) { + FileLog.e("[CodeHighlighter] Something went terribly wrong, ABORT, ABORT!"); + return; + } + + if (currentNode.value.string == null || currentNode.value.token) { + continue; + } + + String str = currentNode.value.string; + + int removeCount = 1; + Match match; + if (pattern.greedy) { + match = matchPattern(pattern, pos, text); + if (match == null || match.index >= text.length()) { + break; + } + + int from = match.index; + int to = match.index + match.length; + int p = pos; + + p += currentNode.value.length(); + while (from >= p) { + currentNode = currentNode.next; + p += currentNode.value.length(); + } + p -= currentNode.value.length(); + pos = p; + + if (currentNode.value.string == null || currentNode.value.token) { + continue; + } + + for ( + Node k = currentNode; + k != tokenList.tail && (p < to || !k.value.token); + k = k.next + ) { + removeCount++; + p += k.value.length(); + } + removeCount--; + + str = text.substring(pos, p); + match.index -= pos; + } else { + match = matchPattern(pattern, 0, str); + if (match == null) { + continue; + } + } + + int from = match.index; + String before = str.substring(0, from); + String after = str.substring(from + match.length); + + int reach = pos + str.length(); + if (rematch != null && reach > rematch.reach) { + rematch.reach = reach; + } + + Node removeFrom = currentNode.prev; + if (before.length() > 0) { + removeFrom = tokenList.addAfter(removeFrom, new StringToken(before)); + pos += before.length(); + } + + tokenList.removeRange(removeFrom, removeCount); + + StringToken wrapped; + if (pattern.insideTokenPatterns != null) { + wrapped = new StringToken(pattern.group, tokenize(match.string, pattern.insideTokenPatterns), match.length); + } else if (pattern.insideLanguage != null) { + wrapped = new StringToken(pattern.group, tokenize(match.string, compiledPatterns.get(pattern.insideLanguage), pattern), match.length); + } else { + wrapped = new StringToken(pattern.group, match.string); + } + currentNode = tokenList.addAfter(removeFrom, wrapped); + + if (after.length() > 0) { + tokenList.addAfter(currentNode, new StringToken(after)); + } + + if (removeCount > 1) { + RematchOptions nestedRematch = new RematchOptions(); + nestedRematch.cause = pattern; + nestedRematch.reach = reach; + matchGrammar(text, tokenList, grammar, currentNode.prev, pos, nestedRematch, ignorePattern); + + if (rematch != null && nestedRematch.reach > rematch.reach) { + rematch.reach = nestedRematch.reach; + } + } + } + } + } + + private static Match matchPattern(TokenPattern pattern, int pos, String text) { + Matcher matcher = pattern.pattern.getPattern().matcher(text); + matcher.region(pos, text.length()); + if (!matcher.find()) { + return null; + } + Match match = new Match(); + match.index = matcher.start(); + if (pattern.lookbehind && matcher.groupCount() >= 1) { + match.index += matcher.end(1) - matcher.start(1); + } + match.length = matcher.end() - match.index; + match.string = text.substring(match.index, match.index + match.length); + return match; + } + + private static class RematchOptions { + TokenPattern cause; + int reach; + } + + private static class Match { + int index; + int length; + String string; + } + + private static class LinkedList { + public Node head; + public Node tail; + public int length = 0; + + public LinkedList() { + head = new Node(); + tail = new Node(); + head.next = tail; + tail.prev = head; + } + + public Node addAfter(Node node, StringToken value) { + Node next = node.next; + Node newNode = new Node(); + newNode.value = value; + newNode.prev = node; + newNode.next = next; + node.next = newNode; + next.prev = newNode; + length++; + return newNode; + } + + public void removeRange(Node node, int count) { + Node next = node.next; + int i = 0; + for (; i < count && next != tail; ++i) { + next = next.next; + } + node.next = next; + next.prev = node; + length -= i; + } + + public StringToken[] toArray() { + StringToken[] array = new StringToken[length]; + Node node = head.next; + for (int i = 0; i < length && node != tail; node = node.next, ++i) { + array[i] = node.value; + } + return array; + } + } + private static class Node { + public Node prev; + public Node next; + public StringToken value; + } + private static class StringToken { + final boolean token; + final int group; + final String string; + final CodeHighlighting.LinkedList inside; + final int insideLength; + public StringToken(int group, String string) { + this.token = true; + this.group = group; + this.string = string; + this.inside = null; + this.insideLength = 0; + } + public StringToken(int group, CodeHighlighting.LinkedList inside, int len) { + this.token = true; + this.group = group; + this.string = null; + this.inside = inside; + this.insideLength = len; + } + public StringToken(String string) { + this.token = false; + this.group = -1; + this.string = string; + this.inside = null; + this.insideLength = 0; + } + + public int length() { + if (string != null) { + return string.length(); + } + return insideLength; + } + } + + private static HashMap compiledPatterns; + private static void parse() { + GZIPInputStream zipStream = null; + BufferedInputStream bufStream = null; + InputStream stream = null; + try { + long start = System.currentTimeMillis(); + stream = ApplicationLoader.applicationContext.getAssets().open("codelng.gzip"); + zipStream = new GZIPInputStream(stream, 65536); + bufStream = new BufferedInputStream(zipStream, 65536); + StreamReader reader = new StreamReader(bufStream); + + HashMap languages = new HashMap<>(); + int languagesCount = reader.readUint8(); + for (int i = 0; i < languagesCount; ++i) { + int lngid = reader.readUint8(); + int aliasesCount = reader.readUint8(); + String[] aliases = new String[aliasesCount]; + for (int j = 0; j < aliasesCount; ++j) { + aliases[j] = reader.readString(); + } + languages.put(lngid, aliases); + } + + int patternsCount = reader.readUint16(); + ParsedPattern[] patterns = new ParsedPattern[patternsCount]; + for (int i = 0; i < patternsCount; ++i) { + patterns[i] = new ParsedPattern(); + int b = reader.readUint8(); + patterns[i].multiline = (b & 1) != 0; + patterns[i].caseInsensitive = (b & 2) != 0; + patterns[i].pattern = reader.readString(); + } + + if (compiledPatterns == null) { + compiledPatterns = new HashMap<>(); + } + for (int i = 0; i < languagesCount; ++i) { + int lngid = reader.readUint8(); + TokenPattern[] tokens = readTokens(reader, patterns, languages); + String[] aliases = languages.get(lngid); + for (String alias : aliases) { + compiledPatterns.put(alias, tokens); + } + } + + FileLog.d("[CodeHighlighter] Successfully read " + languagesCount + " languages, " + patternsCount + " patterns in " + (System.currentTimeMillis() - start) + "ms from codelng.gzip"); + + } catch (Exception e) { + FileLog.e(e); + } finally { + try { + if (zipStream != null) { + zipStream.close(); + } + if (bufStream != null) { + bufStream.close(); + } + if (stream != null) { + stream.close(); + } + } catch (Exception e) { + FileLog.e(e); + } + } + } + + private static class ParsedPattern { + String pattern; + boolean multiline; + boolean caseInsensitive; + public int flags() { + return (multiline ? Pattern.MULTILINE : 0) | (caseInsensitive ? Pattern.CASE_INSENSITIVE : 0); + } + + private CachedPattern cachedPattern; + public CachedPattern getCachedPattern() { + if (cachedPattern == null) { + cachedPattern = new CachedPattern(pattern, flags()); + } + return cachedPattern; + } + } + + private static TokenPattern[] readTokens(StreamReader reader, ParsedPattern[] patterns, HashMap languages) throws IOException { + int count = reader.readUint8(); + TokenPattern[] tokens = new TokenPattern[count]; + for (int i = 0; i < count; ++i) { + int b = reader.readUint8(); + int type = b & 0x03; + int match = (b >> 2) & 0x07; + boolean greedy = (b & (1 << 5)) != 0; + boolean lookbehind = (b & (1 << 6)) != 0; + int pid = reader.readUint16(); + if (type == 0) { + tokens[i] = new TokenPattern(match, patterns[pid].getCachedPattern()); + } else if (type == 1) { + if (match == 0) { + tokens[i] = new TokenPattern(patterns[pid].getCachedPattern(), readTokens(reader, patterns, languages)); + } else { + tokens[i] = new TokenPattern(match, patterns[pid].getCachedPattern(), readTokens(reader, patterns, languages)); + } + } else if (type == 2) { + int lid = reader.readUint8(); + tokens[i] = new TokenPattern(patterns[pid].getCachedPattern(), languages.get(lid)[0]); + } + if (greedy) tokens[i].greedy = true; + if (lookbehind) tokens[i].lookbehind = true; + } + return tokens; + } + + private static class StreamReader { + private final InputStream is; + public StreamReader(InputStream is) { + this.is = is; + } + + public int readUint8() throws IOException { + return is.read() & 0xFF; + } + public int readUint16() throws IOException { + return (is.read() & 0xFF) | ((is.read() & 0xFF) << 8); + } + public String readString() throws IOException { + int l = is.read(); + if (l >= 254) { + l = is.read() | (is.read() << 8) | (is.read() << 16); + } + byte[] b = new byte[l]; + for (int i = 0; i < l; ++i) + b[i] = (byte) is.read(); + return new String(b, StandardCharsets.US_ASCII); + } + } + + private static class TokenPattern { + public final CachedPattern pattern; + public int group = -1; + public boolean lookbehind; + public boolean greedy; + public TokenPattern[] insideTokenPatterns; + public String insideLanguage; + + public TokenPattern(int group, CachedPattern pattern) { + this.pattern = pattern; + this.group = group; + } + + public TokenPattern(CachedPattern pattern, TokenPattern...inside) { + this.pattern = pattern; + this.insideTokenPatterns = inside; + } + + public TokenPattern(CachedPattern pattern, String lang) { + this.pattern = pattern; + this.insideLanguage = lang; + } + + public TokenPattern(int group, CachedPattern pattern, TokenPattern...inside) { + this.group = group; + this.pattern = pattern; + this.insideTokenPatterns = inside; + } + } + + private static class CachedPattern { + private Pattern pattern; + private String patternSource; + private int patternSourceFlags; + + public CachedPattern(String pattern, int flags) { + patternSource = pattern; + patternSourceFlags = flags; + } + + public Pattern getPattern() { + if (pattern == null) { + pattern = Pattern.compile(patternSource, patternSourceFlags); + } + return pattern; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java index ec004ce78..d634c91f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java @@ -27,6 +27,7 @@ import android.provider.ContactsContract; import android.text.TextUtils; import android.util.SparseArray; +import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import com.google.android.exoplayer2.util.Log; @@ -2227,7 +2228,7 @@ public class ContactsController extends BaseController { if (systemAccount == null || user == null) { return -1; } - if (!hasContactsPermission()) { + if (!hasContactsWritePermission()) { return -1; } long res = -1; @@ -2252,8 +2253,8 @@ public class ContactsController extends BaseController { if (result != null && result.length > 0 && result[0].uri != null) { res = Long.parseLong(result[0].uri.getLastPathSegment()); } - } catch (Exception ignore) { - + } catch (Exception e) { + FileLog.e(e); } synchronized (observerLock) { ignoreChanges = false; @@ -2876,6 +2877,7 @@ public class ContactsController extends BaseController { } } + @NonNull public static String formatName(TLRPC.User user) { if (user == null) { return ""; @@ -2891,10 +2893,12 @@ public class ContactsController extends BaseController { return UserConfig.getChatTitleOverride(accountNum, user.id, formatName(user.first_name, user.last_name)); } + @NonNull public static String formatName(String firstName, String lastName) { return formatName(firstName, lastName, 0); } + @NonNull public static String formatName(String firstName, String lastName, int maxLength) { /*if ((firstName == null || firstName.length() == 0) && (lastName == null || lastName.length() == 0)) { return LocaleController.getString("HiddenName", R.string.HiddenName); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index b52a05a47..1bf6c8537 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1376,6 +1376,14 @@ public class DatabaseMigrationHelper { version = 134; } + if (version == 134) { + database.executeFast("DROP TABLE user_photos").stepThis().dispose(); + database.executeFast("CREATE TABLE dialog_photos(uid INTEGER, id INTEGER, num INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); + database.executeFast("CREATE TABLE dialog_photos_count(uid INTEGER PRIMARY KEY, count INTEGER)").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 135").stepThis().dispose(); + version = 135; + } + return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index c1150ea12..f19eecc69 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -535,14 +535,14 @@ public class Emoji { } public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, boolean createNew) { - return replaceEmoji(cs, fontMetrics, AndroidUtilities.dp(16), createNew, null); + return replaceEmoji(cs, fontMetrics, createNew, null); } public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew) { - return replaceEmoji(cs, fontMetrics, size, createNew, null); + return replaceEmoji(cs, fontMetrics, createNew, null); } - public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly) { + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, boolean createNew, int[] emojiOnly) { return replaceEmoji(cs, fontMetrics, createNew, emojiOnly, DynamicDrawableSpan.ALIGN_BOTTOM); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 7f14790c7..8b4fe0f7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -8,15 +8,12 @@ package org.telegram.messenger; -import android.os.Build; - -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.utils.ImmutableByteArrayOutputStream; 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_stories; import org.telegram.ui.LaunchActivity; import org.telegram.ui.Storage.CacheModel; @@ -783,7 +780,7 @@ public class FileLoadOperation { public boolean start(final FileLoadOperationStream stream, final long streamOffset, final boolean streamPriority) { startTime = System.currentTimeMillis(); updateParams(); - isStory = parentObject instanceof TLRPC.TL_storyItem; + isStory = parentObject instanceof TL_stories.TL_storyItem; if (currentDownloadChunkSize == 0) { if (forceSmallChunk) { if (BuildVars.LOGS_ENABLED) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index 5de954d13..9f4fa3c08 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -13,6 +13,7 @@ import android.util.SparseArray; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.LaunchActivity; import java.io.File; @@ -69,8 +70,8 @@ public class FileLoader extends BaseController { fileMeta.messageType = messageObject.type; fileMeta.messageSize = messageObject.getSize(); return fileMeta; - } else if (parentObject instanceof TLRPC.StoryItem) { - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) parentObject; + } else if (parentObject instanceof TL_stories.StoryItem) { + TL_stories.StoryItem storyItem = (TL_stories.StoryItem) parentObject; FilePathDatabase.FileMeta fileMeta = new FilePathDatabase.FileMeta(); fileMeta.dialogId = storyItem.dialogId; fileMeta.messageType = MessageObject.TYPE_STORY; @@ -824,9 +825,10 @@ public class FileLoader extends BaseController { type = MEDIA_DIR_DOCUMENT; } } + FileLoaderPriorityQueue loaderQueue; int index = Utilities.clamp(operation.getDatacenterId() - 1, 4, 0); - boolean isStory = parentObject instanceof TLRPC.StoryItem; + boolean isStory = parentObject instanceof TL_stories.StoryItem; if (operation.totalBytesCount > 20 * 1024 * 1024 || isStory) { loaderQueue = largeFilesQueue[index]; } else { @@ -982,15 +984,15 @@ public class FileLoader extends BaseController { loaderQueue.checkLoadingOperations(operation.isStory && priority >= PRIORITY_HIGH); if (BuildVars.LOGS_ENABLED) { - FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); + FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + " size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); } return operation; } - private boolean canSaveAsFile(Object parentObject) { + public static boolean canSaveAsFile(Object parentObject) { if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; - if (!messageObject.isDocument()) { + if (!messageObject.isDocument() || messageObject.isRoundVideo() || messageObject.isVoice()) { return false; } return true; @@ -1169,10 +1171,6 @@ public class FileLoader extends BaseController { } public File getPathToMessage(TLRPC.Message message, boolean useFileDatabaseQueue) { - return getPathToMessage(message, useFileDatabaseQueue, false); - } - - public File getPathToMessage(TLRPC.Message message, boolean useFileDatabaseQueue, boolean saveAsFile) { if (message == null) { return new File(""); } @@ -1188,7 +1186,7 @@ public class FileLoader extends BaseController { } } else { if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaDocument) { - return getPathToAttach(MessageObject.getMedia(message).document, null,null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue, saveAsFile); + return getPathToAttach(MessageObject.getMedia(message).document, null, MessageObject.getMedia(message).ttl_seconds != 0, useFileDatabaseQueue); } else if (MessageObject.getMedia(message) instanceof TLRPC.TL_messageMediaPhoto) { ArrayList sizes = MessageObject.getMedia(message).photo.sizes; if (sizes.size() > 0) { @@ -1225,22 +1223,21 @@ public class FileLoader extends BaseController { } public File getPathToAttach(TLObject attach, String ext, boolean forceCache) { - return getPathToAttach(attach, null, ext, forceCache, true, false); + return getPathToAttach(attach, null, ext, forceCache, true); } public File getPathToAttach(TLObject attach, String ext, boolean forceCache, boolean useFileDatabaseQueue) { - return getPathToAttach(attach, null, ext, forceCache, useFileDatabaseQueue, false); + return getPathToAttach(attach, null, ext, forceCache, useFileDatabaseQueue); } /** * Return real file name. Used before file.exist() */ - public File getPathToAttach(TLObject attach, String size, String ext, boolean forceCache, boolean useFileDatabaseQueue, boolean saveAsFile) { + public File getPathToAttach(TLObject attach, String size, String ext, boolean forceCache, boolean useFileDatabaseQueue) { File dir = null; long documentId = 0; int dcId = 0; int type = 0; - String fileName = null; if (forceCache) { dir = getDirectory(MEDIA_DIR_CACHE); } else { @@ -1257,13 +1254,7 @@ public class FileLoader extends BaseController { } else if (MessageObject.isVideoDocument(document)) { type = MEDIA_DIR_VIDEO; } else { - String documentFileName = getDocumentFileName(document); - if (saveAsFile && !TextUtils.isEmpty(documentFileName)) { - fileName = documentFileName; - type = MEDIA_DIR_FILES; - } else { - type = MEDIA_DIR_DOCUMENT; - } + type = MEDIA_DIR_DOCUMENT; } } documentId = document.id; @@ -1334,10 +1325,7 @@ public class FileLoader extends BaseController { return new File(path); } } - if (fileName == null) { - fileName = getAttachFileName(attach, ext); - } - return new File(dir, fileName); + return new File(dir, getAttachFileName(attach, ext)); } public FilePathDatabase getFileDatabase() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index df4506643..7cea675b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -2,15 +2,14 @@ package org.telegram.messenger; import android.os.SystemClock; -import org.checkerframework.checker.units.qual.A; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; public class FileRefController extends BaseController { @@ -70,8 +69,8 @@ public class FileRefController extends BaseController { } public static String getKeyForParentObject(Object parentObject) { - if (parentObject instanceof TLRPC.StoryItem) { - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) parentObject; + if (parentObject instanceof TL_stories.StoryItem) { + TL_stories.StoryItem storyItem = (TL_stories.StoryItem) parentObject; if (storyItem.dialogId == 0) { FileLog.d("failed request reference can't find dialogId"); return null; @@ -134,8 +133,8 @@ public class FileRefController extends BaseController { if (BuildVars.LOGS_ENABLED) { FileLog.d("start loading request reference parent " + getObjectString(parentObject) + " args = " + args[0]); } - if (args[0] instanceof TLRPC.TL_storyItem) { - TLRPC.TL_storyItem storyItem = (TLRPC.TL_storyItem) args[0]; + if (args[0] instanceof TL_stories.TL_storyItem) { + TL_stories.TL_storyItem storyItem = (TL_stories.TL_storyItem) args[0]; locationKey = "story_" + storyItem.id; location = new TLRPC.TL_inputDocumentFileLocation(); location.id = storyItem.media.document.id; @@ -326,8 +325,8 @@ public class FileRefController extends BaseController { if (parentObject instanceof String) { return (String) parentObject; } - if (parentObject instanceof TLRPC.StoryItem) { - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) parentObject; + if (parentObject instanceof TL_stories.StoryItem) { + TL_stories.StoryItem storyItem = (TL_stories.StoryItem) parentObject; return "story(dialogId=" + storyItem.dialogId + " id=" + storyItem.id + ")"; } if (parentObject instanceof MessageObject) { @@ -349,9 +348,9 @@ public class FileRefController extends BaseController { } private void requestReferenceFromServer(Object parentObject, String locationKey, String parentKey, Object[] args) { - if (parentObject instanceof TLRPC.StoryItem) { - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) parentObject; - TLRPC.TL_stories_getStoriesByID req = new TLRPC.TL_stories_getStoriesByID(); + if (parentObject instanceof TL_stories.StoryItem) { + TL_stories.StoryItem storyItem = (TL_stories.StoryItem) parentObject; + TL_stories.TL_stories_getStoriesByID req = new TL_stories.TL_stories_getStoriesByID(); req.peer = getMessagesController().getInputPeer(storyItem.dialogId); req.id.add(storyItem.id); getConnectionsManager().sendRequest(req, (response, error) -> { @@ -546,8 +545,8 @@ public class FileRefController extends BaseController { if (BuildVars.DEBUG_VERSION) { FileLog.d("fileref updated for " + requester.args[0] + " " + requester.locationKey); } - if (requester.args[0] instanceof TLRPC.TL_storyItem) { - TLRPC.TL_storyItem storyItem = (TLRPC.TL_storyItem) requester.args[0]; + if (requester.args[0] instanceof TL_stories.TL_storyItem) { + TL_stories.TL_storyItem storyItem = (TL_stories.TL_storyItem) requester.args[0]; storyItem.media.document.file_reference = file_reference; return true; } else if (requester.args[0] instanceof TLRPC.TL_inputSingleMedia) { @@ -917,6 +916,11 @@ public class FileRefController extends BaseController { result = getFileReference(appUpdate.sticker, requester.location, needReplacement, locationReplacement); } */ + } else if (response instanceof TLRPC.TL_messages_webPage) { + TLRPC.TL_messages_webPage res = (TLRPC.TL_messages_webPage) response; + getMessagesController().putChats(res.chats, false); + getMessagesController().putUsers(res.users, false); + result = getFileReference(res.webpage, requester.location, needReplacement, locationReplacement); } else if (response instanceof TLRPC.WebPage) { result = getFileReference((TLRPC.WebPage) response, requester.location, needReplacement, locationReplacement); } else if (response instanceof TLRPC.TL_account_wallPapers) { @@ -1044,11 +1048,11 @@ public class FileRefController extends BaseController { break; } } - } else if (response instanceof TLRPC.TL_stories_stories) { - TLRPC.TL_stories_stories stories = (TLRPC.TL_stories_stories) response; - TLRPC.StoryItem newStoryItem = null; + } else if (response instanceof TL_stories.TL_stories_stories) { + TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; + TL_stories.StoryItem newStoryItem = null; if (!stories.stories.isEmpty()) { - TLRPC.StoryItem storyItem = stories.stories.get(0); + TL_stories.StoryItem storyItem = stories.stories.get(0); if (storyItem.media != null) { newStoryItem = storyItem; if (storyItem.media.photo != null) { @@ -1062,12 +1066,12 @@ public class FileRefController extends BaseController { Object arg = requester.args[1]; if (arg instanceof FileLoadOperation) { FileLoadOperation operation = (FileLoadOperation) requester.args[1]; - if (operation.parentObject instanceof TLRPC.StoryItem) { - TLRPC.StoryItem storyItem = (TLRPC.StoryItem) operation.parentObject; + if (operation.parentObject instanceof TL_stories.StoryItem) { + TL_stories.StoryItem storyItem = (TL_stories.StoryItem) operation.parentObject; if (newStoryItem == null) { - TLRPC.TL_updateStory story = new TLRPC.TL_updateStory(); + TL_stories.TL_updateStory story = new TL_stories.TL_updateStory(); story.peer = getMessagesController().getPeer(storyItem.dialogId); - story.story = new TLRPC.TL_storyItemDeleted(); + story.story = new TL_stories.TL_storyItemDeleted(); story.story.id = storyItem.id; ArrayList updates = new ArrayList<>(); updates.add(story); @@ -1079,7 +1083,7 @@ public class FileRefController extends BaseController { } } if (newStoryItem != null && result == null) { - TLRPC.TL_updateStory updateStory = new TLRPC.TL_updateStory(); + TL_stories.TL_updateStory updateStory = new TL_stories.TL_updateStory(); updateStory.peer = MessagesController.getInstance(currentAccount).getPeer(storyItem.dialogId); updateStory.story = newStoryItem; ArrayList updates = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ForwardingMessagesParams.java b/TMessagesProj/src/main/java/org/telegram/messenger/ForwardingMessagesParams.java deleted file mode 100644 index 6454df01a..000000000 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ForwardingMessagesParams.java +++ /dev/null @@ -1,193 +0,0 @@ -package org.telegram.messenger; - -import android.text.TextUtils; -import android.util.LongSparseArray; -import android.util.SparseBooleanArray; - -import org.telegram.tgnet.TLRPC; - -import java.util.ArrayList; - -public class ForwardingMessagesParams { - - public LongSparseArray groupedMessagesMap = new LongSparseArray<>(); - public ArrayList messages; - public ArrayList previewMessages = new ArrayList<>(); - public SparseBooleanArray selectedIds = new SparseBooleanArray(); - public boolean hideForwardSendersName; - public boolean hideCaption; - public boolean hasCaption; - public boolean hasSenders; - public boolean isSecret; - public boolean willSeeSenders; - public boolean multiplyUsers; - public boolean hasSpoilers; - - public ArrayList pollChoosenAnswers = new ArrayList<>(); - - public ForwardingMessagesParams(ArrayList messages, long newDialogId) { - this.messages = messages; - hasCaption = false; - hasSenders = false; - isSecret = DialogObject.isEncryptedDialog(newDialogId); - hasSpoilers = false; - ArrayList hiddenSendersName = new ArrayList<>(); - for (int i = 0; i < messages.size(); i++) { - MessageObject messageObject = messages.get(i); - if (!TextUtils.isEmpty(messageObject.caption)) { - hasCaption = true; - } - selectedIds.put(messageObject.getId(), true); - - TLRPC.Message message = new TLRPC.TL_message(); - message.id = messageObject.messageOwner.id; - message.grouped_id = messageObject.messageOwner.grouped_id; - message.peer_id = messageObject.messageOwner.peer_id; - message.from_id = messageObject.messageOwner.from_id; - message.message = messageObject.messageOwner.message; - message.media = messageObject.messageOwner.media; - message.action = messageObject.messageOwner.action; - message.edit_date = 0; - if (messageObject.messageOwner.entities != null) { - message.entities.addAll(messageObject.messageOwner.entities); - if (!hasSpoilers) { - for (TLRPC.MessageEntity e : message.entities) { - if (e instanceof TLRPC.TL_messageEntitySpoiler) { - hasSpoilers = true; - break; - } - } - } - } - - message.out = true; - message.unread = false; - message.via_bot_id = messageObject.messageOwner.via_bot_id; - message.reply_markup = messageObject.messageOwner.reply_markup; - message.post = messageObject.messageOwner.post; - message.legacy = messageObject.messageOwner.legacy; - message.restriction_reason = messageObject.messageOwner.restriction_reason; - message.replyMessage = messageObject.messageOwner.replyMessage; - - TLRPC.MessageFwdHeader header = null; - - long clientUserId = UserConfig.getInstance(messageObject.currentAccount).clientUserId; - if (!isSecret) { - if (messageObject.messageOwner.fwd_from != null) { - header = messageObject.messageOwner.fwd_from; - if (!messageObject.isDice()) { - hasSenders = true; - } else { - willSeeSenders = true; - } - if (header.from_id == null && !hiddenSendersName.contains(header.from_name)) { - hiddenSendersName.add(header.from_name); - } - } else if (messageObject.messageOwner.from_id.user_id == 0 || messageObject.messageOwner.dialog_id != clientUserId || messageObject.messageOwner.from_id.user_id != clientUserId) { - header = new TLRPC.TL_messageFwdHeader(); - header.from_id = messageObject.messageOwner.from_id; - if (!messageObject.isDice()) { - hasSenders = true; - } else { - willSeeSenders = true; - } - } - } - - if (header != null) { - message.fwd_from = header; - message.flags |= TLRPC.MESSAGE_FLAG_FWD; - } - message.dialog_id = newDialogId; - - MessageObject previewMessage = new MessageObject(messageObject.currentAccount, message, true, false) { - @Override - public boolean needDrawForwarded() { - if (hideForwardSendersName) { - return false; - } - return super.needDrawForwarded(); - } - }; - previewMessage.preview = true; - if (previewMessage.getGroupId() != 0) { - MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(previewMessage.getGroupId(), null); - if (groupedMessages == null) { - groupedMessages = new MessageObject.GroupedMessages(); - groupedMessagesMap.put(previewMessage.getGroupId(), groupedMessages); - } - groupedMessages.messages.add(previewMessage); - } - previewMessages.add(0, previewMessage); - - if (messageObject.isPoll()) { - TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; - PreviewMediaPoll newMediaPoll = new PreviewMediaPoll(); - newMediaPoll.poll = mediaPoll.poll; - newMediaPoll.provider = mediaPoll.provider; - newMediaPoll.results = new TLRPC.TL_pollResults(); - newMediaPoll.totalVotersCached = newMediaPoll.results.total_voters = mediaPoll.results.total_voters; - - previewMessage.messageOwner.media = newMediaPoll; - - if (messageObject.canUnvote()) { - for (int a = 0, N = mediaPoll.results.results.size(); a < N; a++) { - TLRPC.TL_pollAnswerVoters answer = mediaPoll.results.results.get(a); - if (answer.chosen) { - TLRPC.TL_pollAnswerVoters newAnswer = new TLRPC.TL_pollAnswerVoters(); - newAnswer.chosen = answer.chosen; - newAnswer.correct = answer.correct; - newAnswer.flags = answer.flags; - newAnswer.option = answer.option; - newAnswer.voters = answer.voters; - pollChoosenAnswers.add(newAnswer); - newMediaPoll.results.results.add(newAnswer); - } else { - newMediaPoll.results.results.add(answer); - } - } - } - } - } - - ArrayList uids = new ArrayList<>(); - for (int a = 0; a < messages.size(); a++) { - MessageObject object = messages.get(a); - long uid; - if (object.isFromUser()) { - uid = object.messageOwner.from_id.user_id; - } else { - TLRPC.Chat chat = MessagesController.getInstance(object.currentAccount).getChat(object.messageOwner.peer_id.channel_id); - if (ChatObject.isChannel(chat) && chat.megagroup && object.isForwardedChannelPost()) { - uid = -object.messageOwner.fwd_from.from_id.channel_id; - } else { - uid = -object.messageOwner.peer_id.channel_id; - } - } - if (!uids.contains(uid)) { - uids.add(uid); - } - } - if (uids.size() + hiddenSendersName.size() > 1) { - multiplyUsers = true; - } - for (int i = 0; i < groupedMessagesMap.size(); i++) { - groupedMessagesMap.valueAt(i).calculate(); - } - } - - public void getSelectedMessages(ArrayList messagesToForward) { - messagesToForward.clear(); - for (int i = 0; i < messages.size(); i++) { - MessageObject messageObject = messages.get(i); - int id = messageObject.getId(); - if (selectedIds.get(id, false)) { - messagesToForward.add(messageObject); - } - } - } - - public class PreviewMediaPoll extends TLRPC.TL_messageMediaPoll { - public int totalVotersCached; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index e0e3530d1..bdec42be0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -32,6 +32,7 @@ import android.os.Environment; import android.os.SystemClock; import android.provider.MediaStore; import android.text.TextUtils; +import android.util.Log; import android.util.Pair; import android.util.SparseArray; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 271d2f888..8e7243c1b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -2308,7 +2308,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } } - public void setImageX(int x) { + public void setImageX(float x) { imageX = x; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java index aa6306257..c48221982 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java @@ -108,11 +108,12 @@ public class LiteMode { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public static int getBatteryLevel() { - if (lastBatteryLevelCached < 0 || System.currentTimeMillis() - lastBatteryLevelChecked > 1000 * 12) { + long time = 0; + if (lastBatteryLevelCached < 0 || (time = System.currentTimeMillis()) - lastBatteryLevelChecked > 1000 * 12) { BatteryManager batteryManager = (BatteryManager) ApplicationLoader.applicationContext.getSystemService(Context.BATTERY_SERVICE); if (batteryManager != null) { lastBatteryLevelCached = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); - lastBatteryLevelChecked = System.currentTimeMillis(); + lastBatteryLevelChecked = time; } } return lastBatteryLevelCached; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index a10fb2e2a..6e535f926 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -71,6 +71,10 @@ public class LocaleController { public FastDateFormat formatterScheduleDay; public FastDateFormat formatterScheduleYear; public FastDateFormat formatterMonthYear; + public FastDateFormat formatterGiveawayCard; + public FastDateFormat formatterBoostExpired; + public FastDateFormat formatterGiveawayMonthDay; + public FastDateFormat formatterGiveawayMonthDayYear; public FastDateFormat[] formatterScheduleSend = new FastDateFormat[15]; private static HashMap resourcesCacheMap = new HashMap<>(); @@ -1914,6 +1918,10 @@ public class LocaleController { || currentLocaleInfo != null && currentLocaleInfo.isRtl; nameDisplayOrder = lang.equals("ko") ? 2 : 1; + formatterBoostExpired = createFormatter(locale, getStringInternal("formatterBoostExpired", R.string.formatterBoostExpired), "MMM dd, yyyy"); + formatterGiveawayCard = createFormatter(locale, getStringInternal("formatterGiveawayCard", R.string.formatterGiveawayCard), "dd MMM yyyy"); + formatterGiveawayMonthDay = createFormatter(locale, getStringInternal("formatterGiveawayMonthDay", R.string.formatterGiveawayMonthDay), "MMMM dd"); + formatterGiveawayMonthDayYear = createFormatter(locale, getStringInternal("formatterGiveawayMonthDayYear", R.string.formatterGiveawayMonthDayYear), "MMMM dd, yyyy"); formatterMonthYear = createFormatter(locale, getStringInternal("formatterMonthYear", R.string.formatterMonthYear), "MMM yyyy"); formatterDayMonth = createFormatter(locale, getStringInternal("formatterMonth", R.string.formatterMonth), "dd MMM"); formatterYear = createFormatter(locale, getStringInternal("formatterYear", R.string.formatterYear), "dd.MM.yy"); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 4fb4d54e5..8d1715f3c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -74,6 +74,7 @@ import org.telegram.tgnet.AbstractSerializedData; 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.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -129,6 +130,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return false; } + public VideoConvertMessage getCurrentForegroundConverMessage() { + return currentForegroundConvertingVideo; + } + private static class AudioBuffer { public AudioBuffer(int capacity) { buffer = ByteBuffer.allocateDirect(capacity); @@ -490,6 +495,21 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, this.hasSpoiler = state instanceof PhotoEntry && ((PhotoEntry) state).hasSpoiler; } + public PhotoEntry clone() { + PhotoEntry photoEntry = new PhotoEntry(bucketId, imageId, dateTaken, path, isVideo ? duration : orientation, isVideo, width, height, size); + photoEntry.invert = invert; + photoEntry.isMuted = isMuted; + photoEntry.canDeleteAfter = canDeleteAfter; + photoEntry.hasSpoiler = hasSpoiler; + photoEntry.isChatPreviewSpoilerRevealed = isChatPreviewSpoilerRevealed; + photoEntry.isAttachSpoilerRevealed = isAttachSpoilerRevealed; + photoEntry.emojiMarkup = emojiMarkup; + photoEntry.gradientTopColor = gradientTopColor; + photoEntry.gradientBottomColor = gradientBottomColor; + photoEntry.copyFrom(this); + return photoEntry; + } + @Override public String getPath() { return path; @@ -559,6 +579,26 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return imageUrl; } } + + public SearchImage clone() { + SearchImage searchImage = new SearchImage(); + searchImage.id = id; + searchImage.imageUrl = imageUrl; + searchImage.thumbUrl = thumbUrl; + searchImage.width = width; + searchImage.height = height; + searchImage.size = size; + searchImage.type = type; + searchImage.date = date; + searchImage.caption = caption; + searchImage.document = document; + searchImage.photo = photo; + searchImage.photoSize = photoSize; + searchImage.thumbPhotoSize = thumbPhotoSize; + searchImage.inlineResult = inlineResult; + searchImage.params = params; + return searchImage; + } } AudioManager.OnAudioFocusChangeListener audioRecordFocusChangedListener = focusChange -> { @@ -620,7 +660,10 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private static final int AUDIO_FOCUSED = 2; private static final ConcurrentHashMap cachedEncoderBitrates = new ConcurrentHashMap<>(); - private static class VideoConvertMessage { + private ArrayList foregroundConvertingMessages = new ArrayList<>(); + private VideoConvertMessage currentForegroundConvertingVideo; + + public static class VideoConvertMessage { public MessageObject messageObject; public VideoEditedInfo videoEditedInfo; public int currentAccount; @@ -723,7 +766,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private long recordDialogId; private MessageObject recordReplyingMsg; private MessageObject recordReplyingTopMsg; - private TLRPC.StoryItem recordReplyingStory; + private TL_stories.StoryItem recordReplyingStory; private short[] recordSamples = new short[1024]; private long samplesCount; @@ -3743,7 +3786,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return downloadingCurrentMessage; } - public void setReplyingMessage(MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem) { + public void setReplyingMessage(MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem) { recordReplyingMsg = replyToMsg; recordReplyingTopMsg = replyToTopMsg; recordReplyingStory = storyItem; @@ -3765,7 +3808,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } - public void startRecording(int currentAccount, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem replyStory, int guid, boolean manual) { + public void startRecording(int currentAccount, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem replyStory, int guid, boolean manual) { boolean paused = false; if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) { paused = true; @@ -4068,7 +4111,18 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } if (path == null || path.length() == 0) { - path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner, true, !isMusic).toString(); + path = null; + TLRPC.Document document = message.getDocument(); + if (!TextUtils.isEmpty(FileLoader.getDocumentFileName(document)) && 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(); + } } File sourceFile = new File(path); if (!sourceFile.exists()) { @@ -4122,7 +4176,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } if (path == null || path.length() == 0) { - path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner, true, !isMusic).toString(); + path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); } File sourceFile = new File(path); if (!sourceFile.exists()) { @@ -4996,7 +5050,12 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } else if (isEmpty) { new File(messageObject.messageOwner.attachPath).delete(); } - videoConvertQueue.add(new VideoConvertMessage(messageObject, messageObject.videoEditedInfo, withForeground)); + VideoConvertMessage videoConvertMessage = new VideoConvertMessage(messageObject, messageObject.videoEditedInfo, withForeground); + videoConvertQueue.add(videoConvertMessage); + if (videoConvertMessage.foreground) { + foregroundConvertingMessages.add(videoConvertMessage); + checkForegroundConvertMessage(false); + } if (videoConvertQueue.size() == 1) { startVideoConvertFromQueue(); } @@ -5015,7 +5074,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, videoConvertMessage.videoEditedInfo.canceled = true; } } else { - videoConvertQueue.remove(a); + VideoConvertMessage convertMessage = videoConvertQueue.remove(a); + foregroundConvertingMessages.remove(convertMessage); + checkForegroundConvertMessage(true); } break; } @@ -5024,6 +5085,17 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } + private void checkForegroundConvertMessage(boolean cancelled) { + if (!foregroundConvertingMessages.isEmpty()) { + currentForegroundConvertingVideo = foregroundConvertingMessages.get(0); + } else { + currentForegroundConvertingVideo = null; + } + if (currentForegroundConvertingVideo != null || cancelled) { + VideoEncodingService.start(cancelled); + } + } + private boolean startVideoConvertFromQueue() { if (!videoConvertQueue.isEmpty()) { VideoConvertMessage videoConvertMessage = videoConvertQueue.get(0); @@ -5033,28 +5105,6 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, videoEditedInfo.canceled = false; } } - if (videoConvertMessage.foreground) { - MessageObject messageObject = videoConvertMessage.messageObject; - Intent intent = new Intent(ApplicationLoader.applicationContext, VideoEncodingService.class); - intent.putExtra("path", messageObject.messageOwner.attachPath); - intent.putExtra("currentAccount", messageObject.currentAccount); - if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.document != null) { - for (int a = 0; a < messageObject.messageOwner.media.document.attributes.size(); a++) { - TLRPC.DocumentAttribute documentAttribute = messageObject.messageOwner.media.document.attributes.get(a); - if (documentAttribute instanceof TLRPC.TL_documentAttributeAnimated) { - intent.putExtra("gif", true); - break; - } - } - } - if (messageObject.getId() != 0) { - try { - ApplicationLoader.applicationContext.startService(intent); - } catch (Throwable e) { - FileLog.e(e); - } - } - } VideoConvertRunnable.runConversion(videoConvertMessage); return true; } @@ -5156,10 +5206,13 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } AndroidUtilities.runOnUIThread(() -> { if (error || last) { + boolean cancelled = message.videoEditedInfo.canceled; synchronized (videoConvertSync) { message.videoEditedInfo.canceled = false; } videoConvertQueue.remove(message); + foregroundConvertingMessages.remove(message); + checkForegroundConvertMessage(cancelled || error); startVideoConvertFromQueue(); } if (error) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index affe60b6b..825444c39 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -60,11 +60,13 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.EmojiThemes; +import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.ChatThemeBottomSheet; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.StickerSetBulletinLayout; import org.telegram.ui.Components.StickersArchiveAlert; import org.telegram.ui.Components.TextStyleSpan; @@ -5460,6 +5462,7 @@ public class MediaDataController extends BaseController { object.replyMessageObject = messageObject; object.applyTimestampsHighlightForReplyMsg(); object.messageOwner.reply_to = new TLRPC.TL_messageReplyHeader(); + object.messageOwner.reply_to.flags |= 16; object.messageOwner.reply_to.reply_to_msg_id = messageObject.getId(); } } @@ -6153,8 +6156,6 @@ public class MediaDataController extends BaseController { newRun.flags = TextStyleSpan.FLAG_STYLE_STRIKE; } else if (entity instanceof TLRPC.TL_messageEntityUnderline) { newRun.flags = TextStyleSpan.FLAG_STYLE_UNDERLINE; - } else if (entity instanceof TLRPC.TL_messageEntityBlockquote) { - newRun.flags = TextStyleSpan.FLAG_STYLE_QUOTE; } else if (entity instanceof TLRPC.TL_messageEntityBold) { newRun.flags = TextStyleSpan.FLAG_STYLE_BOLD; } else if (entity instanceof TLRPC.TL_messageEntityItalic) { @@ -6257,8 +6258,6 @@ public class MediaDataController extends BaseController { entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityStrike(), spanStart, spanEnd)); if ((flags & TextStyleSpan.FLAG_STYLE_UNDERLINE) != 0) entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityUnderline(), spanStart, spanEnd)); - if ((flags & TextStyleSpan.FLAG_STYLE_QUOTE) != 0) - entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityBlockquote(), spanStart, spanEnd)); } private TLRPC.MessageEntity setEntityStartEnd(TLRPC.MessageEntity entity, int spanStart, int spanEnd) { @@ -6298,8 +6297,16 @@ public class MediaDataController extends BaseController { if (isPre) { int firstChar = start > 0 ? message[0].charAt(start - 1) : 0; boolean replacedFirst = firstChar == ' ' || firstChar == '\n'; + String language = ""; + int firstNewLine = TextUtils.indexOf(message[0], '\n', start + 3); + if (firstNewLine >= 0 && firstNewLine - (start + 3) > 0) { + language = message[0].toString().substring(start + 3, firstNewLine); + } CharSequence startMessage = substring(message[0], 0, start - (replacedFirst ? 1 : 0)); - CharSequence content = substring(message[0], start + 3, index); + int contentStart = start + 3 + language.length() + (!language.isEmpty() ? 1 : 0); + if (contentStart < 0 || contentStart >= message[0].length() || contentStart > index) + continue; + CharSequence content = substring(message[0], contentStart, index); firstChar = index + 3 < message[0].length() ? message[0].charAt(index + 3) : 0; CharSequence endMessage = substring(message[0], index + 3 + (firstChar == ' ' || firstChar == '\n' ? 1 : 0), message[0].length()); if (startMessage.length() != 0) { @@ -6307,15 +6314,18 @@ public class MediaDataController extends BaseController { } else { replacedFirst = true; } - if (endMessage.length() != 0) { + if (endMessage.length() > 0 && endMessage.charAt(0) != '\n') { endMessage = AndroidUtilities.concat("\n", endMessage); } + if (content.length() > 0 && content.charAt(content.length() - 1) == '\n') { + content = substring(content, 0, content.length() - 1); + } if (!TextUtils.isEmpty(content)) { message[0] = AndroidUtilities.concat(startMessage, content, endMessage); TLRPC.TL_messageEntityPre entity = new TLRPC.TL_messageEntityPre(); entity.offset = start + (replacedFirst ? 0 : 1); - entity.length = index - start - 3 + (replacedFirst ? 0 : 1); - entity.language = ""; + entity.length = index - start - 3 - (language.length() + (!language.isEmpty() ? 1 : 0)) + (replacedFirst ? 0 : 1); + entity.language = language; entities.add(entity); lastIndex -= 6; } @@ -6421,6 +6431,47 @@ public class MediaDataController extends BaseController { } } + CodeHighlighting.Span[] codeSpans = spannable.getSpans(0, message[0].length(), CodeHighlighting.Span.class); + if (codeSpans != null && codeSpans.length > 0) { + if (entities == null) { + entities = new ArrayList<>(); + } + for (int b = 0; b < codeSpans.length; ++b) { + CodeHighlighting.Span span = codeSpans[b]; + if (span != null) { + try { + TLRPC.TL_messageEntityPre entity = new TLRPC.TL_messageEntityPre(); + entity.offset = spannable.getSpanStart(span); + entity.length = Math.min(spannable.getSpanEnd(span), message[0].length()) - entity.offset; + entity.language = span.lng; + entities.add(entity); + } catch (Exception e) { + FileLog.e(e); + } + } + } + } + + QuoteSpan[] quoteSpans = spannable.getSpans(0, message[0].length(), QuoteSpan.class); + if (quoteSpans != null && quoteSpans.length > 0) { + if (entities == null) { + entities = new ArrayList<>(); + } + for (int b = 0; b < quoteSpans.length; ++b) { + QuoteSpan span = quoteSpans[b]; + if (span != null) { + try { + TLRPC.TL_messageEntityBlockquote entity = new TLRPC.TL_messageEntityBlockquote(); + entity.offset = spannable.getSpanStart(span); + entity.length = Math.min(spannable.getSpanEnd(span), message[0].length()) - entity.offset; + entities.add(entity); + } catch (Exception e) { + FileLog.e(e); + } + } + } + } + if (spannable instanceof Spannable) { AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS, false, false); URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class); @@ -6468,6 +6519,17 @@ public class MediaDataController extends BaseController { allowEntity = false; } } + if (allowEntity) { + // check if it is inside a code block: do not convert __ ** || to styles inside code + for (int i = 0; i < entities.size(); ++i) { + if (entities.get(i) instanceof TLRPC.TL_messageEntityPre) { + if (AndroidUtilities.intersect1d(m.start() - offset, m.end() - offset, entities.get(i).offset, entities.get(i).offset + entities.get(i).length)) { + allowEntity = false; + break; + } + } + } + } if (allowEntity) { cs = cs.subSequence(0, m.start() - offset) + gr + cs.subSequence(m.end() - offset, cs.length()); @@ -6572,10 +6634,10 @@ public class MediaDataController extends BaseController { } public void saveDraft(long dialogId, int threadId, CharSequence message, ArrayList entities, TLRPC.Message replyToMessage, boolean noWebpage) { - saveDraft(dialogId, threadId, message, entities, replyToMessage, noWebpage, false); + saveDraft(dialogId, threadId, message, entities, replyToMessage, null, noWebpage, false); } - public void saveDraft(long dialogId, int threadId, CharSequence message, ArrayList entities, TLRPC.Message replyToMessage, boolean noWebpage, boolean clean) { + public void saveDraft(long dialogId, int threadId, CharSequence message, ArrayList entities, TLRPC.Message replyToMessage, ChatActivity.ReplyQuote quote, boolean noWebpage, boolean clean) { TLRPC.DraftMessage draftMessage; if (getMessagesController().isForum(dialogId) && threadId == 0) { replyToMessage = null; @@ -6589,8 +6651,28 @@ public class MediaDataController extends BaseController { draftMessage.message = message == null ? "" : message.toString(); draftMessage.no_webpage = noWebpage; if (replyToMessage != null) { - draftMessage.reply_to_msg_id = replyToMessage.id; - draftMessage.flags |= 1; + draftMessage.reply_to = new TLRPC.TL_inputReplyToMessage(); + draftMessage.flags |= 16; + draftMessage.reply_to.reply_to_msg_id = replyToMessage.id; + if (quote != null) { + draftMessage.reply_to.quote_text = quote.getText(); + if (draftMessage.reply_to.quote_text != null) { + draftMessage.reply_to.flags |= 64; + } + draftMessage.reply_to.quote_entities = quote.getEntities(); + if (draftMessage.reply_to.quote_entities != null && !draftMessage.reply_to.quote_entities.isEmpty()) { + draftMessage.reply_to.quote_entities = new ArrayList<>(draftMessage.reply_to.quote_entities); + draftMessage.reply_to.flags |= 128; + } + if (quote.message != null && quote.message.messageOwner != null) { + TLRPC.Peer peer2 = getMessagesController().getPeer(dialogId); + TLRPC.Peer thisPeer = quote.message.messageOwner.peer_id; + if (peer2 != null && !MessageObject.peersEqual(peer2, thisPeer)) { + draftMessage.reply_to.flags |= 1; + draftMessage.reply_to.reply_to_peer_id = getMessagesController().getInputPeer(peer2); + } + } + } } if (entities != null && !entities.isEmpty()) { draftMessage.entities = entities; @@ -6600,8 +6682,10 @@ public class MediaDataController extends BaseController { SparseArray threads = drafts.get(dialogId); TLRPC.DraftMessage currentDraft = threads == null ? null : threads.get(threadId); if (!clean) { - if (currentDraft != null && currentDraft.message.equals(draftMessage.message) && currentDraft.reply_to_msg_id == draftMessage.reply_to_msg_id && currentDraft.no_webpage == draftMessage.no_webpage || - currentDraft == null && TextUtils.isEmpty(draftMessage.message) && draftMessage.reply_to_msg_id == 0) { + if ( + currentDraft != null && currentDraft.message.equals(draftMessage.message) && replyToEquals(currentDraft.reply_to, draftMessage.reply_to) && currentDraft.no_webpage == draftMessage.no_webpage || + currentDraft == null && TextUtils.isEmpty(draftMessage.message) && (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) + ) { return; } } @@ -6615,14 +6699,16 @@ public class MediaDataController extends BaseController { if (req.peer == null) { return; } - if (threadId != 0) { - req.top_msg_id = threadId; - } req.message = draftMessage.message; req.no_webpage = draftMessage.no_webpage; - req.reply_to_msg_id = draftMessage.reply_to_msg_id; - req.entities = draftMessage.entities; - req.flags = draftMessage.flags; + req.reply_to = draftMessage.reply_to; + if (req.reply_to != null) { + req.flags |= 16; + } + if ((draftMessage.flags & 8) != 0) { + req.entities = draftMessage.entities; + req.flags |= 8; + } getConnectionsManager().sendRequest(req, (response, error) -> { }); @@ -6632,9 +6718,65 @@ public class MediaDataController extends BaseController { } } + private static boolean replyToEquals(TLRPC.InputReplyTo a, TLRPC.InputReplyTo b) { + if (a == b) { + return true; + } + if (a instanceof TLRPC.TL_inputReplyToMessage != b instanceof TLRPC.TL_inputReplyToMessage) { + return false; + } + if (a instanceof TLRPC.TL_inputReplyToMessage) { + if (!MessageObject.peersEqual(a.reply_to_peer_id, b.reply_to_peer_id)) { + return false; + } + if (!TextUtils.equals(a.quote_text, b.quote_text)) { + return false; + } + return a.reply_to_msg_id == b.reply_to_msg_id; + } + if (a instanceof TLRPC.TL_inputReplyToStory) { + return a.user_id == b.user_id && a.story_id == b.story_id; + } + return true; + } + + private static TLRPC.InputReplyTo toInputReplyTo(int currentAccount, TLRPC.MessageReplyHeader reply_to) { + if (reply_to instanceof TLRPC.TL_messageReplyStoryHeader) { + TLRPC.TL_inputReplyToStory inputReplyTo = new TLRPC.TL_inputReplyToStory(); + inputReplyTo.user_id = MessagesController.getInstance(currentAccount).getInputUser(reply_to.user_id); + inputReplyTo.story_id = reply_to.story_id; + return inputReplyTo; + } else if (reply_to instanceof TLRPC.TL_messageReplyHeader) { + TLRPC.TL_inputReplyToMessage inputReplyTo = new TLRPC.TL_inputReplyToMessage(); + inputReplyTo.reply_to_msg_id = reply_to.reply_to_msg_id; + if ((reply_to.flags & 1) != 0) { + inputReplyTo.reply_to_peer_id = MessagesController.getInstance(currentAccount).getInputPeer(reply_to.reply_to_peer_id); + if (inputReplyTo.reply_to_peer_id != null) { + inputReplyTo.flags |= 2; + } + } + if ((reply_to.flags & 2) != 0) { + inputReplyTo.flags |= 1; + inputReplyTo.top_msg_id = reply_to.reply_to_top_id; + } + if ((reply_to.flags & 64) != 0) { + inputReplyTo.flags |= 4; + inputReplyTo.quote_text = reply_to.quote_text; + } + if ((reply_to.flags & 128) != 0) { + inputReplyTo.flags |= 8; + inputReplyTo.quote_entities = reply_to.quote_entities; + } + return inputReplyTo; + } + return null; + } + public void saveDraft(long dialogId, int threadId, TLRPC.DraftMessage draft, TLRPC.Message replyToMessage, boolean fromServer) { if (getMessagesController().isForum(dialogId) && threadId == 0 && TextUtils.isEmpty(draft.message)) { - draft.reply_to_msg_id = 0; + if (draft.reply_to instanceof TLRPC.TL_inputReplyToMessage) { + ((TLRPC.TL_inputReplyToMessage) draft.reply_to).reply_to_msg_id = 0; + } } SharedPreferences.Editor editor = draftPreferences.edit(); MessagesController messagesController = getMessagesController(); @@ -6683,6 +6825,16 @@ public class MediaDataController extends BaseController { } } SparseArray threads = draftMessages.get(dialogId); + if (replyToMessage == null && draft != null && draft.reply_to != null) { + if (threads != null) { + replyToMessage = threads.get(threadId); + } + if (replyToMessage == null || replyToMessage.id != draft.reply_to.reply_to_msg_id || !MessageObject.peersEqual(replyToMessage.peer_id, getMessagesController().getPeer(draft.reply_to.reply_to_msg_id))) { + replyToMessage = null; + } + } else if (draft != null && draft.reply_to == null) { + replyToMessage = null; + } if (replyToMessage == null) { if (threads != null) { threads.remove(threadId); @@ -6709,7 +6861,7 @@ public class MediaDataController extends BaseController { } editor.commit(); if (fromServer && (threadId == 0 || getMessagesController().isForum(dialogId))) { - if (draft != null && draft.reply_to_msg_id != 0 && replyToMessage == null) { + if (draft != null && draft.reply_to != null && draft.reply_to.reply_to_msg_id != 0 && replyToMessage == null) { TLRPC.User user = null; TLRPC.Chat chat = null; if (DialogObject.isUserDialog(dialogId)) { @@ -6719,7 +6871,7 @@ public class MediaDataController extends BaseController { } if (user != null || chat != null) { long channelId = ChatObject.isChannel(chat) ? chat.id : 0; - int messageId = draft.reply_to_msg_id; + int messageId = draft.reply_to.reply_to_msg_id; getMessagesStorage().getStorageQueue().postRunnable(() -> { try { @@ -6779,7 +6931,7 @@ public class MediaDataController extends BaseController { AndroidUtilities.runOnUIThread(() -> { SparseArray threads = drafts.get(dialogId); TLRPC.DraftMessage draftMessage = threads != null ? threads.get(threadId) : null; - if (draftMessage != null && draftMessage.reply_to_msg_id == message.id) { + if (draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id == message.id) { SparseArray threads2 = draftMessages.get(dialogId); if (threads2 == null) { threads2 = new SparseArray<>(); @@ -6838,10 +6990,12 @@ public class MediaDataController extends BaseController { } else { draftPreferences.edit().remove("t_" + dialogId + "_" + threadId).remove("rt_" + dialogId + "_" + threadId).commit(); } - } else if (draftMessage.reply_to_msg_id != 0) { - draftMessage.reply_to_msg_id = 0; + } else if (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id != 0) { + if (draftMessage.reply_to != null) { + draftMessage.reply_to.reply_to_msg_id = 0; + } draftMessage.flags &= ~1; - saveDraft(dialogId, threadId, draftMessage.message, draftMessage.entities, null, draftMessage.no_webpage, true); + saveDraft(dialogId, threadId, draftMessage.message, draftMessage.entities, null, null, draftMessage.no_webpage, true); } } @@ -7492,10 +7646,10 @@ public class MediaDataController extends BaseController { } public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, final CountDownLatch sync, boolean allowAnimated, boolean allowTopicIcons, boolean includeSingleEmoji, Integer maxAnimatedPerEmoji) { - getEmojiSuggestions(langCodes, keyword, fullMatch, callback, sync, allowAnimated, allowTopicIcons, includeSingleEmoji, false, maxAnimatedPerEmoji); + getEmojiSuggestions(langCodes, keyword, fullMatch, callback, sync, allowAnimated, allowTopicIcons, includeSingleEmoji, false, maxAnimatedPerEmoji, false); } - public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, final CountDownLatch sync, boolean allowAnimated, boolean allowTopicIcons, boolean includeSingleEmoji, boolean forcePremium, Integer maxAnimatedPerEmoji) { + public void getEmojiSuggestions(String[] langCodes, String keyword, boolean fullMatch, KeywordResultCallback callback, final CountDownLatch sync, boolean allowAnimated, boolean allowTopicIcons, boolean includeSingleEmoji, boolean forcePremium, Integer maxAnimatedPerEmoji, boolean includeOnlyTextColor) { if (callback == null) { return; } @@ -7629,8 +7783,8 @@ public class MediaDataController extends BaseController { } }); String aliasFinal = alias; - if (allowAnimated && SharedConfig.suggestAnimatedEmoji) { - fillWithAnimatedEmoji(result, maxAnimatedPerEmoji, allowTopicIcons, forcePremium, () -> { + if (allowAnimated) { + fillWithAnimatedEmoji(result, maxAnimatedPerEmoji, allowTopicIcons, forcePremium, includeOnlyTextColor, () -> { if (sync != null) { callback.run(result, aliasFinal); sync.countDown(); @@ -7658,7 +7812,7 @@ public class MediaDataController extends BaseController { private boolean triedLoadingEmojipacks = false; - public void fillWithAnimatedEmoji(ArrayList result, Integer maxAnimatedPerEmojiInput, boolean allowTopicIcons, boolean forcePremium, Runnable onDone) { + public void fillWithAnimatedEmoji(ArrayList result, Integer maxAnimatedPerEmojiInput, boolean allowTopicIcons, boolean forcePremium, boolean includeOnlyTextColor, Runnable onDone) { if (result == null || result.isEmpty()) { if (onDone != null) { onDone.run(); @@ -8263,4 +8417,42 @@ public class MediaDataController extends BaseController { })); } } + + public TLRPC.TL_emojiList replyIconsDefault; + public void loadReplyIcons() { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("replyicons_" + currentAccount, Context.MODE_PRIVATE); + + String value = preferences.getString("replyicons", null); + long lastCheckTime = preferences.getLong("replyicons_last_check", 0); + + TLRPC.TL_emojiList emojiList = null; + if (value != null) { + SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); + try { + emojiList = (TLRPC.TL_emojiList) TLRPC.TL_emojiList.TLdeserialize(serializedData, serializedData.readInt32(true), true); + replyIconsDefault = emojiList; + } catch (Throwable e) { + FileLog.e(e); + } + } + + if (emojiList == null || (System.currentTimeMillis() - lastCheckTime) > 24 * 60 * 60 * 1000 || BuildVars.DEBUG_PRIVATE_VERSION) { + TLRPC.TL_account_getDefaultBackgroundEmojis req = new TLRPC.TL_account_getDefaultBackgroundEmojis(); + if (emojiList != null) { + req.hash = emojiList.hash; + } + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_emojiList) { + SerializedData data = new SerializedData(response.getObjectSize()); + response.serializeToStream(data); + SharedPreferences.Editor editor = preferences.edit(); + replyIconsDefault = (TLRPC.TL_emojiList) response; + editor.putString("replyicons", Utilities.bytesToHex(data.toByteArray())); + editor.putLong("replyicons_last_check", System.currentTimeMillis()); + + editor.apply(); + } + })); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MemberRequestsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MemberRequestsController.java index dbcd4d90f..2c68fca57 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MemberRequestsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MemberRequestsController.java @@ -1,6 +1,7 @@ package org.telegram.messenger; import android.text.TextUtils; +import android.util.Log; import android.util.LongSparseArray; import androidx.annotation.Nullable; @@ -57,7 +58,8 @@ public class MemberRequestsController extends BaseController { AndroidUtilities.runOnUIThread(() -> { if (error == null) { TLRPC.TL_messages_chatInviteImporters importers = (TLRPC.TL_messages_chatInviteImporters) response; - firstImportersCache.put(chatId, importers); + if (lastImporter == null && isEmptyQuery) + firstImportersCache.put(chatId, importers); } onComplete.run(response, error); }); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 6c9990dc8..d097e1387 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -8,7 +8,12 @@ package org.telegram.messenger; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; @@ -27,7 +32,9 @@ import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.Base64; +import android.util.Pair; +import androidx.annotation.NonNull; import androidx.collection.LongSparseArray; import org.telegram.PhoneFormat.PhoneFormat; @@ -38,13 +45,16 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.Forum.ForumBubbleDrawable; import org.telegram.ui.Components.Forum.ForumUtilities; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; import org.telegram.ui.Components.TextStyleSpan; @@ -70,7 +80,9 @@ import java.util.Calendar; import java.util.Collections; import java.util.GregorianCalendar; import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.TreeSet; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -106,6 +118,8 @@ public class MessageObject { public static final int TYPE_ACTION_WALLPAPER = 22; public static final int TYPE_STORY = 23; public static final int TYPE_STORY_MENTION = 24; + public static final int TYPE_GIFT_PREMIUM_CHANNEL = 25; + public static final int TYPE_GIVEAWAY = 26; public int localType; public String localName; @@ -117,11 +131,12 @@ public class MessageObject { public Boolean cachedIsSupergroup; public boolean localEdit; public TLRPC.Message messageOwner; - public TLRPC.StoryItem storyItem; + public TL_stories.StoryItem storyItem; public TLRPC.Document emojiAnimatedSticker; public Long emojiAnimatedStickerId; public boolean isTopicMainMessage; public boolean settingAvatar; + public boolean flickerLoading; public TLRPC.VideoSize emojiMarkup; private boolean emojiAnimatedStickerLoading; public String emojiAnimatedStickerColor; @@ -189,6 +204,10 @@ public class MessageObject { public boolean sponsoredRecommended; public String sponsoredInfo, sponsoredAdditionalInfo; public TLRPC.TL_sponsoredWebPage sponsoredWebPage; + public boolean replyTextEllipsized; + public boolean replyTextRevealed; + public int overrideLinkColor = -1; + public long overrideLinkEmoji = -1; public TLRPC.TL_forumTopic replyToForumTopic; // used only for reply message in view all messages @@ -209,6 +228,7 @@ public class MessageObject { public boolean scheduled; public boolean preview; + public boolean previewForward; public ArrayList checkedVotes; @@ -231,12 +251,6 @@ public class MessageObject { public boolean forceUpdate; - public int lastLineWidth; - public int textWidth; - public int textHeight; - public boolean hasRtl; - public float textXOffset; - public SendAnimationData sendAnimationData; private boolean hasUnwrappedEmoji; @@ -284,6 +298,7 @@ public class MessageObject { " & ", " . " }; + public boolean forceAvatar; public Drawable customAvatarDrawable; private byte[] randomWaveform; @@ -503,7 +518,7 @@ public class MessageObject { } public boolean isExpiredStory() { - return (type == MessageObject.TYPE_STORY || type == MessageObject.TYPE_STORY_MENTION) && messageOwner.media.storyItem instanceof TLRPC.TL_storyItemDeleted; + return (type == MessageObject.TYPE_STORY || type == MessageObject.TYPE_STORY_MENTION) && messageOwner.media.storyItem instanceof TL_stories.TL_storyItemDeleted; } public static class SendAnimationData { @@ -644,8 +659,11 @@ public class MessageObject { public static class TextLayoutBlock { public final static int FLAG_RTL = 1, FLAG_NOT_RTL = 2; + public boolean first, last; + public AtomicReference spoilersPatchedTextLayout = new AtomicReference<>(); public StaticLayout textLayout; + public int padTop, padBottom; public float textYOffset; public int charactersOffset; public int charactersEnd; @@ -653,6 +671,10 @@ public class MessageObject { public int heightByOffset; public byte directionFlags; public List spoilers = new ArrayList<>(); + public float maxRight; + + public boolean code; + public boolean quote; public boolean isRtl() { return (directionFlags & FLAG_RTL) != 0 && (directionFlags & FLAG_NOT_RTL) == 0; @@ -701,6 +723,7 @@ public class MessageObject { public ArrayList messages = new ArrayList<>(); public ArrayList posArray = new ArrayList<>(); public HashMap positions = new HashMap<>(); + public MessageObject captionMessage; public boolean isDocuments; private int maxSizeWidth = 800; @@ -739,12 +762,16 @@ public class MessageObject { public void calculate() { posArray.clear(); positions.clear(); + captionMessage = null; maxSizeWidth = 800; int firstSpanAdditionalSize = 200; int count = messages.size(); - if (count <= 1) { + if (count == 1) { + captionMessage = messages.get(0); + return; + } else if (count < 1) { return; } @@ -759,6 +786,7 @@ public class MessageObject { hasSibling = false; hasCaption = false; + boolean checkCaption = true; for (int a = 0; a < count; a++) { MessageObject messageObject = messages.get(a); @@ -796,6 +824,12 @@ public class MessageObject { posArray.add(position); if (messageObject.caption != null) { + if (checkCaption && captionMessage == null) { + captionMessage = messageObject; + checkCaption = false; + } else { + captionMessage = null; + } hasCaption = true; } } @@ -827,14 +861,14 @@ public class MessageObject { firstSpanAdditionalSize += 50; } - int minHeight = AndroidUtilities.dp(120); - int minWidth = (int) (AndroidUtilities.dp(120) / (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float) maxSizeWidth)); - int paddingsWidth = (int) (AndroidUtilities.dp(40) / (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float) maxSizeWidth)); + int minHeight = dp(120); + int minWidth = (int) (dp(120) / (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float) maxSizeWidth)); + int paddingsWidth = (int) (dp(40) / (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) / (float) maxSizeWidth)); float maxAspectRatio = maxSizeWidth / maxSizeHeight; averageAspectRatio = averageAspectRatio / count; - float minH = AndroidUtilities.dp(100) / maxSizeHeight; + float minH = dp(100) / maxSizeHeight; if (!forceCalc && (count == 2 || count == 3 || count == 4)) { if (count == 2) { @@ -918,9 +952,9 @@ public class MessageObject { int w0 = (int) Math.max(minWidth, Math.min(maxSizeWidth * 0.4f, h * position2.aspectRatio)); int w2 = (int) Math.max(Math.max(minWidth, maxSizeWidth * 0.33f), h * position4.aspectRatio); int w1 = maxSizeWidth - w0 - w2; - if (w1 < AndroidUtilities.dp(58)) { - int diff = AndroidUtilities.dp(58) - w1; - w1 = AndroidUtilities.dp(58); + if (w1 < dp(58)) { + int diff = dp(58) - w1; + w1 = dp(58); w0 -= diff / 2; w2 -= (diff - diff / 2); } @@ -1123,6 +1157,25 @@ public class MessageObject { return findMessageWithFlags(MessageObject.POSITION_FLAG_TOP | MessageObject.POSITION_FLAG_LEFT); } + public MessageObject findCaptionMessageObject() { + if (!messages.isEmpty() && positions.isEmpty()) { + calculate(); + } + + MessageObject result = null; + for (int i = 0; i < messages.size(); ++i) { + MessageObject object = messages.get(i); + if (!TextUtils.isEmpty(object.caption)) { + if (result != null) { + return null; + } else { + result = object; + } + } + } + return result; + } + public MessageObject findMessageWithFlags(int flags) { if (!messages.isEmpty() && positions.isEmpty()) { calculate(); @@ -1168,14 +1221,38 @@ public class MessageObject { backgroundChangeBounds = false; } } + + public boolean contains(int messageId) { + if (messages == null) { + return false; + } + for (int i = 0; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg != null && msg.getId() == messageId) { + return true; + } + } + return false; + } } private static final int LINES_PER_BLOCK = 10; private static final int LINES_PER_BLOCK_WITH_EMOJI = 5; + public int lastLineWidth; + public int textWidth; + public int textHeight; + public boolean hasRtl; + public float textXOffset; public ArrayList textLayoutBlocks; + public boolean hasCode; + public boolean hasWideCode; + public boolean hasCodeAtTop, hasCodeAtBottom; + public boolean hasQuote; + public boolean hasSingleQuote; + public boolean hasQuoteAtBottom; - public MessageObject(int accountNum, TLRPC.StoryItem storyItem) { + public MessageObject(int accountNum, TL_stories.StoryItem storyItem) { currentAccount = accountNum; this.storyItem = storyItem; if (storyItem != null) { @@ -1278,7 +1355,7 @@ public class MessageObject { if (messageOwner.action == null) { messageText = Utils.fixMessage(messageText); } - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), false, emojiOnly); messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt()); if (emojiOnly != null && emojiOnly[0] > 1) { replaceEmojiToLottieFrame(messageText, emojiOnly); @@ -1406,7 +1483,7 @@ public class MessageObject { } private void checkEmojiOnly(Integer emojiOnly) { - if (emojiOnly != null && emojiOnly >= 1) { + if (emojiOnly != null && emojiOnly >= 1 && messageOwner != null && !hasNonEmojiEntities()) { Emoji.EmojiSpan[] spans = ((Spannable) messageText).getSpans(0, messageText.length(), Emoji.EmojiSpan.class); AnimatedEmojiSpan[] aspans = ((Spannable) messageText).getSpans(0, messageText.length(), AnimatedEmojiSpan.class); emojiOnlyCount = Math.max(emojiOnly, (spans == null ? 0 : spans.length) + (aspans == null ? 0 : aspans.length)); @@ -1423,7 +1500,7 @@ public class MessageObject { if (emojiOnlyCount == 0 || hasUnwrappedEmoji) { if (aspans != null && aspans.length > 0) { for (int a = 0; a < aspans.length; a++) { - aspans[a].replaceFontMetrics(Theme.chat_msgTextPaint.getFontMetricsInt(), (int) (Theme.chat_msgTextPaint.getTextSize() + AndroidUtilities.dp(4)), -1); + aspans[a].replaceFontMetrics(Theme.chat_msgTextPaint.getFontMetricsInt(), (int) (Theme.chat_msgTextPaint.getTextSize() + dp(4)), -1); aspans[a].full = false; } } @@ -1465,7 +1542,7 @@ public class MessageObject { emojiPaint = Theme.chat_msgTextPaintEmoji[5]; break; } - int size = (int) (emojiPaint.getTextSize() + AndroidUtilities.dp(large ? 4 : 4)); + int size = (int) (emojiPaint.getTextSize() + dp(large ? 4 : 4)); if (spans != null && spans.length > 0) { for (int a = 0; a < spans.length; a++) { spans[a].replaceFontMetrics(emojiPaint.getFontMetricsInt(), size); @@ -1482,7 +1559,7 @@ public class MessageObject { if (aspans != null && aspans.length > 0) { totalAnimatedEmojiCount = aspans.length; for (int a = 0; a < aspans.length; a++) { - aspans[a].replaceFontMetrics(Theme.chat_msgTextPaint.getFontMetricsInt(), (int) (Theme.chat_msgTextPaint.getTextSize() + AndroidUtilities.dp(4)), -1); + aspans[a].replaceFontMetrics(Theme.chat_msgTextPaint.getFontMetricsInt(), (int) (Theme.chat_msgTextPaint.getTextSize() + dp(4)), -1); aspans[a].full = false; } } else { @@ -2442,6 +2519,30 @@ public class MessageObject { "un1", fromUser ); + } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeColor) { + TLRPC.TL_channelAdminLogEventActionChangeColor action = (TLRPC.TL_channelAdminLogEventActionChangeColor) event.action; + messageText = replaceWithLink(LocaleController.formatString(R.string.EventLogChangedColor, AvatarDrawable.colorName(action.prev_value).toLowerCase(), AvatarDrawable.colorName(action.new_value).toLowerCase()), "un1", fromUser); + } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji) { + TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji action = (TLRPC.TL_channelAdminLogEventActionChangeBackgroundEmoji) event.action; + messageText = replaceWithLink(LocaleController.getString(R.string.EventLogChangedEmoji), "un1", fromUser); + + SpannableString emoji1; + if (action.prev_value == 0) { + emoji1 = new SpannableString(LocaleController.getString(R.string.EventLogEmojiNone)); + } else { + emoji1 = new SpannableString("e"); + emoji1.setSpan(new AnimatedEmojiSpan(action.prev_value, Theme.chat_actionTextPaint.getFontMetricsInt()), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + messageText = AndroidUtilities.replaceCharSequence("%1$s", messageText, emoji1); + + SpannableString emoji2; + if (action.new_value == 0) { + emoji2 = new SpannableString(LocaleController.getString(R.string.EventLogEmojiNone)); + } else { + emoji2 = new SpannableString("e"); + emoji2.setSpan(new AnimatedEmojiSpan(action.new_value, Theme.chat_actionTextPaint.getFontMetricsInt()), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + messageText = AndroidUtilities.replaceCharSequence("%2$s", messageText, emoji2); } else { messageText = "unsupported " + event.action; } @@ -2519,7 +2620,7 @@ public class MessageObject { } int[] emojiOnly = allowsBigEmoji() ? new int[1] : null; - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), false, emojiOnly); messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt()); if (emojiOnly != null && emojiOnly[0] > 1) { replaceEmojiToLottieFrame(messageText, emojiOnly); @@ -2695,7 +2796,7 @@ public class MessageObject { paint = Theme.chat_msgTextPaint; } int[] emojiOnly = allowsBigEmoji() ? new int[1] : null; - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), false, emojiOnly); messageText = replaceAnimatedEmoji(messageText, entities, paint.getFontMetricsInt()); if (emojiOnly != null && emojiOnly[0] > 1) { replaceEmojiToLottieFrame(messageText, emojiOnly); @@ -2822,7 +2923,7 @@ public class MessageObject { messageText = replaceWithLink(LocaleController.getString("ActionPinnedPhoto", R.string.ActionPinnedPhoto), "un1", fromUser != null ? fromUser : chat); } else if (getMedia(replyMessageObject) instanceof TLRPC.TL_messageMediaGame) { messageText = replaceWithLink(LocaleController.formatString("ActionPinnedGame", R.string.ActionPinnedGame, "\uD83C\uDFAE " + getMedia(replyMessageObject).game.title), "un1", fromUser != null ? fromUser : chat); - messageText = Emoji.replaceEmoji(messageText, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + messageText = Emoji.replaceEmoji(messageText, Theme.chat_msgTextPaint.getFontMetricsInt(), dp(20), false); } else if (replyMessageObject.messageText != null && replyMessageObject.messageText.length() > 0) { CharSequence mess = AnimatedEmojiSpan.cloneSpans(replyMessageObject.messageText); boolean ellipsize = false; @@ -2830,7 +2931,7 @@ public class MessageObject { mess = mess.subSequence(0, 20); ellipsize = true; } - mess = Emoji.replaceEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + mess = Emoji.replaceEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt(), dp(20), false); if (replyMessageObject != null && replyMessageObject.messageOwner != null) { mess = replyMessageObject.replaceAnimatedEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt()); } @@ -3199,19 +3300,19 @@ public class MessageObject { if (str == null) { str = ""; } - text = Emoji.replaceEmoji(str, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + text = Emoji.replaceEmoji(str, Theme.chat_msgBotButtonPaint.getFontMetricsInt(), dp(15), false); } - StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, AndroidUtilities.dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (staticLayout.getLineCount() > 0) { float width = staticLayout.getLineWidth(0); float left = staticLayout.getLineLeft(0); if (left < width) { width -= left; } - maxButtonSize = Math.max(maxButtonSize, (int) Math.ceil(width) + AndroidUtilities.dp(4)); + maxButtonSize = Math.max(maxButtonSize, (int) Math.ceil(width) + dp(4)); } } - wantedBotKeyboardWidth = Math.max(wantedBotKeyboardWidth, (maxButtonSize + AndroidUtilities.dp(12)) * size + AndroidUtilities.dp(5) * (size - 1)); + wantedBotKeyboardWidth = Math.max(wantedBotKeyboardWidth, (maxButtonSize + dp(12)) * size + dp(5) * (size - 1)); } } } @@ -3480,6 +3581,11 @@ public class MessageObject { } else { messageText = replaceWithLink(LocaleController.getString("ActionInviteUser", R.string.ActionInviteUser), "un1", fromObject); } + } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiveawayLaunch) { + TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(chats, sChats, messageOwner.peer_id.channel_id) : null; + messageText = LocaleController.formatString("BoostingGiveawayJustStarted", R.string.BoostingGiveawayJustStarted, chat != null ? chat.title : ""); + } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { + messageText = LocaleController.getString("BoostingReceivedGiftNoName", R.string.BoostingReceivedGiftNoName); } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { if (fromObject instanceof TLRPC.User && ((TLRPC.User) fromObject).self) { TLRPC.User user = getUser(users, sUsers, messageOwner.peer_id.user_id); @@ -3724,7 +3830,7 @@ public class MessageObject { forumTopic.title = createAction.title; forumTopic.icon_color = createAction.icon_color; - messageTextShort = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicWasCreatedAction", R.string.TopicWasCreatedAction), ForumUtilities.getTopicSpannedName(forumTopic, null)); + messageTextShort = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString("TopicWasCreatedAction", R.string.TopicWasCreatedAction), ForumUtilities.getTopicSpannedName(forumTopic, null, false)); } else if (messageOwner.action instanceof TLRPC.TL_messageActionTopicEdit) { TLRPC.TL_messageActionTopicEdit editAction = (TLRPC.TL_messageActionTopicEdit) messageOwner.action; @@ -3766,7 +3872,7 @@ public class MessageObject { forumTopic.title = editAction.title; forumTopic.icon_color = ForumBubbleDrawable.serverSupportedColor[0]; - CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable); + CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable, false); CharSequence str = AndroidUtilities.replaceCharSequence("%1$s", LocaleController.getString("TopicChangeIconAndTitleTo", R.string.TopicChangeIconAndTitleTo), name); messageText = AndroidUtilities.replaceCharSequence("%2$s", str, topicName); messageTextShort = LocaleController.getString("TopicRenamed", R.string.TopicRenamed); @@ -3776,7 +3882,7 @@ public class MessageObject { forumTopic.icon_emoji_id = editAction.icon_emoji_id; forumTopic.title = ""; forumTopic.icon_color = ForumBubbleDrawable.serverSupportedColor[0]; - CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable); + CharSequence topicName = ForumUtilities.getTopicSpannedName(forumTopic, null, topicIconDrawable, false); CharSequence str = AndroidUtilities.replaceCharSequence("%1$s", LocaleController.getString("TopicIconChangedTo", R.string.TopicIconChangedTo), name); messageText = AndroidUtilities.replaceCharSequence("%2$s", str, topicName); messageTextShort = LocaleController.getString("TopicIconChanged", R.string.TopicIconChanged); @@ -3957,7 +4063,10 @@ public class MessageObject { messageText = restrictionReason; isRestrictedMessage = true; } else if (!isMediaEmpty()) { - if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaStory) { +// messageText = getMediaTitle(getMedia(messageOwner)); // I'm afraid doing this + if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGiveaway) { + messageText = LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway); + } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaStory) { if (getMedia(messageOwner).via_mention) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(getMedia(messageOwner).user_id); String link = null, username; @@ -4057,6 +4166,91 @@ public class MessageObject { } } + public CharSequence getMediaTitle(TLRPC.MessageMedia media) { + if (media instanceof TLRPC.TL_messageMediaGiveaway) { + return LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway); + } else if (media instanceof TLRPC.TL_messageMediaStory) { + if (media.via_mention) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(media.user_id); + String link = null, username; + if (user != null && (username = UserObject.getPublicUsername(user)) != null) { + link = MessagesController.getInstance(currentAccount).linkPrefix + "/" + username + "/s/" + media.id; + } + if (link != null) { + SpannableString str = new SpannableString(link); + ((SpannableString) str).setSpan(new URLSpanReplacement("https://" + link, new TextStyleSpan.TextStyleRun()), 0, messageText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return str; + } else { + return ""; + } + } else { + return LocaleController.getString("ForwardedStory", R.string.ForwardedStory); + } + } else if (media instanceof TLRPC.TL_messageMediaDice) { + return getDiceEmoji(); + } else if (media instanceof TLRPC.TL_messageMediaPoll) { + if (((TLRPC.TL_messageMediaPoll) media).poll.quiz) { + return LocaleController.getString("QuizPoll", R.string.QuizPoll); + } else { + return LocaleController.getString("Poll", R.string.Poll); + } + } else if (media instanceof TLRPC.TL_messageMediaPhoto) { + if (media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { + return LocaleController.getString("AttachDestructingPhoto", R.string.AttachDestructingPhoto); + } else if (getGroupId() != 0) { + return LocaleController.getString("Album", R.string.Album); + } else { + return LocaleController.getString("AttachPhoto", R.string.AttachPhoto); + } + } else if (media != null && (isVideoDocument(media.document) || media instanceof TLRPC.TL_messageMediaDocument && (media.document instanceof TLRPC.TL_documentEmpty || media.document == null) && media.ttl_seconds != 0)) { + if (media.ttl_seconds != 0 && !(messageOwner instanceof TLRPC.TL_message_secret)) { + return LocaleController.getString("AttachDestructingVideo", R.string.AttachDestructingVideo); + } else { + return LocaleController.getString("AttachVideo", R.string.AttachVideo); + } + } else if (isVoice()) { + return LocaleController.getString("AttachAudio", R.string.AttachAudio); + } else if (isRoundVideo()) { + return LocaleController.getString("AttachRound", R.string.AttachRound); + } else if (media instanceof TLRPC.TL_messageMediaGeo || media instanceof TLRPC.TL_messageMediaVenue) { + return LocaleController.getString("AttachLocation", R.string.AttachLocation); + } else if (media instanceof TLRPC.TL_messageMediaGeoLive) { + return LocaleController.getString("AttachLiveLocation", R.string.AttachLiveLocation); + } else if (media instanceof TLRPC.TL_messageMediaContact) { +// if (!TextUtils.isEmpty(media.vcard)) { +// vCardData = VCardData.parse(media.vcard); +// } + return LocaleController.getString("AttachContact", R.string.AttachContact); + } else if (media instanceof TLRPC.TL_messageMediaGame) { + return messageOwner.message; + } else if (media instanceof TLRPC.TL_messageMediaInvoice) { + return media.description; + } else if (media instanceof TLRPC.TL_messageMediaUnsupported) { + return LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia); + } else if (media instanceof TLRPC.TL_messageMediaDocument) { + if (isSticker() || isAnimatedStickerDocument(media.document, true)) { + String sch = getStickerChar(); + if (sch != null && sch.length() > 0) { + return String.format("%s %s", sch, LocaleController.getString("AttachSticker", R.string.AttachSticker)); + } else { + return LocaleController.getString("AttachSticker", R.string.AttachSticker); + } + } else if (isMusic()) { + return LocaleController.getString("AttachMusic", R.string.AttachMusic); + } else if (isGif()) { + return LocaleController.getString("AttachGif", R.string.AttachGif); + } else { + String name = FileLoader.getDocumentFileName(media.document); + if (!TextUtils.isEmpty(name)) { + return name; + } else { + return LocaleController.getString("AttachDocument", R.string.AttachDocument); + } + } + } + return null; + } + public static TLRPC.MessageMedia getMedia(MessageObject messageObject) { if (messageObject == null || messageObject.messageOwner == null) { return null; @@ -4083,6 +4277,15 @@ public class MessageObject { return messageOwner.media != null && messageOwner.media.extended_media instanceof TLRPC.TL_messageExtendedMediaPreview; } + private boolean hasNonEmojiEntities() { + if (messageOwner == null || messageOwner.entities == null) + return false; + for (int i = 0; i < messageOwner.entities.size(); ++i) + if (!(messageOwner.entities.get(i) instanceof TLRPC.TL_messageEntityCustomEmoji)) + return true; + return false; + } + public void setType() { int oldType = type; type = 1000; @@ -4096,7 +4299,7 @@ public class MessageObject { } else { type = TYPE_ANIMATED_STICKER; } - } else if (isMediaEmpty(false) && !isDice() && emojiOnlyCount >= 1 && !hasUnwrappedEmoji) { + } else if (isMediaEmpty(false) && !isDice() && emojiOnlyCount >= 1 && !hasUnwrappedEmoji && messageOwner != null && !hasNonEmojiEntities()) { type = TYPE_EMOJIS; } else if (isMediaEmpty()) { type = TYPE_TEXT; @@ -4108,6 +4311,8 @@ public class MessageObject { } else if (getMedia(messageOwner).ttl_seconds != 0 && (getMedia(messageOwner).photo instanceof TLRPC.TL_photoEmpty || getDocument() instanceof TLRPC.TL_documentEmpty || getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDocument && getDocument() == null || forceExpired)) { contentType = 1; type = TYPE_DATE; + } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGiveaway) { + type = TYPE_GIVEAWAY; } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaDice) { type = TYPE_ANIMATED_STICKER; if (getMedia(messageOwner).document == null) { @@ -4186,6 +4391,9 @@ public class MessageObject { photoThumbsObject = messageOwner.action.photo; } else if (messageOwner.action instanceof TLRPC.TL_messageActionLoginUnknownLocation) { type = TYPE_TEXT; + } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { + contentType = 1; + type = TYPE_GIFT_PREMIUM_CHANNEL; } else if (messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { contentType = 1; type = TYPE_GIFT_PREMIUM; @@ -4222,7 +4430,7 @@ public class MessageObject { } if (layoutCreated) { int newMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : AndroidUtilities.displaySize.x; - if (Math.abs(generatedWithMinSize - newMinSize) > AndroidUtilities.dp(52) || generatedWithDensity != AndroidUtilities.density) { + if (Math.abs(generatedWithMinSize - newMinSize) > dp(52) || generatedWithDensity != AndroidUtilities.density) { layoutCreated = false; } } @@ -4239,7 +4447,7 @@ public class MessageObject { paint = Theme.chat_msgTextPaint; } int[] emojiOnly = allowsBigEmoji() ? new int[1] : null; - messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), AndroidUtilities.dp(20), false, emojiOnly); + messageText = Emoji.replaceEmoji(messageText, paint.getFontMetricsInt(), false, emojiOnly); messageText = replaceAnimatedEmoji(messageText, paint.getFontMetricsInt()); if (emojiOnly != null && emojiOnly[0] > 1) { replaceEmojiToLottieFrame(messageText, emojiOnly); @@ -4613,7 +4821,7 @@ public class MessageObject { id = "invite"; spanObject = invite; } else if (object instanceof TLRPC.ForumTopic) { - name = ForumUtilities.getTopicSpannedName((TLRPC.ForumTopic) object, null); + name = ForumUtilities.getTopicSpannedName((TLRPC.ForumTopic) object, null, false); id = "topic"; spanObject = object; } else { @@ -4792,7 +5000,7 @@ public class MessageObject { FileLog.e(e); } } - linkDescription = Emoji.replaceEmoji(linkDescription, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + linkDescription = Emoji.replaceEmoji(linkDescription, Theme.chat_msgTextPaint.getFontMetricsInt(), dp(20), false); if (webPageDescriptionEntities != null) { addEntitiesToText(linkDescription, webPageDescriptionEntities, isOut(), allowUsernames, false, !allowUsernames); replaceAnimatedEmoji(linkDescription, webPageDescriptionEntities, Theme.chat_msgTextPaint.getFontMetricsInt()); @@ -4823,7 +5031,7 @@ public class MessageObject { } CharSequence text = messageOwner.voiceTranscription; if (!TextUtils.isEmpty(text)) { - text = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + text = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), dp(20), false); } return text; } @@ -4833,7 +5041,7 @@ public class MessageObject { if (voiceTranscription == null) { return 0; } - int width = AndroidUtilities.displaySize.x - AndroidUtilities.dp(this.needDrawAvatar() ? 147 : 95); + int width = AndroidUtilities.displaySize.x - dp(this.needDrawAvatar() ? 147 : 95); StaticLayout captionLayout; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { captionLayout = StaticLayout.Builder.obtain(voiceTranscription, 0, voiceTranscription.length(), Theme.chat_msgTextPaint, width) @@ -4884,7 +5092,7 @@ public class MessageObject { entities = messageOwner.translatedText.entities; } if (!isMediaEmpty() && !(getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) && !TextUtils.isEmpty(text)) { - caption = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + caption = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), dp(20), false); caption = replaceAnimatedEmoji(caption, entities, Theme.chat_msgTextPaint.getFontMetricsInt(), false); boolean hasEntities; @@ -5313,7 +5521,11 @@ public class MessageObject { } } - if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { + if ( + entity instanceof TLRPC.TL_messageEntityCustomEmoji || + entity instanceof TLRPC.TL_messageEntityBlockquote || + entity instanceof TLRPC.TL_messageEntityPre + ) { continue; } @@ -5327,14 +5539,17 @@ public class MessageObject { newRun.flags = TextStyleSpan.FLAG_STYLE_STRIKE; } else if (entity instanceof TLRPC.TL_messageEntityUnderline) { newRun.flags = TextStyleSpan.FLAG_STYLE_UNDERLINE; - } else if (entity instanceof TLRPC.TL_messageEntityBlockquote) { - newRun.flags = TextStyleSpan.FLAG_STYLE_QUOTE; +// } else if (entity instanceof TLRPC.TL_messageEntityBlockquote) { +// newRun.flags = TextStyleSpan.FLAG_STYLE_QUOTE; } else if (entity instanceof TLRPC.TL_messageEntityBold) { newRun.flags = TextStyleSpan.FLAG_STYLE_BOLD; } else if (entity instanceof TLRPC.TL_messageEntityItalic) { newRun.flags = TextStyleSpan.FLAG_STYLE_ITALIC; - } else if (entity instanceof TLRPC.TL_messageEntityCode || entity instanceof TLRPC.TL_messageEntityPre) { + } else if (entity instanceof TLRPC.TL_messageEntityCode) { newRun.flags = TextStyleSpan.FLAG_STYLE_MONO; +// } else if (entity instanceof TLRPC.TL_messageEntityPre) { +// newRun.flags = TextStyleSpan.FLAG_STYLE_CODE; +// newRun.lng = entity.language; } else if (entity instanceof TLRPC.TL_messageEntityMentionName) { if (!usernames) { continue; @@ -5483,11 +5698,32 @@ public class MessageObject { spannable.setSpan(new TextStyleSpan(run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } + for (int a = 0, N = entitiesCopy.size(); a < N; a++) { + TLRPC.MessageEntity entity = entitiesCopy.get(a); + if (entity.length <= 0 || entity.offset < 0 || entity.offset >= text.length()) { + continue; + } else if (entity.offset + entity.length > text.length()) { + entity.length = text.length() - entity.offset; + } + + if (entity instanceof TLRPC.TL_messageEntityBlockquote) { + QuoteSpan.putQuote(spannable, entity.offset, entity.offset + entity.length); + } else if (entity instanceof TLRPC.TL_messageEntityPre) { + final int start = entity.offset; + final int end = entity.offset + entity.length; + spannable.setSpan(new CodeHighlighting.Span(true, 0, null, entity.language, spannable.subSequence(start, end).toString()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); +// CodeHighlighting.highlight(spannable, entity.offset, entity.offset + entity.length, entity.language, t, null, true); + } + } return hasUrls; } public boolean needDrawShareButton() { - if (preview) { + if (isSponsored()) { + return false; + } else if (hasCode) { + return false; + } else if (preview) { return false; } else if (scheduled) { return false; @@ -5539,33 +5775,41 @@ public class MessageObject { public int getMaxMessageTextWidth() { int maxWidth = 0; if (AndroidUtilities.isTablet() && eventId != 0) { - generatedWithMinSize = AndroidUtilities.dp(530); + generatedWithMinSize = dp(530); } else { generatedWithMinSize = AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() : getParentWidth(); } generatedWithDensity = AndroidUtilities.density; - if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage != null && "telegram_background".equals(getMedia(messageOwner).webpage.type)) { + if (hasCode) { + maxWidth = generatedWithMinSize - dp(45); + if (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage) { + maxWidth -= dp(52); + } + } else if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage != null && "telegram_background".equals(getMedia(messageOwner).webpage.type)) { try { Uri uri = Uri.parse(getMedia(messageOwner).webpage.url); String segment = uri.getLastPathSegment(); if (uri.getQueryParameter("bg_color") != null) { - maxWidth = AndroidUtilities.dp(220); + maxWidth = dp(220); } else if (segment.length() == 6 || segment.length() == 13 && segment.charAt(6) == '-') { - maxWidth = AndroidUtilities.dp(200); + maxWidth = dp(200); } } catch (Exception ignore) { } } else if (isAndroidTheme()) { - maxWidth = AndroidUtilities.dp(200); + maxWidth = dp(200); } if (maxWidth == 0) { - maxWidth = generatedWithMinSize - AndroidUtilities.dp(needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage ? 132 : 80); + maxWidth = generatedWithMinSize - dp(80); + if (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage) { + maxWidth -= dp(52); + } if (needDrawShareButton() && !isOutOwner()) { - maxWidth -= AndroidUtilities.dp(10); + maxWidth -= dp(10); } if (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaGame) { - maxWidth -= AndroidUtilities.dp(10); + maxWidth -= dp(10); } } if (emojiOnlyCount >= 1 && totalAnimatedEmojiCount <= 100 && (emojiOnlyCount - totalAnimatedEmojiCount) < (SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_HIGH ? 100 : 50) && (hasValidReplyMessageObject() || isForwarded())) { @@ -5637,7 +5881,7 @@ public class MessageObject { } if (!(messageText instanceof Spannable)) { - messageText = new SpannableString(messageText); + messageText = new SpannableStringBuilder(messageText); } return addEntitiesToText(messageText, useManualParse); } @@ -5651,8 +5895,26 @@ public class MessageObject { textLayoutBlocks = new ArrayList<>(); textWidth = 0; + hasCode = messageText instanceof Spanned && ((Spanned) messageText).getSpans(0, messageText.length(), CodeHighlighting.Span.class).length > 0; + hasQuote = messageText instanceof Spanned && ((Spanned) messageText).getSpans(0, messageText.length(), QuoteSpan.QuoteStyleSpan.class).length > 0; + hasSingleQuote = false; + + if (messageText instanceof Spanned) { + Spanned spanned = (Spanned) messageText; + QuoteSpan[] quoteSpans = spanned.getSpans(0, spanned.length(), QuoteSpan.class); + for (int i = 0; i < quoteSpans.length; ++i) { + quoteSpans[i].adaptLineHeight = false; + } + hasSingleQuote = quoteSpans.length == 1 && spanned.getSpanStart(quoteSpans[0]) == 0 && spanned.getSpanEnd(quoteSpans[0]) == spanned.length(); + } + + int maxWidth = getMaxMessageTextWidth(); + if (hasSingleQuote) { + maxWidth -= AndroidUtilities.dp(32); + } + StaticLayout textLayout; TextPaint paint; @@ -5688,7 +5950,11 @@ public class MessageObject { return; } - textHeight = textLayout.getHeight(); + if (hasSingleQuote) { + maxWidth += AndroidUtilities.dp(32); + } + + textHeight = 0; int linesCount = textLayout.getLineCount(); int linesPreBlock = totalAnimatedEmojiCount >= 50 ? LINES_PER_BLOCK_WITH_EMOJI : LINES_PER_BLOCK; @@ -5702,51 +5968,147 @@ public class MessageObject { int linesOffset = 0; float prevOffset = 0; - for (int a = 0; a < blocksCount; a++) { - int currentBlockLinesCount; - if (singleLayout) { - currentBlockLinesCount = linesCount; - } else { - currentBlockLinesCount = Math.min(linesPreBlock, linesCount - linesOffset); + ArrayList textRanges = new ArrayList<>(); + if (messageText instanceof Spanned && (hasQuote || hasCode)) { + singleLayout = false; + cutIntoRanges(messageText, textRanges); + } else if (singleLayout || blocksCount == 1) { + textRanges.add(new TextRange(0, textLayout.getText().length())); + } else { + for (int a = 0; a < blocksCount; a++) { + int currentBlockLinesCount; + if (singleLayout) { + currentBlockLinesCount = linesCount; + } else { + currentBlockLinesCount = Math.min(linesPreBlock, linesCount - linesOffset); + } + + int startCharacter = textLayout.getLineStart(linesOffset); + int endCharacter = textLayout.getLineEnd(linesOffset + currentBlockLinesCount - 1); + if (endCharacter < startCharacter) { + continue; + } + + textRanges.add(new TextRange(startCharacter, endCharacter)); + + linesOffset += currentBlockLinesCount; } + } + blocksCount = textRanges.size(); + + hasCodeAtTop = false; + hasCodeAtBottom = false; + hasQuoteAtBottom = false; + hasSingleQuote = false; + float offset = 0; + for (int a = 0; a < textRanges.size(); a++) { TextLayoutBlock block = new TextLayoutBlock(); + TextRange range = textRanges.get(a); + + block.code = range.code; + block.quote = range.quote; + + block.first = a == 0; + block.last = a == textRanges.size() - 1; + + if (block.first) { + hasCodeAtTop = block.code; + } + if (block.last) { + hasQuoteAtBottom = block.quote; + hasCodeAtBottom = block.code; + } + hasSingleQuote = block.first && block.last && block.quote; + + if (block.quote) { + if (block.first && block.last) { + block.padTop = block.padBottom = AndroidUtilities.dp(6); + } else { + block.padTop = AndroidUtilities.dp(block.first ? 8 : 6); + block.padBottom = AndroidUtilities.dp(7); + } + } else if (block.code) { + block.padTop = block.first ? 0 : AndroidUtilities.dp(5); + block.padBottom = block.last ? 0 : AndroidUtilities.dp(5); + } + + TextPaint layoutPaint = paint; + if (block.code) { + final int length = range.end - range.start; + if (length > 220) { + layoutPaint = Theme.chat_msgTextCode3Paint; + } else if (length > 80) { + layoutPaint = Theme.chat_msgTextCode2Paint; + } else { + layoutPaint = Theme.chat_msgTextCodePaint; + } + } + + CharSequence blockText = messageText.subSequence(range.start, range.end); if (blocksCount == 1) { + if (block.code && !block.quote && textLayout.getText() instanceof Spannable && !TextUtils.isEmpty(range.language)) { + SpannableString sb = CodeHighlighting.getHighlighted(blockText.toString(), range.language); + if (hasUrls && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0) + dp(2)) + .setLineSpacing(lineAdd, lineSpacing) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) + .setAlignment(align); + if (emojiOnlyCount > 0) { + builder.setIncludePad(false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + builder.setUseLineSpacingFromFallbacks(false); + } + } + textLayout = builder.build(); + } else { + textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); + } + } + block.textLayout = textLayout; block.textYOffset = 0; block.charactersOffset = 0; block.charactersEnd = textLayout.getText().length(); + block.height = textLayout.getHeight(); + textHeight = block.padTop + block.height + block.padBottom; if (emojiOnlyCount != 0) { switch (emojiOnlyCount) { case 1: - textHeight -= AndroidUtilities.dp(5.3f); - block.textYOffset -= AndroidUtilities.dp(5.3f); + textHeight -= dp(5.3f); + block.textYOffset -= dp(5.3f); break; case 2: - textHeight -= AndroidUtilities.dp(4.5f); - block.textYOffset -= AndroidUtilities.dp(4.5f); + textHeight -= dp(4.5f); + block.textYOffset -= dp(4.5f); break; case 3: - textHeight -= AndroidUtilities.dp(4.2f); - block.textYOffset -= AndroidUtilities.dp(4.2f); + textHeight -= dp(4.2f); + block.textYOffset -= dp(4.2f); break; } } - block.height = textHeight; } else { - int startCharacter = textLayout.getLineStart(linesOffset); - int endCharacter = textLayout.getLineEnd(linesOffset + currentBlockLinesCount - 1); + int startCharacter = range.start; + int endCharacter = range.end; if (endCharacter < startCharacter) { continue; } block.charactersOffset = startCharacter; block.charactersEnd = endCharacter; try { - SpannableStringBuilder sb = SpannableStringBuilder.valueOf(messageText.subSequence(startCharacter, endCharacter)); + SpannableString sb; + if (block.code && !block.quote) { + sb = CodeHighlighting.getHighlighted(blockText.toString(), range.language); + } else { + sb = SpannableString.valueOf(blockText); + } if (hasUrls && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { StaticLayout.Builder builder = - StaticLayout.Builder.obtain(sb, 0, sb.length(), paint, maxWidth + AndroidUtilities.dp(2)) + StaticLayout.Builder.obtain(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0) + dp(2)) .setLineSpacing(lineAdd, lineSpacing) .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) @@ -5759,31 +6121,28 @@ public class MessageObject { } block.textLayout = builder.build(); } else { - block.textLayout = new StaticLayout(sb, 0, sb.length(), paint, maxWidth, align, lineSpacing, lineAdd, false); + block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, maxWidth - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); } - block.textYOffset = textLayout.getLineTop(linesOffset); + block.textYOffset = offset; if (a != 0 && emojiOnlyCount <= 0) { block.height = (int) (block.textYOffset - prevOffset); } - block.height = Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1)); + block.height = block.textLayout.getHeight();//Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1)); + textHeight += block.padTop + block.height + block.padBottom; prevOffset = block.textYOffset; } catch (Exception e) { FileLog.e(e); continue; } - if (a == blocksCount - 1) { - currentBlockLinesCount = Math.max(currentBlockLinesCount, block.textLayout.getLineCount()); - try { - textHeight = Math.max(textHeight, (int) (block.textYOffset + block.textLayout.getHeight())); - } catch (Exception e) { - FileLog.e(e); - } - } } + offset += block.padTop + block.height + block.padBottom; + textLayoutBlocks.add(block); + final int currentBlockLinesCount = block.textLayout.getLineCount(); + float lastLeft; try { lastLeft = block.textLayout.getLineLeft(currentBlockLinesCount - 1); @@ -5805,6 +6164,9 @@ public class MessageObject { lastLine = 0; FileLog.e(e); } + if (block.quote) { + lastLine += AndroidUtilities.dp(32); + } int linesMaxWidth = (int) Math.ceil(lastLine); if (linesMaxWidth > maxWidth + 80) { @@ -5819,6 +6181,17 @@ public class MessageObject { linesMaxWidthWithLeft = lastLineWidthWithLeft = (int) Math.ceil(linesMaxWidth + Math.max(0, lastLeft)); + if (block.quote) { + block.maxRight = 0; + for (int n = 0; n < currentBlockLinesCount; n++) { + try { + block.maxRight = Math.max(block.maxRight, block.textLayout.getLineRight(n)); + } catch (Exception ignore) { + block.maxRight = textWidth; + } + } + } + if (currentBlockLinesCount > 1) { boolean hasNonRTL = false; float textRealMaxWidth = 0, textRealMaxWidthWithLeft = 0, lineWidth, lineLeft; @@ -5829,6 +6202,10 @@ public class MessageObject { lineWidth = 0; } + if (block.quote) { + lineWidth += AndroidUtilities.dp(32); + } + try { lineLeft = block.textLayout.getLineLeft(n); } catch (Exception ignore) { @@ -5840,7 +6217,7 @@ public class MessageObject { lineLeft = 0; } - if (lineLeft > 0) { + if (lineLeft > 0 || block.textLayout.getParagraphDirection(n) == Layout.DIR_RIGHT_TO_LEFT) { textXOffset = Math.min(textXOffset, lineLeft); block.directionFlags |= TextLayoutBlock.FLAG_RTL; hasRtl = true; @@ -5892,6 +6269,347 @@ public class MessageObject { SpoilerEffect.addSpoilers(null, block.textLayout, -1, linesMaxWidthWithLeft, null, block.spoilers); } } + + hasWideCode = hasCode && textWidth > generatedWithMinSize - dp(80 + (needDrawAvatarInternal() && !isOutOwner() && !messageOwner.isThreadMessage ? 52 : 0)); + } + + public static class TextLayoutBlocks { + + public final CharSequence text; + public int lastLineWidth; + public int textWidth; + public int textHeight; + public boolean hasRtl; + public float textXOffset; + public final ArrayList textLayoutBlocks = new ArrayList<>(); + public boolean hasCode; + public boolean hasCodeAtTop, hasCodeAtBottom; + public boolean hasQuote; + public boolean hasSingleQuote; + public boolean hasQuoteAtBottom; + + public TextLayoutBlocks(MessageObject messageObject, @NonNull CharSequence text, TextPaint textPaint, int width) { + this.text = text; + textWidth = 0; + + hasCode = text instanceof Spanned && ((Spanned) text).getSpans(0, text.length(), CodeHighlighting.Span.class).length > 0; + hasQuote = text instanceof Spanned && ((Spanned) text).getSpans(0, text.length(), QuoteSpan.QuoteStyleSpan.class).length > 0; + hasSingleQuote = false; + + if (text instanceof Spanned) { + Spanned spanned = (Spanned) text; + QuoteSpan[] quoteSpans = spanned.getSpans(0, spanned.length(), QuoteSpan.class); + for (int i = 0; i < quoteSpans.length; ++i) { + quoteSpans[i].adaptLineHeight = false; + } + hasSingleQuote = quoteSpans.length == 1 && spanned.getSpanStart(quoteSpans[0]) == 0 && spanned.getSpanEnd(quoteSpans[0]) == spanned.length(); + } + + StaticLayout textLayout; + + if (hasSingleQuote) { + width -= AndroidUtilities.dp(32); + } + + final float lineSpacing = 1f; + final float lineAdd = 0; + Layout.Alignment align = Layout.Alignment.ALIGN_NORMAL; //type == TYPE_EMOJIS && isOut() ? Layout.Alignment.ALIGN_OPPOSITE : Layout.Alignment.ALIGN_NORMAL; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(text, 0, text.length(), textPaint, width) + .setLineSpacing(lineAdd, lineSpacing) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) + .setAlignment(align); + textLayout = builder.build(); + } else { + textLayout = new StaticLayout(text, textPaint, width, align, lineSpacing, lineAdd, false); + } + } catch (Exception e) { + FileLog.e(e); + return; + } + + if (hasSingleQuote) { + width += AndroidUtilities.dp(32); + } + + textHeight = 0; + int linesCount = textLayout.getLineCount(); + int linesPreBlock = LINES_PER_BLOCK; + + int blocksCount; + boolean singleLayout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + if (singleLayout) { + blocksCount = 1; + } else { + blocksCount = (int) Math.ceil((float) linesCount / linesPreBlock); + } + int linesOffset = 0; + float prevOffset = 0; + + ArrayList textRanges = new ArrayList<>(); + if (text instanceof Spanned && (hasQuote || hasCode)) { + singleLayout = false; + cutIntoRanges(text, textRanges); + } else if (singleLayout || blocksCount == 1) { + textRanges.add(new TextRange(0, textLayout.getText().length())); + } else { + for (int a = 0; a < blocksCount; a++) { + int currentBlockLinesCount = Math.min(linesPreBlock, linesCount - linesOffset); + + int startCharacter = textLayout.getLineStart(linesOffset); + int endCharacter = textLayout.getLineEnd(linesOffset + currentBlockLinesCount - 1); + if (endCharacter < startCharacter) { + continue; + } + + textRanges.add(new TextRange(startCharacter, endCharacter)); + + linesOffset += currentBlockLinesCount; + } + } + blocksCount = textRanges.size(); + + hasCodeAtTop = false; + hasCodeAtBottom = false; + hasQuoteAtBottom = false; + hasSingleQuote = false; + float offset = 0; + for (int a = 0; a < textRanges.size(); a++) { + TextLayoutBlock block = new TextLayoutBlock(); + + TextRange range = textRanges.get(a); + + block.code = range.code; + block.quote = range.quote; + + block.first = a == 0; + block.last = a == textRanges.size() - 1; + + if (block.first) { + hasCodeAtTop = block.code; + } + if (block.last) { + hasQuoteAtBottom = block.quote; + hasCodeAtBottom = block.code; + } + hasSingleQuote = block.first && block.last && block.quote; + + if (block.quote) { + if (block.first && block.last) { + block.padTop = block.padBottom = AndroidUtilities.dp(6); + } else { + block.padTop = AndroidUtilities.dp(block.first ? 8 : 6); + block.padBottom = AndroidUtilities.dp(7); + } + } else if (block.code) { + block.padTop = block.first ? 0 : AndroidUtilities.dp(5); + block.padBottom = block.last ? 0 : AndroidUtilities.dp(5); + } + + TextPaint layoutPaint = textPaint; + if (block.code) { + final int length = range.end - range.start; + if (length > 220) { + layoutPaint = Theme.chat_msgTextCode3Paint; + } else if (length > 80) { + layoutPaint = Theme.chat_msgTextCode2Paint; + } else { + layoutPaint = Theme.chat_msgTextCodePaint; + } + } + + if (blocksCount == 1) { + if (block.code && !block.quote && textLayout.getText() instanceof Spannable && !TextUtils.isEmpty(range.language)) { + SpannableString sb = CodeHighlighting.getHighlighted(text.subSequence(range.start, range.end).toString(), range.language); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + StaticLayout.Builder builder = + StaticLayout.Builder.obtain(sb, 0, text.length(), layoutPaint, width) + .setLineSpacing(lineAdd, lineSpacing) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) + .setAlignment(align); + textLayout = builder.build(); + } else { + textLayout = new StaticLayout(sb, layoutPaint, width, align, lineSpacing, lineAdd, false); + } + } + + block.textLayout = textLayout; + block.textYOffset = 0; + block.charactersOffset = 0; + block.charactersEnd = textLayout.getText().length(); + + block.height = textLayout.getHeight(); + textHeight = block.padTop + block.height + block.padBottom; + } else { + int startCharacter = range.start; + int endCharacter = range.end; + if (endCharacter < startCharacter) { + continue; + } + block.charactersOffset = startCharacter; + block.charactersEnd = endCharacter; + try { + SpannableString sb; + if (block.code && !block.quote) { + sb = CodeHighlighting.getHighlighted(text.subSequence(startCharacter, endCharacter).toString(), range.language); + } else { + sb = SpannableString.valueOf(text.subSequence(startCharacter, endCharacter)); + } + block.textLayout = new StaticLayout(sb, 0, sb.length(), layoutPaint, width - (block.quote ? dp(24) : 0), align, lineSpacing, lineAdd, false); + + block.textYOffset = offset; + if (a != 0) { + block.height = (int) (block.textYOffset - prevOffset); + } + block.height = block.textLayout.getHeight(); // Math.max(block.height, block.textLayout.getLineBottom(block.textLayout.getLineCount() - 1)); + textHeight += block.padTop + block.height + block.padBottom; + prevOffset = block.textYOffset; + } catch (Exception e) { + FileLog.e(e); + continue; + } + } + + if (block.code && block.textLayout.getText() instanceof Spannable && TextUtils.isEmpty(range.language)) { + CodeHighlighting.highlight((Spannable) block.textLayout.getText(), 0, block.textLayout.getText().length(), range.language, 0, null, true); + } + + offset += block.padTop + block.height + block.padBottom; + + textLayoutBlocks.add(block); + + final int currentBlockLinesCount = block.textLayout.getLineCount(); + + float lastLeft; + try { + lastLeft = block.textLayout.getLineLeft(currentBlockLinesCount - 1); + if (a == 0 && lastLeft >= 0) { + textXOffset = lastLeft; + } + } catch (Exception e) { + lastLeft = 0; + if (a == 0) { + textXOffset = 0; + } + FileLog.e(e); + } + + float lastLine; + try { + lastLine = block.textLayout.getLineWidth(currentBlockLinesCount - 1); + } catch (Exception e) { + lastLine = 0; + FileLog.e(e); + } + + int linesMaxWidth = (int) Math.ceil(lastLine); + if (linesMaxWidth > width + 80) { + linesMaxWidth = width; + } + int lastLineWidthWithLeft; + int linesMaxWidthWithLeft; + + if (a == blocksCount - 1) { + lastLineWidth = linesMaxWidth; + } + + linesMaxWidthWithLeft = lastLineWidthWithLeft = (int) Math.ceil(linesMaxWidth + Math.max(0, lastLeft)); + + if (block.quote) { + block.maxRight = 0; + for (int n = 0; n < currentBlockLinesCount; n++) { + try { + block.maxRight = Math.max(block.maxRight, block.textLayout.getLineRight(n)); + } catch (Exception ignore) { + block.maxRight = textWidth; + } + } + } + + if (currentBlockLinesCount > 1) { + boolean hasNonRTL = false; + float textRealMaxWidth = 0, textRealMaxWidthWithLeft = 0, lineWidth, lineLeft; + for (int n = 0; n < currentBlockLinesCount; n++) { + try { + lineWidth = block.textLayout.getLineWidth(n); + } catch (Exception ignore) { + lineWidth = 0; + } + + if (block.quote) { + lineWidth += AndroidUtilities.dp(32); + } + + try { + lineLeft = block.textLayout.getLineLeft(n); + } catch (Exception ignore) { + lineLeft = 0; + } + + if (lineWidth > width + 20) { + lineWidth = width; + lineLeft = 0; + } + + if (lineLeft > 0 || block.textLayout.getParagraphDirection(n) == Layout.DIR_RIGHT_TO_LEFT) { + textXOffset = Math.min(textXOffset, lineLeft); + block.directionFlags |= TextLayoutBlock.FLAG_RTL; + hasRtl = true; + } else { + block.directionFlags |= TextLayoutBlock.FLAG_NOT_RTL; + } + + try { + if (!hasNonRTL && lineLeft == 0 && block.textLayout.getParagraphDirection(n) == Layout.DIR_LEFT_TO_RIGHT) { + hasNonRTL = true; + } + } catch (Exception ignore) { + hasNonRTL = true; + } + + textRealMaxWidth = Math.max(textRealMaxWidth, lineWidth); + textRealMaxWidthWithLeft = Math.max(textRealMaxWidthWithLeft, lineWidth + lineLeft); + linesMaxWidth = Math.max(linesMaxWidth, (int) Math.ceil(lineWidth)); + linesMaxWidthWithLeft = Math.max(linesMaxWidthWithLeft, (int) Math.ceil(lineWidth + lineLeft)); + } + if (hasNonRTL) { + textRealMaxWidth = textRealMaxWidthWithLeft; + if (a == blocksCount - 1) { + lastLineWidth = lastLineWidthWithLeft; + } + } else if (a == blocksCount - 1) { + lastLineWidth = linesMaxWidth; + } + textWidth = Math.max(textWidth, (int) Math.ceil(textRealMaxWidth)); + } else { + if (lastLeft > 0) { + textXOffset = Math.min(textXOffset, lastLeft); + if (textXOffset == 0) { + linesMaxWidth += lastLeft; + } + hasRtl = blocksCount != 1; + block.directionFlags |= TextLayoutBlock.FLAG_RTL; + } else { + block.directionFlags |= TextLayoutBlock.FLAG_NOT_RTL; + } + + textWidth = Math.max(textWidth, Math.min(width, linesMaxWidth)); +// if (block.quote && hasSingleQuote) { +// textWidth += AndroidUtilities.dp(32); +// } + } + + linesOffset += currentBlockLinesCount; + if (messageObject != null && !messageObject.isSpoilersRevealed && !messageObject.spoiledLoginCode) { + SpoilerEffect.addSpoilers(null, block.textLayout, -1, linesMaxWidthWithLeft, null, block.spoilers); + } + } + } + } public boolean isOut() { @@ -5900,7 +6618,7 @@ public class MessageObject { public Boolean isOutOwnerCached; public boolean isOutOwner() { - if (preview) { + if (previewForward) { return true; } if (isOutOwnerCached != null) { @@ -5922,7 +6640,7 @@ public class MessageObject { } public boolean needDrawAvatar() { - if (customAvatarDrawable != null) { + if (forceAvatar || customAvatarDrawable != null) { return true; } if (isSponsored() && (isFromChat() || sponsoredShowPeerPhoto)) { @@ -5932,7 +6650,7 @@ public class MessageObject { } private boolean needDrawAvatarInternal() { - if (customAvatarDrawable != null) { + if (forceAvatar || customAvatarDrawable != null) { return true; } if (isSponsored() && (isFromChat() || sponsoredShowPeerPhoto)) { @@ -5984,6 +6702,28 @@ public class MessageObject { } } + public static boolean peersEqual(TLRPC.InputPeer a, TLRPC.InputPeer b) { + if (a == null && b == null) { + return true; + } + if (a == null || b == null) { + return false; + } + if (a instanceof TLRPC.TL_inputPeerChat && b instanceof TLRPC.TL_inputPeerChat) { + return a.chat_id == b.chat_id; + } + if (a instanceof TLRPC.TL_inputPeerChannel && b instanceof TLRPC.TL_inputPeerChannel) { + return a.channel_id == b.channel_id; + } + if (a instanceof TLRPC.TL_inputPeerUser && b instanceof TLRPC.TL_inputPeerUser) { + return a.user_id == b.user_id; + } + if (a instanceof TLRPC.TL_inputPeerSelf && b instanceof TLRPC.TL_inputPeerSelf) { + return true; + } + return false; + } + public static boolean peersEqual(TLRPC.Peer a, TLRPC.Peer b) { if (a == null && b == null) { return true; @@ -6065,6 +6805,18 @@ public class MessageObject { return messageOwner.from_id instanceof TLRPC.TL_peerUser && !messageOwner.post; } + public boolean isFromChannel() { + TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null; + if (messageOwner.peer_id instanceof TLRPC.TL_peerChannel && ChatObject.isChannelAndNotMegaGroup(chat)) { + return true; + } + chat = messageOwner.from_id != null && messageOwner.from_id.channel_id != 0 ? getChat(null, null, messageOwner.from_id.channel_id) : null; + if (messageOwner.from_id instanceof TLRPC.TL_peerChannel && ChatObject.isChannelAndNotMegaGroup(chat)) { + return true; + } + return false; + } + public boolean isFromGroup() { TLRPC.Chat chat = messageOwner.peer_id != null && messageOwner.peer_id.channel_id != 0 ? getChat(null, null, messageOwner.peer_id.channel_id) : null; return messageOwner.from_id instanceof TLRPC.TL_peerChannel && ChatObject.isChannel(chat) && chat.megagroup; @@ -6315,8 +7067,8 @@ public class MessageObject { if (secretOnceSpan == null) { secretOnceSpan = new SpannableString("v"); ColoredImageSpan span = new ColoredImageSpan(R.drawable.mini_viewonce); - span.setTranslateX(-AndroidUtilities.dp(3)); - span.setWidth(AndroidUtilities.dp(13)); + span.setTranslateX(-dp(3)); + span.setWidth(dp(13)); ((Spannable) secretOnceSpan).setSpan(span, 0, secretOnceSpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } return TextUtils.concat(secretOnceSpan, "1"); @@ -6331,8 +7083,8 @@ public class MessageObject { if (secretPlaySpan == null) { secretPlaySpan = new SpannableString("p"); ColoredImageSpan span = new ColoredImageSpan(R.drawable.play_mini_video); - span.setTranslateX(AndroidUtilities.dp(1)); - span.setWidth(AndroidUtilities.dp(13)); + span.setTranslateX(dp(1)); + span.setWidth(dp(13)); ((Spannable) secretPlaySpan).setSpan(span, 0, secretPlaySpan.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } return TextUtils.concat(secretPlaySpan, str); @@ -6563,7 +7315,7 @@ public class MessageObject { } public static boolean isRoundVideoMessage(TLRPC.Message message) { - if (getMedia(message) instanceof TLRPC.TL_messageMediaWebPage) { + if (getMedia(message) instanceof TLRPC.TL_messageMediaWebPage && getMedia(message).webpage != null) { return isRoundVideoDocument(getMedia(message).webpage.document); } return getMedia(message) != null && isRoundVideoDocument(getMedia(message).document); @@ -6720,6 +7472,19 @@ public class MessageObject { return false; } + public static boolean isTextColorSet(TLRPC.TL_messages_stickerSet set) { + if (set == null || set.set == null) { + return false; + } + if (set.set.text_color) { + return true; + } + if (set.documents == null || set.documents.isEmpty()) { + return false; + } + return MessageObject.isTextColorEmoji(set.documents.get(0)); + } + public static boolean isPremiumEmojiPack(TLRPC.TL_messages_stickerSet set) { if (set != null && set.set != null && !set.set.emojis) { return false; @@ -6796,31 +7561,31 @@ public class MessageObject { public int getApproximateHeight() { if (type == TYPE_TEXT) { - int height = textHeight + (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage ? AndroidUtilities.dp(100) : 0); + int height = textHeight + (getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage ? dp(100) : 0); if (isReply()) { - height += AndroidUtilities.dp(42); + height += dp(42); } return height; } else if (type == TYPE_EXTENDED_MEDIA_PREVIEW) { return AndroidUtilities.getPhotoSize(); } else if (type == TYPE_VOICE) { - return AndroidUtilities.dp(72); + return dp(72); } else if (type == TYPE_CONTACT) { - return AndroidUtilities.dp(71); + return dp(71); } else if (type == TYPE_FILE) { - return AndroidUtilities.dp(100); + return dp(100); } else if (type == TYPE_GEO) { - return AndroidUtilities.dp(114); + return dp(114); } else if (type == TYPE_MUSIC) { - return AndroidUtilities.dp(82); + return dp(82); } else if (type == 10) { - return AndroidUtilities.dp(30); - } else if (type == TYPE_ACTION_PHOTO || type == TYPE_GIFT_PREMIUM || type == TYPE_SUGGEST_PHOTO) { - return AndroidUtilities.dp(50); + return dp(30); + } else if (type == TYPE_ACTION_PHOTO || type == TYPE_GIFT_PREMIUM || type == TYPE_GIFT_PREMIUM_CHANNEL || type == TYPE_SUGGEST_PHOTO) { + return dp(50); } else if (type == TYPE_ROUND_VIDEO) { return AndroidUtilities.roundMessageSize; } else if (type == TYPE_EMOJIS) { - return textHeight + AndroidUtilities.dp(30); + return textHeight + dp(30); } else if (type == TYPE_STICKER || type == TYPE_ANIMATED_STICKER) { float maxHeight = AndroidUtilities.displaySize.y * 0.4f; float maxWidth; @@ -6844,7 +7609,7 @@ public class MessageObject { } if (photoWidth == 0) { photoHeight = (int) maxHeight; - photoWidth = photoHeight + AndroidUtilities.dp(100); + photoWidth = photoHeight + dp(100); } if (photoHeight > maxHeight) { photoWidth *= maxHeight / photoHeight; @@ -6853,7 +7618,7 @@ public class MessageObject { if (photoWidth > maxWidth) { photoHeight *= maxWidth / photoWidth; } - return photoHeight + AndroidUtilities.dp(14); + return photoHeight + dp(14); } else { int photoHeight; int photoWidth; @@ -6863,7 +7628,7 @@ public class MessageObject { } else { photoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); } - photoHeight = photoWidth + AndroidUtilities.dp(100); + photoHeight = photoWidth + dp(100); if (photoWidth > AndroidUtilities.getPhotoSize()) { photoWidth = AndroidUtilities.getPhotoSize(); } @@ -6876,12 +7641,12 @@ public class MessageObject { float scale = (float) currentPhotoObject.w / (float) photoWidth; int h = (int) (currentPhotoObject.h / scale); if (h == 0) { - h = AndroidUtilities.dp(100); + h = dp(100); } if (h > photoHeight) { h = photoHeight; - } else if (h < AndroidUtilities.dp(120)) { - h = AndroidUtilities.dp(120); + } else if (h < dp(120)) { + h = dp(120); } if (needDrawBluredPreview()) { if (AndroidUtilities.isTablet()) { @@ -6893,7 +7658,7 @@ public class MessageObject { photoHeight = h; } - return photoHeight + AndroidUtilities.dp(14); + return photoHeight + dp(14); } } @@ -7016,7 +7781,7 @@ public class MessageObject { if (media == null) { return false; } - TLRPC.StoryItem storyItem = media.storyItem; + TL_stories.StoryItem storyItem = media.storyItem; if (storyItem == null || storyItem.media == null) { return false; } @@ -7162,7 +7927,7 @@ public class MessageObject { } TLRPC.Document document = getDocument(); if (document == null && type == TYPE_STORY) { - TLRPC.StoryItem storyItem = getMedia(messageOwner).storyItem; + TL_stories.StoryItem storyItem = getMedia(messageOwner).storyItem; if (storyItem != null && storyItem.media != null) { document = storyItem.media.document; } @@ -7710,11 +8475,21 @@ public class MessageObject { String[] queryWord = query.split("\\P{L}+"); ArrayList searchForWords = new ArrayList<>(); + if (messageOwner.reply_to != null && !TextUtils.isEmpty(messageOwner.reply_to.quote_text)) { + String message = messageOwner.reply_to.quote_text.trim().toLowerCase(); + if (message.contains(query) && !foundWords.contains(query)) { + foundWords.add(query); + handleFoundWords(foundWords, queryWord, true); + return; + } + String[] words = message.split("\\P{L}+"); + searchForWords.addAll(Arrays.asList(words)); + } if (!TextUtils.isEmpty(messageOwner.message)) { String message = messageOwner.message.trim().toLowerCase(); if (message.contains(query) && !foundWords.contains(query)) { foundWords.add(query); - handleFoundWords(foundWords, queryWord); + handleFoundWords(foundWords, queryWord, false); return; } String[] words = message.split("\\P{L}+"); @@ -7786,10 +8561,10 @@ public class MessageObject { } } } - handleFoundWords(foundWords, queryWord); + handleFoundWords(foundWords, queryWord, false); } - private void handleFoundWords(ArrayList foundWords, String[] queryWord) { + private void handleFoundWords(ArrayList foundWords, String[] queryWord, boolean inQuote) { if (!foundWords.isEmpty()) { boolean foundExactly = false; for (int i = 0; i < foundWords.size(); i++) { @@ -7825,9 +8600,23 @@ public class MessageObject { } highlightedWords = foundWords; if (messageOwner.message != null) { -// String str = messageOwner.message.replace('\n', ' ').replaceAll(" +", " ").trim(); applyEntities(); - CharSequence charSequence = AndroidUtilities.replaceCharSequence("\n", messageText, " "); + CharSequence text = null; + if (!TextUtils.isEmpty(caption)) { + text = caption; + } else { + text = messageText; + } + CharSequence charSequence = AndroidUtilities.replaceCharSequence("\n", text, " "); + if (inQuote && messageOwner != null && messageOwner.reply_to != null && messageOwner.reply_to.quote_text != null) { + SpannableStringBuilder quoteText = new SpannableStringBuilder(messageOwner.reply_to.quote_text); + addEntitiesToText(quoteText, messageOwner.reply_to.quote_entities, isOutOwner(), false, false, false); + SpannableString quoteIcon = new SpannableString("q "); + ColoredImageSpan quoteIconSpan = new ColoredImageSpan(R.drawable.mini_quote); + quoteIconSpan.setOverrideColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); + quoteIcon.setSpan(quoteIconSpan, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + charSequence = new SpannableStringBuilder(quoteIcon).append(quoteText).append('\n').append(charSequence); + } String str = charSequence.toString(); int lastIndex = str.length(); int startHighlightedIndex = str.toLowerCase().indexOf(foundWords.get(0)); @@ -7846,7 +8635,7 @@ public class MessageObject { public void createMediaThumbs() { if (isStoryMedia()) { - TLRPC.StoryItem storyItem = getMedia(messageOwner).storyItem; + TL_stories.StoryItem storyItem = getMedia(messageOwner).storyItem; if (storyItem != null && storyItem.media != null) { TLRPC.Document document = storyItem.media.document; if (document != null) { @@ -8081,4 +8870,279 @@ public class MessageObject { public boolean isStoryMention() { return type == MessageObject.TYPE_STORY_MENTION && !isExpiredStory(); } + + public boolean isGiveaway() { + return type == MessageObject.TYPE_GIVEAWAY; + } + + public boolean isAnyGift() { + return type == MessageObject.TYPE_GIFT_PREMIUM || type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL; + } + + private static CharSequence userSpan; + public static CharSequence userSpan() { + if (userSpan == null) { + userSpan = new SpannableStringBuilder("u"); + ColoredImageSpan span = new ColoredImageSpan(R.drawable.mini_reply_user); + span.spaceScaleX = .9f; + span.translate(0, AndroidUtilities.dp(1)); +// span.setScale(.7f, .7f); + ((SpannableStringBuilder) userSpan).setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return userSpan; + } + private static CharSequence groupSpan; + public static CharSequence groupSpan() { + if (groupSpan == null) { + groupSpan = new SpannableStringBuilder("g"); + ColoredImageSpan span = new ColoredImageSpan(R.drawable.msg_folders_groups); + span.setScale(.7f, .7f); + ((SpannableStringBuilder) groupSpan).setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return groupSpan; + } + private static CharSequence channelSpan; + public static CharSequence channelSpan() { + if (channelSpan == null) { + channelSpan = new SpannableStringBuilder("c"); + ColoredImageSpan span = new ColoredImageSpan(R.drawable.msg_folders_channels); + span.setScale(.7f, .7f); + ((SpannableStringBuilder) channelSpan).setSpan(span, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return channelSpan; + } + + public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer) { + return peerNameWithIcon(currentAccount, peer, false); + } + + public static CharSequence peerNameWithIcon(int currentAccount, TLRPC.Peer peer, boolean anotherChat) { + if (peer instanceof TLRPC.TL_peerUser) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(peer.user_id); + if (user != null) { + if (anotherChat) { + return new SpannableStringBuilder(userSpan()).append(" ").append(UserObject.getUserName(user)); + } else { + return UserObject.getUserName(user); + } + } + } else if (peer instanceof TLRPC.TL_peerChat) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(peer.chat_id); + if (chat != null) { + return new SpannableStringBuilder(ChatObject.isChannelAndNotMegaGroup(chat) ? channelSpan() : groupSpan()).append(" ").append(chat.title); + } + } else if (peer instanceof TLRPC.TL_peerChannel) { + TLRPC.Chat channel = MessagesController.getInstance(currentAccount).getChat(peer.channel_id); + if (channel != null) { + return new SpannableStringBuilder(ChatObject.isChannelAndNotMegaGroup(channel) ? channelSpan() : groupSpan()).append(" ").append(channel.title); + } + } + return ""; + } + + public static CharSequence peerNameWithIcon(int currentAccount, long did) { + return peerNameWithIcon(currentAccount, did, false); + } + + public static CharSequence peerNameWithIcon(int currentAccount, long did, boolean anotherChat) { + if (did >= 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); + if (user != null) { + return UserObject.getUserName(user); + } + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-did); + if (chat != null) { + return new SpannableStringBuilder(ChatObject.isChannelAndNotMegaGroup(chat) ? channelSpan() : groupSpan()).append(" ").append(chat.title); + } + } + return ""; + } + + public CharSequence getReplyQuoteNameWithIcon() { + if (messageOwner == null) { + return ""; + } + CharSequence senderName = null; + CharSequence chatName = null; + if (messageOwner.reply_to == null) { + if (DialogObject.isChatDialog(getDialogId())) { + chatName = peerNameWithIcon(currentAccount, getDialogId()); + } else { + senderName = peerNameWithIcon(currentAccount, getDialogId()); + } + } else if (messageOwner.reply_to.reply_from != null) { + if (messageOwner.reply_to.reply_from.from_id != null) { + if (messageOwner.reply_to.reply_from.from_id instanceof TLRPC.TL_peerUser) { + senderName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_from.from_id, true); + } else { + chatName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_from.from_id, true); + } + } else if (messageOwner.reply_to.reply_from.saved_from_peer != null) { + if (messageOwner.reply_to.reply_from.saved_from_peer instanceof TLRPC.TL_peerUser) { + senderName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_from.saved_from_peer, true); + } else { + chatName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_from.saved_from_peer, true); + } + } else if (!TextUtils.isEmpty(messageOwner.reply_to.reply_from.from_name)) { + senderName = new SpannableStringBuilder(userSpan()).append(" ").append(messageOwner.reply_to.reply_from.from_name); + } + } + if (messageOwner.reply_to.reply_to_peer_id != null && DialogObject.getPeerDialogId(messageOwner.reply_to.reply_to_peer_id) != getDialogId()) { + if (messageOwner.reply_to.reply_to_peer_id instanceof TLRPC.TL_peerUser) { + senderName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_to_peer_id, true); + } else { + chatName = peerNameWithIcon(currentAccount, messageOwner.reply_to.reply_to_peer_id); + } + } + if (replyMessageObject != null) { + if (DialogObject.isChatDialog(replyMessageObject.getSenderId())) { + if (chatName == null) { + chatName = peerNameWithIcon(currentAccount, replyMessageObject.getSenderId()); + } + } else { + if (senderName == null) { + senderName = peerNameWithIcon(currentAccount, replyMessageObject.getSenderId()); + } + } + } + if (chatName != null && senderName != null) { + return new SpannableStringBuilder(senderName).append(" ").append(chatName); + } else if (chatName != null) { + return chatName; + } else if (senderName != null) { + return senderName; + } + return LocaleController.getString(R.string.Loading); + } + + public boolean hasLinkMediaToMakeSmall() { + final boolean hasLinkPreview = !isRestrictedMessage && MessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && MessageObject.getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage; + final TLRPC.WebPage webpage = hasLinkPreview ? MessageObject.getMedia(messageOwner).webpage : null; + final String webpageType = webpage != null ? webpage.type : null; + return hasLinkPreview && !isGiveaway() && + webpage != null && (webpage.photo != null || isVideoDocument(webpage.document)) && + !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && + !(isSponsored() && sponsoredWebPage == null && sponsoredChannelPost == 0) && // drawInstantViewType = 1 + !"telegram_megagroup".equals(webpageType) && // drawInstantViewType = 2 + !"telegram_background".equals(webpageType) && // drawInstantViewType = 6 + !"telegram_voicechat".equals(webpageType) && // drawInstantViewType = 9 + !"telegram_livestream".equals(webpageType) && // drawInstantViewType = 11 + !"telegram_user".equals(webpageType) && // drawInstantViewType = 13 + !"telegram_story".equals(webpageType) && // drawInstantViewType = 17 + !"telegram_channel_boost".equals(webpageType) // drawInstantViewType = 18 + ; + } + + public boolean isLinkMediaSmall() { + final boolean hasLinkPreview = !isRestrictedMessage && MessageObject.getMedia(messageOwner) instanceof TLRPC.TL_messageMediaWebPage && MessageObject.getMedia(messageOwner).webpage instanceof TLRPC.TL_webPage; + final TLRPC.WebPage webpage = hasLinkPreview ? MessageObject.getMedia(messageOwner).webpage : null; + final String webpageType = webpage != null ? webpage.type : null; + return !(webpage != null && TextUtils.isEmpty(webpage.description) && TextUtils.isEmpty(webpage.title)) && ("app".equals(webpageType) || "profile".equals(webpageType) || + "article".equals(webpageType) || "telegram_bot".equals(webpageType) || + "telegram_user".equals(webpageType) || "telegram_channel".equals(webpageType) || + "telegram_megagroup".equals(webpageType) || "telegram_voicechat".equals(webpageType) || + "telegram_livestream".equals(webpageType) || "telegram_channel_boost".equals(webpageType)); + } + + + public static class TextRange { + public int start, end; + + public boolean quote; + public boolean code; + public String language; + + public TextRange(int start, int end) { + this.start = start; + this.end = end; + } + public TextRange(int start, int end, boolean quote, boolean code, String language) { + this.start = start; + this.end = end; + this.quote = quote; + this.code = code; + this.language = language; + } + } + + public static void cutIntoRanges(CharSequence text, ArrayList ranges) { + if (text == null) { + return; + } + if (!(text instanceof Spanned)) { + ranges.add(new TextRange(0, text.length())); + return; + } + + final int QUOTE_START = 1; + final int QUOTE_END = 2; + final int CODE_START = 4; + final int CODE_END = 8; + + final TreeSet cutIndexes = new TreeSet<>(); + final HashMap cutToType = new HashMap<>(); + + Spanned spanned = (Spanned) text; + QuoteSpan.QuoteStyleSpan[] quoteSpans = spanned.getSpans(0, spanned.length(), QuoteSpan.QuoteStyleSpan.class); + for (int i = 0; i < quoteSpans.length; ++i) { + quoteSpans[i].span.adaptLineHeight = false; + + int start = spanned.getSpanStart(quoteSpans[i]); + int end = spanned.getSpanEnd(quoteSpans[i]); + + cutIndexes.add(start); + cutToType.put(start, (cutToType.containsKey(start) ? cutToType.get(start) : 0) | QUOTE_START); + + cutIndexes.add(end); + cutToType.put(end, (cutToType.containsKey(end) ? cutToType.get(end) : 0) | QUOTE_END); + } + + int codeSpanIndex = 0; + CodeHighlighting.Span[] codeSpans = spanned.getSpans(0, spanned.length(), CodeHighlighting.Span.class); + for (int i = 0; i < codeSpans.length; ++i) { + int start = spanned.getSpanStart(codeSpans[i]); + int end = spanned.getSpanEnd(codeSpans[i]); + + cutIndexes.add(start); + cutToType.put(start, (cutToType.containsKey(start) ? cutToType.get(start) : 0) | CODE_START); + + cutIndexes.add(end); + cutToType.put(end, (cutToType.containsKey(end) ? cutToType.get(end) : 0) | CODE_END); + } + + int from = 0; + int quoteCount = 0, codeCount = 0; + for (Iterator i = cutIndexes.iterator(); i.hasNext(); ) { + int cutIndex = i.next(); + final int type = cutToType.get(cutIndex); + + if (from != cutIndex) { + int to = cutIndex; + if (cutIndex - 1 >= 0 && cutIndex - 1 < text.length() && text.charAt(cutIndex - 1) == '\n') { + to--; + } + + String lng = null; + if ((type & CODE_END) != 0 && codeSpanIndex < codeSpans.length) { + lng = codeSpans[codeSpanIndex].lng; + codeSpanIndex++; + } + + ranges.add(new TextRange(from, to, quoteCount > 0, codeCount > 0, lng)); + from = cutIndex; + if (from + 1 < text.length() && text.charAt(from) == '\n') { + from++; + } + } + + if ((type & QUOTE_END) != 0) quoteCount--; + if ((type & QUOTE_START) != 0) quoteCount++; + if ((type & CODE_END) != 0) codeCount--; + if ((type & CODE_START) != 0) codeCount++; + } + if (from < text.length()) { + ranges.add(new TextRange(from, text.length(), quoteCount > 0, codeCount > 0, null)); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java new file mode 100644 index 000000000..410da63f6 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagePreviewParams.java @@ -0,0 +1,557 @@ +package org.telegram.messenger; + +import android.net.Uri; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.text.util.Linkify; +import android.util.Log; +import android.util.LongSparseArray; +import android.util.SparseBooleanArray; + +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.MessagePreviewView; + +import java.io.File; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MessagePreviewParams { + + private static ArrayList singletonArrayList(MessageObject obj) { + ArrayList list = new ArrayList(); + list.add(obj); + return list; + } + + public class Messages { + private Boolean out; + private int type; + private long dialogId; + + public LongSparseArray groupedMessagesMap = new LongSparseArray<>(); + public ArrayList messages; + public ArrayList previewMessages = new ArrayList<>(); + public SparseBooleanArray selectedIds = new SparseBooleanArray(); + public ArrayList pollChosenAnswers = new ArrayList<>(); + public boolean hasSpoilers; + public boolean hasText; + + public Messages(Boolean out, int type, MessageObject message) { + this(out, type, singletonArrayList(message), message.getDialogId(), null); + } + + public Messages(Boolean out, int type, MessageObject message, long newDialogId) { + this(out, type, singletonArrayList(message), newDialogId, null); + } + + public Messages(Boolean out, int type, ArrayList messages, long newDialogId, SparseBooleanArray pastSelectedIds) { + this.out = out; + this.type = type; + this.dialogId = newDialogId; + this.messages = messages; + if (pastSelectedIds != null) { + selectedIds = pastSelectedIds; + } + for (int i = 0; i < messages.size(); i++) { + MessageObject messageObject = messages.get(i); + if (type == 0 && pastSelectedIds == null) { + selectedIds.put(messageObject.getId(), true); + } + + MessageObject previewMessage = toPreviewMessage(messageObject, out, type); + if (!hasSpoilers) { + for (TLRPC.MessageEntity e : previewMessage.messageOwner.entities) { + if (e instanceof TLRPC.TL_messageEntitySpoiler) { + hasSpoilers = true; + break; + } + } + } + previewMessage.messageOwner.dialog_id = newDialogId; + if (previewMessage.getGroupId() != 0) { + MessageObject.GroupedMessages groupedMessages = groupedMessagesMap.get(previewMessage.getGroupId(), null); + if (groupedMessages == null) { + groupedMessages = new MessageObject.GroupedMessages(); + groupedMessagesMap.put(previewMessage.getGroupId(), groupedMessages); + } + groupedMessages.messages.add(previewMessage); + } + previewMessages.add(0, previewMessage); + + if (messageObject.isPoll()) { + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; + PreviewMediaPoll newMediaPoll = new PreviewMediaPoll(); + newMediaPoll.poll = mediaPoll.poll; + newMediaPoll.provider = mediaPoll.provider; + newMediaPoll.results = new TLRPC.TL_pollResults(); + newMediaPoll.totalVotersCached = newMediaPoll.results.total_voters = mediaPoll.results.total_voters; + + previewMessage.messageOwner.media = newMediaPoll; + + if (messageObject.canUnvote()) { + for (int a = 0, N = mediaPoll.results.results.size(); a < N; a++) { + TLRPC.TL_pollAnswerVoters answer = mediaPoll.results.results.get(a); + if (answer.chosen) { + TLRPC.TL_pollAnswerVoters newAnswer = new TLRPC.TL_pollAnswerVoters(); + newAnswer.chosen = answer.chosen; + newAnswer.correct = answer.correct; + newAnswer.flags = answer.flags; + newAnswer.option = answer.option; + newAnswer.voters = answer.voters; + pollChosenAnswers.add(newAnswer); + newMediaPoll.results.results.add(newAnswer); + } else { + newMediaPoll.results.results.add(answer); + } + } + } + } + } + for (int i = 0; i < groupedMessagesMap.size(); i++) { + groupedMessagesMap.valueAt(i).calculate(); + } + if (groupedMessagesMap != null && groupedMessagesMap.size() > 0) { + MessageObject.GroupedMessages group = groupedMessagesMap.valueAt(0); + hasText = group.findCaptionMessageObject() != null; + } else if (messages.size() == 1) { + MessageObject msg = messages.get(0); + if (msg.type == MessageObject.TYPE_TEXT || msg.type == MessageObject.TYPE_EMOJIS) { + hasText = !TextUtils.isEmpty(msg.messageText); + } else { + hasText = !TextUtils.isEmpty(msg.caption); + } + } + } + + public void getSelectedMessages(ArrayList messagesToForward) { + messagesToForward.clear(); + for (int i = 0; i < messages.size(); i++) { + MessageObject messageObject = messages.get(i); + int id = messageObject.getId(); + if (selectedIds.get(id, false)) { + messagesToForward.add(messageObject); + } + } + } + + public Messages checkEdits(ArrayList replaceMessageObjects) { + if (messages == null || messages.size() > 1 || replaceMessageObjects == null) { + return null; + } + + boolean replaced = false; + for (int i = 0; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg == null) continue; + for (int j = 0; j < replaceMessageObjects.size(); ++j) { + MessageObject msg2 = replaceMessageObjects.get(j); + if (msg2 == null) continue; + if (msg.getId() == msg2.getId() && msg.getDialogId() == msg2.getDialogId()) { + messages.set(i, msg2); + replaced = true; + break; + } + } + } + if (replaced) { + return new Messages(out, type, messages, dialogId, null); + } + return null; + } + } + + public Messages replyMessage; + public Messages forwardMessages; + public Messages linkMessage; + + public TLRPC.WebPage linkMedia; + + public ChatActivity.ReplyQuote quote; + public int quoteStart, quoteEnd; + public boolean hasCaption; + public boolean hasSenders; + public boolean isSecret; + public boolean multipleUsers; + + public boolean hideForwardSendersName; + public boolean hideCaption; + public boolean willSeeSenders; + + public boolean singleLink; + public boolean hasMedia; + public boolean webpageSmall; + public boolean webpageTop; + public boolean webpagePhoto; + + public boolean secret; + public boolean noforwards; + + public TLRPC.WebPage webpage; + public CharacterStyle currentLink; + + public MessagePreviewParams(boolean secret, boolean noforwards) { + this.secret = secret; + this.noforwards = secret || noforwards; + } + + public void updateReply(MessageObject replyMessageObject, MessageObject.GroupedMessages group, long dialogId, ChatActivity.ReplyQuote replyQuote) { + if (replyMessageObject == null || replyMessageObject.type == MessageObject.TYPE_DATE || replyMessageObject.type == MessageObject.TYPE_ACTION_PHOTO || replyMessageObject.type == MessageObject.TYPE_ACTION_WALLPAPER || replyMessageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) { + replyMessageObject = null; + replyQuote = null; + } + if (replyMessageObject != null || replyQuote != null) { + if (group != null) { + replyMessage = new Messages(null, 1, group.messages, dialogId, null); + } else { + replyMessage = new Messages(null, 1, replyMessageObject != null ? replyMessageObject : replyQuote.message, dialogId); + } + if (!replyMessage.messages.isEmpty()) { + this.quote = replyQuote; + if (replyQuote != null) { + quoteStart = replyQuote.start; + quoteEnd = replyQuote.end; + } + } else { + replyMessage = null; + } + } else { + replyMessage = null; + quote = null; + } + } + + public void updateLinkInvertMedia(boolean invertMedia) { + webpageTop = invertMedia; + } + + public void updateLink(int currentAccount, TLRPC.WebPage foundWebpage, CharSequence messageText, MessageObject replyMessageObject, ChatActivity.ReplyQuote replyQuote, MessageObject inherit) { + hasMedia = false; + singleLink = true; + boolean wasDifferent = webpage != foundWebpage; + webpage = foundWebpage; + if (TextUtils.isEmpty(messageText) && webpage == null) { + this.linkMessage = null; + } else { + if (messageText == null) { + messageText = ""; + } + + boolean wasEmpty = linkMessage == null || wasDifferent; + if (linkMessage == null && inherit != null && inherit.messageOwner != null) { + webpageTop = inherit.messageOwner.invert_media; + if (inherit.messageOwner.media != null && inherit.messageOwner.media.force_small_media) { + webpageSmall = true; + } + } + + TLRPC.Message message = new TLRPC.TL_message(); + messageText = new SpannableStringBuilder(AndroidUtilities.getTrimmedString(messageText)); + CharSequence[] cs = new CharSequence[] { messageText }; + message.peer_id = new TLRPC.TL_peerUser(); + message.peer_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); + message.from_id = new TLRPC.TL_peerUser(); + message.from_id.user_id = UserConfig.getInstance(currentAccount).getClientUserId(); + message.entities = MediaDataController.getInstance(currentAccount).getEntities(cs, true); + message.message = cs[0].toString(); + message.invert_media = webpageTop; + if (foundWebpage != null) { + message.flags |= 512; + message.media = new TLRPC.TL_messageMediaWebPage(); + message.media.webpage = foundWebpage; + message.media.force_large_media = !webpageSmall; + message.media.force_small_media = webpageSmall; + hasMedia = message.media.webpage.photo != null; + } else { + hasMedia = false; + } + message.out = true; + message.unread = false; + + if (replyMessageObject != null) { + message.replyMessage = replyMessageObject.messageOwner; + message.reply_to = new TLRPC.TL_messageReplyHeader(); + if (replyQuote != null) { + message.reply_to.quote_text = replyQuote.getText(); + message.reply_to.flags |= 64; + + message.reply_to.quote_entities = replyQuote.getEntities(); + if (message.reply_to.quote_entities != null) { + message.reply_to.flags |= 128; + } + } + } + + this.linkMessage = new Messages(true, 2, new MessageObject(currentAccount, message, true, false)); + if (this.linkMessage.messages.isEmpty()) { + this.linkMessage = null; + } else { + final MessageObject msg = this.linkMessage.messages.get(0); + if (msg.messageText instanceof Spanned && !TextUtils.isEmpty(msg.messageText)) { + URLSpan[] links = ((Spanned) msg.messageText).getSpans(0, msg.messageText.length(), URLSpan.class); + singleLink = links == null || links.length <= 1; + } else if (msg.caption instanceof Spanned && !TextUtils.isEmpty(msg.caption)) { + URLSpan[] links = ((Spanned) msg.messageText).getSpans(0, msg.caption.length(), URLSpan.class); + singleLink = links == null || links.length <= 1; + } + hasMedia = msg.hasLinkMediaToMakeSmall(); + if (wasEmpty && inherit != null && inherit.messageOwner != null && inherit.messageOwner.media != null) { + webpageSmall = inherit.messageOwner.media.force_small_media || msg.isLinkMediaSmall() && !inherit.messageOwner.media.force_large_media; + } else if (wasEmpty) { + webpageSmall = msg.isLinkMediaSmall(); + } + if (msg != null && msg.messageOwner != null && msg.messageOwner.media != null) { + msg.messageOwner.media.force_large_media = !webpageSmall; + msg.messageOwner.media.force_small_media = webpageSmall; + } + } + } + + if (previewView != null) { + previewView.updateLink(); + } + } + + public void checkCurrentLink(MessageObject msg) { + currentLink = null; + if (msg != null && msg.messageText instanceof Spanned && webpage != null && webpage.url != null) { + Spanned spanned = (Spanned) msg.messageText; + URLSpan[] urlSpans = spanned.getSpans(0, spanned.length(), URLSpan.class); + + for (int i = 0; i < urlSpans.length; ++i) { + if (areUrlsEqual(urlSpans[i].getURL(), webpage.url)) { + currentLink = urlSpans[i]; + break; + } + } + } + } + + public boolean hasLink(CharSequence text, String url) { + if (url != null) { + Spannable spanned = SpannableString.valueOf(text); + try { + AndroidUtilities.addLinks(spanned, Linkify.WEB_URLS); + } catch (Exception e) { + FileLog.e(e); + } + URLSpan[] urlSpans = spanned.getSpans(0, spanned.length(), URLSpan.class); + + for (int i = 0; i < urlSpans.length; ++i) { + if (areUrlsEqual(urlSpans[i].getURL(), url)) { + return true; + } + } + } + return false; + } + + public static boolean areUrlsEqual(String url1, String url2) { + if (url1 == null || url2 == null) { + return url1 == null; + } + Uri uri1 = Uri.parse(url1); + Uri uri2 = Uri.parse(url2); + return uri1 == uri2 || uri1 != null && uri2 != null && + (uri1.getHost() != null && uri1.getHost().equalsIgnoreCase(uri2.getHost())) && + uri1.getPort() == uri2.getPort() && + normalizePath(uri1.getPath()).equals(normalizePath(uri2.getPath())) && + (uri1.getQuery() == null ? uri2.getQuery() == null : uri1.getQuery().equals(uri2.getQuery())); + } + + private static String normalizePath(String path) { + if (path == null) return ""; + return (path.endsWith("/") ? path : path + "/"); + } + + public void updateForward(ArrayList forwardMessages, long dialogId) { + hasCaption = false; + hasSenders = false; + isSecret = DialogObject.isEncryptedDialog(dialogId); + multipleUsers = false; + + if (forwardMessages != null) { + ArrayList hiddenSendersName = new ArrayList<>(); + for (int i = 0; i < forwardMessages.size(); ++i) { + MessageObject messageObject = forwardMessages.get(i); + if (!TextUtils.isEmpty(messageObject.caption)) { + hasCaption = true; + } + if (!isSecret) { + if (messageObject.messageOwner.fwd_from != null) { + TLRPC.MessageFwdHeader header = messageObject.messageOwner.fwd_from; + if (header.from_id == null && !hiddenSendersName.contains(header.from_name)) { + hiddenSendersName.add(header.from_name); + } + } + } + } + this.forwardMessages = new Messages(true, 0, forwardMessages, dialogId, this.forwardMessages != null ? this.forwardMessages.selectedIds : null); + if (this.forwardMessages.messages.isEmpty()) { + this.forwardMessages = null; + } + + ArrayList uids = new ArrayList<>(); + for (int a = 0; a < forwardMessages.size(); a++) { + MessageObject object = forwardMessages.get(a); + long uid; + if (object.isFromUser()) { + uid = object.messageOwner.from_id.user_id; + } else { + TLRPC.Chat chat = MessagesController.getInstance(object.currentAccount).getChat(object.messageOwner.peer_id.channel_id); + if (ChatObject.isChannel(chat) && chat.megagroup && object.isForwardedChannelPost()) { + uid = -object.messageOwner.fwd_from.from_id.channel_id; + } else { + uid = -object.messageOwner.peer_id.channel_id; + } + } + if (!uids.contains(uid)) { + uids.add(uid); + } + } + if (uids.size() + hiddenSendersName.size() > 1) { + multipleUsers = true; + } + } else { + this.forwardMessages = null; + } + } + + private MessageObject toPreviewMessage(MessageObject messageObject, Boolean out, final int msgtype) { + TLRPC.Message message = new TLRPC.TL_message(); + if (msgtype != 1) { + message.date = ConnectionsManager.getInstance(messageObject.currentAccount).getCurrentTime(); + } else { + message.date = messageObject.messageOwner.date; + } + message.id = messageObject.messageOwner.id; + message.grouped_id = messageObject.messageOwner.grouped_id; + message.peer_id = messageObject.messageOwner.peer_id; + message.from_id = messageObject.messageOwner.from_id; + message.message = messageObject.messageOwner.message; + message.media = messageObject.messageOwner.media; + message.action = messageObject.messageOwner.action; + message.edit_date = 0; + if (messageObject.messageOwner.entities != null) { + message.entities.addAll(messageObject.messageOwner.entities); + } + + message.out = out == null ? messageObject.messageOwner.out : out; + message.unread = false; + message.via_bot_id = messageObject.messageOwner.via_bot_id; + message.reply_markup = messageObject.messageOwner.reply_markup; + message.post = messageObject.messageOwner.post; + message.legacy = messageObject.messageOwner.legacy; + message.restriction_reason = messageObject.messageOwner.restriction_reason; + message.replyMessage = messageObject.messageOwner.replyMessage; + if (message.replyMessage == null && messageObject.replyMessageObject != null) { + message.replyMessage = messageObject.replyMessageObject.messageOwner; + } + message.reply_to = messageObject.messageOwner.reply_to; + message.invert_media = messageObject.messageOwner.invert_media; + + if (msgtype == 0) { + TLRPC.MessageFwdHeader header = null; + long clientUserId = UserConfig.getInstance(messageObject.currentAccount).clientUserId; + if (!isSecret) { + if (messageObject.messageOwner.fwd_from != null) { + header = messageObject.messageOwner.fwd_from; + if (!messageObject.isDice()) { + hasSenders = true; + } else { + willSeeSenders = true; + } + } else if (messageObject.messageOwner.from_id.user_id == 0 || messageObject.messageOwner.dialog_id != clientUserId || messageObject.messageOwner.from_id.user_id != clientUserId) { + header = new TLRPC.TL_messageFwdHeader(); + header.from_id = messageObject.messageOwner.from_id; + if (!messageObject.isDice()) { + hasSenders = true; + } else { + willSeeSenders = true; + } + } + } + if (header != null) { + message.fwd_from = header; + message.flags |= TLRPC.MESSAGE_FLAG_FWD; + } + } + + MessageObject previewMessage = new MessageObject(messageObject.currentAccount, message, true, false) { + @Override + public void generateLayout(TLRPC.User fromUser) { + super.generateLayout(fromUser); + if (msgtype == 2) { + checkCurrentLink(this); + } + } + + @Override + public boolean needDrawForwarded() { + if (hideForwardSendersName) { + return false; + } + return super.needDrawForwarded(); + } + }; + previewMessage.previewForward = msgtype == 0; +// previewMessage.forceAvatar = msgtype == 1 && !message.out; + previewMessage.preview = true; + return previewMessage; + } + + public static class PreviewMediaPoll extends TLRPC.TL_messageMediaPoll { + public int totalVotersCached; + } + + public boolean isEmpty() { + return ( + (forwardMessages == null || forwardMessages.messages == null || forwardMessages.messages.isEmpty()) && + (replyMessage == null || replyMessage.messages == null || replyMessage.messages.isEmpty()) && + (linkMessage == null || linkMessage.messages == null || linkMessage.messages.isEmpty()) + ); + } + + private MessagePreviewView previewView; + public void attach(MessagePreviewView previewView) { + this.previewView = previewView; + } + + public void checkEdits(ArrayList replaceMessageObjects) { + boolean replaced = false; + if (forwardMessages != null) { + Messages newForwardMessages = forwardMessages.checkEdits(replaceMessageObjects); + if (newForwardMessages != null) { + forwardMessages = newForwardMessages; + replaced = true; + } + } + if (replyMessage != null) { + Messages newReplyMessages = replyMessage.checkEdits(replaceMessageObjects); + if (newReplyMessages != null) { + replyMessage = newReplyMessages; + replaced = true; + } + } + if (linkMessage != null) { + Messages newLinkMessages = linkMessage.checkEdits(replaceMessageObjects); + if (newLinkMessages != null) { + linkMessage = newLinkMessages; + replaced = true; + } + } + if (replaced && previewView != null) { + previewView.updateAll(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index ed06860fa..c35d8ffb5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -30,12 +30,13 @@ import android.os.SystemClock; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Base64; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.collection.LongSparseArray; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationManagerCompat; @@ -59,6 +60,8 @@ import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -158,6 +161,11 @@ public class MessagesController extends BaseController implements NotificationCe private boolean hasStories; public long storiesChangelogUserId = 777000; private ChannelBoostsController channelBoostsControler; + public long giveawayAddPeersMax = 10; + public long giveawayPeriodMax = 7; + public long giveawayCountriesMax = 10; + public long giveawayBoostsPerPremium = 4; + public long boostsPerSentGift = 3; public static TLRPC.Peer getPeerFromInputPeer(TLRPC.InputPeer peer) { if (peer.chat_id != 0) { @@ -192,13 +200,13 @@ public class MessagesController extends BaseController implements NotificationCe public ChatlistUpdatesStat() { this.loading = true; } - public ChatlistUpdatesStat(TLRPC.TL_chatlists_chatlistUpdates value) { + public ChatlistUpdatesStat(TL_chatlists.TL_chatlists_chatlistUpdates value) { this.lastRequestTime = System.currentTimeMillis(); this.lastValue = value; } boolean loading = false; long lastRequestTime; - TLRPC.TL_chatlists_chatlistUpdates lastValue; + TL_chatlists.TL_chatlists_chatlistUpdates lastValue; } private boolean dialogsInTransaction; @@ -534,6 +542,10 @@ public class MessagesController extends BaseController implements NotificationCe public int ringtoneSizeMax; public boolean storiesExportNopublicLink; public int authorizationAutoconfirmPeriod; + public int channelColorLevelMin; + public int quoteLengthMax; + public boolean giveawayGiftsPurchaseAvailable; + public PeerColors peerColors; public int channelsLimitDefault; public int channelsLimitPremium; @@ -1040,7 +1052,7 @@ public class MessagesController extends BaseController implements NotificationCe public ArrayList dialogs = new ArrayList<>(); public ArrayList dialogsForward = new ArrayList<>(); - public ArrayList invites = null; + public ArrayList invites = null; private static int dialogFilterPointer = 10; public int localId = dialogFilterPointer++; @@ -1412,6 +1424,11 @@ public class MessagesController extends BaseController implements NotificationCe largeQueueMaxActiveOperations = mainPreferences.getInt("largeQueueMaxActiveOperations", 2); stealthModeFuture = mainPreferences.getInt("stories_stealth_future_period", 25 * 60); storiesChangelogUserId = mainPreferences.getLong("stories_changelog_user_id", 777000); + giveawayAddPeersMax = mainPreferences.getLong("giveaway_add_peers_max", 10); + giveawayCountriesMax = mainPreferences.getLong("giveaway_countries_max", 10); + giveawayBoostsPerPremium = mainPreferences.getLong("giveaway_boosts_per_premium", 4); + boostsPerSentGift = mainPreferences.getLong("boosts_per_sent_gift", 3); + giveawayPeriodMax = mainPreferences.getLong("giveaway_period_max", 7); stealthModePast = mainPreferences.getInt("stories_stealth_past_period", 5 * 60); stealthModeCooldown = mainPreferences.getInt("stories_stealth_cooldown_period", 60 * 60); boolean isTest = ConnectionsManager.native_isTestBackend(currentAccount) != 0; @@ -1429,6 +1446,10 @@ public class MessagesController extends BaseController implements NotificationCe storiesEntities = mainPreferences.getString("storiesEntities", "premium"); storiesExportNopublicLink = mainPreferences.getBoolean("storiesExportNopublicLink", false); authorizationAutoconfirmPeriod = mainPreferences.getInt("authorization_autoconfirm_period", 604800); + channelColorLevelMin = mainPreferences.getInt("channelColorLevelMin", 1); + quoteLengthMax = mainPreferences.getInt("quoteLengthMax", 1024); + giveawayGiftsPurchaseAvailable = mainPreferences.getBoolean("giveawayGiftsPurchaseAvailable", false); + peerColors = PeerColors.fromString(mainPreferences.getString("peerColors", "")); BuildVars.GOOGLE_AUTH_CLIENT_ID = mainPreferences.getString("googleAuthClientId", BuildVars.GOOGLE_AUTH_CLIENT_ID); if (mainPreferences.contains("dcDomainName2")) { dcDomainName = mainPreferences.getString("dcDomainName2", "apv3.stel.com"); @@ -2195,9 +2216,66 @@ public class MessagesController extends BaseController implements NotificationCe boolean keelAliveChanged = false; resetAppConfig(); TLRPC.TL_jsonObject liteAppOptions = null; + TLRPC.TL_jsonObject peer_colors = null, dark_peer_colors = null; + TLRPC.TL_jsonArray peer_colors_available = null; for (int a = 0, N = object.value.size(); a < N; a++) { TLRPC.TL_jsonObjectValue value = object.value.get(a); switch (value.key) { + case "boosts_per_sent_gift": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + long val = (long) ((TLRPC.TL_jsonNumber) value.value).value; + if (val != boostsPerSentGift) { + boostsPerSentGift = val; + editor.putLong("boosts_per_sent_gift", boostsPerSentGift); + changed = true; + } + } + break; + } + case "giveaway_boosts_per_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + long val = (long) ((TLRPC.TL_jsonNumber) value.value).value; + if (val != giveawayBoostsPerPremium) { + giveawayBoostsPerPremium = val; + editor.putLong("giveaway_boosts_per_premium", giveawayBoostsPerPremium); + changed = true; + } + } + break; + } + case "giveaway_period_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + long val = (long) ((TLRPC.TL_jsonNumber) value.value).value; + if (val != giveawayPeriodMax) { + giveawayPeriodMax = val; + editor.putLong("giveaway_period_max", giveawayPeriodMax); + changed = true; + } + } + break; + } + case "giveaway_add_peers_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + long val = (long) ((TLRPC.TL_jsonNumber) value.value).value; + if (val != giveawayAddPeersMax) { + giveawayAddPeersMax = val; + editor.putLong("giveaway_add_peers_max", giveawayAddPeersMax); + changed = true; + } + } + break; + } + case "giveaway_countries_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + long val = (long) ((TLRPC.TL_jsonNumber) value.value).value; + if (val != giveawayCountriesMax) { + giveawayCountriesMax = val; + editor.putLong("giveaway_countries_max", giveawayCountriesMax); + changed = true; + } + } + break; + } case "stories_changelog_user_id": { if (value.value instanceof TLRPC.TL_jsonNumber) { storiesChangelogUserId = (long) ((TLRPC.TL_jsonNumber) value.value).value; @@ -3412,8 +3490,66 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "channel_color_level_min": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (channelColorLevelMin != num.value) { + channelColorLevelMin = (int) num.value; + editor.putInt("channelColorLevelMin", channelColorLevelMin); + changed = true; + } + } + break; + } + case "quote_length_max": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber num = (TLRPC.TL_jsonNumber) value.value; + if (quoteLengthMax != num.value) { + quoteLengthMax = (int) num.value; + editor.putInt("quoteLengthMax", quoteLengthMax); + changed = true; + } + } + break; + } + case "peer_colors": { + if (value.value instanceof TLRPC.TL_jsonObject) { + peer_colors = (TLRPC.TL_jsonObject) value.value; + } + break; + } + case "dark_peer_colors": { + if (value.value instanceof TLRPC.TL_jsonObject) { + dark_peer_colors = (TLRPC.TL_jsonObject) value.value; + } + break; + } + case "peer_colors_available": { + if (value.value instanceof TLRPC.TL_jsonArray) { + peer_colors_available = (TLRPC.TL_jsonArray) value.value; + } + break; + } + case "giveaway_gifts_purchase_available": { + if (value.value instanceof TLRPC.TL_jsonBool) { + if (giveawayGiftsPurchaseAvailable != ((TLRPC.TL_jsonBool) value.value).value) { + giveawayGiftsPurchaseAvailable = ((TLRPC.TL_jsonBool) value.value).value; + editor.putBoolean("giveawayGiftsPurchaseAvailable", giveawayGiftsPurchaseAvailable); + changed = true; + } + } + break; + } } } + + PeerColors newPeerColors = PeerColors.fromJSON(peer_colors, dark_peer_colors, peer_colors_available); + if (peerColors == null || !TextUtils.equals(peerColors.toString(), newPeerColors.toString())) { + peerColors = newPeerColors; + editor.putString("peerColors", peerColors.toString()); + changed = true; + } + if (changed) { editor.apply(); } @@ -3433,6 +3569,196 @@ public class MessagesController extends BaseController implements NotificationCe logDeviceStats(); } + public static class PeerColors { + + public final ArrayList colors = new ArrayList<>(); + private final LongSparseArray colorsById = new LongSparseArray<>(); + + private PeerColors() {} + + @Nullable + public PeerColor getColor(int colorId) { + return colorsById.get(colorId); + } + + @NonNull + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < colors.size(); ++i) { + PeerColor color = colors.get(i); + if (i > 0) sb.append(";"); + color.appendString(sb); + } + return sb.toString(); + } + + public static PeerColors fromString(String str) { + if (str == null) return null; + final PeerColors peerColors = new PeerColors(); + final String[] colorParts = str.split(";"); + for (int i = 0; i < colorParts.length; ++i) { + PeerColor peerColor = PeerColor.fromString(colorParts[i]); + if (peerColor == null) + continue; + peerColors.colors.add(peerColor); + peerColors.colorsById.put(peerColor.id, peerColor); + } + return peerColors; + } + + private static int color(String str) { + return Integer.parseUnsignedInt("ff" + str, 16); + } + + public static PeerColors fromJSON( + TLRPC.TL_jsonObject peer_colors, + TLRPC.TL_jsonObject dark_peer_colors, + TLRPC.TL_jsonArray peer_colors_available + ) { + try { + PeerColors peerColors = new PeerColors(); + if (peer_colors != null) { + for (TLRPC.TL_jsonObjectValue pair : peer_colors.value) { + final int id = Utilities.parseInt(pair.key); + if (!(pair.value instanceof TLRPC.TL_jsonArray)) + continue; + ArrayList val = ((TLRPC.TL_jsonArray) pair.value).value; + if (val.isEmpty()) + continue; + + PeerColor peerColor = new PeerColor(); + try { + peerColor.id = id; + peerColor.color1 = peerColor.darkColor1 = color(((TLRPC.TL_jsonString) val.get(0)).value); + peerColor.color2 = peerColor.darkColor2 = val.size() > 1 ? color(((TLRPC.TL_jsonString) val.get(1)).value) : peerColor.color1; + peerColor.color3 = peerColor.darkColor3 = val.size() > 2 ? color(((TLRPC.TL_jsonString) val.get(2)).value) : peerColor.color1; + } catch (Exception e2) { + FileLog.e(e2); + continue; + } + if (peerColor.id < 7) continue; + peerColors.colorsById.put(id, peerColor); + } + } + if (dark_peer_colors != null) { + for (TLRPC.TL_jsonObjectValue pair : dark_peer_colors.value) { + final int id = Utilities.parseInt(pair.key); + if (!(pair.value instanceof TLRPC.TL_jsonArray)) + continue; + ArrayList val = ((TLRPC.TL_jsonArray) pair.value).value; + if (val.isEmpty()) + continue; + + PeerColor peerColor = peerColors.colorsById.get(id); + if (peerColor == null) continue; + try { + peerColor.id = id; + peerColor.darkColor1 = color(((TLRPC.TL_jsonString) val.get(0)).value); + peerColor.darkColor2 = val.size() > 1 ? color(((TLRPC.TL_jsonString) val.get(1)).value) : peerColor.darkColor1; + peerColor.darkColor3 = val.size() > 2 ? color(((TLRPC.TL_jsonString) val.get(2)).value) : peerColor.darkColor1; + } catch (Exception e2) { + FileLog.e(e2); + continue; + } + peerColors.colorsById.put(id, peerColor); + } + } + peerColors.colors.clear(); + if (peer_colors_available != null) { + for (TLRPC.JSONValue idvalue : peer_colors_available.value) { + if (!(idvalue instanceof TLRPC.TL_jsonNumber)) + continue; + final int id = (int) ((TLRPC.TL_jsonNumber) idvalue).value; + PeerColor color = peerColors.colorsById.get(id); + if (color == null) continue; + peerColors.colors.add(color); + } + } + return peerColors; + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + } + + public static class PeerColor { + public int id; + private int color1, color2, color3; + private int darkColor1, darkColor2, darkColor3; + public int getColor1() { + return Theme.isCurrentThemeDark() ? darkColor1 : color1; + } + public int getColor2() { + return Theme.isCurrentThemeDark() ? darkColor2 : color2; + } + public int getColor3() { + return Theme.isCurrentThemeDark() ? darkColor3 : color3; + } + public boolean hasColor2() { + return getColor2() != getColor1(); + } + public boolean hasColor3() { + return getColor3() != getColor1(); + } + public void appendString(StringBuilder sb) { + sb.append("#"); + sb.append(id); + sb.append("{"); + sb.append(color1); + if (color2 != color1) { + sb.append(","); + sb.append(color2); + if (color3 != color1) { + sb.append(","); + sb.append(color3); + } + } + if (darkColor1 != color1 || darkColor2 != color2 || darkColor3 != color3) { + sb.append("@"); + sb.append(darkColor1); + if (darkColor2 != darkColor1) { + sb.append(","); + sb.append(darkColor2); + if (darkColor3 != darkColor1) { + sb.append(","); + sb.append(darkColor3); + } + } + } + sb.append("}"); + } + public static PeerColor fromString(String string) { + if (string == null || string.isEmpty() || string.charAt(0) != '#') + return null; + int index = string.indexOf('{'); + if (index < 0) return null; + try { + final PeerColor peerColor = new PeerColor(); + peerColor.id = Utilities.parseInt(string.substring(1, index)); + final String[] parts = string.substring(index + 1, string.length() - 1).split("@"); + String[] colorsString = parts[0].split(","); + peerColor.color1 = Utilities.parseInt(colorsString[0]); + peerColor.color2 = colorsString.length >= 2 ? Utilities.parseInt(colorsString[1]) : peerColor.color1; + peerColor.color3 = colorsString.length >= 3 ? Utilities.parseInt(colorsString[2]) : peerColor.color1; + if (parts.length >= 2) { + colorsString = parts[1].split(","); + peerColor.darkColor1 = Utilities.parseInt(colorsString[0]); + peerColor.darkColor2 = colorsString.length >= 2 ? Utilities.parseInt(colorsString[1]) : peerColor.color1; + peerColor.darkColor3 = colorsString.length >= 3 ? Utilities.parseInt(colorsString[2]) : peerColor.color1; + } else { + peerColor.darkColor1 = peerColor.color1; + peerColor.darkColor2 = peerColor.color2; + peerColor.darkColor3 = peerColor.color3; + } + return peerColor; + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + } + private void resetAppConfig() { getfileExperimentalParams = false; collectDeviceStats = false; @@ -3848,7 +4174,8 @@ public class MessagesController extends BaseController implements NotificationCe if (bigSize != null) { user.photo.photo_big = bigSize.location; } - getMessagesStorage().clearUserPhotos(user.id); + getDialogPhotos(user.id).reset(); + getDialogPhotos(user.id).load(0, DialogPhotos.STEP); ArrayList users = new ArrayList<>(); users.add(user); getMessagesStorage().putUsersAndChats(users, null, false, true); @@ -5137,7 +5464,7 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.TL_messages_chatFull res = (TLRPC.TL_messages_chatFull) response; getMessagesStorage().putUsersAndChats(res.users, res.chats, true, true); getMessagesStorage().updateChatInfo(res.full_chat, false); - + getStoriesController().updateStoriesFromFullPeer(dialogId, res.full_chat.stories); if (ChatObject.isChannel(chat)) { Integer value = dialogs_read_inbox_max.get(dialogId); if (value == null) { @@ -5252,6 +5579,7 @@ public class MessagesController extends BaseController implements NotificationCe putChats(res.chats, false); res.full_user.user = getUser(res.full_user.id); getMessagesStorage().updateUserInfo(userFull, false); + getStoriesController().updateStoriesFromFullPeer(dialogId, userFull.stories); ChatThemeController.getInstance(currentAccount).saveChatWallpaper(res.full_user.id, res.full_user.wallpaper); AndroidUtilities.runOnUIThread(() -> { @@ -5762,55 +6090,340 @@ public class MessagesController extends BaseController implements NotificationCe }); } - public void loadDialogPhotos(long did, int count, int maxId, boolean fromCache, int classGuid) { - if (fromCache) { - getMessagesStorage().getDialogPhotos(did, count, maxId, classGuid); - } else { - if (did > 0) { - TLRPC.User user = getUser(did); + private LongSparseArray dialogPhotos = new LongSparseArray<>(); + + public DialogPhotos getDialogPhotos(long dialogId) { + DialogPhotos photos = dialogPhotos.get(dialogId); + if (photos == null) { + dialogPhotos.put(dialogId, photos = new DialogPhotos(dialogId)); + } + return photos; + } + + public class DialogPhotos { + + public final long dialogId; + public final ArrayList photos = new ArrayList<>(); + public boolean fromCache = true; + public boolean loaded = false; + + public final static int STEP = 80; + + public DialogPhotos(long dialogId) { + this.dialogId = dialogId; + } + + public void loadAfter(int position, boolean after) { + if (photos.isEmpty()) { + load(0, STEP); + return; + } + if (position < 0) { + position += photos.size(); + } + if (position >= photos.size()) { + position -= photos.size(); + } + if (position < 0 || position >= photos.size()) { + return; + } + + boolean hasEmpty = false; + for (int i = 0; i < photos.size(); ++i) { + if (photos.get(i) == null) { + hasEmpty = true; + break; + } + } + + if (!hasEmpty) { + return; + } + + if (after) { + int p = position; + while (photos.get(p) != null) { + p++; + if (p >= photos.size()) { + p = 0; + } + } + int count; + for (count = 0; count <= STEP && p + count < photos.size() && photos.get(p + count) == null; ++count); + if (count > 0) { + load(p, count); + } + } else { + int p = position; + while (photos.get(p) != null) { + p--; + if (p < 0) { + p = photos.size() - 1; + } + } + int count; + for (count = 0; count <= STEP && p - count >= 0 && photos.get(p - count) == null; ++count); + if (count > 0) { + load(p - count, count); + } + } + } + + + private boolean loading; + public void load(int offset, int count) { + if (loading || count <= 0 || offset < 0) { + return; + } + + loading = true; + int reqId; + if (dialogId >= 0) { + TLRPC.User user = getUser(dialogId); if (user == null) { + loading = false; return; } TLRPC.TL_photos_getUserPhotos req = new TLRPC.TL_photos_getUserPhotos(); + req.offset = offset; req.limit = count; - req.offset = 0; - req.max_id = maxId; + req.max_id = 0; req.user_id = getInputUser(user); - int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { + reqId = getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { - TLRPC.photos_Photos res = (TLRPC.photos_Photos) response; - processLoadedUserPhotos(res, null, did, count, maxId, false, classGuid); + final TLRPC.photos_Photos res = (TLRPC.photos_Photos) response; + getMessagesStorage().putUsersAndChats(res.users, null, true, true); + AndroidUtilities.runOnUIThread(() -> { + putUsers(res.users, false); + onLoaded(offset, count, res); + }); } }); - getConnectionsManager().bindRequestToGuid(reqId, classGuid); - } else if (did < 0) { + } else { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.filter = new TLRPC.TL_inputMessagesFilterChatPhotos(); + req.add_offset = offset; req.limit = count; - req.offset_id = maxId; + req.offset_id = 0; req.q = ""; - req.peer = getInputPeer(did); - int reqId = getConnectionsManager().sendRequest(req, (response, error) -> { + req.peer = getInputPeer(dialogId); + reqId = getConnectionsManager().sendRequest(req, (response, error) -> { if (error == null) { TLRPC.messages_Messages messages = (TLRPC.messages_Messages) response; - TLRPC.TL_photos_photos res = new TLRPC.TL_photos_photos(); - ArrayList arrayList = new ArrayList<>(); - res.count = messages.count; - res.users.addAll(messages.users); - for (int a = 0; a < messages.messages.size(); a++) { - TLRPC.Message message = messages.messages.get(a); - if (message.action == null || message.action.photo == null) { - continue; + getMessagesStorage().putUsersAndChats(messages.users, messages.chats, true, true); + AndroidUtilities.runOnUIThread(() -> { + putUsers(messages.users, false); + putChats(messages.chats, false); + TLRPC.photos_Photos res = new TLRPC.TL_photos_photos(); + res.count = messages.count; + for (int a = 0; a < messages.messages.size(); a++) { + TLRPC.Message message = messages.messages.get(a); + if (message.action == null || message.action.photo == null) { + continue; + } + res.photos.add(message.action.photo); } - res.photos.add(message.action.photo); - arrayList.add(message); - } - processLoadedUserPhotos(res, arrayList, did, count, maxId, false, classGuid); + onLoaded(offset, count, res); + }); } }); - getConnectionsManager().bindRequestToGuid(reqId, classGuid); } } + + private void onLoaded(int offset, int count, TLRPC.photos_Photos res) { + boolean wasLoaded = loaded; + loading = false; + loaded = true; + fromCache = false; + + res.count = Math.max(res.count, res.photos.size()); + + boolean reset = res.count != photos.size() || offset + count > photos.size(); + if (!reset) { + for (int i = 0; i < res.photos.size(); ++i) { + if (photos.get(offset + i) != null && photos.get(offset + i).id != res.photos.get(i).id) { + reset = true; + break; + } + } + } + + if (reset) { + photos.clear(); + for (int i = 0; i < res.count; ++i) { + int lindex = i - offset; + photos.add(lindex >= 0 && lindex < res.photos.size() ? res.photos.get(lindex) : null); + } + } else { + for (int i = 0; i < res.photos.size(); ++i) { + photos.set(offset + i, res.photos.get(i)); + } + } + + saveCache(); + getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosUpdate, this); + + if (!wasLoaded && offset == 0 && count < photos.size() && photos.size() - count > STEP) { + load(photos.size() - STEP, STEP); + } + } + + public void addPhotoAtStart(TLRPC.Photo photo) { + if (true) { + return; + } + if (photo == null || !loaded && !fromCache) { + return; + } + + removePhotoInternal(photo.id); + photos.add(0, photo); + saveCache(); + + getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosUpdate, this); + } + + public void removePhoto(long photoId) { + if (removePhotoInternal(photoId)) { + saveCache(); + getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosUpdate, this); + } + } + + public void moveToStart(int index) { + if (index < 0 || index >= photos.size()) { + return; + } + + photos.add(0, photos.remove(index)); + saveCache(); + getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosUpdate, this); + } + + private boolean removePhotoInternal(long photoId) { + boolean changed = false; + for (int i = 0; i < photos.size(); ++i) { + TLRPC.Photo p = photos.get(i); + if (p != null && p.id == photoId) { + photos.remove(i); + i--; + changed = true; + } + } + return changed; + } + + public int getCount() { + return photos.size(); + } + + public void loadCache() { + getMessagesStorage().getStorageQueue().postRunnable(() -> { + SQLiteDatabase database = getMessagesStorage().getDatabase(); + SQLiteCursor cursor = null; + int count = 0; + final HashMap photoEntries = new HashMap<>(); + try { + cursor = database.queryFinalized(String.format(Locale.US, "SELECT count FROM dialog_photos_count WHERE uid = %d", dialogId)); + if (cursor.next()) { + count = cursor.intValue(0); + } + cursor.dispose(); + cursor = null; + + cursor = database.queryFinalized(String.format(Locale.US, "SELECT num, data FROM dialog_photos WHERE uid = %d", dialogId)); + while (cursor.next()) { + int position = cursor.intValue(0); + TLRPC.Photo photo = null; + NativeByteBuffer data = cursor.byteBufferValue(1); + if (data != null) { + int magic = data.readInt32(false); + if (magic == TLRPC.TL_null.constructor) { + photo = null; + } else { + photo = TLRPC.Photo.TLdeserialize(data, magic, false); + } + } + if (photo != null) { + photoEntries.put(position, photo); + } + } + cursor.dispose(); + cursor = null; + } catch (Exception e) { + + } finally { + if (cursor != null) { + cursor.dispose(); + cursor = null; + } + } + + count = Math.max(count, photoEntries.size()); + final int finalCount = count; + AndroidUtilities.runOnUIThread(() -> { + photos.clear(); + for (int i = 0; i < finalCount; ++i) { + photos.add(null); + } + for (Map.Entry entry : photoEntries.entrySet()) { + photos.set(entry.getKey(), entry.getValue()); + } + getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosUpdate, this); + + load(0, STEP); + }); + }); + } + + private void saveCache() { + getMessagesStorage().getStorageQueue().postRunnable(() -> { + SQLiteDatabase database = getMessagesStorage().getDatabase(); + SQLitePreparedStatement state = null; + try { + database.executeFast("DELETE FROM dialog_photos WHERE uid = " + dialogId).stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos_count WHERE uid = " + dialogId).stepThis().dispose(); + + database.executeFast("REPLACE INTO dialog_photos_count VALUES(" + dialogId + ", " + photos.size() + ")").stepThis().dispose(); + + state = database.executeFast("REPLACE INTO dialog_photos VALUES(?, ?, ?, ?)"); + for (int i = 0; i < photos.size(); ++i) { + TLRPC.Photo photo = photos.get(i); + if (photo == null) { + continue; + } + if (photo.file_reference == null) { + photo.file_reference = new byte[0]; + } + + state.requery(); + NativeByteBuffer data = new NativeByteBuffer(photo.getObjectSize()); + photo.serializeToStream(data); + state.bindLong(1, dialogId); + state.bindLong(2, photo.id); + state.bindInteger(3, i); + state.bindByteBuffer(4, data); + state.step(); + data.reuse(); + } + state.dispose(); + state = null; + } catch (Exception e) { + + } finally { + if (state != null) { + state.dispose(); + state = null; + } + } + }); + } + + public void reset() { + photos.clear(); + fromCache = true; + saveCache(); + } } public void blockPeer(long id) { @@ -6046,7 +6659,17 @@ public class MessagesController extends BaseController implements NotificationCe } public void deleteUserPhoto(TLRPC.InputPhoto photo) { + long dialogId = getUserConfig().getClientUserId(); if (photo == null) { + + DialogPhotos photos = getDialogPhotos(dialogId); + if (photos != null && photos.photos.size() > 0) { + TLRPC.Photo removingPhoto = photos.photos.get(0); + if (removingPhoto != null) { + photos.removePhoto(removingPhoto.id); + } + } + TLRPC.TL_photos_updateProfilePhoto req = new TLRPC.TL_photos_updateProfilePhoto(); req.id = new TLRPC.TL_inputPhotoEmpty(); // getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty(); @@ -6092,7 +6715,7 @@ public class MessagesController extends BaseController implements NotificationCe user1.photo = new TLRPC.TL_userProfilePhotoEmpty(); } - TLRPC.UserFull userFull = getUserFull(getUserConfig().getClientUserId()); + TLRPC.UserFull userFull = getUserFull(dialogId); userFull.profile_photo = photos_photo.photo; getMessagesStorage().updateUserInfo(userFull, false); @@ -6109,25 +6732,13 @@ public class MessagesController extends BaseController implements NotificationCe } else { TLRPC.TL_photos_deletePhotos req = new TLRPC.TL_photos_deletePhotos(); req.id.add(photo); + getDialogPhotos(dialogId).removePhoto(photo.id); getConnectionsManager().sendRequest(req, (response, error) -> { }); } } - public void processLoadedUserPhotos(final TLRPC.photos_Photos res, ArrayList messages, long did, int count, int maxId, boolean fromCache, int classGuid) { - if (!fromCache) { - getMessagesStorage().putUsersAndChats(res.users, null, true, true); - getMessagesStorage().putDialogPhotos(did, res, messages); - } else if (res == null || res.photos.isEmpty()) { - loadDialogPhotos(did, count, maxId, false, classGuid); - } - AndroidUtilities.runOnUIThread(() -> { - putUsers(res.users, fromCache); - getNotificationCenter().postNotificationName(NotificationCenter.dialogPhotosLoaded, did, count, fromCache, classGuid, res.photos, messages); - }); - } - public void uploadAndApplyUserAvatar(TLRPC.FileLocation location) { if (location == null) { return; @@ -8489,16 +9100,6 @@ public class MessagesController extends BaseController implements NotificationCe reload = ((SystemClock.elapsedRealtime() - lastScheduledServerQueryTime.get(dialogId, 0L)) > 60 * 1000); } else { reload = resCount == 0 && (!isInitialLoading || (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 60 * 1000 || (isCache && isTopic)); -// if (isCache && dialogId < 0) { -// TLRPC.Chat chat = getChat(-dialogId); -// if (chat == null) { -// chat = chatsDict.get(-dialogId); -// } -// if (chat != null && mode == 0 && ChatObject.isNotInChat(chat) && (SystemClock.elapsedRealtime() - lastServerQueryTime.get(dialogId, 0L)) > 24 * 60 * 60 * 1000) { -// messagesRes.messages.clear(); -// reload = true; -// } -// } } if (!DialogObject.isEncryptedDialog(dialogId) && isCache && reload) { int hash; @@ -8620,6 +9221,14 @@ public class MessagesController extends BaseController implements NotificationCe if (loaderLogger != null) { loaderLogger.logStageQueueProcessing(); } + if (mode == ChatActivity.MODE_SCHEDULED) { + Collections.sort(objects, (o1, o2) -> { + if (o1.messageOwner.date == o2.messageOwner.date && o1.getId() >= 0 && o2.getId() >= 0) { + return o2.getId() - o1.getId(); + } + return o2.messageOwner.date - o1.messageOwner.date; + }); + } AndroidUtilities.runOnUIThread(() -> { putUsers(messagesRes.users, isCache); putChats(messagesRes.chats, isCache); @@ -8648,7 +9257,7 @@ public class MessagesController extends BaseController implements NotificationCe } } if (mode == 1 && count == 1) { - getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialogId, objects.size()); + getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, dialogId, objects.size(), false); } ArrayList messArr = (ArrayList) objects; @@ -12197,7 +12806,7 @@ public class MessagesController extends BaseController implements NotificationCe File src = new File(videoPath); src.renameTo(destFile); } - getMessagesStorage().addDialogPhoto(-chatId, photo); + getDialogPhotos(-chatId).addPhotoAtStart(photo); } } processUpdates(updates, false); @@ -14978,8 +15587,8 @@ public class MessagesController extends BaseController implements NotificationCe chatInfoToUpdate = new ArrayList<>(); } chatInfoToUpdate.add(update.participants); - } if (baseUpdate instanceof TLRPC.TL_updateStory) { - getStoriesController().processUpdate((TLRPC.TL_updateStory) baseUpdate); + } if (baseUpdate instanceof TL_stories.TL_updateStory) { + getStoriesController().processUpdate((TL_stories.TL_updateStory) baseUpdate); } else if (baseUpdate instanceof TLRPC.TL_updateUserStatus) { interfaceUpdateMask |= UPDATE_MASK_STATUS; if (updatesOnMainThread == null) { @@ -15002,6 +15611,9 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.TL_updateUserPhoto update = (TLRPC.TL_updateUserPhoto) baseUpdate; interfaceUpdateMask |= UPDATE_MASK_AVATAR; getMessagesStorage().clearUserPhotos(update.user_id); + if (dialogPhotos.get(update.user_id) != null) { + dialogPhotos.get(update.user_id).reset(); + } if (updatesOnMainThread == null) { updatesOnMainThread = new ArrayList<>(); } @@ -15020,8 +15632,8 @@ public class MessagesController extends BaseController implements NotificationCe updatesOnMainThread = new ArrayList<>(); } updatesOnMainThread.add(baseUpdate); - } else if (baseUpdate instanceof TLRPC.TL_updateReadStories) { - TLRPC.TL_updateReadStories updateReadStories = (TLRPC.TL_updateReadStories) baseUpdate; + } else if (baseUpdate instanceof TL_stories.TL_updateReadStories) { + TL_stories.TL_updateReadStories updateReadStories = (TL_stories.TL_updateReadStories) baseUpdate; long dialogId = DialogObject.getPeerDialogId(updateReadStories.peer); getStoriesController().markStoriesAsReadFromServer(dialogId, updateReadStories.max_id); } else if (baseUpdate instanceof TLRPC.TL_updatePeerSettings) { @@ -15172,6 +15784,7 @@ public class MessagesController extends BaseController implements NotificationCe } if ((update.flags & 2) != 0) { TLRPC.TL_message newMessage = new TLRPC.TL_message(); + newMessage.invert_media = update.invert_media; newMessage.local_id = newMessage.id = getUserConfig().getNewMessageId(); getUserConfig().saveConfig(false); newMessage.unread = true; @@ -15216,7 +15829,7 @@ public class MessagesController extends BaseController implements NotificationCe } pushMessages.add(obj); } - } else if (baseUpdate instanceof TLRPC.TL_updateStoriesStealthMode) { + } else if (baseUpdate instanceof TL_stories.TL_updateStoriesStealthMode) { if (updatesOnMainThread == null) { updatesOnMainThread = new ArrayList<>(); } @@ -16242,8 +16855,8 @@ public class MessagesController extends BaseController implements NotificationCe } int threadId = update.top_msg_id; getMediaDataController().saveDraft(did, threadId, update.draft, null, true); - } else if (baseUpdate instanceof TLRPC.TL_updateStoriesStealthMode) { - TLRPC.TL_updateStoriesStealthMode storiesStealthModeUpdate = (TLRPC.TL_updateStoriesStealthMode) baseUpdate; + } else if (baseUpdate instanceof TL_stories.TL_updateStoriesStealthMode) { + TL_stories.TL_updateStoriesStealthMode storiesStealthModeUpdate = (TL_stories.TL_updateStoriesStealthMode) baseUpdate; getStoriesController().setStealthMode(storiesStealthModeUpdate.stealth_mode); } else if (baseUpdate instanceof TLRPC.TL_updateReadFeaturedStickers) { getMediaDataController().markFeaturedStickersAsRead(false, false); @@ -17915,7 +18528,7 @@ public class MessagesController extends BaseController implements NotificationCe } for (int a = 0, N = reasons.size(); a < N; a++) { TLRPC.TL_restrictionReason reason = reasons.get(a); - if ("all".equals(reason.platform) || !BuildVars.isStandaloneApp() && !BuildVars.isBetaApp() && "android".equals(reason.platform)) { + if ("all".equals(reason.platform) || !ApplicationLoader.isStandaloneBuild() && !BuildVars.isBetaApp() && "android".equals(reason.platform)) { return reason.text; } } @@ -18770,12 +19383,12 @@ public class MessagesController extends BaseController implements NotificationCe } final ChatlistUpdatesStat finalStat = stat; finalStat.loading = false; - TLRPC.TL_chatlists_getChatlistUpdates req = new TLRPC.TL_chatlists_getChatlistUpdates(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_getChatlistUpdates req = new TL_chatlists.TL_chatlists_getChatlistUpdates(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - if (res instanceof TLRPC.TL_chatlists_chatlistUpdates) { - TLRPC.TL_chatlists_chatlistUpdates updates = (TLRPC.TL_chatlists_chatlistUpdates) res; + if (res instanceof TL_chatlists.TL_chatlists_chatlistUpdates) { + TL_chatlists.TL_chatlists_chatlistUpdates updates = (TL_chatlists.TL_chatlists_chatlistUpdates) res; putChats(updates.chats, false); putUsers(updates.users, false); chatlistFoldersUpdates.put(filterId, new ChatlistUpdatesStat(updates)); @@ -18787,7 +19400,7 @@ public class MessagesController extends BaseController implements NotificationCe } } - public TLRPC.TL_chatlists_chatlistUpdates getChatlistFolderUpdates(int filterId) { + public TL_chatlists.TL_chatlists_chatlistUpdates getChatlistFolderUpdates(int filterId) { ChatlistUpdatesStat stat = chatlistFoldersUpdates.get(filterId); if (stat == null) { return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 8a6a931ae..e91636db0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -36,6 +36,7 @@ import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.DialogsActivity; @@ -100,7 +101,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 134; + public final static int LAST_DB_VERSION = 135; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -465,7 +466,7 @@ public class MessagesStorage extends BaseController { "channel_users_v2", "channel_admins_v3", "contacts", - "user_photos", + "dialog_photos", "dialog_settings", "web_recent_v3", "stickers_v2", @@ -593,7 +594,8 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE channel_users_v2(did INTEGER, uid INTEGER, date INTEGER, data BLOB, PRIMARY KEY(did, uid))").stepThis().dispose(); database.executeFast("CREATE TABLE channel_admins_v3(did INTEGER, uid INTEGER, data BLOB, PRIMARY KEY(did, uid))").stepThis().dispose(); database.executeFast("CREATE TABLE contacts(uid INTEGER PRIMARY KEY, mutual INTEGER)").stepThis().dispose(); - database.executeFast("CREATE TABLE user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); + database.executeFast("CREATE TABLE dialog_photos(uid INTEGER, id INTEGER, num INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose(); + database.executeFast("CREATE TABLE dialog_photos_count(uid INTEGER PRIMARY KEY, count INTEGER)").stepThis().dispose(); database.executeFast("CREATE TABLE dialog_settings(did INTEGER PRIMARY KEY, flags INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE web_recent_v3(id TEXT, type INTEGER, image_url TEXT, thumb_url TEXT, local_url TEXT, width INTEGER, height INTEGER, size INTEGER, date INTEGER, document BLOB, PRIMARY KEY (id, type));").stepThis().dispose(); database.executeFast("CREATE TABLE stickers_v2(id INTEGER PRIMARY KEY, data BLOB, date INTEGER, hash INTEGER);").stepThis().dispose(); @@ -1351,6 +1353,8 @@ public class MessagesStorage extends BaseController { database.executeFast("DELETE FROM chat_pinned_count").stepThis().dispose(); database.executeFast("DELETE FROM profile_stories").stepThis().dispose(); database.executeFast("DELETE FROM story_pushes").stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos").stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos_count").stepThis().dispose(); cursor = database.queryFinalized("SELECT did FROM dialogs WHERE 1"); while (cursor.next()) { @@ -4070,51 +4074,11 @@ public class MessagesStorage extends BaseController { }); } - public void getDialogPhotos(long did, int count, int maxId, int classGuid) { - storageQueue.postRunnable(() -> { - SQLiteCursor cursor = null; - try { - - if (maxId != 0) { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d AND id < %d ORDER BY rowid ASC LIMIT %d", did, maxId, count)); - } else { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d ORDER BY rowid ASC LIMIT %d", did, count)); - } - - TLRPC.photos_Photos res = new TLRPC.TL_photos_photos(); - ArrayList messages = new ArrayList<>(); - - while (cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - TLRPC.Photo photo = TLRPC.Photo.TLdeserialize(data, data.readInt32(false), false); - if (data.remaining() > 0) { - messages.add(TLRPC.Message.TLdeserialize(data, data.readInt32(false), false)); - } else { - messages.add(null); - } - data.reuse(); - res.photos.add(photo); - } - } - cursor.dispose(); - cursor = null; - - Utilities.stageQueue.postRunnable(() -> getMessagesController().processLoadedUserPhotos(res, messages, did, count, maxId, true, classGuid)); - } catch (Exception e) { - checkSQLException(e); - } finally { - if (cursor != null) { - cursor.dispose(); - } - } - }); - } - public void clearUserPhotos(long dialogId) { storageQueue.postRunnable(() -> { try { - database.executeFast("DELETE FROM user_photos WHERE uid = " + dialogId).stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos WHERE uid = " + dialogId).stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos_count WHERE uid = " + dialogId).stepThis().dispose(); } catch (Exception e) { checkSQLException(e); } @@ -4124,7 +4088,8 @@ public class MessagesStorage extends BaseController { public void clearUserPhoto(long dialogId, long pid) { storageQueue.postRunnable(() -> { try { - database.executeFast("DELETE FROM user_photos WHERE uid = " + dialogId + " AND id = " + pid).stepThis().dispose(); + database.executeFast("DELETE FROM dialog_photos WHERE uid = " + dialogId + " AND id = " + pid).stepThis().dispose(); + database.executeFast("UPDATE dialog_photos_count SET count = count - 1 WHERE uid = " + dialogId + " AND count > 0").stepThis().dispose(); } catch (Exception e) { checkSQLException(e); } @@ -4292,92 +4257,6 @@ public class MessagesStorage extends BaseController { }); } - public void putDialogPhotos(long did, TLRPC.photos_Photos photos, ArrayList messages) { - if (photos == null) { - return; - } - storageQueue.postRunnable(() -> { - putDialogPhotosInternal(did, photos, messages); - }); - } - - private void putDialogPhotosInternal(long did, TLRPC.photos_Photos photos, ArrayList messages) { - SQLitePreparedStatement state = null; - try { - database.executeFast("DELETE FROM user_photos WHERE uid = " + did).stepThis().dispose(); - state = database.executeFast("REPLACE INTO user_photos VALUES(?, ?, ?)"); - for (int a = 0, N = photos.photos.size(); a < N; a++) { - TLRPC.Photo photo = photos.photos.get(a); - if (photo instanceof TLRPC.TL_photoEmpty || photo == null) { - continue; - } - if (photo.file_reference == null) { - photo.file_reference = new byte[0]; - } - state.requery(); - int size = photo.getObjectSize(); - if (messages != null && a < messages.size() && messages.get(a) != null) { - size += messages.get(a).getObjectSize(); - } - NativeByteBuffer data = new NativeByteBuffer(size); - photo.serializeToStream(data); - if (messages != null && a < messages.size() && messages.get(a) != null) { - messages.get(a).serializeToStream(data); - } - state.bindLong(1, did); - state.bindLong(2, photo.id); - state.bindByteBuffer(3, data); - state.step(); - data.reuse(); - } - state.dispose(); - state = null; - } catch (Exception e) { - checkSQLException(e); - } finally { - if (state != null) { - state.dispose(); - } - } - } - - public void addDialogPhoto(long did, TLRPC.Photo photoToAdd) { - storageQueue.postRunnable(() -> { - SQLiteCursor cursor = null; - try { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM user_photos WHERE uid = %d ORDER BY rowid ASC", did)); - - TLRPC.photos_Photos res = new TLRPC.TL_photos_photos(); - ArrayList messages = new ArrayList<>(); - - while (cursor.next()) { - NativeByteBuffer data = cursor.byteBufferValue(0); - if (data != null) { - TLRPC.Photo photo = TLRPC.Photo.TLdeserialize(data, data.readInt32(false), false); - if (data.remaining() > 0) { - messages.add(TLRPC.Message.TLdeserialize(data, data.readInt32(false), false)); - } else { - messages.add(null); - } - data.reuse(); - res.photos.add(photo); - messages.add(null); - } - } - cursor.dispose(); - cursor = null; - res.photos.add(0, photoToAdd); - putDialogPhotosInternal(did, res, messages); - } catch (Exception e) { - checkSQLException(e); - } finally { - if (cursor != null) { - cursor.dispose(); - } - } - }); - } - public void emptyMessagesMedia(long dialogId, ArrayList mids) { storageQueue.postRunnable(() -> { SQLiteCursor cursor = null; @@ -7088,6 +6967,19 @@ public class MessagesStorage extends BaseController { if (info != null && info.inviterId != 0) { getUsersInternal("" + info.inviterId, loadedUsers); } + if (info != null && info.recent_requesters != null && !info.recent_requesters.isEmpty()) { + StringBuilder usersToLoad = new StringBuilder(); + for (int i = 0; i < Math.min(3, info.recent_requesters.size()); ++i) { + long uid = info.recent_requesters.get(info.recent_requesters.size() - 1 - i); + if (i > 0) { + usersToLoad.append(','); + } + usersToLoad.append(uid); + } + if (usersToLoad.length() > 0) { + getUsersInternal(usersToLoad.toString(), loadedUsers); + } + } cursor = getMessagesStorage().getDatabase().queryFinalized(String.format(Locale.US, "SELECT mid FROM chat_pinned_v2 WHERE uid = %d ORDER BY mid DESC", -chatId)); while (cursor.next()) { @@ -8537,7 +8429,7 @@ public class MessagesStorage extends BaseController { if (!cursor.isNull(6)) { data = cursor.byteBufferValue(6); if (data != null) { - message.replyStory = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(false), false); + message.replyStory = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(false), false); data.reuse(); } } @@ -8661,6 +8553,7 @@ public class MessagesStorage extends BaseController { TLRPC.Message object = arrayList.get(a); object.replyMessage = message; if (object.reply_to != null) { + object.reply_to.flags |= 16; object.reply_to.reply_to_msg_id = message.id; } } @@ -9472,6 +9365,31 @@ public class MessagesStorage extends BaseController { return str.toString().toLowerCase(); } + public boolean containsLocalDialog(long did) { + CountDownLatch countDownLatch = new CountDownLatch(1); + Boolean[] result = new Boolean[] { false }; + storageQueue.postRunnable(() -> { + SQLiteCursor cursor = null; + try { + cursor = database.queryFinalized("SELECT date FROM dialogs WHERE did = " + did); + result[0] = cursor.next(); + } catch (Exception e) { + checkSQLException(e); + } finally { + if (cursor != null) { + cursor.dispose(); + } + } + countDownLatch.countDown(); + }); + try { + countDownLatch.await(); + } catch (Exception e) { + checkSQLException(e); + } + return result[0]; + } + private void putUsersInternal(List users) throws Exception { if (users == null || users.isEmpty()) { return; @@ -12299,7 +12217,7 @@ public class MessagesStorage extends BaseController { } cursor.dispose(); cursor = null; - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, did, count)); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.scheduledMessagesUpdated, did, count, true)); } catch (Exception e) { checkSQLException(e); } finally { @@ -14223,22 +14141,8 @@ public class MessagesStorage extends BaseController { } if (message.action instanceof TLRPC.TL_messageActionGeoProximityReached) { TLRPC.TL_messageActionGeoProximityReached action = (TLRPC.TL_messageActionGeoProximityReached) message.action; - long id = MessageObject.getPeerId(action.from_id); - if (DialogObject.isUserDialog(id)) { - if (!usersToLoad.contains(id)) { - usersToLoad.add(id); - } - } else if (!chatsToLoad.contains(-id)) { - chatsToLoad.add(-id); - } - id = MessageObject.getPeerId(action.to_id); - if (id > 0) { - if (!usersToLoad.contains(id)) { - usersToLoad.add(id); - } - } else if (!chatsToLoad.contains(-id)) { - chatsToLoad.add(-id); - } + addLoadPeerInfo(action.from_id, usersToLoad, chatsToLoad); + addLoadPeerInfo(action.to_id, usersToLoad, chatsToLoad); } if (!message.action.users.isEmpty()) { for (int a = 0; a < message.action.users.size(); a++) { @@ -14269,82 +14173,28 @@ public class MessagesStorage extends BaseController { TLRPC.TL_messageMediaPoll messageMediaPoll = (TLRPC.TL_messageMediaPoll) message.media; if (!messageMediaPoll.results.recent_voters.isEmpty()) { for (int i = 0; i < messageMediaPoll.results.recent_voters.size(); i++) { - TLRPC.Peer peer = messageMediaPoll.results.recent_voters.get(i); - if (peer.user_id != 0) { - usersToLoad.add(peer.user_id); - } else if (peer.chat_id != 0) { - chatsToLoad.add(-peer.chat_id); - } else if (peer.channel_id != 0) { - chatsToLoad.add(-peer.channel_id); - } + addLoadPeerInfo(messageMediaPoll.results.recent_voters.get(i), usersToLoad, chatsToLoad); } } } if (message.media.peer != null) { - long dialogId = DialogObject.getPeerDialogId(message.media.peer); - if (dialogId > 0) { - usersToLoad.add(dialogId); - } - if (dialogId < 0) { - chatsToLoad.add(-dialogId); - } + addLoadPeerInfo(message.media.peer, usersToLoad, chatsToLoad); } } if (message.replies != null) { for (int a = 0, N = message.replies.recent_repliers.size(); a < N; a++) { - long id = MessageObject.getPeerId(message.replies.recent_repliers.get(a)); - if (DialogObject.isUserDialog(id)) { - if (!usersToLoad.contains(id)) { - usersToLoad.add(id); - } - } else if (DialogObject.isChatDialog(id)) { - if (!chatsToLoad.contains(-id)) { - chatsToLoad.add(-id); - } - } + addLoadPeerInfo(message.replies.recent_repliers.get(a), usersToLoad, chatsToLoad); } } if (message.reply_to != null && message.reply_to.reply_to_peer_id != null) { - long id = MessageObject.getPeerId(message.reply_to.reply_to_peer_id); - if (DialogObject.isUserDialog(id)) { - if (!usersToLoad.contains(id)) { - usersToLoad.add(id); - } - } else if (DialogObject.isChatDialog(id)) { - if (!chatsToLoad.contains(-id)) { - chatsToLoad.add(-id); - } - } + addLoadPeerInfo(message.reply_to.reply_to_peer_id, usersToLoad, chatsToLoad); } if (message.fwd_from != null) { - if (message.fwd_from.from_id instanceof TLRPC.TL_peerUser) { - if (!usersToLoad.contains(message.fwd_from.from_id.user_id)) { - usersToLoad.add(message.fwd_from.from_id.user_id); - } - } else if (message.fwd_from.from_id instanceof TLRPC.TL_peerChannel) { - if (!chatsToLoad.contains(message.fwd_from.from_id.channel_id)) { - chatsToLoad.add(message.fwd_from.from_id.channel_id); - } - } else if (message.fwd_from.from_id instanceof TLRPC.TL_peerChat) { - if (!chatsToLoad.contains(message.fwd_from.from_id.chat_id)) { - chatsToLoad.add(message.fwd_from.from_id.chat_id); - } - } - if (message.fwd_from.saved_from_peer != null) { - if (message.fwd_from.saved_from_peer.user_id != 0) { - if (!chatsToLoad.contains(message.fwd_from.saved_from_peer.user_id)) { - usersToLoad.add(message.fwd_from.saved_from_peer.user_id); - } - } else if (message.fwd_from.saved_from_peer.channel_id != 0) { - if (!chatsToLoad.contains(message.fwd_from.saved_from_peer.channel_id)) { - chatsToLoad.add(message.fwd_from.saved_from_peer.channel_id); - } - } else if (message.fwd_from.saved_from_peer.chat_id != 0) { - if (!chatsToLoad.contains(message.fwd_from.saved_from_peer.chat_id)) { - chatsToLoad.add(message.fwd_from.saved_from_peer.chat_id); - } - } - } + addLoadPeerInfo(message.fwd_from.from_id, usersToLoad, chatsToLoad); + addLoadPeerInfo(message.fwd_from.saved_from_peer, usersToLoad, chatsToLoad); + } + if (message.reply_to != null && message.reply_to.reply_from != null && message.reply_to.reply_from.from_id != null) { + addLoadPeerInfo(message.reply_to.reply_from.from_id, usersToLoad, chatsToLoad); } if (message.params != null) { String peerIdStr = message.params.get("fwd_peer"); @@ -14359,6 +14209,22 @@ public class MessagesStorage extends BaseController { } } + private static void addLoadPeerInfo(TLRPC.Peer peer, ArrayList usersToLoad, ArrayList chatsToLoad) { + if (peer instanceof TLRPC.TL_peerUser) { + if (!usersToLoad.contains(peer.user_id)) { + usersToLoad.add(peer.user_id); + } + } else if (peer instanceof TLRPC.TL_peerChannel) { + if (!chatsToLoad.contains(peer.channel_id)) { + chatsToLoad.add(peer.channel_id); + } + } else if (peer instanceof TLRPC.TL_peerChat) { + if (!chatsToLoad.contains(peer.chat_id)) { + chatsToLoad.add(peer.chat_id); + } + } + } + public void getDialogs(int folderId, int offset, int count, boolean loadDraftsPeersAndFolders) { long[] draftsDialogIds; if (loadDraftsPeersAndFolders) { @@ -15614,7 +15480,7 @@ public class MessagesStorage extends BaseController { if (dialogsType != 4 && (replies).startsWith(search1) || replies2.startsWith(search1)) { TLRPC.User user = getMessagesController().getUser(708513L); if (user == null) { - user = getMessagesController().getUser(1271266957L); + user = getMessagesController().getUser(UserObject.REPLY_BOT); } if (user != null) { DialogsSearchAdapter.DialogSearchResult dialogSearchResult = new DialogsSearchAdapter.DialogSearchResult(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index 39edd98d2..8b37f0757 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -37,6 +37,7 @@ import android.widget.RemoteViews; import androidx.core.app.NotificationCompat; import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.util.Log; import org.telegram.messenger.audioinfo.AudioInfo; import org.telegram.ui.LaunchActivity; @@ -65,6 +66,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No private Bitmap albumArtPlaceholder; private int notificationMessageID; private ImageReceiver imageReceiver; + private boolean foregroundServiceIsStarted; private String loadingFilePath; @@ -311,12 +313,22 @@ public class MusicPlayerService extends Service implements NotificationCenter.No notification = bldr.build(); - if (isPlaying) { - startForeground(ID_NOTIFICATION, notification); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!foregroundServiceIsStarted) { + foregroundServiceIsStarted = true; + startForeground(ID_NOTIFICATION, notification); + } else { + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + nm.notify(ID_NOTIFICATION, notification); + } } else { - stopForeground(false); - NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - nm.notify(ID_NOTIFICATION, notification); + if (isPlaying) { + startForeground(ID_NOTIFICATION, notification); + } else { + stopForeground(false); + NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + nm.notify(ID_NOTIFICATION, notification); + } } } else { @@ -504,6 +516,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No public void onDestroy() { unregisterReceiver(headsetPlugReceiver); super.onDestroy(); + stopForeground(true); if (remoteControlClient != null) { RemoteControlClient.MetadataEditor metadataEditor = remoteControlClient.editMetadata(true); metadataEditor.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java index 6e895ac7b..eb6199d08 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NativeLoader.java @@ -22,7 +22,7 @@ import java.util.zip.ZipFile; public class NativeLoader { - private final static int LIB_VERSION = 46; + private final static int LIB_VERSION = 47; private final static String LIB_NAME = "tmessages." + LIB_VERSION; private final static String LIB_SO_NAME = "lib" + LIB_NAME + ".so"; private final static String LOCALE_LIB_SO_NAME = "lib" + LIB_NAME + "loc.so"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 9a22daef3..01970e187 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -209,6 +209,8 @@ public class NotificationCenter { public static final int updateBotMenuButton = totalEvents++; + public static final int boostedChannelByUser = totalEvents++; + public static final int boostByChannelCreated = totalEvents++; public static final int didUpdatePremiumGiftStickers = totalEvents++; public static final int didUpdatePremiumGiftFieldIcon = totalEvents++; public static final int storiesEnabledUpdate = totalEvents++; @@ -216,6 +218,7 @@ public class NotificationCenter { public static final int storiesLimitUpdate = totalEvents++; public static final int storiesSendAsUpdate = totalEvents++; public static final int unconfirmedAuthUpdate = totalEvents++; + public static final int dialogPhotosUpdate = totalEvents++; //fake passcode public static final int dialogDeletedByAction = totalEvents++; @@ -236,7 +239,6 @@ public class NotificationCenter { //global public static final int pushMessagesUpdated = totalEvents++; - public static final int stopEncodingService = totalEvents++; public static final int wallpapersDidLoad = totalEvents++; public static final int wallpapersNeedReload = totalEvents++; public static final int didReceiveSmsCode = totalEvents++; @@ -313,7 +315,8 @@ public class NotificationCenter { public static final int uploadStoryEnd = totalEvents++; public static final int customTypefacesLoaded = totalEvents++; public static final int stealthModeChanged = totalEvents++; - public static final int onReceivedChannelDifference = totalEvents++;; + public static final int onReceivedChannelDifference = totalEvents++; + public static final int storiesReadUpdated = totalEvents++; public static boolean alreadyLogged; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index 01cea75e3..1ff53cf95 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -1878,6 +1878,8 @@ public class NotificationsController extends BaseController { } return LocaleController.formatString("NotificationGroupInvitedToCall", R.string.NotificationGroupInvitedToCall, name, chat.title, names.toString()); } + } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { + return LocaleController.getString("BoostingReceivedGiftNoName", R.string.BoostingReceivedGiftNoName); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatJoinedByLink) { return LocaleController.formatString("NotificationInvitedToGroupByLink", R.string.NotificationInvitedToGroupByLink, name, chat.title); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) { @@ -2190,6 +2192,8 @@ public class NotificationsController extends BaseController { } else { return LocaleController.getString("Poll", R.string.Poll); } + } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { + return LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { return LocaleController.getString("AttachLocation", R.string.AttachLocation); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { @@ -2436,6 +2440,9 @@ public class NotificationsController extends BaseController { } 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)); + } 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); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; if (mediaPoll.poll.quiz) { @@ -2563,6 +2570,15 @@ public class NotificationsController extends BaseController { } msg = LocaleController.formatString("NotificationGroupInvitedToCall", 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; + TLRPC.Chat fromChat = MessagesController.getInstance(currentAccount).getChat(-DialogObject.getPeerDialogId(giftCode.boost_peer)); + String from = fromChat == null ? null : fromChat.title; + if (from == null) { + msg = LocaleController.getString("BoostingReceivedGiftNoName", R.string.BoostingReceivedGiftNoName); + } else { + msg = LocaleController.formatString("NotificationMessageGiftCode", 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); } else if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatEditTitle) { @@ -2803,6 +2819,9 @@ public class NotificationsController extends BaseController { } else { msg = LocaleController.formatString("ChannelMessagePoll2", R.string.ChannelMessagePoll2, name, mediaPoll.poll.question); } + } 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); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeo || messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaVenue) { msg = LocaleController.formatString("ChannelMessageMap", R.string.ChannelMessageMap, name); } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGeoLive) { @@ -2875,6 +2894,9 @@ public class NotificationsController extends BaseController { } } else if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { msg = LocaleController.formatString("NotificationMessageGroupGame", 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); } 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) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java index cc3d5709e..f80b2397d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/PushListenerController.java @@ -622,11 +622,26 @@ public class PushListenerController { localMessage = true; break; } + case "MESSAGE_GIFTCODE": { + messageText = LocaleController.formatString("NotificationMessageGiftCode", R.string.NotificationMessageGiftCode, args[0], LocaleController.formatPluralString("Months", Utilities.parseInt(args[1]))); + localMessage = true; + break; + } + case "MESSAGE_GIVEAWAY": { + messageText = LocaleController.formatString("NotificationMessageGiveaway", R.string.NotificationMessageGiveaway, args[0], args[1], args[2]); + localMessage = true; + break; + } case "MESSAGES": { messageText = LocaleController.formatString("NotificationMessageAlbum", R.string.NotificationMessageAlbum, args[0]); localMessage = true; break; } + case "CHANNEL_MESSAGE_GIVEAWAY": { + messageText = LocaleController.formatString("NotificationMessageChannelGiveaway", R.string.NotificationMessageChannelGiveaway, args[0], args[1], args[2]); + message1 = LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway); + break; + } case "CHANNEL_MESSAGE_NOTEXT": { messageText = LocaleController.formatString("ChannelMessageNoText", R.string.ChannelMessageNoText, args[0]); message1 = LocaleController.getString("Message", R.string.Message); @@ -737,6 +752,11 @@ public class PushListenerController { localMessage = true; break; } + case "CHAT_MESSAGE_GIVEAWAY": { + messageText = LocaleController.formatString("NotificationMessageChatGiveaway", R.string.NotificationMessageChatGiveaway, args[0], args[1], args[2], args[3]); + message1 = LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway); + break; + } case "CHAT_MESSAGE_TEXT": { messageText = LocaleController.formatString("NotificationMessageGroupText", R.string.NotificationMessageGroupText, args[0], args[1], args[2]); message1 = args[2]; @@ -1038,6 +1058,10 @@ public class PushListenerController { } break; } + case "PINNED_GIVEAWAY": { + messageText = LocaleController.formatString("NotificationPinnedGiveaway", R.string.NotificationPinnedGiveaway, args[0]); + break; + } case "PINNED_QUIZ": { if (dialogId > 0) { messageText = LocaleController.formatString("NotificationActionPinnedQuizUser", R.string.NotificationActionPinnedQuizUser, args[0], args[1]); @@ -1307,6 +1331,12 @@ public class PushListenerController { case "REACT_GIF": { return LocaleController.formatString("PushReactGif", R.string.PushReactGif, args); } + case "REACT_GIVEAWAY": { + return LocaleController.formatString("NotificationReactGiveaway", R.string.NotificationReactGiveaway, args); + } + case "CHAT_REACT_GIVEAWAY": { + return LocaleController.formatString("NotificationChatReactGiveaway", R.string.NotificationChatReactGiveaway, args); + } case "CHAT_REACT_TEXT": { return LocaleController.formatString("PushChatReactText", R.string.PushChatReactText, args); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index 9a66f39fd..3880ca670 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -761,9 +761,6 @@ public class SecretChatHelper extends BaseController { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SENT; getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, newMsgObj.id, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, false); getSendMessagesHelper().processSentMessage(newMsgObj.id); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj)) { - getSendMessagesHelper().stopVideoService(attachPath); - } getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); }); @@ -773,9 +770,6 @@ public class SecretChatHelper extends BaseController { newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); getSendMessagesHelper().processSentMessage(newMsgObj.id); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj)) { - getSendMessagesHelper().stopVideoService(newMsgObj.attachPath); - } getSendMessagesHelper().removeFromSendingMessages(newMsgObj.id, false); }); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 24398a158..a5dd4d5d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -34,6 +34,7 @@ import android.provider.OpenableColumns; import android.text.Spannable; import android.text.TextUtils; import android.util.Base64; +import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; @@ -58,6 +59,7 @@ import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -66,6 +68,7 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AnimatedFileDrawable; +import org.telegram.ui.Components.BotWebViewSheet; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Point; @@ -128,27 +131,69 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return false; } - public TLRPC.InputReplyTo creteReplyInput(TLRPC.StoryItem storyItem) { + public TLRPC.InputReplyTo createReplyInput(TL_stories.StoryItem storyItem) { TLRPC.TL_inputReplyToStory replyTo = new TLRPC.TL_inputReplyToStory(); replyTo.story_id = storyItem.id; replyTo.user_id = getMessagesController().getInputUser(storyItem.dialogId); return replyTo; } - public static TLRPC.InputReplyTo creteReplyInput(int replyToMsgId) { - return creteReplyInput(replyToMsgId, 0); + public TLRPC.InputReplyTo createReplyInput(int replyToMsgId) { + return createReplyInput(null, replyToMsgId, 0, null); } - public static TLRPC.InputReplyTo creteReplyInput(int replyToMsgId, int topMessageId) { + public TLRPC.InputReplyTo createReplyInput(TLRPC.InputPeer sendToPeer, int replyToMsgId, int topMessageId, ChatActivity.ReplyQuote replyQuote) { TLRPC.TL_inputReplyToMessage replyTo = new TLRPC.TL_inputReplyToMessage(); replyTo.reply_to_msg_id = replyToMsgId; if (topMessageId != 0) { replyTo.flags |= 1; replyTo.top_msg_id = topMessageId; } + if (replyQuote != null) { + replyTo.quote_text = replyQuote.getText(); + if (!TextUtils.isEmpty(replyTo.quote_text)) { + replyTo.flags |= 4; + replyTo.quote_entities = replyQuote.getEntities(); + if (replyTo.quote_entities != null && !replyTo.quote_entities.isEmpty()) { + replyTo.quote_entities = new ArrayList<>(replyTo.quote_entities); + replyTo.flags |= 8; + } + } + } + if (replyQuote != null && replyQuote.message != null) { + long did = replyQuote.message.getDialogId(); + TLRPC.InputPeer peer = getMessagesController().getInputPeer(did); + if (peer != null && !MessageObject.peersEqual(peer, sendToPeer)) { + replyTo.flags |= 2; + replyTo.reply_to_peer_id = peer; + } + } return replyTo; } + public TLRPC.InputReplyTo createReplyInput(TLRPC.TL_messageReplyHeader replyHeader) { + TLRPC.TL_inputReplyToMessage replyTo = new TLRPC.TL_inputReplyToMessage(); + replyTo.reply_to_msg_id = replyHeader.reply_to_msg_id; + if ((replyHeader.flags & 2) != 0) { + replyTo.flags |= 1; + replyTo.top_msg_id = replyHeader.reply_to_top_id; + } + if ((replyHeader.flags & 1) != 0) { + replyTo.flags |= 2; + replyTo.reply_to_peer_id = MessagesController.getInstance(currentAccount).getInputPeer(replyHeader.reply_to_peer_id); + } + if (replyHeader.quote) { + if ((replyHeader.flags & 64) != 0) { + replyTo.flags |= 4; + replyTo.quote_text = replyHeader.quote_text; + } + if ((replyHeader.flags & 128) != 0) { + replyTo.flags |= 8; + replyTo.quote_entities = replyHeader.quote_entities; + } + } + return replyTo; + } public class ImportingHistory { public String historyPath; @@ -944,9 +989,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe media.file = file; MessageObject messageObject = (MessageObject) message.extraHashMap.get(location + "_i"); int index = message.messageObjects.indexOf(messageObject); - if (index >= 0) { - stopVideoService(message.messageObjects.get(index).messageOwner.attachPath); - } message.photoSize = (TLRPC.PhotoSize) message.extraHashMap.get(location + "_t"); if (media.thumb == null && message.photoSize != null && message.photoSize.location != null) { message.performMediaUpload = true; @@ -975,9 +1017,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (index >= 0) { req.files.set(index, encryptedFile); if (inputEncryptedFile.id == 1) { - MessageObject messageObject = (MessageObject) message.extraHashMap.get(location + "_i"); message.photoSize = (TLRPC.PhotoSize) message.extraHashMap.get(location + "_t"); - stopVideoService(message.messageObjects.get(index).messageOwner.attachPath); } decryptedMessage = req.messages.get(index); } @@ -1076,7 +1116,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe boolean isEncrypted = DialogObject.isEncryptedDialog(messageObject.getDialogId()); getFileLoader().checkUploadNewDataAvailable(finalPath, isEncrypted, availableSize, finalSize, progress); if (finalSize != 0) { - stopVideoService(messageObject.messageOwner.attachPath); ArrayList arr = delayedMessages.get(messageObject.messageOwner.attachPath); if (arr != null) { for (int a = 0; a < arr.size(); a++) { @@ -1114,7 +1153,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe return; } String finalPath = (String) args[1]; - stopVideoService(messageObject.messageOwner.attachPath); ArrayList arr = delayedMessages.get(finalPath); if (arr != null) { @@ -1395,7 +1433,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { getFileLoader().cancelFileUpload(key, enc); } - stopVideoService(key); delayedMessages.remove(key); } for (int a = 0, N = checkReadyToSendGroups.size(); a < N; a++) { @@ -1546,7 +1583,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe TLRPC.Message message; if (resendMessage != null) { message = resendMessage; - req.reply_to = SendMessagesHelper.creteReplyInput(messageId); + req.reply_to = createReplyInput(messageId); req.random_id = resendMessage.random_id; } else { message = new TLRPC.TL_messageService(); @@ -1560,6 +1597,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe message.flags |= 256; message.flags |= 8; message.reply_to = new TLRPC.TL_messageReplyHeader(); + message.reply_to.flags |= 16; message.reply_to.reply_to_msg_id = messageId; message.peer_id = new TLRPC.TL_peerUser(); message.peer_id.user_id = user.id; @@ -1583,7 +1621,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe performSendMessageRequest(req, newMsgObj, null, null, null, null, false); } - public void sendSticker(TLRPC.Document document, String query, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, MessageObject.SendAnimationData sendAnimationData, boolean notify, int scheduleDate, boolean updateStickersOrder, Object parentObject) { + public void sendSticker(TLRPC.Document document, String query, long peer, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject.SendAnimationData sendAnimationData, boolean notify, int scheduleDate, boolean updateStickersOrder, Object parentObject) { if (document == null) { return; } @@ -1683,6 +1721,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } SendMessageParams sendMessageParams = SendMessageParams.of((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, null, notify, scheduleDate, 0, parentObject, sendAnimationData, false); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; sendMessage(sendMessageParams); }); }); @@ -1696,6 +1735,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } SendMessageParams sendMessageParams = SendMessageParams.of((TLRPC.TL_document) finalDocument, null, null, peer, replyToMsg, replyToTopMsg, null, null, null, params, notify, scheduleDate, 0, parentObject, sendAnimationData, updateStickersOrder); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; sendMessage(sendMessageParams); } } @@ -2052,6 +2092,15 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsg.media_unread = true; } } + if (replyToTopMsg == null && msgObj.messageOwner.reply_to != null) { + if ( + !(msgObj.messageOwner.reply_to.reply_to_peer_id == null || MessageObject.peersEqual(msgObj.messageOwner.reply_to.reply_to_peer_id, msgObj.messageOwner.peer_id)) || + ids != null && (msgObj.messageOwner.reply_to.flags & 16) != 0 && ids.contains(msgObj.messageOwner.reply_to.reply_to_msg_id) + ) { + newMsg.flags |= 8; + newMsg.reply_to = msgObj.messageOwner.reply_to; + } + } MessageObject newMsgObj = new MessageObject(currentAccount, newMsg, true, true); newMsgObj.scheduled = scheduleDate != 0; newMsgObj.messageOwner.send_state = MessageObject.MESSAGE_SEND_STATE_SENDING; @@ -2078,6 +2127,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (replyToTopMsg != null) { newMsg.reply_to = new TLRPC.TL_messageReplyHeader(); + newMsg.reply_to.flags |= 16; newMsg.reply_to.reply_to_msg_id = replyToTopMsg.getId(); if (replyToTopMsg.isTopicMainMessage) { newMsg.reply_to.forum_topic = true; @@ -2517,7 +2567,15 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (type >= 1 && type <= 3 || type >= 5 && type <= 8) { TLRPC.InputMedia inputMedia = null; if (type == 1) { - + if ((newMsg.media == null || newMsg.media instanceof TLRPC.TL_messageMediaEmpty || newMsg.media != null && newMsg.media.webpage instanceof TLRPC.TL_webPageEmpty) && !messageObject.editingMessageSearchWebPage) { + inputMedia = new TLRPC.TL_inputMediaEmpty(); + } else if (newMsg != null && newMsg.media != null && newMsg.media.webpage != null) { + TLRPC.TL_inputMediaWebPage inputWebpage = new TLRPC.TL_inputMediaWebPage(); + inputWebpage.url = newMsg.media.webpage.url; + inputWebpage.force_small_media = newMsg.media.force_small_media; + inputWebpage.force_large_media = newMsg.media.force_large_media; + inputMedia = inputWebpage; + } } else if (type == 2) { TLRPC.TL_inputMediaUploadedPhoto uploadedPhoto = new TLRPC.TL_inputMediaUploadedPhoto(); uploadedPhoto.spoiler = hasMediaSpoilers; @@ -2662,6 +2720,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe TLRPC.TL_messages_editMessage request = new TLRPC.TL_messages_editMessage(); request.id = messageObject.getId(); request.peer = getMessagesController().getInputPeer(peer); + request.invert_media = messageObject.messageOwner.invert_media; if (inputMedia != null) { request.flags |= 16384; request.media = inputMedia; @@ -3213,19 +3272,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe inputInvoice.msg_id = messageObject.getId(); inputInvoice.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id); req.invoice = inputInvoice; - try { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("bg_color", Theme.getColor(Theme.key_windowBackgroundWhite)); - jsonObject.put("text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - jsonObject.put("hint_color", Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - jsonObject.put("link_color", Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); - jsonObject.put("button_color", Theme.getColor(Theme.key_featuredStickers_addButton)); - jsonObject.put("button_text_color", Theme.getColor(Theme.key_featuredStickers_buttonText)); + final JSONObject themeParams = BotWebViewSheet.makeThemeParams(null); + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = jsonObject.toString(); + req.theme_params.data = themeParams.toString(); req.flags |= 1; - } catch (Exception e) { - FileLog.e(e); } getConnectionsManager().sendRequest(req, requestDelegate, ConnectionsManager.RequestFlagFailOnServerErrors); } else { @@ -3332,6 +3383,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe MessageObject replyToMsg = sendMessageParams.replyToMsg; MessageObject replyToTopMsg = sendMessageParams.replyToTopMsg; TLRPC.WebPage webPage = sendMessageParams.webPage; + TLRPC.TL_messageMediaWebPage mediaWebPage = sendMessageParams.mediaWebPage; boolean searchLinks = sendMessageParams.searchLinks; MessageObject retryMessageObject = sendMessageParams.retryMessageObject; ArrayList entities = sendMessageParams.entities; @@ -3344,8 +3396,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe MessageObject.SendAnimationData sendAnimationData = sendMessageParams.sendAnimationData; boolean updateStickersOrder = sendMessageParams.updateStickersOrder; boolean hasMediaSpoilers = sendMessageParams.hasMediaSpoilers; - TLRPC.StoryItem replyToStoryItem = sendMessageParams.replyToStoryItem; - TLRPC.StoryItem sendingStory = sendMessageParams.sendingStory; + TL_stories.StoryItem replyToStoryItem = sendMessageParams.replyToStoryItem; + TL_stories.StoryItem sendingStory = sendMessageParams.sendingStory; + ChatActivity.ReplyQuote replyQuote = sendMessageParams.replyQuote; + boolean invert_media = sendMessageParams.invert_media; + if (user != null && user.phone == null) { return; } @@ -3356,6 +3411,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe caption = ""; } + if (replyQuote != null && replyQuote.message != null && replyToMsg != null) { + replyToMsg = replyQuote.message; + } + String originalPath = null; if (params != null && params.containsKey("originalPath")) { originalPath = params.get("originalPath"); @@ -3514,7 +3573,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe type = MEDIA_TYPE_DICE; caption = ""; } else { - if (webPage == null) { + if (mediaWebPage != null) { + newMsg.media = mediaWebPage; + } else if (webPage == null) { newMsg.media = new TLRPC.TL_messageMediaEmpty(); } else { newMsg.media = new TLRPC.TL_messageMediaWebPage(); @@ -3781,6 +3842,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } newMsg.flags |= TLRPC.MESSAGE_FLAG_HAS_MEDIA; newMsg.dialog_id = peer; + newMsg.invert_media = invert_media; if (replyToStoryItem != null) { newMsg.reply_to = new TLRPC.TL_messageReplyStoryHeader(); newMsg.reply_to.story_id = replyToStoryItem.id; @@ -3795,6 +3857,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { newMsg.flags |= TLRPC.MESSAGE_FLAG_REPLY; } + newMsg.reply_to.flags |= 16; newMsg.reply_to.reply_to_msg_id = replyToMsg.getId(); if (replyToTopMsg != null && replyToTopMsg != replyToMsg && replyToTopMsg.getId() != 1) { newMsg.reply_to.reply_to_top_id = replyToTopMsg.getId(); @@ -3809,6 +3872,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsg.reply_to.flags |= 8; } } + if (replyQuote != null) { + newMsg.reply_to.quote_text = replyQuote.getText(); + if (!TextUtils.isEmpty(newMsg.reply_to.quote_text)) { + newMsg.reply_to.quote = true; + newMsg.reply_to.flags |= 64; + newMsg.reply_to.quote_entities = replyQuote.getEntities(); + if (newMsg.reply_to.quote_entities != null && !newMsg.reply_to.quote_entities.isEmpty()) { + newMsg.reply_to.quote_entities = new ArrayList<>(newMsg.reply_to.quote_entities); + newMsg.reply_to.flags |= 128; + } + } + } } if (linkedToGroup != 0) { newMsg.replies = new TLRPC.TL_messageReplies(); @@ -3878,6 +3953,46 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } } } + boolean destroyReply = false; + if (replyToMsg != null && replyToStoryItem == null && newMsg.reply_to != null) { + boolean convertToQuote = false; + TLRPC.Peer peer2 = getMessagesController().getPeer(replyToMsg.getDialogId() > 0 ? replyToMsg.getSenderId() : replyToMsg.getDialogId()); + boolean anotherChat = peer2 != null && !MessageObject.peersEqual(getMessagesController().getPeer(replyToMsg.getDialogId()), newMsg.peer_id); + if (replyToMsg.isForwarded() && !replyToMsg.isImportedForward() && replyToMsg.messageOwner.fwd_from.saved_from_peer == null) { + if (replyToMsg.messageOwner.fwd_from.from_id != null && (replyToMsg.messageOwner.fwd_from.flags & 4) != 0) { + peer2 = replyToMsg.messageOwner.fwd_from.from_id; + newMsg.reply_to.reply_to_msg_id = replyToMsg.messageOwner.fwd_from.channel_post; + destroyReply = true; + anotherChat = true; + } + } + final boolean anotherTopic = replyToTopMsg != null && replyToTopMsg.getId() != replyToMsg.getId() && MessageObject.getTopicId(replyToMsg.messageOwner, true) != replyToTopMsg.getId(); + if (anotherChat || anotherTopic) { + newMsg.reply_to.flags |= 1; + newMsg.reply_to.reply_to_peer_id = peer2; + convertToQuote = true; + } + if (convertToQuote) { + if (replyQuote == null) { + newMsg.reply_to.quote = false; + replyQuote = ChatActivity.ReplyQuote.from(replyToMsg); + } + if (replyQuote != null) { + if (replyToMsg.messageOwner != null && replyToMsg.messageOwner.media != null) { + newMsg.reply_to.flags |= 256; + newMsg.reply_to.reply_media = replyToMsg.messageOwner.media; + } + if (replyQuote.getText() != null) { + newMsg.reply_to.flags |= 64; + newMsg.reply_to.quote_text = replyQuote.getText(); + } + if (replyQuote.getEntities() != null) { + newMsg.reply_to.flags |= 128; + newMsg.reply_to.quote_entities = replyQuote.getEntities(); + } + } + } + } if (MessageObject.isVoiceMessage(newMsg) || MessageObject.isRoundVideoMessage(newMsg)) { newMsg.media_unread = true; } @@ -3900,7 +4015,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } MessageObject reply = replyToMsg; - if (replyToTopMsg != null && replyToTopMsg == reply && replyToTopMsg.getId() == 1) { + if (replyToTopMsg != null && replyToTopMsg == reply && replyToTopMsg.getId() == 1 || destroyReply) { reply = null; } newMsgObj = new MessageObject(currentAccount, newMsg, reply, true, true); @@ -3960,40 +4075,80 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (type == 0 || type == 9 && message != null && encryptedChat != null) { if (encryptedChat == null) { - TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage(); - reqSend.message = message; - reqSend.clear_draft = retryMessageObject == null; - reqSend.silent = newMsg.silent; - reqSend.peer = sendToPeer; - reqSend.random_id = newMsg.random_id; - if (replyToStoryItem != null) { - reqSend.reply_to = creteReplyInput(replyToStoryItem); - reqSend.flags |= 1; - } else if (newMsg.reply_to != null) { - int topMsgId = replyToTopMsg == null ? 0 : replyToTopMsg.getId(); - reqSend.reply_to = SendMessagesHelper.creteReplyInput(newMsg.reply_to.reply_to_msg_id, topMsgId); - reqSend.flags |= 1; - } - if (updateStickersOrder && SharedConfig.updateStickersOrderOnSend) { - reqSend.update_stickersets_order = true; - } - if (newMsg.from_id != null) { - reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id); - } - if (!searchLinks) { - reqSend.no_webpage = true; - } - if (entities != null && !entities.isEmpty()) { - reqSend.entities = entities; - reqSend.flags |= 8; - } - if (scheduleDate != 0) { - reqSend.schedule_date = scheduleDate; - reqSend.flags |= 1024; - } - performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); - if (retryMessageObject == null) { - getMediaDataController().cleanDraft(peer, replyToTopMsg != null ? replyToTopMsg.getId() : 0, false); + if (mediaWebPage != null) { + TLRPC.TL_messages_sendMedia reqSend = new TLRPC.TL_messages_sendMedia(); + reqSend.message = message; + reqSend.clear_draft = retryMessageObject == null; + reqSend.silent = newMsg.silent; + reqSend.peer = sendToPeer; + reqSend.random_id = newMsg.random_id; + TLRPC.TL_inputMediaWebPage inputWebPage = new TLRPC.TL_inputMediaWebPage(); + inputWebPage.url = mediaWebPage.webpage.url; + inputWebPage.force_large_media = mediaWebPage.force_large_media; + inputWebPage.force_small_media = mediaWebPage.force_small_media; + reqSend.media = inputWebPage; + if (replyToStoryItem != null) { + reqSend.reply_to = createReplyInput(replyToStoryItem); + reqSend.flags |= 1; + } else if (newMsg.reply_to instanceof TLRPC.TL_messageReplyHeader) { + reqSend.reply_to = createReplyInput((TLRPC.TL_messageReplyHeader) newMsg.reply_to); + reqSend.flags |= 1; + } + if (updateStickersOrder && SharedConfig.updateStickersOrderOnSend) { + reqSend.update_stickersets_order = true; + } + if (newMsg.from_id != null) { + reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id); + } + if (entities != null && !entities.isEmpty()) { + reqSend.entities = entities; + reqSend.flags |= 8; + } + if (scheduleDate != 0) { + reqSend.schedule_date = scheduleDate; + reqSend.flags |= 1024; + } + reqSend.invert_media = newMsg.invert_media; + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); + if (retryMessageObject == null) { + getMediaDataController().cleanDraft(peer, replyToTopMsg != null ? replyToTopMsg.getId() : 0, false); + } + } else { + TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage(); + reqSend.message = message; + reqSend.clear_draft = retryMessageObject == null; + reqSend.silent = newMsg.silent; + reqSend.peer = sendToPeer; + reqSend.random_id = newMsg.random_id; + if (replyToStoryItem != null) { + reqSend.reply_to = createReplyInput(replyToStoryItem); + reqSend.flags |= 1; + } else if (newMsg.reply_to instanceof TLRPC.TL_messageReplyHeader) { + reqSend.reply_to = createReplyInput((TLRPC.TL_messageReplyHeader) newMsg.reply_to); + reqSend.flags |= 1; + } + if (updateStickersOrder && SharedConfig.updateStickersOrderOnSend) { + reqSend.update_stickersets_order = true; + } + if (newMsg.from_id != null) { + reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id); + } + if (!searchLinks) { + reqSend.no_webpage = true; + } + if (entities != null && !entities.isEmpty()) { + reqSend.entities = entities; + reqSend.flags |= 8; + } + if (scheduleDate != 0) { + reqSend.schedule_date = scheduleDate; + reqSend.flags |= 1024; + } + reqSend.invert_media = newMsg.invert_media; + performSendMessageRequest(reqSend, newMsgObj, null, null, parentObject, params, scheduleDate != 0); + if (retryMessageObject == null) { + getMediaDataController().cleanDraft(peer, replyToTopMsg != null ? replyToTopMsg.getId() : 0, false); + } } } else { TLRPC.TL_decryptedMessage reqSend; @@ -4314,11 +4469,10 @@ public class SendMessagesHelper extends BaseController implements NotificationCe if (newMsg.replyStory != null) { request.flags |= 1; - request.reply_to = creteReplyInput(replyToStoryItem); - } else if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) { - int replyToTopMsgId = replyToTopMsg != null ? replyToTopMsg.getId() : 0; + request.reply_to = createReplyInput(replyToStoryItem); + } else if (newMsg.reply_to instanceof TLRPC.TL_messageReplyHeader) { request.flags |= 1; - request.reply_to = SendMessagesHelper.creteReplyInput(newMsg.reply_to.reply_to_msg_id, replyToTopMsgId); + request.reply_to = createReplyInput((TLRPC.TL_messageReplyHeader) newMsg.reply_to); } if (scheduleDate != 0) { request.schedule_date = scheduleDate; @@ -4353,11 +4507,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe replyToTopMsgInt = replyToTopMsg.getId(); } if (replyToStoryItem != null) { - request.reply_to = creteReplyInput(replyToStoryItem); + request.reply_to = createReplyInput(replyToStoryItem); request.flags |= 1; - } else if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) { + } else if (newMsg.reply_to instanceof TLRPC.TL_messageReplyHeader) { request.flags |= 1; - request.reply_to = SendMessagesHelper.creteReplyInput(newMsg.reply_to.reply_to_msg_id, replyToTopMsgInt); + request.reply_to = createReplyInput((TLRPC.TL_messageReplyHeader) newMsg.reply_to); } request.random_id = newMsg.random_id; if (newMsg.from_id != null) { @@ -4751,21 +4905,17 @@ public class SendMessagesHelper extends BaseController implements NotificationCe TLRPC.TL_messages_sendInlineBotResult reqSend = new TLRPC.TL_messages_sendInlineBotResult(); reqSend.peer = sendToPeer; reqSend.random_id = newMsg.random_id; - if (replyToTopMsg != null) { - reqSend.reply_to = SendMessagesHelper.creteReplyInput(replyToTopMsg.getId()); - reqSend.flags |= 512; - } if (newMsg.from_id != null) { reqSend.send_as = getMessagesController().getInputPeer(newMsg.from_id); } reqSend.hide_via = !params.containsKey("bot"); if (replyToStoryItem != null) { - reqSend.reply_to = creteReplyInput(replyToStoryItem); + reqSend.reply_to = createReplyInput(replyToStoryItem); reqSend.flags |= 1; - } else if (newMsg.reply_to != null && newMsg.reply_to.reply_to_msg_id != 0) { + } else if (newMsg.reply_to instanceof TLRPC.TL_messageReplyHeader) { reqSend.flags |= 1; - reqSend.reply_to = SendMessagesHelper.creteReplyInput(newMsg.reply_to.reply_to_msg_id); + reqSend.reply_to = createReplyInput((TLRPC.TL_messageReplyHeader) newMsg.reply_to); } reqSend.silent = newMsg.silent; if (scheduleDate != 0) { @@ -5302,10 +5452,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe message.sendDelayedRequests(); } - public void stopVideoService(final String path) { - getMessagesStorage().getStorageQueue().postRunnable(() -> AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopEncodingService, path, currentAccount))); - } - protected void putToSendingMessages(TLRPC.Message message, boolean scheduled) { if (Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { AndroidUtilities.runOnUIThread(() -> putToSendingMessages(message, scheduled, true)); @@ -5525,6 +5671,13 @@ public class SendMessagesHelper extends BaseController implements NotificationCe Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.peer_id.channel_id)); updatesArr.remove(a); a--; + if (newMessage.message.pinned) { + Utilities.stageQueue.postRunnable(() -> { + ArrayList mids = new ArrayList<>(); + mids.add(newMessage.message.id); + getMessagesStorage().updatePinnedMessages(-channelId, mids, true, -1, 0, false, null); + }); + } } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update; newMessages.put(newMessage.message.id, newMessage.message); @@ -5724,14 +5877,9 @@ public class SendMessagesHelper extends BaseController implements NotificationCe removeFromSendingMessages(newMsgObj.id, scheduled); }); }); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { - stopVideoService(attachPath); - } + } else { AlertsCreator.processError(currentAccount, error, null, req); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { - stopVideoService(newMsgObj.attachPath); - } removeFromSendingMessages(newMsgObj.id, scheduled); revertEditingMessageObject(msgObj); } @@ -5823,6 +5971,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe sentMessages.add(message = newMessage.message); Utilities.stageQueue.postRunnable(() -> getMessagesController().processNewChannelDifferenceParams(newMessage.pts, newMessage.pts_count, newMessage.message.peer_id.channel_id)); updatesArr.remove(a); + a--; + if (newMessage.message.pinned) { + Utilities.stageQueue.postRunnable(() -> { + ArrayList mids = new ArrayList<>(); + mids.add(newMessage.message.id); + getMessagesStorage().updatePinnedMessages(-channelId, mids, true, -1, 0, false, null); + }); + } break; } else if (update instanceof TLRPC.TL_updateNewScheduledMessage) { final TLRPC.TL_updateNewScheduledMessage newMessage = (TLRPC.TL_updateNewScheduledMessage) update; @@ -5895,9 +6051,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { - stopVideoService(attachPath); - } }); } else { getNotificationCenter().postNotificationName(NotificationCenter.messageReceivedByServer, oldId, newMsgObj.id, newMsgObj, newMsgObj.dialog_id, 0L, existFlags, scheduled); @@ -5910,9 +6063,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe processSentMessage(oldId); removeFromSendingMessages(oldId, scheduled); }); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { - stopVideoService(attachPath); - } }); } } @@ -5925,9 +6075,6 @@ public class SendMessagesHelper extends BaseController implements NotificationCe newMsgObj.send_state = MessageObject.MESSAGE_SEND_STATE_SEND_ERROR; getNotificationCenter().postNotificationName(NotificationCenter.messageSendError, newMsgObj.id); processSentMessage(newMsgObj.id); - if (MessageObject.isVideoMessage(newMsgObj) || MessageObject.isRoundVideoMessage(newMsgObj) || MessageObject.isNewGifMessage(newMsgObj)) { - stopVideoService(newMsgObj.attachPath); - } removeFromSendingMessages(newMsgObj.id, scheduled); } }); @@ -6435,7 +6582,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe private final static int ERROR_TYPE_UNSUPPORTED = 1; private final static int ERROR_TYPE_FILE_TOO_LARGE = 2; - private static int prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, final ArrayList entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, CharSequence caption, boolean notify, int scheduleDate, Integer[] docType, boolean forceDocument) { + private static int prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, final ArrayList entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, CharSequence caption, boolean notify, int scheduleDate, Integer[] docType, boolean forceDocument) { if ((path == null || path.length() == 0) && uri == null) { return ERROR_TYPE_UNSUPPORTED; } @@ -6710,6 +6857,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessagesHelper.SendMessageParams.of(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null, false); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); @@ -6741,7 +6889,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } @UiThread - public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent) { + public static void prepareSendingDocument(AccountInstance accountInstance, String path, String originalPath, Uri uri, String caption, String mine, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent) { if ((path == null || originalPath == null) && uri == null) { return; } @@ -6756,11 +6904,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe paths.add(path); originalPaths.add(originalPath); } - prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialogId, replyToMsg, replyToTopMsg, storyItem, editingMessageObject, notify, scheduleDate, inputContent); + prepareSendingDocuments(accountInstance, paths, originalPaths, uris, caption, mine, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, editingMessageObject, notify, scheduleDate, inputContent); } @UiThread - public static void prepareSendingAudioDocuments(AccountInstance accountInstance, ArrayList messageObjects, CharSequence caption, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, boolean notify, int scheduleDate, MessageObject editingMessageObject) { + public static void prepareSendingAudioDocuments(AccountInstance accountInstance, ArrayList messageObjects, CharSequence caption, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, boolean notify, int scheduleDate, MessageObject editingMessageObject) { new Thread(() -> { int count = messageObjects.size(); long groupId = 0; @@ -6853,7 +7001,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } @UiThread - public static void prepareSendingDocuments(AccountInstance accountInstance, ArrayList paths, ArrayList originalPaths, ArrayList uris, String caption, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent) { + public static void prepareSendingDocuments(AccountInstance accountInstance, ArrayList paths, ArrayList originalPaths, ArrayList uris, String caption, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, MessageObject editingMessageObject, boolean notify, int scheduleDate, InputContentInfoCompat inputContent) { if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) { return; } @@ -6878,7 +7026,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } mediaCount++; long prevGroupId = groupId[0]; - error = prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, storyItem, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null); + error = prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null); if (prevGroupId != groupId[0] || groupId[0] == -1) { mediaCount = 1; } @@ -6899,7 +7047,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } mediaCount++; long prevGroupId = groupId[0]; - error = prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, storyItem, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null); + error = prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, captionFinal, notify, scheduleDate, docType, inputContent == null); if (prevGroupId != groupId[0] || groupId[0] == -1) { mediaCount = 1; } @@ -6930,12 +7078,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } @UiThread - public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate) { - prepareSendingPhoto(accountInstance, imageFilePath, null, imageUri, dialogId, replyToMsg, replyToTopMsg, null, entities, stickers, inputContent, ttl, editingMessageObject, null, notify, scheduleDate, false, caption); + public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, ChatActivity.ReplyQuote quote, CharSequence caption, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate) { + prepareSendingPhoto(accountInstance, imageFilePath, null, imageUri, dialogId, replyToMsg, replyToTopMsg, null, null, entities, stickers, inputContent, ttl, editingMessageObject, null, notify, scheduleDate, false, caption); } @UiThread - public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, String thumbFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument, CharSequence caption) { + public static void prepareSendingPhoto(AccountInstance accountInstance, String imageFilePath, String thumbFilePath, Uri imageUri, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList entities, ArrayList stickers, InputContentInfoCompat inputContent, int ttl, MessageObject editingMessageObject, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument, CharSequence caption) { SendingMediaInfo info = new SendingMediaInfo(); info.path = imageFilePath; info.thumbPath = thumbFilePath; @@ -6951,11 +7099,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe info.videoEditedInfo = videoEditedInfo; ArrayList infos = new ArrayList<>(); infos.add(info); - prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, null, forceDocument, false, editingMessageObject, notify, scheduleDate, false, inputContent); + prepareSendingMedia(accountInstance, infos, dialogId, replyToMsg, replyToTopMsg, null, quote, forceDocument, false, editingMessageObject, notify, scheduleDate, false, inputContent); } @UiThread - public static void prepareSendingBotContextResult(BaseFragment fragment, AccountInstance accountInstance, TLRPC.BotInlineResult result, HashMap params, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, boolean notify, int scheduleDate) { + public static void prepareSendingBotContextResult(BaseFragment fragment, AccountInstance accountInstance, TLRPC.BotInlineResult result, HashMap params, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, boolean notify, int scheduleDate) { if (result == null) { return; } @@ -7236,6 +7384,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } if (params2 != null) { params2.replyToStoryItem = storyItem; + params2.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(params2); } }); @@ -7308,6 +7457,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe messageMediaInvoice.total_amount = invoice.total_amount; messageMediaInvoice.start_param = ""; accountInstance.getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of(messageMediaInvoice, dialogId, replyToMsg, replyToTopMsg, result.send_message.reply_markup, params, notify, scheduleDate)); + } else if (result.send_message instanceof TLRPC.TL_botInlineMessageMediaWebPage) { + TLRPC.TL_botInlineMessageMediaWebPage request = (TLRPC.TL_botInlineMessageMediaWebPage) result.send_message; + TLRPC.WebPage webPage = new TLRPC.TL_webPagePending(); + webPage.url = request.url; + accountInstance.getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of(result.send_message.message, dialogId, replyToMsg, replyToTopMsg, webPage, !result.send_message.no_webpage, result.send_message.entities, result.send_message.reply_markup, params, notify, scheduleDate, null, false)); } } @@ -7486,7 +7640,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe */ @UiThread - public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean updateStikcersOrder, InputContentInfoCompat inputContent) { + public static void prepareSendingMedia(AccountInstance accountInstance, ArrayList media, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, boolean forceDocument, boolean groupMedia, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean updateStikcersOrder, InputContentInfoCompat inputContent) { if (media.isEmpty()) { return; } @@ -7517,7 +7671,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe boolean isWebP = false; if (tempPath != null && info.ttl <= 0 && (tempPath.endsWith(".gif") || (isWebP = tempPath.endsWith(".webp")))) { - if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(tempPath, null))) { + if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(tempPath, null)) && TextUtils.isEmpty(info.caption)) { continue; } else { info.forceImage = true; @@ -7526,7 +7680,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe continue; } else if (tempPath == null && info.uri != null) { if (MediaController.isGif(info.uri) || (isWebP = MediaController.isWebp(info.uri))) { - if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(null, info.uri))) { + if (media.size() <= 1 && (!isWebP || shouldSendWebPAsSticker(null, info.uri)) && TextUtils.isEmpty(info.caption)) { continue; } else { info.forceImage = true; @@ -7692,6 +7846,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessageParams.of(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, 0, parentFinal, null, false, info.hasMediaSpoilers); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); @@ -7765,6 +7920,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessageParams.of(photoFinal, needDownloadHttpFinal ? info.searchImage.imageUrl : null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, false, info.hasMediaSpoilers); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); @@ -7941,6 +8097,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessageParams.of(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, null, false, info.hasMediaSpoilers); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); @@ -8140,6 +8297,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessageParams.of(photoFinal, null, dialogId, replyToMsg, replyToTopMsg, info.caption, info.entities, null, params, notify, scheduleDate, info.ttl, parentFinal, updateStikcersOrder, info.hasMediaSpoilers); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); @@ -8176,7 +8334,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe mediaCount = 0; } mediaCount++; - int error = prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, storyItem, sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, sendAsDocumentsCaptions.get(a), notify, scheduleDate, null, forceDocument); + int error = prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, sendAsDocumentsCaptions.get(a), notify, scheduleDate, null, forceDocument); handleError(error, accountInstance); } } @@ -8441,7 +8599,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } @UiThread - public static void prepareSendingVideo(AccountInstance accountInstance, String videoPath, VideoEditedInfo info, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TLRPC.StoryItem storyItem, ArrayList entities, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean forceDocument, boolean hasMediaSpoilers, CharSequence caption) { + public static void prepareSendingVideo(AccountInstance accountInstance, String videoPath, VideoEditedInfo info, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, TL_stories.StoryItem storyItem, ChatActivity.ReplyQuote quote, ArrayList entities, int ttl, MessageObject editingMessageObject, boolean notify, int scheduleDate, boolean forceDocument, boolean hasMediaSpoilers, CharSequence caption) { if (videoPath == null || videoPath.length() == 0) { return; } @@ -8590,11 +8748,12 @@ public class SendMessagesHelper extends BaseController implements NotificationCe } else { SendMessageParams sendMessageParams = SendMessageParams.of(videoFinal, videoEditedInfo, finalPath, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, ttl, parentFinal, null, false, hasMediaSpoilers); sendMessageParams.replyToStoryItem = storyItem; + sendMessageParams.replyQuote = quote; accountInstance.getSendMessagesHelper().sendMessage(sendMessageParams); } }); } else { - prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, storyItem, entities, editingMessageObject, null, false, caption, notify, scheduleDate, null, forceDocument); + prepareSendingDocumentInternal(accountInstance, videoPath, videoPath, null, null, dialogId, replyToMsg, replyToTopMsg, storyItem, quote, entities, editingMessageObject, null, false, caption, notify, scheduleDate, null, forceDocument); } }).start(); } @@ -8610,6 +8769,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe public TLRPC.TL_game game; public TLRPC.TL_messageMediaPoll poll; public TLRPC.TL_messageMediaInvoice invoice; + public TLRPC.TL_messageMediaWebPage mediaWebPage; public long peer; public String path; public MessageObject replyToMsg; @@ -8627,9 +8787,11 @@ public class SendMessagesHelper extends BaseController implements NotificationCe public MessageObject.SendAnimationData sendAnimationData; public boolean updateStickersOrder; public boolean hasMediaSpoilers; - public TLRPC.StoryItem replyToStoryItem; - public TLRPC.StoryItem sendingStory; + public TL_stories.StoryItem replyToStoryItem; + public TL_stories.StoryItem sendingStory; public Integer autoDeleteDelay; + public ChatActivity.ReplyQuote replyQuote; + public boolean invert_media; public static SendMessageParams of(String string, long dialogId) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 474407ca3..31e8ebc3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -164,6 +164,14 @@ public class SharedConfig { return allowPreparingHevcPlayers; } + public static void togglePaymentByInvoice() { + payByInvoice = !payByInvoice; + ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) + .edit() + .putBoolean("payByInvoice", payByInvoice) + .apply(); + } + public static void toggleSurfaceInStories() { useSurfaceInStories = !useSurfaceInStories; ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) @@ -270,17 +278,19 @@ public class SharedConfig { public static int scheduledHintShows; public static long scheduledHintSeenAt; public static int lockRecordAudioVideoHint; - public static boolean forwardingOptionsHintShown; + public static boolean forwardingOptionsHintShown, replyingOptionsHintShown; public static boolean searchMessagesAsListUsed; public static boolean stickersReorderingHintUsed; public static int dayNightWallpaperSwitchHint; public static boolean storyReactionsLongPressHint; + public static boolean storiesIntroShown; public static boolean disableVoiceAudioEffects; public static boolean forceDisableTabletMode; public static boolean updateStickersOrderOnSend = true; public static boolean bigCameraForRound; public static boolean useSurfaceInStories; public static boolean photoViewerBlur = true; + public static boolean payByInvoice; public static int stealthModeSendMessageConfirm = 2; private static int lastLocalId = -210000; @@ -601,6 +611,7 @@ public class SharedConfig { editor.putInt("scheduledHintShows", scheduledHintShows); editor.putLong("scheduledHintSeenAt", scheduledHintSeenAt); editor.putBoolean("forwardingOptionsHintShown", forwardingOptionsHintShown); + editor.putBoolean("replyingOptionsHintShown", replyingOptionsHintShown); editor.putInt("lockRecordAudioVideoHint", lockRecordAudioVideoHint); editor.putString("storageCacheDir", !TextUtils.isEmpty(storageCacheDir) ? storageCacheDir : ""); editor.putBoolean("proxyRotationEnabled", proxyRotationEnabled); @@ -858,12 +869,14 @@ public class SharedConfig { searchMessagesAsListUsed = preferences.getBoolean("searchMessagesAsListUsed", false); stickersReorderingHintUsed = preferences.getBoolean("stickersReorderingHintUsed", false); storyReactionsLongPressHint = preferences.getBoolean("storyReactionsLongPressHint", false); + storiesIntroShown = preferences.getBoolean("storiesIntroShown", false); textSelectionHintShows = preferences.getInt("textSelectionHintShows", 0); scheduledOrNoSoundHintShows = preferences.getInt("scheduledOrNoSoundHintShows", 0); scheduledOrNoSoundHintSeenAt = preferences.getLong("scheduledOrNoSoundHintSeenAt", 0); scheduledHintShows = preferences.getInt("scheduledHintShows", 0); scheduledHintSeenAt = preferences.getLong("scheduledHintSeenAt", 0); forwardingOptionsHintShown = preferences.getBoolean("forwardingOptionsHintShown", false); + replyingOptionsHintShown = preferences.getBoolean("replyingOptionsHintShown", false); lockRecordAudioVideoHint = preferences.getInt("lockRecordAudioVideoHint", 0); disableVoiceAudioEffects = preferences.getBoolean("disableVoiceAudioEffects", false); noiseSupression = preferences.getBoolean("noiseSupression", false); @@ -887,6 +900,7 @@ public class SharedConfig { dayNightWallpaperSwitchHint = preferences.getInt("dayNightWallpaperSwitchHint", 0); bigCameraForRound = preferences.getBoolean("bigCameraForRound", false); useSurfaceInStories = preferences.getBoolean("useSurfaceInStories", Build.VERSION.SDK_INT >= 30); + payByInvoice = preferences.getBoolean("payByInvoice", false); photoViewerBlur = preferences.getBoolean("photoViewerBlur", true); loadDebugConfig(preferences); @@ -1196,6 +1210,7 @@ public class SharedConfig { scheduledHintSeenAt = 0; lockRecordAudioVideoHint = 0; forwardingOptionsHintShown = false; + replyingOptionsHintShown = false; messageSeenHintCount = 3; emojiInteractionsHintCount = 3; dayNightThemeSwitchHintCount = 3; @@ -1238,6 +1253,14 @@ public class SharedConfig { editor.apply(); } + public static void setStoriesIntroShown(boolean isShown) { + storiesIntroShown = isShown; + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("storiesIntroShown", storiesIntroShown); + editor.apply(); + } + public static void increaseTextSelectionHintShowed() { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); @@ -1285,6 +1308,14 @@ public class SharedConfig { editor.apply(); } + public static void replyingOptionsHintHintShowed() { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + replyingOptionsHintShown = true; + editor.putBoolean("replyingOptionsHintShown", replyingOptionsHintShown); + editor.apply(); + } + public static void removeScheduledOrNoSoundHint() { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java index 1ed5fc2a1..b7ddd37cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java @@ -454,7 +454,7 @@ public class TopicsController extends BaseController { if (topicId != 0) { TLRPC.TL_forumTopic topic = findTopic(chat.id, topicId); if (topic != null) { - return ForumUtilities.getTopicSpannedName(topic, paint, drawableToSet); + return ForumUtilities.getTopicSpannedName(topic, paint, drawableToSet, false); } } return null; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java index 8b4f0b8aa..71836aab0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TranslateController.java @@ -11,6 +11,7 @@ import android.view.inputmethod.InputMethodSubtype; import androidx.annotation.Nullable; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.TranslateAlert2; import org.telegram.ui.RestrictedLanguagesSelectActivity; @@ -1021,7 +1022,7 @@ public class TranslateController extends BaseController { private final HashSet translatingStories = new HashSet<>(); // ensure dialogId in storyItem is valid - public void detectStoryLanguage(TLRPC.StoryItem storyItem) { + public void detectStoryLanguage(TL_stories.StoryItem storyItem) { if (storyItem == null || storyItem.detectedLng != null || storyItem.caption == null || storyItem.caption.length() == 0 || !LanguageDetector.hasSupport()) { return; } @@ -1043,14 +1044,14 @@ public class TranslateController extends BaseController { })); } - public boolean canTranslateStory(TLRPC.StoryItem storyItem) { + public boolean canTranslateStory(TL_stories.StoryItem storyItem) { return storyItem != null && !TextUtils.isEmpty(storyItem.caption) && !Emoji.fullyConsistsOfEmojis(storyItem.caption) && ( storyItem.detectedLng == null && storyItem.translatedText != null && TextUtils.equals(storyItem.translatedLng, TranslateAlert2.getToLanguage()) || storyItem.detectedLng != null && !RestrictedLanguagesSelectActivity.getRestrictedLanguages().contains(storyItem.detectedLng) ); } - public void translateStory(TLRPC.StoryItem storyItem, Runnable done) { + public void translateStory(TL_stories.StoryItem storyItem, Runnable done) { if (storyItem == null) { return; } @@ -1120,7 +1121,7 @@ public class TranslateController extends BaseController { }); } - public boolean isTranslatingStory(TLRPC.StoryItem storyItem) { + public boolean isTranslatingStory(TL_stories.StoryItem storyItem) { if (storyItem == null) { return false; } @@ -1131,7 +1132,7 @@ public class TranslateController extends BaseController { public long dialogId; public int storyId; - public StoryKey(TLRPC.StoryItem storyItem) { + public StoryKey(TL_stories.StoryItem storyItem) { dialogId = storyItem.dialogId; storyId = storyItem.id; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java index f408d3d5f..d993207e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserObject.java @@ -10,11 +10,15 @@ package org.telegram.messenger; import android.text.TextUtils; +import androidx.annotation.NonNull; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.tgnet.TLRPC; public class UserObject { + public static final long REPLY_BOT = 1271266957L; + public static boolean isDeleted(TLRPC.User user) { return user == null || user instanceof TLRPC.TL_userDeleted_old2 || user instanceof TLRPC.TL_userEmpty || user.deleted; } @@ -28,13 +32,14 @@ public class UserObject { } public static boolean isReplyUser(TLRPC.User user) { - return user != null && (user.id == 708513 || user.id == 1271266957); + return user != null && (user.id == 708513 || user.id == REPLY_BOT); } public static boolean isReplyUser(long did) { - return did == 708513 || did == 1271266957; + return did == 708513 || did == REPLY_BOT; } + @NonNull public static String getUserName(TLRPC.User user) { if (user == null || isDeleted(user)) { return LocaleController.getString("HiddenName", R.string.HiddenName); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index c4601daec..0609c23b1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -540,6 +540,10 @@ public class Utilities { public ReturnType run(); } + public static interface Callback0Return { + public ReturnType run(); + } + public static interface CallbackReturn { public ReturnType run(Arg arg); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java index 8d41a95e6..001798c0d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java @@ -17,12 +17,12 @@ import org.telegram.messenger.video.MediaCodecVideoConvertor; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.Paint.PaintTypeface; import org.telegram.ui.Components.PhotoFilterView; import org.telegram.ui.Components.Point; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; -import org.telegram.ui.Components.Reactions.ReactionsUtils; import org.telegram.ui.Stories.recorder.StoryEntry; import java.util.ArrayList; @@ -154,7 +154,7 @@ public class VideoEditedInfo { public AnimatedFileDrawable animatedFileDrawable; public Canvas roundRadiusCanvas; - public TLRPC.MediaArea mediaArea; + public TL_stories.MediaArea mediaArea; public TLRPC.MessageMedia mediaGeo; public float density; @@ -202,7 +202,7 @@ public class VideoEditedInfo { } if (type == TYPE_LOCATION) { density = data.readFloat(false); - mediaArea = TLRPC.MediaArea.TLdeserialize(data, data.readInt32(false), false); + mediaArea = TL_stories.MediaArea.TLdeserialize(data, data.readInt32(false), false); mediaGeo = TLRPC.MessageMedia.TLdeserialize(data, data.readInt32(false), false); if (data.remaining() > 0) { int magic = data.readInt32(false); @@ -215,7 +215,7 @@ public class VideoEditedInfo { } } if (type == TYPE_REACTION) { - mediaArea = TLRPC.MediaArea.TLdeserialize(data, data.readInt32(false), false); + mediaArea = TL_stories.MediaArea.TLdeserialize(data, data.readInt32(false), false); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java index 125b06f08..115b0fc21 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEncodingService.java @@ -14,34 +14,63 @@ import android.os.IBinder; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; +import com.google.android.exoplayer2.util.Log; + public class VideoEncodingService extends Service implements NotificationCenter.NotificationCenterDelegate { private NotificationCompat.Builder builder; - private String path; - private int currentProgress; - private int currentAccount; + private MediaController.VideoConvertMessage currentMessage; + private static VideoEncodingService instance; + + int currentAccount; + String currentPath; public VideoEncodingService() { super(); - NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.stopEncodingService); + } + + public static void start(boolean cancelled) { + if (instance == null) { + Intent intent = new Intent(ApplicationLoader.applicationContext, VideoEncodingService.class); + ApplicationLoader.applicationContext.startService(intent); + } else if (cancelled) { + MediaController.VideoConvertMessage messageInController = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (instance.currentMessage != messageInController) { + if (messageInController != null) { + instance.setCurrentMessage(messageInController); + } else { + instance.stopSelf(); + } + } + } + } + + public static void stop() { + if (instance != null) { + instance.stopSelf(); + } } public IBinder onBind(Intent arg2) { return null; } + public void onDestroy() { super.onDestroy(); + instance = null; try { stopForeground(true); } catch (Throwable ignore) { } NotificationManagerCompat.from(ApplicationLoader.applicationContext).cancel(4); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopEncodingService); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + currentMessage = null; if (BuildVars.LOGS_ENABLED) { - FileLog.d("destroy video service"); + FileLog.d("VideoEncodingService: destroy video service"); } } @@ -49,12 +78,12 @@ public class VideoEncodingService extends Service implements NotificationCenter. public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.fileUploadProgressChanged) { String fileName = (String) args[0]; - if (account == currentAccount && path != null && path.equals(fileName)) { + if (account == currentAccount && currentPath != null && currentPath.equals(fileName)) { Long loadedSize = (Long) args[1]; Long totalSize = (Long) args[2]; float progress = Math.min(1f, loadedSize / (float) totalSize); Boolean enc = (Boolean) args[3]; - currentProgress = (int) (progress * 100); + int currentProgress = (int) (progress * 100); builder.setProgress(100, currentProgress, currentProgress == 0); try { NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); @@ -62,54 +91,86 @@ public class VideoEncodingService extends Service implements NotificationCenter. FileLog.e(e); } } - } else if (id == NotificationCenter.stopEncodingService) { - String filepath = (String) args[0]; - account = (Integer) args[1]; - if (account == currentAccount && (filepath == null || filepath.equals(path))) { - stopSelf(); + } else if (id == NotificationCenter.fileUploaded || id == NotificationCenter.fileUploadFailed) { + String fileName = (String) args[0]; + if (account == currentAccount && currentPath != null && currentPath.equals(fileName)) { + AndroidUtilities.runOnUIThread(() -> { + MediaController.VideoConvertMessage message = MediaController.getInstance().getCurrentForegroundConverMessage(); + if (message != null) { + setCurrentMessage(message); + } else { + stopSelf(); + } + }); } } } public int onStartCommand(Intent intent, int flags, int startId) { - path = intent.getStringExtra("path"); - int oldAccount = currentAccount; - currentAccount = intent.getIntExtra("currentAccount", UserConfig.selectedAccount); - if (!UserConfig.isValidAccount(currentAccount)) { - stopSelf(); + if (isRunning()) { return Service.START_NOT_STICKY; } - if (oldAccount != currentAccount) { - NotificationCenter.getInstance(oldAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); - } - boolean isGif = intent.getBooleanExtra("gif", false); - if (path == null) { - stopSelf(); - return Service.START_NOT_STICKY; - } - if (BuildVars.LOGS_ENABLED) { - FileLog.d("start video service"); - } + instance = this; + MediaController.VideoConvertMessage videoConvertMessage = MediaController.getInstance().getCurrentForegroundConverMessage(); if (builder == null) { NotificationsController.checkOtherNotificationsChannel(); - builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext); + builder = new NotificationCompat.Builder(ApplicationLoader.applicationContext, NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); builder.setSmallIcon(android.R.drawable.stat_sys_upload); builder.setWhen(System.currentTimeMillis()); builder.setChannelId(NotificationsController.OTHER_NOTIFICATIONS_CHANNEL); builder.setContentTitle(LocaleController.getString("AppName", R.string.AppName)); - if (isGif) { - builder.setTicker(LocaleController.getString("SendingGif", R.string.SendingGif)); - builder.setContentText(LocaleController.getString("SendingGif", R.string.SendingGif)); - } else { - builder.setTicker(LocaleController.getString("SendingVideo", R.string.SendingVideo)); - builder.setContentText(LocaleController.getString("SendingVideo", R.string.SendingVideo)); - } } - currentProgress = 0; - builder.setProgress(100, currentProgress, true); - startForeground(4, builder.build()); - NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + + setCurrentMessage(videoConvertMessage); + try { + startForeground(4, builder.build()); + } catch (Throwable e) { + //ignore ForegroundServiceStartNotAllowedException + FileLog.e(e); + } + AndroidUtilities.runOnUIThread(() -> NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build())); return Service.START_NOT_STICKY; } + + private void updateBuilderForMessage(MediaController.VideoConvertMessage videoConvertMessage) { + if (videoConvertMessage == null) { + return; + } + boolean isGif = videoConvertMessage.messageObject != null && MessageObject.isGifMessage(videoConvertMessage.messageObject.messageOwner); + if (isGif) { + builder.setTicker(LocaleController.getString("SendingGif", R.string.SendingGif)); + builder.setContentText(LocaleController.getString("SendingGif", R.string.SendingGif)); + } else { + builder.setTicker(LocaleController.getString("SendingVideo", R.string.SendingVideo)); + builder.setContentText(LocaleController.getString("SendingVideo", R.string.SendingVideo)); + } + int currentProgress = 0; + builder.setProgress(100, currentProgress, true); + } + + private void setCurrentMessage(MediaController.VideoConvertMessage message) { + if (currentMessage == message) { + return; + } + if (currentMessage != null) { + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadProgressChanged); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); + } + updateBuilderForMessage(message); + currentMessage = message; + currentAccount = message.currentAccount; + currentPath = message.messageObject.messageOwner.attachPath; + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadProgressChanged); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploadFailed); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileUploaded); + if (isRunning()) { + NotificationManagerCompat.from(ApplicationLoader.applicationContext).notify(4, builder.build()); + } + } + + public static boolean isRunning() { + return instance != null; + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java index b8f0d2c9a..b89580efb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -20,6 +20,7 @@ import android.media.MediaMetadataRetriever; import android.media.MediaRecorder; import android.os.Build; import android.provider.MediaStore; +import android.text.TextUtils; import android.util.Base64; import android.util.Log; @@ -577,8 +578,8 @@ public class CameraController implements MediaRecorder.OnInfoListener { } camera.setErrorCallback(getErrorListener(session)); Camera.Parameters params = camera.getParameters(); - List rawFlashModes = params.getSupportedFlashModes(); + List rawFlashModes = params.getSupportedFlashModes(); session.availableFlashModes.clear(); if (rawFlashModes != null) { for (int a = 0; a < rawFlashModes.size(); a++) { @@ -587,7 +588,11 @@ public class CameraController implements MediaRecorder.OnInfoListener { session.availableFlashModes.add(rawFlashMode); } } - session.checkFlashMode(session.availableFlashModes.get(0)); + if (!TextUtils.equals(session.getCurrentFlashMode(), params.getFlashMode()) || !session.availableFlashModes.contains(session.getCurrentFlashMode())) { + session.checkFlashMode(session.availableFlashModes.get(0)); + } else { + session.checkFlashMode(session.getCurrentFlashMode()); + } } if (prestartCallback != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraSession.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraSession.java index 2232dfeac..ae79192cb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraSession.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraSession.java @@ -53,7 +53,7 @@ public class CameraSession { private boolean isRound; private boolean destroyed; - protected ArrayList availableFlashModes = new ArrayList<>(); + public ArrayList availableFlashModes = new ArrayList<>(); private int infoCameraId = -1; Camera.CameraInfo info = new Camera.CameraInfo(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java index b73af1351..8b7398c06 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -99,7 +99,7 @@ import javax.microedition.khronos.opengles.GL; @SuppressLint("NewApi") public class CameraView extends FrameLayout implements TextureView.SurfaceTextureListener, CameraController.ICameraView { - public boolean WRITE_TO_FILE_IN_BACKGROUND = true; + public boolean WRITE_TO_FILE_IN_BACKGROUND = false; public boolean isStory; private Size[] previewSize = new Size[2]; @@ -989,20 +989,19 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private float takePictureProgress = 1f; - public void startTakePictureAnimation() { + public void startTakePictureAnimation(boolean haptic) { takePictureProgress = 0; invalidate(); - runHaptic(); + if (haptic) { + runHaptic(); + } } public void runHaptic() { long[] vibrationWaveFormDurationPattern = {0, 1}; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - final Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); VibrationEffect vibrationEffect = VibrationEffect.createWaveform(vibrationWaveFormDurationPattern, -1); - vibrator.cancel(); vibrator.vibrate(vibrationEffect); } else { @@ -2649,6 +2648,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur movie.setRotation(0); movie.setSize(videoWidth, videoHeight); mediaMuxer = new MP4Builder().createMovie(movie, false, false); + mediaMuxer.setAllowSyncFiles(false); } catch (Exception ioe) { throw new RuntimeException(ioe); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/BillingUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/BillingUtilities.java index 7e07c9a5a..a80a04b0b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/BillingUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/BillingUtilities.java @@ -19,13 +19,17 @@ import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; import java.io.InputStream; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import java.util.Map; public class BillingUtilities { private static final String CURRENCY_FILE = "currencies.json"; private static final String CURRENCY_EXP = "exp"; + private static TLRPC.InputStorePaymentPurpose remPaymentPurpose; + @SuppressWarnings("ConstantConditions") public static void extractCurrencyExp(Map currencyExpMap) { if (!currencyExpMap.isEmpty()) { @@ -56,7 +60,12 @@ public class BillingUtilities { paymentPurpose.serializeToStream(serializedData); String obfuscatedData = Base64.encodeToString(serializedData.toByteArray(), Base64.DEFAULT); serializedData.cleanup(); - + if (paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiftCode || paymentPurpose instanceof TLRPC.TL_inputStorePaymentPremiumGiveaway) { + remPaymentPurpose = paymentPurpose; + return Pair.create(obfuscatedAccountId, obfuscatedAccountId); + } else { + remPaymentPurpose = null; + } return Pair.create(obfuscatedAccountId, obfuscatedData); } @@ -86,10 +95,16 @@ public class BillingUtilities { } try { - byte[] obfuscatedDataBytes = Base64.decode(obfuscatedData, Base64.DEFAULT); - SerializedData data = new SerializedData(obfuscatedDataBytes); - TLRPC.InputStorePaymentPurpose purpose = TLRPC.InputStorePaymentPurpose.TLdeserialize(data, data.readInt32(true), true); - data.cleanup(); + TLRPC.InputStorePaymentPurpose purpose; + if (remPaymentPurpose == null) { + byte[] obfuscatedDataBytes = Base64.decode(obfuscatedData, Base64.DEFAULT); + SerializedData data = new SerializedData(obfuscatedDataBytes); + purpose = TLRPC.InputStorePaymentPurpose.TLdeserialize(data, data.readInt32(true), true); + data.cleanup(); + } else { + purpose = remPaymentPurpose; + remPaymentPurpose = null; + } byte[] obfuscatedAccountIdBytes = Base64.decode(obfuscatedAccountId, Base64.DEFAULT); long accountId = Long.parseLong(new String(obfuscatedAccountIdBytes, Charsets.UTF_8)); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CopyUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CopyUtilities.java index 3724fda57..ffe33c226 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CopyUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CopyUtilities.java @@ -7,15 +7,18 @@ import android.text.Html; import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; +import android.text.TextUtils; import android.text.style.StrikethroughSpan; import android.text.style.StyleSpan; import android.text.style.URLSpan; import android.text.style.UnderlineSpan; +import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.FileLog; import org.telegram.messenger.MediaDataController; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.URLSpanReplacement; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; @@ -30,6 +33,7 @@ public class CopyUtilities { private final static int TYPE_SPOILER = 0; private final static int TYPE_MONO = 1; + private final static int TYPE_QUOTE = 2; public static Spannable fromHTML(String html) { Spanned spanned; @@ -49,6 +53,8 @@ public class CopyUtilities { Object[] spans = spanned.getSpans(0, spanned.length(), Object.class); ArrayList entities = new ArrayList<>(spans.length); + ArrayList codes = new ArrayList<>(); + ArrayList quotes = new ArrayList<>(); for (int i = 0; i < spans.length; ++i) { Object span = spans[i]; int start = spanned.getSpanStart(span); @@ -70,7 +76,13 @@ public class CopyUtilities { if (parsedSpan.type == TYPE_SPOILER) { entities.add(setEntityStartEnd(new TLRPC.TL_messageEntitySpoiler(), start, end)); } else if (parsedSpan.type == TYPE_MONO) { - entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityPre(), start, end)); + if (!TextUtils.isEmpty(parsedSpan.lng)) { + codes.add(parsedSpan); + } else { + entities.add(setEntityStartEnd(new TLRPC.TL_messageEntityPre(), start, end)); + } + } else if (parsedSpan.type == TYPE_QUOTE) { + quotes.add(parsedSpan); } } else if (span instanceof AnimatedEmojiSpan) { TLRPC.TL_messageEntityCustomEmoji entity = new TLRPC.TL_messageEntityCustomEmoji(); @@ -97,6 +109,25 @@ public class CopyUtilities { } } MediaDataController.addAnimatedEmojiSpans(entities, spannable, null); + for (int i = 0; i < codes.size(); ++i) { + ParsedSpan span = codes.get(i); + final int start = spanned.getSpanStart(span); + final int end = spanned.getSpanEnd(span); + spannable.setSpan(new CodeHighlighting.Span(true, 0, null, span.lng, spannable.subSequence(start, end).toString()), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); +// CodeHighlighting.highlight( +// spannable, +// spanned.getSpanStart(span), +// spanned.getSpanEnd(span), +// span.lng, +// 0, +// null, +// false +// ); + } + for (int i = 0; i < quotes.size(); ++i) { + ParsedSpan span = quotes.get(i); + QuoteSpan.putQuote(spannable, spanned.getSpanStart(span), spanned.getSpanEnd(span)); + } return spannable; } @@ -242,7 +273,8 @@ public class CopyUtilities { } } else if (tag.equals("pre")) { if (opening) { - output.setSpan(new ParsedSpan(TYPE_MONO), output.length(), output.length(), Spanned.SPAN_MARK_MARK); + String lang = HTMLTagAttributesHandler.getValue(attributes, "lang"); + output.setSpan(new ParsedSpan(TYPE_MONO, lang), output.length(), output.length(), Spanned.SPAN_MARK_MARK); return true; } else { ParsedSpan obj = getLast(output, ParsedSpan.class, TYPE_MONO); @@ -255,6 +287,21 @@ public class CopyUtilities { return true; } } + } else if (tag.equals("blockquote")) { + if (opening) { + output.setSpan(new ParsedSpan(TYPE_QUOTE), output.length(), output.length(), Spanned.SPAN_MARK_MARK); + return true; + } else { + ParsedSpan obj = getLast(output, ParsedSpan.class, TYPE_QUOTE); + if (obj != null) { + int where = output.getSpanStart(obj); + output.removeSpan(obj); + if (where != output.length()) { + output.setSpan(obj, where, output.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } + return true; + } + } } return false; } @@ -290,9 +337,15 @@ public class CopyUtilities { private static class ParsedSpan { final int type; + final String lng; private ParsedSpan(int type) { this.type = type; + this.lng = null; + } + private ParsedSpan(int type, String lng) { + this.type = type; + this.lng = lng; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java index 61d999e81..d44d91f5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/CustomHtml.java @@ -2,14 +2,15 @@ package org.telegram.messenger.utils; import android.text.Spanned; +import org.telegram.messenger.CodeHighlighting; import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.URLSpanMono; import org.telegram.ui.Components.URLSpanReplacement; public class CustomHtml { - private CustomHtml() { } public static String toHtml(Spanned text) { @@ -136,7 +137,8 @@ public class CustomHtml { } } - toHTML_4_wrapAnimatedEmoji(out, text, i, next); + toHTML_4_wrapMonoscape2(out, text, i, next); + if (spans != null) { for (int j = 0; j < spans.length; ++j) { URLSpanMono span = spans[j]; @@ -146,11 +148,67 @@ public class CustomHtml { } } } - - } - private static void toHTML_4_wrapAnimatedEmoji(StringBuilder out, Spanned text, int start, int end) { + private static void toHTML_4_wrapMonoscape2(StringBuilder out, Spanned text, int start, int end) { + + int next; + for (int i = start; i < end; i = next) { + next = text.nextSpanTransition(i, end, CodeHighlighting.Span.class); + if (next < 0) { + next = end; + } + CodeHighlighting.Span[] spans = text.getSpans(i, next, CodeHighlighting.Span.class); + + if (spans != null) { + for (int j = 0; j < spans.length; ++j) { + CodeHighlighting.Span span = spans[j]; + if (span != null) { + out.append("
");
+                    }
+                }
+            }
+
+            toHTML_5_wrapQuote(out, text, i, next);
+
+            if (spans != null) {
+                for (int j = 0; j < spans.length; ++j) {
+                    CodeHighlighting.Span span = spans[j];
+                    if (span != null) {
+                        out.append("
"); + } + } + } + } + } + + private static void toHTML_5_wrapQuote(StringBuilder out, Spanned text, int start, int end) { + + int next; + for (int i = start; i < end; i = next) { + next = text.nextSpanTransition(i, end, QuoteSpan.class); + if (next < 0) { + next = end; + } + QuoteSpan[] spans = text.getSpans(i, next, QuoteSpan.class); + + if (spans != null) { + for (int j = 0; j < spans.length; ++j) { + out.append("
"); + } + } + + toHTML_6_wrapAnimatedEmoji(out, text, i, next); + + if (spans != null) { + for (int j = 0; j < spans.length; ++j) { + out.append("
"); + } + } + } + } + + private static void toHTML_6_wrapAnimatedEmoji(StringBuilder out, Spanned text, int start, int end) { int next; for (int i = start; i < end; i = next) { next = text.nextSpanTransition(i, end, AnimatedEmojiSpan.class); @@ -168,7 +226,7 @@ public class CustomHtml { } } - toHTML_5_withinStyle(out, text, i, next); + toHTML_7_withinStyle(out, text, i, next); if (spans != null) { for (int j = 0; j < spans.length; ++j) { @@ -181,7 +239,7 @@ public class CustomHtml { } } - private static void toHTML_5_withinStyle(StringBuilder out, CharSequence text, int start, int end) { + private static void toHTML_7_withinStyle(StringBuilder out, CharSequence text, int start, int end) { for (int i = start; i < end; i++) { char c = text.charAt(i); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/PhotoUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/PhotoUtilities.java index 08ba9828e..72c7075f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/PhotoUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/PhotoUtilities.java @@ -211,7 +211,7 @@ public class PhotoUtilities { File src = FileLoader.getInstance(chatActivity.getCurrentAccount()).getPathToAttach(avatarBig[0], true); src.renameTo(destFile); } - chatActivity.getMessagesStorage().addDialogPhoto(user.id, ((TLRPC.TL_photos_photo) response).photo); + chatActivity.getMessagesController().getDialogPhotos(user.id).addPhotoAtStart(((TLRPC.TL_photos_photo) response).photo); ArrayList users = new ArrayList<>(); users.add(user); chatActivity.getMessagesStorage().putUsersAndChats(users, null, false, true); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java index 633d081bb..32a327a52 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MP4Builder.java @@ -62,6 +62,7 @@ public class MP4Builder { private ByteBuffer sizeBuffer = null; private boolean splitMdat; private boolean wasFirstVideoFrame; + private boolean allowSyncFiles = true; public MP4Builder createMovie(Mp4Movie mp4Movie, boolean split, boolean hevc) throws Exception { currentMp4Movie = mp4Movie; @@ -90,7 +91,9 @@ public class MP4Builder { mdat.setDataOffset(0); mdat.setContentSize(0); fos.flush(); - fos.getFD().sync(); + if (allowSyncFiles) { + fos.getFD().sync(); + } } public long writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo, boolean writeLength) throws Exception { @@ -163,7 +166,9 @@ public class MP4Builder { if (flush) { fos.flush(); - fos.getFD().sync(); + if (allowSyncFiles) { + fos.getFD().sync(); + } return fc.position(); } return 0; @@ -194,7 +199,9 @@ public class MP4Builder { Box moov = createMovieBox(currentMp4Movie); moov.getBox(fc); fos.flush(); - fos.getFD().sync(); + if (allowSyncFiles) { + fos.getFD().sync(); + } fc.close(); fos.close(); @@ -209,6 +216,10 @@ public class MP4Builder { return new FileTypeBox("isom", 512, minorBrands); } + public void setAllowSyncFiles(boolean allowSyncFiles) { + this.allowSyncFiles = allowSyncFiles; + } + private static class InterleaveChunkMdat implements Box { private Container parent; private long contentSize = 1024 * 1024 * 1024; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java index 49af6f5ce..53a6283c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/VideoPlayerHolderBase.java @@ -6,6 +6,7 @@ import android.graphics.Paint; import android.graphics.SurfaceTexture; import android.net.Uri; import android.os.Build; +import android.util.Log; import android.view.SurfaceView; import android.view.TextureView; @@ -355,10 +356,14 @@ public class VideoPlayerHolderBase { } else { localProgress = currentPosition / (float) playerDuration; } - if (localProgress < progress) { - return progress; - } +// if (localProgress < progress) { +// return progress; +// } progress = localProgress; + if (!seeking) { + currentSeek = progress; + lastSeek = currentPosition; + } } return progress; } @@ -434,4 +439,63 @@ public class VideoPlayerHolderBase { }); } + + private Runnable onSeekUpdate; + public void setOnSeekUpdate(Runnable onSeekUpdate) { + this.onSeekUpdate = onSeekUpdate; + } + + + private volatile boolean firstSeek = true; + private volatile long lastSeek = -1; + private long lastBetterSeek = -1; + public float currentSeek = 0; + public volatile float currentSeekThread = 0; + private volatile long duration; + + private final Runnable betterSeek = () -> { + if (videoPlayer != null) { +// videoPlayer.seekTo(lastBetterSeek, false); + } + }; + + private final Runnable updateSeek = () -> { + if (videoPlayer == null) { + return; + } + long position = (long) (currentSeekThread * duration); + if (lastSeek <= -1) { + lastSeek = position; + } + if (Math.abs(position - lastSeek) >= (firstSeek ? 350 : 40)) { + firstSeek = false; + lastBetterSeek = position; + dispatchQueue.cancelRunnable(betterSeek); + dispatchQueue.postRunnable(betterSeek, 300); + videoPlayer.seekTo(lastSeek = position, true); + } + }; + + private volatile boolean seeking; + public void setSeeking(boolean seeking) { + if (seeking && !this.seeking) { + firstSeek = true; + } + this.seeking = seeking; + if (!seeking) { + dispatchQueue.cancelRunnable(betterSeek); + } + } + + public float seek(float delta, final long duration) { + if (videoPlayer == null) { + return currentSeek; + } + this.duration = duration; + currentSeek = Utilities.clamp(currentSeek + delta, 1, 0); + currentSeekThread = currentSeek; + dispatchQueue.cancelRunnable(updateSeek); + dispatchQueue.postRunnable(updateSeek); + return currentSeek; + } } 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 e646e61f0..449a3978c 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -77,6 +77,7 @@ import android.telephony.TelephonyManager; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; +import android.util.Log; import android.util.LruCache; import android.view.KeyEvent; import android.view.View; @@ -2924,7 +2925,8 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa builder.setSmallIcon(isMicMute() ? R.drawable.voicechat_muted : R.drawable.voicechat_active); } else { builder.setContentTitle(LocaleController.getString("VoipOutgoingCall", R.string.VoipOutgoingCall)); - builder.setSmallIcon(R.drawable.notification); + builder.setSmallIcon(R.drawable.ic_call); + builder.setOngoing(true); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { Intent endIntent = new Intent(this, VoIPActionsReceiver.class); @@ -3599,7 +3601,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa if (groupCall != null) { bldr.setSmallIcon(isMicMute() ? R.drawable.voicechat_muted : R.drawable.voicechat_active); } else { - bldr.setSmallIcon(R.drawable.notification); + bldr.setSmallIcon(R.drawable.ic_call); } startForeground(ID_ONGOING_CALL_NOTIFICATION, bldr.build()); } @@ -4041,10 +4043,9 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa Notification.Builder builder = new Notification.Builder(this) .setContentTitle(video ? LocaleController.getString("VoipInVideoCallBranding", R.string.VoipInVideoCallBranding) : LocaleController.getString("VoipInCallBranding", R.string.VoipInCallBranding)) - .setSmallIcon(R.drawable.notification) + .setSmallIcon(R.drawable.ic_call) .setContentIntent(PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)); - Uri soundProviderUri = Uri.parse("content://" + ApplicationLoader.getApplicationId() + ".call_sound_provider/start_ringing"); - if (Build.VERSION.SDK_INT >= 26) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { SharedPreferences nprefs = MessagesController.getGlobalNotificationsSettings(); int chanIndex = nprefs.getInt("calls_notification_channel", 0); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); @@ -4052,14 +4053,18 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa if (oldChannel != null) { nm.deleteNotificationChannel(oldChannel.getId()); } - NotificationChannel existingChannel = nm.getNotificationChannel("incoming_calls3" + chanIndex); + oldChannel = nm.getNotificationChannel("incoming_calls3" + chanIndex); + if (oldChannel != null) { + nm.deleteNotificationChannel(oldChannel.getId()); + } + NotificationChannel existingChannel = nm.getNotificationChannel("incoming_calls4" + chanIndex); boolean needCreate = true; if (existingChannel != null) { - if (existingChannel.getImportance() < NotificationManager.IMPORTANCE_HIGH || !soundProviderUri.equals(existingChannel.getSound()) || existingChannel.getVibrationPattern() != null || existingChannel.shouldVibrate()) { + if (existingChannel.getImportance() < NotificationManager.IMPORTANCE_HIGH || existingChannel.getSound() != null) { if (BuildVars.LOGS_ENABLED) { FileLog.d("User messed up the notification channel; deleting it and creating a proper one"); } - nm.deleteNotificationChannel("incoming_calls3" + chanIndex); + nm.deleteNotificationChannel("incoming_calls4" + chanIndex); chanIndex++; nprefs.edit().putInt("calls_notification_channel", chanIndex).commit(); } else { @@ -4072,8 +4077,13 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa .setLegacyStreamType(AudioManager.STREAM_RING) .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .build(); - NotificationChannel chan = new NotificationChannel("incoming_calls3" + chanIndex, LocaleController.getString("IncomingCalls", R.string.IncomingCalls), NotificationManager.IMPORTANCE_HIGH); - chan.setSound(soundProviderUri, attrs); + NotificationChannel chan = new NotificationChannel("incoming_calls4" + chanIndex, LocaleController.getString("IncomingCallsSystemSetting", R.string.IncomingCallsSystemSetting), NotificationManager.IMPORTANCE_HIGH); + try { + chan.setSound(null, attrs); + } catch (Exception e) { + FileLog.e(e); + } + chan.setDescription(LocaleController.getString("IncomingCallsSystemSettingDescription", R.string.IncomingCallsSystemSettingDescription)); chan.enableVibration(false); chan.enableLights(false); chan.setBypassDnd(true); @@ -4085,9 +4095,9 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa return; } } - builder.setChannelId("incoming_calls3" + chanIndex); + builder.setChannelId("incoming_calls4" + chanIndex); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - builder.setSound(soundProviderUri, AudioManager.STREAM_RING); + builder.setSound(null); } Intent endIntent = new Intent(this, VoIPActionsReceiver.class); endIntent.setAction(getPackageName() + ".DECLINE_CALL"); @@ -4126,13 +4136,13 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa Notification incomingNotification; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { Bitmap avatar = getRoundAvatarBitmap(userOrChat); - String presonName = ContactsController.formatName(userOrChat); - if (TextUtils.isEmpty(presonName)) { + String personName = ContactsController.formatName(userOrChat); + if (TextUtils.isEmpty(personName)) { //java.lang.IllegalArgumentException: person must have a non-empty a name - presonName = "___"; + personName = "___"; } Person person = new Person.Builder() - .setName(presonName) + .setName(personName) .setIcon(Icon.createWithAdaptiveBitmap(avatar)).build(); Notification.CallStyle notificationStyle = Notification.CallStyle.forIncomingCall(person, endPendingIntent, answerPendingIntent); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 401d60e2e..1b2160be6 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -30,6 +30,7 @@ import org.telegram.messenger.PushListenerController; 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 java.io.ByteArrayOutputStream; @@ -240,7 +241,11 @@ public class ConnectionsManager extends BaseController { mainPreferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig" + currentAccount, Activity.MODE_PRIVATE); } forceTryIpV6 = mainPreferences.getBoolean("forceTryIpV6", false); - init(BuildVars.BUILD_VERSION, TLRPC.LAYER, BuildVars.APP_ID, deviceModel, systemVersion, appVersion, langCode, systemLangCode, configPath, FileLog.getNetworkLogPath(), pushString, fingerprint, timezoneOffset, getUserConfig().getClientUserId(), enablePushConnection); + boolean userPremium = false; + if (getUserConfig().getCurrentUser() != null) { + userPremium = getUserConfig().getCurrentUser().premium; + } + init(BuildVars.BUILD_VERSION, TLRPC.LAYER, BuildVars.APP_ID, deviceModel, systemVersion, appVersion, langCode, systemLangCode, configPath, FileLog.getNetworkLogPath(), pushString, fingerprint, timezoneOffset, getUserConfig().getClientUserId(), userPremium, enablePushConnection); } private String getRegId() { @@ -447,7 +452,7 @@ public class ConnectionsManager extends BaseController { native_setPushConnectionEnabled(currentAccount, value); } - public void init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String systemLangCode, String configPath, String logPath, String regId, String cFingerprint, int timezoneOffset, long userId, boolean enablePushConnection) { + public void init(int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String systemLangCode, String configPath, String logPath, String regId, String cFingerprint, int timezoneOffset, long userId, boolean userPremium, boolean enablePushConnection) { SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); String proxyAddress = preferences.getString("proxy_ip", ""); String proxyUsername = preferences.getString("proxy_user", ""); @@ -477,7 +482,7 @@ public class ConnectionsManager extends BaseController { packageId = ""; } - native_init(currentAccount, version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, systemLangCode, configPath, logPath, regId, cFingerprint, installer, packageId, timezoneOffset, userId, enablePushConnection, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), SharedConfig.measureDevicePerformanceClass()); + native_init(currentAccount, version, layer, apiId, deviceModel, systemVersion, appVersion, langCode, systemLangCode, configPath, logPath, regId, cFingerprint, installer, packageId, timezoneOffset, userId, userPremium, enablePushConnection, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), SharedConfig.measureDevicePerformanceClass()); checkConnection(); } @@ -801,7 +806,7 @@ public class ConnectionsManager extends BaseController { public static native void native_applyDatacenterAddress(int currentAccount, int datacenterId, String ipAddress, int port); public static native int native_getConnectionState(int currentAccount); public static native void native_setUserId(int currentAccount, long id); - public static native void native_init(int currentAccount, int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String systemLangCode, String configPath, String logPath, String regId, String cFingerprint, String installer, String packageId, int timezoneOffset, long userId, boolean enablePushConnection, boolean hasNetwork, int networkType, int performanceClass); + public static native void native_init(int currentAccount, int version, int layer, int apiId, String deviceModel, String systemVersion, String appVersion, String langCode, String systemLangCode, String configPath, String logPath, String regId, String cFingerprint, String installer, String packageId, int timezoneOffset, long userId, boolean userPremium, boolean enablePushConnection, boolean hasNetwork, int networkType, int performanceClass); public static native void native_setProxySettings(int currentAccount, String address, int port, String username, String password, String secret); public static native void native_setLangCode(int currentAccount, String langCode); public static native void native_setRegId(int currentAccount, String regId); diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index d7bea8dc6..bf46df461 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -26,9 +26,9 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.Utilities; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.messenger.partisan.verification.VerificationRepository; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Stories.MessageMediaStoryFull; import org.telegram.ui.Stories.MessageMediaStoryFull_old; -import org.telegram.ui.Stories.recorder.StoryPrivacyBottomSheet; import java.util.ArrayList; import java.util.HashMap; @@ -77,10 +77,10 @@ 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 = 164; + public static final int LAYER = 166; public static class TL_stats_megagroupStats extends TLObject { - public static int constructor = 0xef7ff916; + public static final int constructor = 0xef7ff916; public TL_statsDateRangeDays period; public TL_statsAbsValueAndPrev members; public TL_statsAbsValueAndPrev messages; @@ -257,7 +257,7 @@ public class TLRPC { } public static class TL_emailVerifyPurposeLoginSetup extends EmailVerifyPurpose { - public static int constructor = 0x4345be73; + public static final int constructor = 0x4345be73; public String phone_number; public String phone_code_hash; @@ -275,7 +275,7 @@ public class TLRPC { } public static class TL_emailVerifyPurposeLoginChange extends EmailVerifyPurpose { - public static int constructor = 0x527d22eb; + public static final int constructor = 0x527d22eb; public void serializeToStream(AbstractSerializedData stream) { @@ -284,7 +284,7 @@ public class TLRPC { } public static class TL_emailVerifyPurposePassport extends EmailVerifyPurpose { - public static int constructor = 0xbbf51685; + public static final int constructor = 0xbbf51685; public void serializeToStream(AbstractSerializedData stream) { @@ -318,7 +318,7 @@ public class TLRPC { } public static class TL_emailVerificationCode extends EmailVerification { - public static int constructor = 0x922e55a9; + public static final int constructor = 0x922e55a9; public String code; @@ -333,7 +333,7 @@ public class TLRPC { } public static class TL_emailVerificationGoogle extends EmailVerification { - public static int constructor = 0xdb909ec2; + public static final int constructor = 0xdb909ec2; public String token; @@ -348,7 +348,7 @@ public class TLRPC { } public static class TL_emailVerificationApple extends EmailVerification { - public static int constructor = 0x96d074fd; + public static final int constructor = 0x96d074fd; public String token; @@ -385,7 +385,7 @@ public class TLRPC { } public static class TL_account_emailVerified extends account_EmailVerified { - public static int constructor = 0x2b96cd1b; + public static final int constructor = 0x2b96cd1b; public String email; @@ -400,7 +400,7 @@ public class TLRPC { } public static class TL_account_emailVerifiedLogin extends account_EmailVerified { - public static int constructor = 0xe1bb0d61; + public static final int constructor = 0xe1bb0d61; public String email; public auth_SentCode sent_code; @@ -418,7 +418,7 @@ public class TLRPC { } public static class TL_chatBannedRights extends TLObject { - public static int constructor = 0x9f120418; + public static final int constructor = 0x9f120418; public int flags; public boolean view_messages; @@ -496,7 +496,7 @@ public class TLRPC { } else { send_media = false; } - if (send_plain && send_media) { + if (send_plain && send_media && send_stickers) { send_messages = true; } else { send_messages = false; @@ -527,7 +527,7 @@ public class TLRPC { } public static class TL_stickers_suggestedShortName extends TLObject { - public static int constructor = 0x85fea03f; + public static final int constructor = 0x85fea03f; public String short_name; @@ -558,21 +558,26 @@ public class TLRPC { public int flags; public boolean no_webpage; - public int reply_to_msg_id; + public boolean invert_media; + public InputReplyTo reply_to; public String message; public ArrayList entities = new ArrayList<>(); + public InputMedia media; public int date; public static DraftMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { DraftMessage result = null; switch (constructor) { - case 0x1b0c841a: + case TL_draftMessageEmpty.constructor: result = new TL_draftMessageEmpty(); break; - case 0xba4baec5: + case TL_draftMessageEmpty_layer81.constructor: result = new TL_draftMessageEmpty_layer81(); break; - case 0xfd8e711f: + case TL_draftMessage_layer165.constructor: + result = new TL_draftMessage_layer165(); + break; + case TL_draftMessage.constructor: result = new TL_draftMessage(); break; } @@ -587,7 +592,7 @@ public class TLRPC { } public static class TL_draftMessageEmpty extends DraftMessage { - public static int constructor = 0x1b0c841a; + public static final int constructor = 0x1b0c841a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -607,7 +612,7 @@ public class TLRPC { } public static class TL_draftMessageEmpty_layer81 extends TL_draftMessageEmpty { - public static int constructor = 0xba4baec5; + public static final int constructor = 0xba4baec5; public void serializeToStream(AbstractSerializedData stream) { @@ -616,13 +621,74 @@ public class TLRPC { } public static class TL_draftMessage extends DraftMessage { - public static int constructor = 0xfd8e711f; + public static final int constructor = 0x3fccf7ef; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + no_webpage = (flags & 2) != 0; + invert_media = (flags & 64) != 0; + if ((flags & 16) != 0) { + reply_to = InputReplyTo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + message = stream.readString(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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + if ((flags & 32) != 0) { + media = InputMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + } + date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = no_webpage ? (flags | 2) : (flags &~ 2); + flags = invert_media ? (flags | 64) : (flags &~ 64); + stream.writeInt32(flags); + if ((flags & 16) != 0) { + reply_to.serializeToStream(stream); + } + stream.writeString(message); + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 32) != 0) { + media.serializeToStream(stream); + } + stream.writeInt32(date); + } + } + + public static class TL_draftMessage_layer165 extends TL_draftMessage { + public static final int constructor = 0xfd8e711f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); no_webpage = (flags & 2) != 0; if ((flags & 1) != 0) { - reply_to_msg_id = stream.readInt32(exception); + TL_inputReplyToMessage reply_to = new TL_inputReplyToMessage(); + reply_to.flags |= 16; + reply_to.reply_to_msg_id = stream.readInt32(exception); + this.reply_to = reply_to; } message = stream.readString(exception); if ((flags & 8) != 0) { @@ -650,7 +716,7 @@ public class TLRPC { flags = no_webpage ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); if ((flags & 1) != 0) { - stream.writeInt32(reply_to_msg_id); + stream.writeInt32(reply_to instanceof TLRPC.TL_inputReplyToMessage ? ((TL_inputReplyToMessage) reply_to).reply_to_msg_id : 0); } stream.writeString(message); if ((flags & 8) != 0) { @@ -713,7 +779,7 @@ public class TLRPC { } public static class TL_chatPhoto extends ChatPhoto { - public static int constructor = 0x1c6e1c11; + public static final int constructor = 0x1c6e1c11; public void readParams(AbstractSerializedData stream, boolean exception) { readParams(stream, exception, true); @@ -756,7 +822,7 @@ public class TLRPC { } public static class TL_chatPhoto_layer115 extends TL_chatPhoto { - public static int constructor = 0x475cdbd5; + public static final int constructor = 0x475cdbd5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -774,7 +840,7 @@ public class TLRPC { } public static class TL_chatPhotoEmpty extends ChatPhoto { - public static int constructor = 0x37c1011c; + public static final int constructor = 0x37c1011c; public void serializeToStream(AbstractSerializedData stream) { @@ -783,7 +849,7 @@ public class TLRPC { } public static class TL_chatPhoto_layer97 extends TL_chatPhoto { - public static int constructor = 0x6153276a; + public static final int constructor = 0x6153276a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -799,7 +865,7 @@ public class TLRPC { } public static class TL_chatPhoto_layer126 extends TL_chatPhoto { - public static int constructor = 0xd20b9f3c; + public static final int constructor = 0xd20b9f3c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -821,7 +887,7 @@ public class TLRPC { } public static class TL_chatPhoto_layer127 extends TL_chatPhoto { - public static int constructor = 0x4790ee05; + public static final int constructor = 0x4790ee05; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -856,7 +922,7 @@ public class TLRPC { } public static class TL_help_termsOfService extends TLObject { - public static int constructor = 0x780a0310; + public static final int constructor = 0x780a0310; public int flags; public boolean popup; @@ -922,7 +988,7 @@ public class TLRPC { } public static class TL_payments_paymentReceipt extends TLObject { - public static int constructor = 0x70c4fe03; + public static final int constructor = 0x70c4fe03; public int flags; public int date; @@ -1058,7 +1124,7 @@ public class TLRPC { } public static class TL_notifyForumTopic extends NotifyPeer { - public static int constructor = 0x226e6308; + public static final int constructor = 0x226e6308; public Peer peer; public int top_msg_id; @@ -1076,7 +1142,7 @@ public class TLRPC { } public static class TL_notifyBroadcasts extends NotifyPeer { - public static int constructor = 0xd612e8ef; + public static final int constructor = 0xd612e8ef; public void serializeToStream(AbstractSerializedData stream) { @@ -1085,7 +1151,7 @@ public class TLRPC { } public static class TL_notifyChats extends NotifyPeer { - public static int constructor = 0xc007cec3; + public static final int constructor = 0xc007cec3; public void serializeToStream(AbstractSerializedData stream) { @@ -1094,7 +1160,7 @@ public class TLRPC { } public static class TL_notifyUsers extends NotifyPeer { - public static int constructor = 0xb4c83b4c; + public static final int constructor = 0xb4c83b4c; public void serializeToStream(AbstractSerializedData stream) { @@ -1103,7 +1169,7 @@ public class TLRPC { } public static class TL_notifyPeer extends NotifyPeer { - public static int constructor = 0x9fd40bd8; + public static final int constructor = 0x9fd40bd8; public Peer peer; @@ -1118,7 +1184,7 @@ public class TLRPC { } public static class TL_phone_joinAsPeers extends TLObject { - public static int constructor = 0xafe5623f; + public static final int constructor = 0xafe5623f; public ArrayList peers = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -1209,7 +1275,7 @@ public class TLRPC { } public static class TL_emojiKeywordsDifference extends TLObject { - public static int constructor = 0x5cc761bd; + public static final int constructor = 0x5cc761bd; public String lang_code; public int from_version; @@ -1289,7 +1355,7 @@ public class TLRPC { } public static class TL_messages_sentEncryptedMessage extends messages_SentEncryptedMessage { - public static int constructor = 0x560f8935; + public static final int constructor = 0x560f8935; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -1303,7 +1369,7 @@ public class TLRPC { } public static class TL_messages_sentEncryptedFile extends messages_SentEncryptedMessage { - public static int constructor = 0x9493ff32; + public static final int constructor = 0x9493ff32; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -1319,7 +1385,7 @@ public class TLRPC { } public static class TL_premiumSubscriptionOption extends TLObject { - public static int constructor = 0x5f2d1df2; + public static final int constructor = 0x5f2d1df2; public int flags; public boolean current; @@ -1385,7 +1451,7 @@ public class TLRPC { } public static class TL_premiumSubscriptionOption_layer151 extends TL_premiumSubscriptionOption { - public static int constructor = 0xb6f11ebe; + public static final int constructor = 0xb6f11ebe; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -1413,7 +1479,7 @@ public class TLRPC { } public static class TL_premiumGiftOption extends TLObject { - public static int constructor = 0x74c34319; + public static final int constructor = 0x74c34319; public int flags; public int months; @@ -1460,7 +1526,7 @@ public class TLRPC { } public static class TL_error extends TLObject { - public static int constructor = 0xc4b9f9bb; + public static final int constructor = 0xc4b9f9bb; public int code; public String text; @@ -1516,7 +1582,7 @@ public class TLRPC { } public static class TL_urlAuthResultDefault extends UrlAuthResult { - public static int constructor = 0xa9d6db1f; + public static final int constructor = 0xa9d6db1f; public void serializeToStream(AbstractSerializedData stream) { @@ -1525,7 +1591,7 @@ public class TLRPC { } public static class TL_urlAuthResultRequest extends UrlAuthResult { - public static int constructor = 0x92d33a0e; + public static final int constructor = 0x92d33a0e; public int flags; public boolean request_write_access; @@ -1549,7 +1615,7 @@ public class TLRPC { } public static class TL_urlAuthResultAccepted extends UrlAuthResult { - public static int constructor = 0x8f8c0e4e; + public static final int constructor = 0x8f8c0e4e; public String url; @@ -1564,7 +1630,7 @@ public class TLRPC { } public static class TL_messages_chatFull extends TLObject { - public static int constructor = 0xe5d7d19c; + public static final int constructor = 0xe5d7d19c; public ChatFull full_chat; public ArrayList chats = new ArrayList<>(); @@ -1635,427 +1701,8 @@ public class TLRPC { } } - public static class TL_inputChatlistDialogFilter extends TLObject { - public static int constructor = 0xf3e0da33; - - public int filter_id; - - public static TL_inputChatlistDialogFilter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_inputChatlistDialogFilter.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_inputChatlistDialogFilter", constructor)); - } else { - return null; - } - } - TL_inputChatlistDialogFilter result = new TL_inputChatlistDialogFilter(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - filter_id = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(filter_id); - } - } - - public static class TL_chatlists_exportedChatlistInvite extends TLObject { - public static int constructor = 0x10e6e3a6; - - public DialogFilter filter; - public TL_exportedChatlistInvite invite; - - public static TL_chatlists_exportedChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_chatlists_exportedChatlistInvite.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_exportedChatlistInvite", constructor)); - } else { - return null; - } - } - TL_chatlists_exportedChatlistInvite result = new TL_chatlists_exportedChatlistInvite(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - filter = DialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); - invite = TL_exportedChatlistInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - filter.serializeToStream(stream); - invite.serializeToStream(stream); - } - } - - public static class TL_exportedChatlistInvite extends TLObject { - public static int constructor = 0xc5181ac; - - public int flags; - public boolean revoked; - public String title; - public String url; - public ArrayList peers = new ArrayList<>(); - - public static TL_exportedChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_exportedChatlistInvite.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_exportedChatlistInvite", constructor)); - } else { - return null; - } - } - TL_exportedChatlistInvite result = new TL_exportedChatlistInvite(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - revoked = (flags & 1) != 0; - title = stream.readString(exception); - url = 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++) { - Peer object = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - peers.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = revoked ? (flags | 1) : (flags & ~1); - stream.writeInt32(flags); - stream.writeString(title); - stream.writeString(url); - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - - public static class TL_chatlists_exportedInvites extends TLObject { - public static int constructor = 0x10ab6dc7; - - public ArrayList invites = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_chatlists_exportedInvites TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_chatlists_exportedInvites.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_exportedInvites", constructor)); - } else { - return null; - } - } - TL_chatlists_exportedInvites result = new TL_chatlists_exportedInvites(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - TL_exportedChatlistInvite object = TL_exportedChatlistInvite.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - invites.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = invites.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - invites.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static abstract class chatlist_ChatlistInvite extends TLObject { - - public static chatlist_ChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - chatlist_ChatlistInvite result = null; - switch (constructor) { - case 0xfa87f659: - result = new TL_chatlists_chatlistInviteAlready(); - break; - case 0x1dcd839d: - result = new TL_chatlists_chatlistInvite(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in chatlist_ChatlistInvite", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_chatlists_chatlistInviteAlready extends chatlist_ChatlistInvite { - public static int constructor = 0xfa87f659; - - public int filter_id; - public ArrayList missing_peers = new ArrayList<>(); - public ArrayList already_peers = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public void readParams(AbstractSerializedData stream, boolean exception) { - filter_id = stream.readInt32(exception); - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Peer object = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - missing_peers.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++) { - Peer object = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - already_peers.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(filter_id); - stream.writeInt32(0x1cb5c415); - int count = missing_peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - missing_peers.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static class TL_chatlists_chatlistInvite extends chatlist_ChatlistInvite { - public static int constructor = 0x1dcd839d; - - public int flags; - public String title; - public String emoticon; - public ArrayList peers = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - title = stream.readString(exception); - if ((flags & 1) > 0) { - emoticon = 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++) { - Peer object = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - peers.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeString(title); - if ((flags & 1) > 0) { - stream.writeString(emoticon); - } - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - public static class TL_account_passwordSettings extends TLObject { - public static int constructor = 0x9a5c33e5; + public static final int constructor = 0x9a5c33e5; public int flags; public String email; @@ -2175,7 +1822,7 @@ public class TLRPC { } public static class TL_documentAttributeSticker_layer55 extends TL_documentAttributeSticker { - public static int constructor = 0x3a556302; + public static final int constructor = 0x3a556302; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2191,7 +1838,7 @@ public class TLRPC { } public static class TL_documentAttributeAudio_old extends TL_documentAttributeAudio { - public static int constructor = 0x51448e5; + public static final int constructor = 0x51448e5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2205,7 +1852,7 @@ public class TLRPC { } public static class TL_documentAttributeSticker extends DocumentAttribute { - public static int constructor = 0x6319d612; + public static final int constructor = 0x6319d612; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2231,7 +1878,7 @@ public class TLRPC { } public static class TL_documentAttributeAnimated extends DocumentAttribute { - public static int constructor = 0x11b58939; + public static final int constructor = 0x11b58939; public void serializeToStream(AbstractSerializedData stream) { @@ -2240,7 +1887,7 @@ public class TLRPC { } public static class TL_documentAttributeFilename extends DocumentAttribute { - public static int constructor = 0x15590068; + public static final int constructor = 0x15590068; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2254,7 +1901,7 @@ public class TLRPC { } public static class TL_documentAttributeVideo extends DocumentAttribute { - public static int constructor = 0xd38ff1c2; + public static final int constructor = 0xd38ff1c2; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -2285,7 +1932,7 @@ public class TLRPC { } public static class TL_documentAttributeVideo_layer159 extends TL_documentAttributeVideo { - public static int constructor = 0xef02ce6; + public static final int constructor = 0xef02ce6; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -2308,7 +1955,7 @@ public class TLRPC { } public static class TL_documentAttributeVideo_layer65 extends TL_documentAttributeVideo { - public static int constructor = 0x5910cccb; + public static final int constructor = 0x5910cccb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2326,7 +1973,7 @@ public class TLRPC { } public static class TL_documentAttributeAudio_layer45 extends TL_documentAttributeAudio { - public static int constructor = 0xded218e0; + public static final int constructor = 0xded218e0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2344,7 +1991,7 @@ public class TLRPC { } public static class TL_documentAttributeSticker_old extends TL_documentAttributeSticker { - public static int constructor = 0xfb0a5727; + public static final int constructor = 0xfb0a5727; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2356,7 +2003,7 @@ public class TLRPC { } public static class TL_documentAttributeHasStickers extends DocumentAttribute { - public static int constructor = 0x9801d2f7; + public static final int constructor = 0x9801d2f7; public void serializeToStream(AbstractSerializedData stream) { @@ -2365,7 +2012,7 @@ public class TLRPC { } public static class TL_documentAttributeSticker_old2 extends TL_documentAttributeSticker { - public static int constructor = 0x994c9882; + public static final int constructor = 0x994c9882; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2379,7 +2026,7 @@ public class TLRPC { } public static class TL_documentAttributeImageSize extends DocumentAttribute { - public static int constructor = 0x6c37c15c; + public static final int constructor = 0x6c37c15c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2395,7 +2042,7 @@ public class TLRPC { } public static class TL_documentAttributeAudio extends DocumentAttribute { - public static int constructor = 0x9852f9c6; + public static final int constructor = 0x9852f9c6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2431,7 +2078,7 @@ public class TLRPC { } public static class TL_documentAttributeCustomEmoji extends DocumentAttribute { - public static int constructor = 0xfd149899; + public static final int constructor = 0xfd149899; public boolean free; public boolean text_color; @@ -2455,7 +2102,7 @@ public class TLRPC { } public static class TL_textPhone extends RichText { - public static int constructor = 0x1ccb966a; + public static final int constructor = 0x1ccb966a; public RichText text; public String phone; @@ -2473,7 +2120,7 @@ public class TLRPC { } public static class TL_textSuperscript extends RichText { - public static int constructor = 0xc7fb5e01; + public static final int constructor = 0xc7fb5e01; public RichText text; @@ -2488,7 +2135,7 @@ public class TLRPC { } public static class TL_textImage extends RichText { - public static int constructor = 0x81ccf4f; + public static final int constructor = 0x81ccf4f; public long document_id; public int w; @@ -2509,7 +2156,7 @@ public class TLRPC { } public static class TL_textEmpty extends RichText { - public static int constructor = 0xdc3d824f; + public static final int constructor = 0xdc3d824f; public void serializeToStream(AbstractSerializedData stream) { @@ -2518,7 +2165,7 @@ public class TLRPC { } public static class TL_textUrl extends RichText { - public static int constructor = 0x3c2884c1; + public static final int constructor = 0x3c2884c1; public RichText text; @@ -2537,7 +2184,7 @@ public class TLRPC { } public static class TL_textAnchor extends RichText { - public static int constructor = 0x35553762; + public static final int constructor = 0x35553762; public RichText text; public String name; @@ -2555,7 +2202,7 @@ public class TLRPC { } public static class TL_textStrike extends RichText { - public static int constructor = 0x9bf8bb95; + public static final int constructor = 0x9bf8bb95; public RichText text; @@ -2570,7 +2217,7 @@ public class TLRPC { } public static class TL_textMarked extends RichText { - public static int constructor = 0x34b8621; + public static final int constructor = 0x34b8621; public RichText text; @@ -2585,7 +2232,7 @@ public class TLRPC { } public static class TL_textFixed extends RichText { - public static int constructor = 0x6c3f19b9; + public static final int constructor = 0x6c3f19b9; public RichText text; @@ -2600,7 +2247,7 @@ public class TLRPC { } public static class TL_textEmail extends RichText { - public static int constructor = 0xde5a0dd6; + public static final int constructor = 0xde5a0dd6; public RichText text; @@ -2617,7 +2264,7 @@ public class TLRPC { } public static class TL_textPlain extends RichText { - public static int constructor = 0x744694e0; + public static final int constructor = 0x744694e0; public String text; @@ -2632,7 +2279,7 @@ public class TLRPC { } public static class TL_textConcat extends RichText { - public static int constructor = 0x7e6260d7; + public static final int constructor = 0x7e6260d7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2665,7 +2312,7 @@ public class TLRPC { } public static class TL_textBold extends RichText { - public static int constructor = 0x6724abc4; + public static final int constructor = 0x6724abc4; public RichText text; @@ -2680,7 +2327,7 @@ public class TLRPC { } public static class TL_textItalic extends RichText { - public static int constructor = 0xd912a59c; + public static final int constructor = 0xd912a59c; public RichText text; @@ -2695,7 +2342,7 @@ public class TLRPC { } public static class TL_textUnderline extends RichText { - public static int constructor = 0xc12622c4; + public static final int constructor = 0xc12622c4; public RichText text; @@ -2710,7 +2357,7 @@ public class TLRPC { } public static class TL_textSubscript extends RichText { - public static int constructor = 0xed6a8504; + public static final int constructor = 0xed6a8504; public RichText text; @@ -2725,7 +2372,7 @@ public class TLRPC { } public static class TL_statsURL extends TLObject { - public static int constructor = 0x47a971e0; + public static final int constructor = 0x47a971e0; public String url; @@ -2753,7 +2400,7 @@ public class TLRPC { } public static class TL_popularContact extends TLObject { - public static int constructor = 0x5ce14175; + public static final int constructor = 0x5ce14175; public long client_id; public int importers; @@ -2784,7 +2431,7 @@ public class TLRPC { } public static class TL_messages_botCallbackAnswer extends TLObject { - public static int constructor = 0x36585ea4; + public static final int constructor = 0x36585ea4; public int flags; public boolean alert; @@ -2838,7 +2485,7 @@ public class TLRPC { } public static class TL_dataJSON extends TLObject { - public static int constructor = 0x7d748d04; + public static final int constructor = 0x7d748d04; public String data; @@ -2866,7 +2513,7 @@ public class TLRPC { } public static class TL_contactStatus extends TLObject { - public static int constructor = 0x16d9703b; + public static final int constructor = 0x16d9703b; public long user_id; public UserStatus status; @@ -2940,7 +2587,7 @@ public class TLRPC { } public static class TL_groupCallDiscarded extends GroupCall { - public static int constructor = 0x7780bcb4; + public static final int constructor = 0x7780bcb4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -2958,7 +2605,7 @@ public class TLRPC { } public static class TL_groupCall extends GroupCall { - public static int constructor = 0xd597650c; + public static final int constructor = 0xd597650c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -3028,7 +2675,7 @@ public class TLRPC { } public static class TL_channelBannedRights_layer92 extends TLObject { - public static int constructor = 0x58cf4249; + public static final int constructor = 0x58cf4249; public int flags; public boolean view_messages; @@ -3105,7 +2752,7 @@ public class TLRPC { } public static class TL_dialogPeer extends DialogPeer { - public static int constructor = 0xe56dbf05; + public static final int constructor = 0xe56dbf05; public Peer peer; @@ -3120,7 +2767,7 @@ public class TLRPC { } public static class TL_dialogPeerFolder extends DialogPeer { - public static int constructor = 0x514519e2; + public static final int constructor = 0x514519e2; public int folder_id; @@ -3171,7 +2818,7 @@ public class TLRPC { } public static class TL_messagePeerReaction extends MessagePeerReaction { - public static int constructor = 0x8c79b63c; + public static final int constructor = 0x8c79b63c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -3194,7 +2841,7 @@ public class TLRPC { } public static class TL_messagePeerReaction_layer154 extends MessagePeerReaction { - public static int constructor = 0xb156fe9c; + public static final int constructor = 0xb156fe9c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -3215,7 +2862,7 @@ public class TLRPC { } public static class TL_messagePeerReaction_layer144 extends MessagePeerReaction { - public static int constructor = 0x51b67eff; + public static final int constructor = 0x51b67eff; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -3240,7 +2887,7 @@ public class TLRPC { } public static class TL_messagePeerReaction_layer137 extends MessagePeerReaction { - public static int constructor = 0x932844fa; + public static final int constructor = 0x932844fa; public long user_id; @@ -3288,7 +2935,7 @@ public class TLRPC { } public static class TL_auth_authorizationSignUpRequired extends auth_Authorization { - public static int constructor = 0x44747e9a; + public static final int constructor = 0x44747e9a; public int flags; public TL_help_termsOfService terms_of_service; @@ -3310,7 +2957,7 @@ public class TLRPC { } public static class TL_auth_authorization extends auth_Authorization { - public static int constructor = 0x2ea2c0d4; + public static final int constructor = 0x2ea2c0d4; public int flags; public boolean setup_password_required; @@ -3352,7 +2999,7 @@ public class TLRPC { } public static class TL_pollAnswer extends TLObject { - public static int constructor = 0x6ca9c2e9; + public static final int constructor = 0x6ca9c2e9; public String text; public byte[] option; @@ -3417,7 +3064,7 @@ public class TLRPC { } public static class TL_jsonBool extends JSONValue { - public static int constructor = 0xc7345e6a; + public static final int constructor = 0xc7345e6a; public boolean value; @@ -3432,7 +3079,7 @@ public class TLRPC { } public static class TL_jsonNull extends JSONValue { - public static int constructor = 0x3f6d7b68; + public static final int constructor = 0x3f6d7b68; public void serializeToStream(AbstractSerializedData stream) { @@ -3441,7 +3088,7 @@ public class TLRPC { } public static class TL_jsonString extends JSONValue { - public static int constructor = 0xb71e767a; + public static final int constructor = 0xb71e767a; public String value; @@ -3456,7 +3103,7 @@ public class TLRPC { } public static class TL_jsonArray extends JSONValue { - public static int constructor = 0xf7444763; + public static final int constructor = 0xf7444763; public ArrayList value = new ArrayList<>(); @@ -3490,7 +3137,7 @@ public class TLRPC { } public static class TL_jsonObject extends JSONValue { - public static int constructor = 0x99c1d49d; + public static final int constructor = 0x99c1d49d; public ArrayList value = new ArrayList<>(); @@ -3524,7 +3171,7 @@ public class TLRPC { } public static class TL_jsonNumber extends JSONValue { - public static int constructor = 0x2be0dfa4; + public static final int constructor = 0x2be0dfa4; public double value; @@ -3564,7 +3211,7 @@ public class TLRPC { } public static class TL_inputWallPaper extends InputWallPaper { - public static int constructor = 0xe630b979; + public static final int constructor = 0xe630b979; public long id; public long access_hash; @@ -3582,7 +3229,7 @@ public class TLRPC { } public static class TL_inputWallPaperNoFile extends InputWallPaper { - public static int constructor = 0x967a462e; + public static final int constructor = 0x967a462e; public long id; @@ -3597,7 +3244,7 @@ public class TLRPC { } public static class TL_inputWallPaperSlug extends InputWallPaper { - public static int constructor = 0x72091c80; + public static final int constructor = 0x72091c80; public String slug; @@ -3612,7 +3259,7 @@ public class TLRPC { } public static class TL_messages_historyImportParsed extends TLObject { - public static int constructor = 0x5e0fb7b9; + public static final int constructor = 0x5e0fb7b9; public int flags; public boolean pm; @@ -3653,7 +3300,7 @@ public class TLRPC { } public static class TL_folder extends TLObject { - public static int constructor = 0xff544e65; + public static final int constructor = 0xff544e65; public int flags; public boolean autofill_new_broadcasts; @@ -3742,7 +3389,7 @@ public class TLRPC { } public static class TL_messages_messagesSlice extends messages_Messages { - public static int constructor = 0x3a54685e; + public static final int constructor = 0x3a54685e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -3835,7 +3482,7 @@ public class TLRPC { } public static class TL_messages_messages extends messages_Messages { - public static int constructor = 0x8c718e87; + public static final int constructor = 0x8c718e87; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -3910,7 +3557,7 @@ public class TLRPC { } public static class TL_messages_channelMessages extends messages_Messages { - public static int constructor = 0xc776ba4e; + public static final int constructor = 0xc776ba4e; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -4019,7 +3666,7 @@ public class TLRPC { } public static class TL_messages_messagesNotModified extends messages_Messages { - public static int constructor = 0x74535f21; + public static final int constructor = 0x74535f21; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4033,7 +3680,7 @@ public class TLRPC { } public static class TL_statsGroupTopAdmin extends TLObject { - public static int constructor = 0xd7584c87; + public static final int constructor = 0xd7584c87; public long user_id; public int deleted; @@ -4070,7 +3717,7 @@ public class TLRPC { } public static class TL_payments_paymentForm extends TLObject { - public static int constructor = 0xa0058751; + public static final int constructor = 0xa0058751; public int flags; public boolean can_save_credentials; @@ -4227,7 +3874,7 @@ public class TLRPC { } public static class TL_paymentFormMethod extends TLObject { - public static int constructor = 0x88f8f21b; + public static final int constructor = 0x88f8f21b; public String url; public String title; @@ -4283,7 +3930,7 @@ public class TLRPC { } public static class TL_contactLinkNone extends ContactLink_layer101 { - public static int constructor = 0xfeedd3ad; + public static final int constructor = 0xfeedd3ad; public void serializeToStream(AbstractSerializedData stream) { @@ -4292,7 +3939,7 @@ public class TLRPC { } public static class TL_contactLinkContact extends ContactLink_layer101 { - public static int constructor = 0xd502c2d0; + public static final int constructor = 0xd502c2d0; public void serializeToStream(AbstractSerializedData stream) { @@ -4301,7 +3948,7 @@ public class TLRPC { } public static class TL_contactLinkUnknown extends ContactLink_layer101 { - public static int constructor = 0x5f4f9247; + public static final int constructor = 0x5f4f9247; public void serializeToStream(AbstractSerializedData stream) { @@ -4311,7 +3958,7 @@ public class TLRPC { public static class TL_contacts_link_layer101 extends TLObject { - public static int constructor = 0x3ace484c; + public static final int constructor = 0x3ace484c; public ContactLink_layer101 my_link; public ContactLink_layer101 foreign_link; @@ -4375,7 +4022,7 @@ public class TLRPC { } public static class TL_encryptedFile extends EncryptedFile { - public static int constructor = 0xa8008cd8; + public static final int constructor = 0xa8008cd8; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); @@ -4396,7 +4043,7 @@ public class TLRPC { } public static class TL_encryptedFile_layer142 extends EncryptedFile { - public static int constructor = 0x4a70994c; + public static final int constructor = 0x4a70994c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4418,7 +4065,7 @@ public class TLRPC { } public static class TL_encryptedFileEmpty extends EncryptedFile { - public static int constructor = 0xc21f497e; + public static final int constructor = 0xc21f497e; public void serializeToStream(AbstractSerializedData stream) { @@ -4465,7 +4112,7 @@ public class TLRPC { } public static class TL_peerChannel_layer131 extends TL_peerChannel { - public static int constructor = 0xbddde532; + public static final int constructor = 0xbddde532; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4479,7 +4126,7 @@ public class TLRPC { } public static class TL_peerUser extends Peer { - public static int constructor = 0x59511722; + public static final int constructor = 0x59511722; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4493,7 +4140,7 @@ public class TLRPC { } public static class TL_peerChannel extends Peer { - public static int constructor = 0xa2a5371e; + public static final int constructor = 0xa2a5371e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4507,7 +4154,7 @@ public class TLRPC { } public static class TL_peerChat extends Peer { - public static int constructor = 0x36c6019a; + public static final int constructor = 0x36c6019a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4521,7 +4168,7 @@ public class TLRPC { } public static class TL_peerUser_layer131 extends TL_peerUser { - public static int constructor = 0x9db1bc6d; + public static final int constructor = 0x9db1bc6d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4535,7 +4182,7 @@ public class TLRPC { } public static class TL_peerChat_layer131 extends TL_peerChat { - public static int constructor = 0xbad0e5bb; + public static final int constructor = 0xbad0e5bb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -4549,7 +4196,7 @@ public class TLRPC { } public static class TL_labeledPrice extends TLObject { - public static int constructor = 0xcb296bf8; + public static final int constructor = 0xcb296bf8; public String label; public long amount; @@ -4580,7 +4227,7 @@ public class TLRPC { } public static class TL_messages_exportedChatInvites extends TLObject { - public static int constructor = 0xbdc62dcc; + public static final int constructor = 0xbdc62dcc; public int count; public ArrayList invites = new ArrayList<>(); @@ -4652,7 +4299,7 @@ public class TLRPC { } public static class TL_inputStickerSetItem extends TLObject { - public static int constructor = 0xffa0a496; + public static final int constructor = 0xffa0a496; public int flags; public InputDocument document; @@ -4693,7 +4340,7 @@ public class TLRPC { } public static class TL_langPackDifference extends TLObject { - public static int constructor = 0xf385c1f6; + public static final int constructor = 0xf385c1f6; public String lang_code; public int from_version; @@ -4771,7 +4418,7 @@ public class TLRPC { } public static class TL_help_deepLinkInfoEmpty extends help_DeepLinkInfo { - public static int constructor = 0x66afa166; + public static final int constructor = 0x66afa166; public void serializeToStream(AbstractSerializedData stream) { @@ -4780,7 +4427,7 @@ public class TLRPC { } public static class TL_help_deepLinkInfo extends help_DeepLinkInfo { - public static int constructor = 0x6a4ee832; + public static final int constructor = 0x6a4ee832; public int flags; public boolean update_app; @@ -4827,7 +4474,7 @@ public class TLRPC { } public static class TL_chatAdminRights extends TLObject { - public static int constructor = 0x5fb224d5; + public static final int constructor = 0x5fb224d5; public int flags; public boolean change_info; @@ -4900,7 +4547,7 @@ public class TLRPC { } public static class TL_statsAbsValueAndPrev extends TLObject { - public static int constructor = 0xcb43acde; + public static final int constructor = 0xcb43acde; public double current; public double previous; @@ -4970,7 +4617,7 @@ public class TLRPC { } public static class TL_pollResults_layer108 extends TL_pollResults { - public static int constructor = 0x5755785a; + public static final int constructor = 0x5755785a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -5017,7 +4664,7 @@ public class TLRPC { } public static class TL_pollResults_layer111 extends PollResults { - public static int constructor = 0xc87024a2; + public static final int constructor = 0xc87024a2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -5087,7 +4734,7 @@ public class TLRPC { } public static class TL_pollResults_layer131 extends TL_pollResults { - public static int constructor = 0xbadcc1a3; + public static final int constructor = 0xbadcc1a3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -5188,7 +4835,7 @@ public class TLRPC { } public static class TL_pollResults extends PollResults { - public static int constructor = 0x7adf2420; + public static final int constructor = 0x7adf2420; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -5290,7 +4937,7 @@ public class TLRPC { } public static class TL_pollResults_layer158 extends PollResults { - public static int constructor = 0xdcb82ea3; + public static final int constructor = 0xdcb82ea3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -5413,7 +5060,7 @@ public class TLRPC { } public static class TL_secureFileEmpty extends SecureFile { - public static int constructor = 0x64199744; + public static final int constructor = 0x64199744; public void serializeToStream(AbstractSerializedData stream) { @@ -5422,7 +5069,7 @@ public class TLRPC { } public static class TL_secureFile extends SecureFile { - public static int constructor = 0x7d09c27e; + public static final int constructor = 0x7d09c27e; public long id; public long access_hash; @@ -5455,7 +5102,7 @@ public class TLRPC { } public static class TL_secureFile_layer142 extends TL_secureFile { - public static int constructor = 0xe0277a62; + public static final int constructor = 0xe0277a62; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); @@ -5480,7 +5127,7 @@ public class TLRPC { } public static class TL_messages_affectedMessages extends TLObject { - public static int constructor = 0x84d19185; + public static final int constructor = 0x84d19185; public int pts; public int pts_count; @@ -5511,7 +5158,7 @@ public class TLRPC { } public static class TL_messages_chatInviteImporters extends TLObject { - public static int constructor = 0x81b6b00a; + public static final int constructor = 0x81b6b00a; public int count; public ArrayList importers = new ArrayList<>(); @@ -5583,7 +5230,7 @@ public class TLRPC { } public static class TL_pollAnswerVoters extends TLObject { - public static int constructor = 0x3b6ddad2; + public static final int constructor = 0x3b6ddad2; public int flags; public boolean chosen; @@ -5623,7 +5270,7 @@ public class TLRPC { } public static class TL_channels_channelParticipant extends TLObject { - public static int constructor = 0xdfb80317; + public static final int constructor = 0xdfb80317; public ChannelParticipant participant; public ArrayList chats = new ArrayList<>(); @@ -5695,7 +5342,7 @@ public class TLRPC { } public static class TL_authorization extends TLObject { - public static int constructor = 0xad01d61d; + public static final int constructor = 0xad01d61d; public int flags; public boolean current; @@ -5802,7 +5449,7 @@ public class TLRPC { } public static class TL_statsGraph extends StatsGraph { - public static int constructor = 0x8ea464b6; + public static final int constructor = 0x8ea464b6; public int flags; public TL_dataJSON json; @@ -5827,7 +5474,7 @@ public class TLRPC { } public static class TL_statsGraphAsync extends StatsGraph { - public static int constructor = 0x4a27eb2d; + public static final int constructor = 0x4a27eb2d; public String token; @@ -5842,7 +5489,7 @@ public class TLRPC { } public static class TL_statsGraphError extends StatsGraph { - public static int constructor = 0xbedc9822; + public static final int constructor = 0xbedc9822; public String error; @@ -5857,7 +5504,7 @@ public class TLRPC { } public static class TL_messageInteractionCounters extends TLObject { - public static int constructor = 0xad4fc9bd; + public static final int constructor = 0xad4fc9bd; public int msg_id; public int views; @@ -5929,7 +5576,7 @@ public class TLRPC { } public static class TL_updates_difference extends updates_Difference { - public static int constructor = 0xf49ca0; + public static final int constructor = 0xf49ca0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6048,7 +5695,7 @@ public class TLRPC { } public static class TL_updates_differenceSlice extends updates_Difference { - public static int constructor = 0xa8fb1981; + public static final int constructor = 0xa8fb1981; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6167,7 +5814,7 @@ public class TLRPC { } public static class TL_updates_differenceTooLong extends updates_Difference { - public static int constructor = 0x4afe8f6d; + public static final int constructor = 0x4afe8f6d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6181,7 +5828,7 @@ public class TLRPC { } public static class TL_updates_differenceEmpty extends updates_Difference { - public static int constructor = 0x5d75a138; + public static final int constructor = 0x5d75a138; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6243,7 +5890,7 @@ public class TLRPC { } public static class TL_privacyKeyStatusTimestamp extends PrivacyKey { - public static int constructor = 0xbc2eab30; + public static final int constructor = 0xbc2eab30; public void serializeToStream(AbstractSerializedData stream) { @@ -6252,7 +5899,7 @@ public class TLRPC { } public static class TL_privacyKeyPhoneP2P extends PrivacyKey { - public static int constructor = 0x39491cc8; + public static final int constructor = 0x39491cc8; public void serializeToStream(AbstractSerializedData stream) { @@ -6261,7 +5908,7 @@ public class TLRPC { } public static class TL_privacyKeyChatInvite extends PrivacyKey { - public static int constructor = 0x500e6dfa; + public static final int constructor = 0x500e6dfa; public void serializeToStream(AbstractSerializedData stream) { @@ -6270,7 +5917,7 @@ public class TLRPC { } public static class TL_privacyKeyPhoneCall extends PrivacyKey { - public static int constructor = 0x3d662b7b; + public static final int constructor = 0x3d662b7b; public void serializeToStream(AbstractSerializedData stream) { @@ -6279,7 +5926,7 @@ public class TLRPC { } public static class TL_privacyKeyAddedByPhone extends PrivacyKey { - public static int constructor = 0x42ffd42b; + public static final int constructor = 0x42ffd42b; public void serializeToStream(AbstractSerializedData stream) { @@ -6288,7 +5935,7 @@ public class TLRPC { } public static class TL_privacyKeyAbout extends PrivacyKey { - public static int constructor = 0xa486b761; + public static final int constructor = 0xa486b761; public void serializeToStream(AbstractSerializedData stream) { @@ -6297,7 +5944,7 @@ public class TLRPC { } public static class TL_privacyKeyVoiceMessages extends PrivacyKey { - public static int constructor = 0x697f414; + public static final int constructor = 0x697f414; public void serializeToStream(AbstractSerializedData stream) { @@ -6306,7 +5953,7 @@ public class TLRPC { } public static class TL_privacyKeyForwards extends PrivacyKey { - public static int constructor = 0x69ec56a3; + public static final int constructor = 0x69ec56a3; public void serializeToStream(AbstractSerializedData stream) { @@ -6315,7 +5962,7 @@ public class TLRPC { } public static class TL_privacyKeyPhoneNumber extends PrivacyKey { - public static int constructor = 0xd19ae46d; + public static final int constructor = 0xd19ae46d; public void serializeToStream(AbstractSerializedData stream) { @@ -6324,7 +5971,7 @@ public class TLRPC { } public static class TL_privacyKeyProfilePhoto extends PrivacyKey { - public static int constructor = 0x96151fed; + public static final int constructor = 0x96151fed; public void serializeToStream(AbstractSerializedData stream) { @@ -6366,7 +6013,7 @@ public class TLRPC { } public static class TL_geoPoint_layer119 extends TL_geoPoint { - public static int constructor = 0x296f104; + public static final int constructor = 0x296f104; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6384,7 +6031,7 @@ public class TLRPC { } public static class TL_geoPoint_layer81 extends TL_geoPoint { - public static int constructor = 0x2049d70c; + public static final int constructor = 0x2049d70c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6400,7 +6047,7 @@ public class TLRPC { } public static class TL_geoPointEmpty extends GeoPoint { - public static int constructor = 0x1117dd5f; + public static final int constructor = 0x1117dd5f; public void serializeToStream(AbstractSerializedData stream) { @@ -6409,7 +6056,7 @@ public class TLRPC { } public static class TL_geoPoint extends GeoPoint { - public static int constructor = 0xb2a2f663; + public static final int constructor = 0xb2a2f663; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6435,7 +6082,7 @@ public class TLRPC { } public static class TL_account_privacyRules extends TLObject { - public static int constructor = 0x50a04e45; + public static final int constructor = 0x50a04e45; public ArrayList rules = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -6543,13 +6190,17 @@ public class TLRPC { public boolean verified; public boolean scam; public boolean fake; + public int color; public static ChatInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { ChatInvite result = null; switch (constructor) { - case 0x300c44c1: + case TL_chatInvite.constructor: result = new TL_chatInvite(); break; + case TL_chatInvite_layer165.constructor: + result = new TL_chatInvite_layer165(); + break; case 0x61695cb0: result = new TL_chatInvitePeek(); break; @@ -6568,7 +6219,7 @@ public class TLRPC { } public static class TL_chatInvite extends ChatInvite { - public static int constructor = 0x300c44c1; + public static final int constructor = 0xcde0ec40; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -6604,6 +6255,7 @@ public class TLRPC { participants.add(object); } } + color = stream.readInt32(exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -6632,11 +6284,86 @@ public class TLRPC { participants.get(a).serializeToStream(stream); } } + stream.writeInt32(color); + } + } + + public static class TL_chatInvite_layer165 extends ChatInvite { + public static final int constructor = 0x300c44c1; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + channel = (flags & 1) != 0; + broadcast = (flags & 2) != 0; + isPublic = (flags & 4) != 0; + megagroup = (flags & 8) != 0; + request_needed = (flags & 64) != 0; + verified = (flags & 128) != 0; + scam = (flags & 256) != 0; + fake = (flags & 512) != 0; + title = stream.readString(exception); + boolean hasAbout = (flags & 32) != 0; + if (hasAbout) { + about = stream.readString(exception); + } + photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + participants_count = stream.readInt32(exception); + if ((flags & 16) != 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++) { + User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + participants.add(object); + } + } + if ((flags & 1024) != 0) { + color = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = channel ? (flags | 1) : (flags &~ 1); + flags = broadcast ? (flags | 2) : (flags &~ 2); + flags = isPublic ? (flags | 4) : (flags &~ 4); + flags = megagroup ? (flags | 8) : (flags &~ 8); + flags = about != null ? (flags | 32) : (flags &~ 32); + flags = request_needed ? (flags | 64) : (flags &~ 64); + flags = verified ? (flags | 128) : (flags &~ 128); + flags = scam ? (flags | 256) : (flags &~ 256); + flags = fake ? (flags | 512) : (flags &~ 512); + stream.writeInt32(flags); + stream.writeString(title); + if (about != null) { + stream.writeString(about); + } + photo.serializeToStream(stream); + stream.writeInt32(participants_count); + if ((flags & 16) != 0) { + stream.writeInt32(0x1cb5c415); + int count = participants.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + participants.get(a).serializeToStream(stream); + } + } + if ((flags & 1024) != 0) { + stream.writeInt32(color); + } } } public static class TL_chatInvitePeek extends ChatInvite { - public static int constructor = 0x61695cb0; + public static final int constructor = 0x61695cb0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6652,7 +6379,7 @@ public class TLRPC { } public static class TL_chatInviteAlready extends ChatInvite { - public static int constructor = 0x5a686d7c; + public static final int constructor = 0x5a686d7c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6666,7 +6393,7 @@ public class TLRPC { } public static class TL_inputGroupCall extends TLObject { - public static int constructor = 0xd8aa840f; + public static final int constructor = 0xd8aa840f; public long id; public long access_hash; @@ -6719,7 +6446,7 @@ public class TLRPC { } public static class TL_help_appUpdate extends help_AppUpdate { - public static int constructor = 0xccbbce30; + public static final int constructor = 0xccbbce30; public int flags; public boolean can_not_skip; @@ -6789,7 +6516,7 @@ public class TLRPC { } public static class TL_help_noAppUpdate extends help_AppUpdate { - public static int constructor = 0xc45a6536; + public static final int constructor = 0xc45a6536; public void serializeToStream(AbstractSerializedData stream) { @@ -6798,7 +6525,7 @@ public class TLRPC { } public static class TL_messages_affectedFoundMessages extends TLObject { - public static int constructor = 0xef8d3e6c; + public static final int constructor = 0xef8d3e6c; public int pts; public int pts_count; @@ -6850,7 +6577,7 @@ public class TLRPC { } public static class TL_channelAdminLogEvent extends TLObject { - public static int constructor = 0x1fad68cd; + public static final int constructor = 0x1fad68cd; public long id; public int date; @@ -6912,7 +6639,7 @@ public class TLRPC { } public static class TL_messages_favedStickersNotModified extends messages_FavedStickers { - public static int constructor = 0x9e8fa6d3; + public static final int constructor = 0x9e8fa6d3; public void serializeToStream(AbstractSerializedData stream) { @@ -6921,7 +6648,7 @@ public class TLRPC { } public static class TL_messages_favedStickers extends messages_FavedStickers { - public static int constructor = 0x2cb51097; + public static final int constructor = 0x2cb51097; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -6977,7 +6704,7 @@ public class TLRPC { } public static class TL_langPackLanguage extends TLObject { - public static int constructor = 0xeeca5ce3; + public static final int constructor = 0xeeca5ce3; public int flags; public boolean official; @@ -7039,7 +6766,7 @@ public class TLRPC { } public static class TL_chatInviteImporter extends TLObject { - public static int constructor = 0x8c5adfd9; + public static final int constructor = 0x8c5adfd9; public int flags; public boolean requested; @@ -7176,7 +6903,7 @@ public class TLRPC { } public static class TL_sendMessageGamePlayAction extends SendMessageAction { - public static int constructor = 0xdd6a8f48; + public static final int constructor = 0xdd6a8f48; public void serializeToStream(AbstractSerializedData stream) { @@ -7185,7 +6912,7 @@ public class TLRPC { } public static class TL_sendMessageRecordAudioAction extends SendMessageAction { - public static int constructor = 0xd52f73f7; + public static final int constructor = 0xd52f73f7; public void serializeToStream(AbstractSerializedData stream) { @@ -7194,7 +6921,7 @@ public class TLRPC { } public static class TL_sendMessageUploadVideoAction_old extends TL_sendMessageUploadVideoAction { - public static int constructor = 0x92042ff7; + public static final int constructor = 0x92042ff7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7206,7 +6933,7 @@ public class TLRPC { } public static class TL_sendMessageEmojiInteraction extends SendMessageAction { - public static int constructor = 0x25972bcb; + public static final int constructor = 0x25972bcb; public String emoticon; public int msg_id; @@ -7227,7 +6954,7 @@ public class TLRPC { } public static class TL_sendMessageUploadAudioAction_old extends TL_sendMessageUploadAudioAction { - public static int constructor = 0xe6ac8a6f; + public static final int constructor = 0xe6ac8a6f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7239,7 +6966,7 @@ public class TLRPC { } public static class TL_sendMessageUploadAudioAction extends SendMessageAction { - public static int constructor = 0xf351d7ab; + public static final int constructor = 0xf351d7ab; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7253,7 +6980,7 @@ public class TLRPC { } public static class TL_sendMessageUploadPhotoAction extends SendMessageAction { - public static int constructor = 0xd1d34a26; + public static final int constructor = 0xd1d34a26; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7267,7 +6994,7 @@ public class TLRPC { } public static class TL_sendMessageUploadDocumentAction_old extends TL_sendMessageUploadDocumentAction { - public static int constructor = 0x8faee98e; + public static final int constructor = 0x8faee98e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7279,7 +7006,7 @@ public class TLRPC { } public static class TL_sendMessageUploadVideoAction extends SendMessageAction { - public static int constructor = 0xe9763aec; + public static final int constructor = 0xe9763aec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7293,7 +7020,7 @@ public class TLRPC { } public static class TL_sendMessageCancelAction extends SendMessageAction { - public static int constructor = 0xfd5ec8f5; + public static final int constructor = 0xfd5ec8f5; public void serializeToStream(AbstractSerializedData stream) { @@ -7302,7 +7029,7 @@ public class TLRPC { } public static class TL_sendMessageGeoLocationAction extends SendMessageAction { - public static int constructor = 0x176f8ba1; + public static final int constructor = 0x176f8ba1; public void serializeToStream(AbstractSerializedData stream) { @@ -7311,7 +7038,7 @@ public class TLRPC { } public static class TL_sendMessageChooseContactAction extends SendMessageAction { - public static int constructor = 0x628cbc6f; + public static final int constructor = 0x628cbc6f; public void serializeToStream(AbstractSerializedData stream) { @@ -7320,7 +7047,7 @@ public class TLRPC { } public static class TL_sendMessageChooseStickerAction extends SendMessageAction { - public static int constructor = 0xb05ac6b1; + public static final int constructor = 0xb05ac6b1; public void serializeToStream(AbstractSerializedData stream) { @@ -7329,7 +7056,7 @@ public class TLRPC { } public static class TL_sendMessageRecordRoundAction extends SendMessageAction { - public static int constructor = 0x88f27fbc; + public static final int constructor = 0x88f27fbc; public void serializeToStream(AbstractSerializedData stream) { @@ -7338,7 +7065,7 @@ public class TLRPC { } public static class TL_sendMessageUploadRoundAction extends SendMessageAction { - public static int constructor = 0x243e1c66; + public static final int constructor = 0x243e1c66; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7352,7 +7079,7 @@ public class TLRPC { } public static class TL_sendMessageEmojiInteractionSeen extends SendMessageAction { - public static int constructor = 0xb665902e; + public static final int constructor = 0xb665902e; public String emoticon; @@ -7367,7 +7094,7 @@ public class TLRPC { } public static class TL_sendMessageTypingAction extends SendMessageAction { - public static int constructor = 0x16bf744e; + public static final int constructor = 0x16bf744e; public void serializeToStream(AbstractSerializedData stream) { @@ -7376,7 +7103,7 @@ public class TLRPC { } public static class TL_sendMessageHistoryImportAction extends SendMessageAction { - public static int constructor = 0xdbda9246; + public static final int constructor = 0xdbda9246; public int progress; @@ -7391,7 +7118,7 @@ public class TLRPC { } public static class TL_sendMessageUploadPhotoAction_old extends TL_sendMessageUploadPhotoAction { - public static int constructor = 0x990a3c1a; + public static final int constructor = 0x990a3c1a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7403,7 +7130,7 @@ public class TLRPC { } public static class TL_sendMessageUploadDocumentAction extends SendMessageAction { - public static int constructor = 0xaa0cd9e4; + public static final int constructor = 0xaa0cd9e4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7417,7 +7144,7 @@ public class TLRPC { } public static class TL_speakingInGroupCallAction extends SendMessageAction { - public static int constructor = 0xd92c2285; + public static final int constructor = 0xd92c2285; public void serializeToStream(AbstractSerializedData stream) { @@ -7426,7 +7153,7 @@ public class TLRPC { } public static class TL_sendMessageRecordVideoAction extends SendMessageAction { - public static int constructor = 0xa187d66f; + public static final int constructor = 0xa187d66f; public void serializeToStream(AbstractSerializedData stream) { @@ -7493,7 +7220,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeApp extends auth_SentCodeType { - public static int constructor = 0x3dbb5986; + public static final int constructor = 0x3dbb5986; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7507,7 +7234,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeCall extends auth_SentCodeType { - public static int constructor = 0x5353e5a7; + public static final int constructor = 0x5353e5a7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7521,7 +7248,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeEmailCode extends auth_SentCodeType { - public static int constructor = 0xf450f59b; + public static final int constructor = 0xf450f59b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7555,7 +7282,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeSetUpEmailRequired extends auth_SentCodeType { - public static int constructor = 0xa5491dea; + public static final int constructor = 0xa5491dea; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -7572,7 +7299,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeFlashCall extends auth_SentCodeType { - public static int constructor = 0xab03c6d9; + public static final int constructor = 0xab03c6d9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7586,7 +7313,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeMissedCall extends auth_SentCodeType { - public static int constructor = 0x82006484; + public static final int constructor = 0x82006484; public void readParams(AbstractSerializedData stream, boolean exception) { prefix = stream.readString(exception); @@ -7601,7 +7328,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeSms extends auth_SentCodeType { - public static int constructor = 0xc000bba2; + public static final int constructor = 0xc000bba2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7615,7 +7342,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeFragmentSms extends auth_SentCodeType { - public static int constructor = 0xd9565c39; + public static final int constructor = 0xd9565c39; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7631,7 +7358,7 @@ public class TLRPC { } public static class TL_auth_sentCodeTypeFirebaseSms extends auth_SentCodeType { - public static int constructor = 0xe57b1432; + public static final int constructor = 0xe57b1432; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7688,7 +7415,7 @@ public class TLRPC { } public static class TL_messages_stickerSetInstallResultSuccess extends messages_StickerSetInstallResult { - public static int constructor = 0x38641628; + public static final int constructor = 0x38641628; public void serializeToStream(AbstractSerializedData stream) { @@ -7697,7 +7424,7 @@ public class TLRPC { } public static class TL_messages_stickerSetInstallResultArchive extends messages_StickerSetInstallResult { - public static int constructor = 0x35e410a8; + public static final int constructor = 0x35e410a8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -7730,7 +7457,7 @@ public class TLRPC { } public static class TL_peerSettings extends TLObject { - public static int constructor = 0xa518110d; + public static final int constructor = 0xa518110d; public int flags; public boolean report_spam; @@ -7806,7 +7533,7 @@ public class TLRPC { } public static class TL_readParticipantDate extends TLObject { - public static int constructor = 0x4a4ff172; + public static final int constructor = 0x4a4ff172; public long user_id; public int date; @@ -7837,7 +7564,7 @@ public class TLRPC { } public static class TL_statsGroupTopInviter extends TLObject { - public static int constructor = 0x535f779d; + public static final int constructor = 0x535f779d; public long user_id; public int invitations; @@ -7890,7 +7617,7 @@ public class TLRPC { } public static class TL_inputDialogPeer extends InputDialogPeer { - public static int constructor = 0xfcaafeb7; + public static final int constructor = 0xfcaafeb7; public InputPeer peer; @@ -7905,7 +7632,7 @@ public class TLRPC { } public static class TL_inputDialogPeerFolder extends InputDialogPeer { - public static int constructor = 0x64600527; + public static final int constructor = 0x64600527; public int folder_id; @@ -7942,7 +7669,7 @@ public class TLRPC { } public static class TL_payments_paymentVerificationNeeded extends payments_PaymentResult { - public static int constructor = 0xd8411139; + public static final int constructor = 0xd8411139; public String url; @@ -7957,7 +7684,7 @@ public class TLRPC { } public static class TL_payments_paymentResult extends payments_PaymentResult { - public static int constructor = 0x4e5f810d; + public static final int constructor = 0x4e5f810d; public Updates updates; @@ -7972,7 +7699,7 @@ public class TLRPC { } public static class TL_channels_adminLogResults extends TLObject { - public static int constructor = 0xed8af74d; + public static final int constructor = 0xed8af74d; public ArrayList events = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -8063,7 +7790,7 @@ public class TLRPC { } public static class TL_inputPhoneContact extends TLObject { - public static int constructor = 0xf392b7f4; + public static final int constructor = 0xf392b7f4; public long client_id; public String phone; @@ -8133,7 +7860,7 @@ public class TLRPC { } public static class TL_themeSettings extends ThemeSettings { - public static int constructor = 0xfa58b6d4; + public static final int constructor = 0xfa58b6d4; public static TL_themeSettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_themeSettings.constructor != constructor) { @@ -8198,7 +7925,7 @@ public class TLRPC { } public static class TL_themeSettings_layer132 extends ThemeSettings { - public static int constructor = 0x8db4e76c; + public static final int constructor = 0x8db4e76c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8245,7 +7972,7 @@ public class TLRPC { } public static class TL_themeSettings_layer131 extends ThemeSettings { - public static int constructor = 0x9c14984a; + public static final int constructor = 0x9c14984a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8287,7 +8014,7 @@ public class TLRPC { } public static class TL_pageCaption extends TLObject { - public static int constructor = 0x6f747657; + public static final int constructor = 0x6f747657; public RichText text; public RichText credit; @@ -8361,7 +8088,7 @@ public class TLRPC { } public static class TL_privacyValueDisallowContacts extends PrivacyRule { - public static int constructor = 0xf888fa1a; + public static final int constructor = 0xf888fa1a; public void serializeToStream(AbstractSerializedData stream) { @@ -8370,7 +8097,7 @@ public class TLRPC { } public static class TL_privacyValueDisallowUsers extends PrivacyRule { - public static int constructor = 0xe4621141; + public static final int constructor = 0xe4621141; public ArrayList users = new ArrayList<>(); @@ -8400,7 +8127,7 @@ public class TLRPC { } public static class TL_privacyValueAllowChatParticipants extends PrivacyRule { - public static int constructor = 0x6b134e8e; + public static final int constructor = 0x6b134e8e; public ArrayList chats = new ArrayList<>(); @@ -8430,7 +8157,7 @@ public class TLRPC { } public static class TL_privacyValueDisallowChatParticipants extends PrivacyRule { - public static int constructor = 0x41c87565; + public static final int constructor = 0x41c87565; public ArrayList chats = new ArrayList<>(); @@ -8460,7 +8187,7 @@ public class TLRPC { } public static class TL_privacyValueAllowAll extends PrivacyRule { - public static int constructor = 0x65427b82; + public static final int constructor = 0x65427b82; public void serializeToStream(AbstractSerializedData stream) { @@ -8469,7 +8196,7 @@ public class TLRPC { } public static class TL_privacyValueDisallowAll extends PrivacyRule { - public static int constructor = 0x8b73e763; + public static final int constructor = 0x8b73e763; public void serializeToStream(AbstractSerializedData stream) { @@ -8478,7 +8205,7 @@ public class TLRPC { } public static class TL_privacyValueAllowUsers extends PrivacyRule { - public static int constructor = 0xb8905fb2; + public static final int constructor = 0xb8905fb2; public ArrayList users = new ArrayList<>(); @@ -8508,7 +8235,7 @@ public class TLRPC { } public static class TL_privacyValueAllowContacts extends PrivacyRule { - public static int constructor = 0xfffe1bac; + public static final int constructor = 0xfffe1bac; public void serializeToStream(AbstractSerializedData stream) { @@ -8517,7 +8244,7 @@ public class TLRPC { } public static class TL_privacyValueAllowCloseFriends extends PrivacyRule { - public static int constructor = 0xf7e8d89b; + public static final int constructor = 0xf7e8d89b; public void serializeToStream(AbstractSerializedData stream) { @@ -8526,7 +8253,7 @@ public class TLRPC { } public static class TL_pageTableCell extends TLObject { - public static int constructor = 0x34566b6a; + public static final int constructor = 0x34566b6a; public int flags; public boolean header; @@ -8590,7 +8317,7 @@ public class TLRPC { } public static class TL_messageMediaUnsupported_old extends TL_messageMediaUnsupported { - public static int constructor = 0x29632a36; + public static final int constructor = 0x29632a36; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8604,7 +8331,7 @@ public class TLRPC { } public static class TL_messageMediaAudio_layer45 extends MessageMedia { - public static int constructor = 0xc6b68300; + public static final int constructor = 0xc6b68300; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8618,7 +8345,7 @@ public class TLRPC { } public static class TL_messageMediaPhoto_old extends TL_messageMediaPhoto { - public static int constructor = 0xc8c45a2a; + public static final int constructor = 0xc8c45a2a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8655,7 +8382,7 @@ public class TLRPC { } public static class TL_messageExtendedMediaPreview extends MessageExtendedMedia { - public static int constructor = 0xad628cc8; + public static final int constructor = 0xad628cc8; public int flags; public int w; @@ -8698,7 +8425,7 @@ public class TLRPC { } public static class TL_messageExtendedMedia extends MessageExtendedMedia { - public static int constructor = 0xee479c64; + public static final int constructor = 0xee479c64; public MessageMedia media; @@ -8713,7 +8440,7 @@ public class TLRPC { } public static class TL_messageMediaInvoice extends MessageMedia { - public static int constructor = 0xf6a548d3; + public static final int constructor = 0xf6a548d3; public WebDocument webPhoto; @@ -8760,7 +8487,7 @@ public class TLRPC { } public static class TL_messageMediaInvoice_layer145 extends TL_messageMediaInvoice { - public static int constructor = 0x84551347; + public static final int constructor = 0x84551347; public WebDocument photo; @@ -8801,7 +8528,7 @@ public class TLRPC { } public static class TL_messageMediaUnsupported extends MessageMedia { - public static int constructor = 0x9f84f49e; + public static final int constructor = 0x9f84f49e; public void serializeToStream(AbstractSerializedData stream) { @@ -8810,7 +8537,7 @@ public class TLRPC { } public static class TL_messageMediaEmpty extends MessageMedia { - public static int constructor = 0x3ded6320; + public static final int constructor = 0x3ded6320; public void serializeToStream(AbstractSerializedData stream) { @@ -8819,7 +8546,7 @@ public class TLRPC { } public static class TL_messageMediaVenue extends MessageMedia { - public static int constructor = 0x2ec0533f; + public static final int constructor = 0x2ec0533f; public String icon; //custom public String emoji; //custom @@ -8847,7 +8574,7 @@ public class TLRPC { } public static class TL_messageMediaVenue_layer71 extends MessageMedia { - public static int constructor = 0x7912b71f; + public static final int constructor = 0x7912b71f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8869,7 +8596,7 @@ public class TLRPC { } public static class TL_messageMediaVideo_old extends TL_messageMediaVideo_layer45 { - public static int constructor = 0xa2d24290; + public static final int constructor = 0xa2d24290; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8883,7 +8610,7 @@ public class TLRPC { } public static class TL_messageMediaDocument extends MessageMedia { - public static int constructor = 0x4cf4d72d; + public static final int constructor = 0x4cf4d72d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8919,7 +8646,7 @@ public class TLRPC { } public static class TL_messageMediaDocument_layer159 extends TL_messageMediaDocument { - public static int constructor = 0x9cb070d7; + public static final int constructor = 0x9cb070d7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8952,7 +8679,7 @@ public class TLRPC { } public static class TL_messageMediaDocument_layer74 extends TL_messageMediaDocument { - public static int constructor = 0x7c4414d3; + public static final int constructor = 0x7c4414d3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -8986,7 +8713,7 @@ public class TLRPC { } public static class TL_messageMediaDocument_old extends TL_messageMediaDocument { - public static int constructor = 0x2fda2204; + public static final int constructor = 0x2fda2204; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9000,7 +8727,7 @@ public class TLRPC { } public static class TL_messageMediaDocument_layer68 extends TL_messageMediaDocument { - public static int constructor = 0xf3e02ea8; + public static final int constructor = 0xf3e02ea8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9016,7 +8743,7 @@ public class TLRPC { } public static class TL_messageMediaPhoto extends MessageMedia { - public static int constructor = 0x695150d7; + public static final int constructor = 0x695150d7; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9045,7 +8772,7 @@ public class TLRPC { } public static class TL_messageMediaPoll extends MessageMedia { - public static int constructor = 0x4bd6e798; + public static final int constructor = 0x4bd6e798; public Poll poll; public PollResults results; @@ -9063,7 +8790,7 @@ public class TLRPC { } public static class TL_messageMediaPhoto_layer74 extends TL_messageMediaPhoto { - public static int constructor = 0xb5223b0f; + public static final int constructor = 0xb5223b0f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9096,7 +8823,7 @@ public class TLRPC { } public static class TL_inputMediaInvoice extends InputMedia { - public static int constructor = 0x1f9338fe; + public static final int constructor = 0x1f9338fe; public int flags; public String title; @@ -9150,7 +8877,7 @@ public class TLRPC { } public static class TL_messageMediaGeoLive extends MessageMedia { - public static int constructor = 0xb940c666; + public static final int constructor = 0xb940c666; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9180,7 +8907,7 @@ public class TLRPC { } public static class TL_messageMediaGeoLive_layer119 extends TL_messageMediaGeoLive { - public static int constructor = 0x7c3c2609; + public static final int constructor = 0x7c3c2609; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9196,7 +8923,7 @@ public class TLRPC { } public static class TL_messageMediaGame extends MessageMedia { - public static int constructor = 0xfdb19008; + public static final int constructor = 0xfdb19008; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9210,7 +8937,7 @@ public class TLRPC { } public static class TL_messageMediaContact_layer81 extends TL_messageMediaContact { - public static int constructor = 0x5e7d2f39; + public static final int constructor = 0x5e7d2f39; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9230,7 +8957,7 @@ public class TLRPC { } public static class TL_messageMediaPhoto_layer68 extends TL_messageMediaPhoto { - public static int constructor = 0x3d8ce53d; + public static final int constructor = 0x3d8ce53d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9246,7 +8973,7 @@ public class TLRPC { } public static class TL_messageMediaVideo_layer45 extends MessageMedia { - public static int constructor = 0x5bcf1675; + public static final int constructor = 0x5bcf1675; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9262,7 +8989,7 @@ public class TLRPC { } public static class TL_messageMediaContact_layer131 extends TL_messageMediaContact { - public static int constructor = 0xcbf24940; + public static final int constructor = 0xcbf24940; public void readParams(AbstractSerializedData stream, boolean exception) { phone_number = stream.readString(exception); @@ -9283,7 +9010,7 @@ public class TLRPC { } public static class TL_messageMediaContact extends MessageMedia { - public static int constructor = 0x70322949; + public static final int constructor = 0x70322949; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9305,7 +9032,7 @@ public class TLRPC { } public static class TL_messageMediaDice extends MessageMedia { - public static int constructor = 0x3f7ee58b; + public static final int constructor = 0x3f7ee58b; public int value; public String emoticon; @@ -9323,7 +9050,7 @@ public class TLRPC { } public static class TL_messageMediaDice_layer111 extends TL_messageMediaDice { - public static int constructor = 0x638fe46b; + public static final int constructor = 0x638fe46b; public void readParams(AbstractSerializedData stream, boolean exception) { value = stream.readInt32(exception); @@ -9336,7 +9063,7 @@ public class TLRPC { } public static class TL_messageMediaGeo extends MessageMedia { - public static int constructor = 0x56e0d474; + public static final int constructor = 0x56e0d474; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9350,7 +9077,30 @@ public class TLRPC { } public static class TL_messageMediaWebPage extends MessageMedia { - public static int constructor = 0xa32dd600; + public static final int constructor = 0xddf10c3b; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + force_large_media = (flags & 1) != 0; + force_small_media = (flags & 2) != 0; + manual = (flags & 8) != 0; + safe = (flags & 16) != 0; + webpage = WebPage.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = force_large_media ? (flags | 1) : (flags &~ 1); + flags = force_small_media ? (flags | 2) : (flags &~ 2); + flags = manual ? (flags | 8) : (flags &~ 8); + flags = safe ? (flags | 16) : (flags &~ 16); + stream.writeInt32(flags); + webpage.serializeToStream(stream); + } + } + + public static class TL_messageMediaWebPage_layer165 extends TL_messageMediaWebPage { + public static final int constructor = 0xa32dd600; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9398,7 +9148,7 @@ public class TLRPC { } public static class TL_langPackStringPluralized extends LangPackString { - public static int constructor = 0x6c47ac9f; + public static final int constructor = 0x6c47ac9f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9446,7 +9196,7 @@ public class TLRPC { } public static class TL_langPackString extends LangPackString { - public static int constructor = 0xcad181f6; + public static final int constructor = 0xcad181f6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9462,7 +9212,7 @@ public class TLRPC { } public static class TL_langPackStringDeleted extends LangPackString { - public static int constructor = 0x2979eeb2; + public static final int constructor = 0x2979eeb2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -9505,7 +9255,7 @@ public class TLRPC { } public static class TL_auth_sentCodeSuccess extends auth_SentCode { - public static int constructor = 0x2390fe44; + public static final int constructor = 0x2390fe44; public void readParams(AbstractSerializedData stream, boolean exception) { authorization = auth_Authorization.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -9518,7 +9268,7 @@ public class TLRPC { } public static class TL_auth_sentCode extends auth_SentCode { - public static int constructor = 0x5e002502; + public static final int constructor = 0x5e002502; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9582,7 +9332,7 @@ public class TLRPC { } public static class TL_botInlineResult extends BotInlineResult { - public static int constructor = 0x11965f3a; + public static final int constructor = 0x11965f3a; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9631,7 +9381,7 @@ public class TLRPC { } public static class TL_botInlineMediaResult extends BotInlineResult { - public static int constructor = 0x17db940b; + public static final int constructor = 0x17db940b; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9674,7 +9424,7 @@ public class TLRPC { } public static class TL_notificationSoundDefault extends NotificationSound { - public static int constructor = 0x97e8bebe; + public static final int constructor = 0x97e8bebe; public void serializeToStream(AbstractSerializedData stream) { @@ -9683,7 +9433,7 @@ public class TLRPC { } public static class TL_notificationSoundNone extends NotificationSound { - public static int constructor = 0x6f0c34df; + public static final int constructor = 0x6f0c34df; public void serializeToStream(AbstractSerializedData stream) { @@ -9692,7 +9442,7 @@ public class TLRPC { } public static class TL_notificationSoundRingtone extends NotificationSound { - public static int constructor = 0xff6c8049; + public static final int constructor = 0xff6c8049; public long id; @@ -9707,7 +9457,7 @@ public class TLRPC { } public static class TL_notificationSoundLocal extends NotificationSound { - public static int constructor = 0x830b9ae4; + public static final int constructor = 0x830b9ae4; public String title; public String data; @@ -9801,7 +9551,7 @@ public class TLRPC { } public static class TL_peerNotifySettings_layer77 extends TL_peerNotifySettings { - public static int constructor = 0x9acda4c0; + public static final int constructor = 0x9acda4c0; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9822,7 +9572,7 @@ public class TLRPC { } public static class TL_peerNotifySettings extends PeerNotifySettings { - public static int constructor = 0x99622c0c; + public static final int constructor = 0x99622c0c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9901,7 +9651,7 @@ public class TLRPC { } public static class TL_peerNotifySettings_layer156 extends TL_peerNotifySettings { - public static int constructor = 0xa83b0426; + public static final int constructor = 0xa83b0426; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9950,7 +9700,7 @@ public class TLRPC { } public static class TL_peerNotifySettings_layer139 extends TL_peerNotifySettings { - public static int constructor = 0xaf509d20; + public static final int constructor = 0xaf509d20; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -9987,7 +9737,7 @@ public class TLRPC { } public static class TL_peerNotifySettings_layer47 extends TL_peerNotifySettings { - public static int constructor = 0x8d5e11ee; + public static final int constructor = 0x8d5e11ee; public void readParams(AbstractSerializedData stream, boolean exception) { mute_until = stream.readInt32(exception); @@ -10006,7 +9756,7 @@ public class TLRPC { } public static class TL_peerNotifySettingsEmpty_layer77 extends PeerNotifySettings { - public static int constructor = 0x70a68512; + public static final int constructor = 0x70a68512; public void serializeToStream(AbstractSerializedData stream) { @@ -10042,7 +9792,7 @@ public class TLRPC { } public static class TL_contacts_blocked extends contacts_Blocked { - public static int constructor = 0xade1591; + public static final int constructor = 0xade1591; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -10117,7 +9867,7 @@ public class TLRPC { } public static class TL_contacts_blockedSlice extends contacts_Blocked { - public static int constructor = 0xe1664194; + public static final int constructor = 0xe1664194; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -10194,7 +9944,7 @@ public class TLRPC { } public static class TL_inputSecureValue extends TLObject { - public static int constructor = 0xdb21d0a7; + public static final int constructor = 0xdb21d0a7; public int flags; public SecureValueType type; @@ -10334,7 +10084,7 @@ public class TLRPC { } public static class TL_help_appConfig extends help_AppConfig { - public static int constructor = 0xdd18782e; + public static final int constructor = 0xdd18782e; public int hash; public JSONValue config; @@ -10352,7 +10102,7 @@ public class TLRPC { } public static class TL_help_appConfigNotModified extends help_AppConfig { - public static int constructor = 0x7cde641d; + public static final int constructor = 0x7cde641d; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -10386,7 +10136,7 @@ public class TLRPC { } public static class TL_messages_dhConfigNotModified extends messages_DhConfig { - public static int constructor = 0xc0e24635; + public static final int constructor = 0xc0e24635; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -10400,7 +10150,7 @@ public class TLRPC { } public static class TL_messages_dhConfig extends messages_DhConfig { - public static int constructor = 0x2c221edd; + public static final int constructor = 0x2c221edd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -10420,7 +10170,7 @@ public class TLRPC { } public static class TL_globalPrivacySettings extends TLObject { - public static int constructor = 0x734c4ccb; + public static final int constructor = 0x734c4ccb; public int flags; public boolean archive_and_mute_new_noncontact_peers; @@ -10457,7 +10207,7 @@ public class TLRPC { } public static class TL_help_premiumPromo_layer144 extends TL_help_premiumPromo { - public static int constructor = 0x8a4f3c29; + public static final int constructor = 0x8a4f3c29; public void readParams(AbstractSerializedData stream, boolean exception) { status_text = stream.readString(exception); @@ -10554,7 +10304,7 @@ public class TLRPC { } public static class TL_help_premiumPromo_layer140 extends TL_help_premiumPromo { - public static int constructor = 0xe0360f1b; + public static final int constructor = 0xe0360f1b; public void readParams(AbstractSerializedData stream, boolean exception) { status_text = stream.readString(exception); @@ -10630,7 +10380,7 @@ public class TLRPC { } public static class TL_help_premiumPromo extends TLObject { - public static int constructor = 0x5334759c; + public static final int constructor = 0x5334759c; public String status_text; public ArrayList status_entities = new ArrayList<>(); @@ -10807,7 +10557,7 @@ public class TLRPC { } public static class TL_help_userInfoEmpty extends help_UserInfo { - public static int constructor = 0xf3ae2eed; + public static final int constructor = 0xf3ae2eed; public void serializeToStream(AbstractSerializedData stream) { @@ -10816,7 +10566,7 @@ public class TLRPC { } public static class TL_help_userInfo extends help_UserInfo { - public static int constructor = 0x1eb3758; + public static final int constructor = 0x1eb3758; public String message; public ArrayList entities = new ArrayList<>(); @@ -10859,7 +10609,7 @@ public class TLRPC { } public static class TL_secureValueHash extends TLObject { - public static int constructor = 0xed1ecdb0; + public static final int constructor = 0xed1ecdb0; public SecureValueType type; public byte[] hash; @@ -10920,7 +10670,7 @@ public class TLRPC { } public static class TL_messages_stickerSet_layer146 extends TL_messages_stickerSet { - public static int constructor = 0xb60a24a6; + public static final int constructor = 0xb60a24a6; public void readParams(AbstractSerializedData stream, boolean exception) { set = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -10975,7 +10725,7 @@ public class TLRPC { } public static class TL_messages_stickerSet extends messages_StickerSet { - public static int constructor = 0x6e153f16; + public static final int constructor = 0x6e153f16; public void readParams(AbstractSerializedData stream, boolean exception) { set = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -11051,7 +10801,7 @@ public class TLRPC { } public static class TL_messages_stickerSetNotModified extends TL_messages_stickerSet { - public static int constructor = 0xd3f924eb; + public static final int constructor = 0xd3f924eb; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -11086,7 +10836,7 @@ public class TLRPC { } public static class TL_inputGeoPoint extends InputGeoPoint { - public static int constructor = 0x48222faf; + public static final int constructor = 0x48222faf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11110,7 +10860,7 @@ public class TLRPC { } public static class TL_inputGeoPointEmpty extends InputGeoPoint { - public static int constructor = 0xe4c123d6; + public static final int constructor = 0xe4c123d6; public void serializeToStream(AbstractSerializedData stream) { @@ -11119,7 +10869,7 @@ public class TLRPC { } public static class TL_help_inviteText extends TLObject { - public static int constructor = 0x18cb9f78; + public static final int constructor = 0x18cb9f78; public String message; @@ -11188,7 +10938,7 @@ public class TLRPC { } public static class TL_audioEmpty_layer45 extends Audio { - public static int constructor = 0x586988d8; + public static final int constructor = 0x586988d8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11202,7 +10952,7 @@ public class TLRPC { } public static class TL_audio_layer45 extends Audio { - public static int constructor = 0xf9e35055; + public static final int constructor = 0xf9e35055; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11228,7 +10978,7 @@ public class TLRPC { } public static class TL_audio_old extends TL_audio_layer45 { - public static int constructor = 0x427425e7; + public static final int constructor = 0x427425e7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11254,7 +11004,7 @@ public class TLRPC { } public static class TL_audioEncrypted extends TL_audio_layer45 { - public static int constructor = 0x555555F6; + public static final int constructor = 0x555555F6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11284,7 +11034,7 @@ public class TLRPC { } public static class TL_audio_old2 extends TL_audio_layer45 { - public static int constructor = 0xc7ac6496; + public static final int constructor = 0xc7ac6496; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11312,7 +11062,7 @@ public class TLRPC { } public static class TL_help_country extends TLObject { - public static int constructor = 0xc3878e23; + public static final int constructor = 0xc3878e23; public int flags; public boolean hidden; @@ -11403,7 +11153,7 @@ public class TLRPC { } public static class TL_securePasswordKdfAlgoPBKDF2HMACSHA512iter100000 extends SecurePasswordKdfAlgo { - public static int constructor = 0xbbf2dda0; + public static final int constructor = 0xbbf2dda0; public byte[] salt; @@ -11418,7 +11168,7 @@ public class TLRPC { } public static class TL_securePasswordKdfAlgoSHA512 extends SecurePasswordKdfAlgo { - public static int constructor = 0x86471d92; + public static final int constructor = 0x86471d92; public byte[] salt; @@ -11433,7 +11183,7 @@ public class TLRPC { } public static class TL_securePasswordKdfAlgoUnknown extends SecurePasswordKdfAlgo { - public static int constructor = 0x4a8537; + public static final int constructor = 0x4a8537; public void serializeToStream(AbstractSerializedData stream) { @@ -11442,7 +11192,7 @@ public class TLRPC { } public static class TL_messages_historyImport extends TLObject { - public static int constructor = 0x1662af0b; + public static final int constructor = 0x1662af0b; public long id; @@ -11470,7 +11220,7 @@ public class TLRPC { } public static class TL_bots_setBotInfo extends TLObject { - public static int constructor = 0x10cf3123; + public static final int constructor = 0x10cf3123; public int flags; public InputUser bot; @@ -11503,7 +11253,7 @@ public class TLRPC { } public static class TL_bots_getBotInfo extends TLObject { - public static int constructor = 0xdcd914fd; + public static final int constructor = 0xdcd914fd; public int flags; public InputUser bot; @@ -11524,7 +11274,7 @@ public class TLRPC { } public static class TL_bots_reorderUsernames extends TLObject { - public static int constructor = 0x9709b1c2; + public static final int constructor = 0x9709b1c2; public InputUser bot; public ArrayList order = new ArrayList<>(); @@ -11546,7 +11296,7 @@ public class TLRPC { } public static class TL_bots_toggleUsername extends TLObject { - public static int constructor = 0x53ca973; + public static final int constructor = 0x53ca973; public InputUser bot; public String username; @@ -11607,7 +11357,7 @@ public class TLRPC { } public static class TL_botInfoEmpty_layer48 extends TL_botInfo { - public static int constructor = 0xbb2e37ce; + public static final int constructor = 0xbb2e37ce; public void serializeToStream(AbstractSerializedData stream) { @@ -11616,7 +11366,7 @@ public class TLRPC { } public static class TL_botInfo_layer131 extends TL_botInfo { - public static int constructor = 0x98e81d3a; + public static final int constructor = 0x98e81d3a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11653,7 +11403,7 @@ public class TLRPC { } public static class TL_botInfo_layer48 extends TL_botInfo { - public static int constructor = 0x9cf585d; + public static final int constructor = 0x9cf585d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11694,7 +11444,7 @@ public class TLRPC { } public static class TL_botInfo_layer139 extends BotInfo { - public static int constructor = 0x1b74b335; + public static final int constructor = 0x1b74b335; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11731,7 +11481,7 @@ public class TLRPC { } public static class TL_botInfo extends BotInfo { - public static int constructor = 0x8f300b57; + public static final int constructor = 0x8f300b57; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11800,7 +11550,7 @@ public class TLRPC { } public static class TL_botInfo_layer140 extends TL_botInfo { - public static int constructor = 0xe4169b5d; + public static final int constructor = 0xe4169b5d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11865,7 +11615,7 @@ public class TLRPC { } public static class TL_inputGameShortName extends InputGame { - public static int constructor = 0xc331e80a; + public static final int constructor = 0xc331e80a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11881,7 +11631,7 @@ public class TLRPC { } public static class TL_inputGameID extends InputGame { - public static int constructor = 0x32c3e77; + public static final int constructor = 0x32c3e77; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11928,7 +11678,7 @@ public class TLRPC { } public static class TL_messageReplies_layer131 extends TL_messageReplies { - public static int constructor = 0x4128faac; + public static final int constructor = 0x4128faac; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -11991,7 +11741,7 @@ public class TLRPC { } public static class TL_messageReplies extends MessageReplies { - public static int constructor = 0x83d60fc2; + public static final int constructor = 0x83d60fc2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12084,7 +11834,7 @@ public class TLRPC { } public static class TL_messages_sponsoredMessagesEmpty extends messages_SponsoredMessages { - public static int constructor = 0x1839490f; + public static final int constructor = 0x1839490f; public void serializeToStream(AbstractSerializedData stream) { @@ -12093,7 +11843,7 @@ public class TLRPC { } public static class TL_messages_sponsoredMessagesLayer147 extends messages_SponsoredMessages { - public static int constructor = 0xc9ee1d87; + public static final int constructor = 0xc9ee1d87; public void readParams(AbstractSerializedData stream, boolean exception) { int magic = stream.readInt32(exception); @@ -12167,7 +11917,7 @@ public class TLRPC { } public static class TL_messages_sponsoredMessages extends messages_SponsoredMessages { - public static int constructor = 0xc9ee1d87; + public static final int constructor = 0xc9ee1d87; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -12249,7 +11999,7 @@ public class TLRPC { } public static class TL_messageViews extends TLObject { - public static int constructor = 0x455b853d; + public static final int constructor = 0x455b853d; public int flags; public int views; @@ -12340,7 +12090,7 @@ public class TLRPC { } public static class TL_replyKeyboardMarkup extends ReplyMarkup { - public static int constructor = 0x85dd99d1; + public static final int constructor = 0x85dd99d1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12389,7 +12139,7 @@ public class TLRPC { } public static class TL_replyKeyboardHide extends ReplyMarkup { - public static int constructor = 0xa03e5b85; + public static final int constructor = 0xa03e5b85; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12405,7 +12155,7 @@ public class TLRPC { } public static class TL_replyKeyboardForceReply extends ReplyMarkup { - public static int constructor = 0x86b40b08; + public static final int constructor = 0x86b40b08; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12429,7 +12179,7 @@ public class TLRPC { } public static class TL_replyKeyboardMarkup_layer129 extends TL_replyKeyboardMarkup { - public static int constructor = 0x3502758c; + public static final int constructor = 0x3502758c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12470,7 +12220,7 @@ public class TLRPC { } public static class TL_replyKeyboardForceReply_layer129 extends TL_replyKeyboardForceReply { - public static int constructor = 0xf4108aa0; + public static final int constructor = 0xf4108aa0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12488,7 +12238,7 @@ public class TLRPC { } public static class TL_replyInlineMarkup extends ReplyMarkup { - public static int constructor = 0x48a30254; + public static final int constructor = 0x48a30254; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12549,17 +12299,16 @@ public class TLRPC { public static class TL_webPageAttributeStory extends WebPageAttribute { public final static int constructor = 0x2e94c3e7; - public int flags; public Peer peer; public int id; - public StoryItem storyItem; + public TL_stories.StoryItem storyItem; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); id = stream.readInt32(exception); if ((flags & 1) != 0) { - storyItem = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -12584,7 +12333,7 @@ public class TLRPC { peer.user_id = user_id; id = stream.readInt32(exception); if ((flags & 1) != 0) { - storyItem = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -12677,7 +12426,7 @@ public class TLRPC { } public static class TL_contacts_contactsNotModified extends contacts_Contacts { - public static int constructor = 0xb74ba9d2; + public static final int constructor = 0xb74ba9d2; public void serializeToStream(AbstractSerializedData stream) { @@ -12686,7 +12435,7 @@ public class TLRPC { } public static class TL_contacts_contacts extends contacts_Contacts { - public static int constructor = 0xeae87e42; + public static final int constructor = 0xeae87e42; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -12764,7 +12513,7 @@ public class TLRPC { } public static class TL_secureRequiredType extends SecureRequiredType { - public static int constructor = 0x829d99da; + public static final int constructor = 0x829d99da; public int flags; public boolean native_names; @@ -12791,7 +12540,7 @@ public class TLRPC { } public static class TL_secureRequiredTypeOneOf extends SecureRequiredType { - public static int constructor = 0x27477b4; + public static final int constructor = 0x27477b4; public ArrayList types = new ArrayList<>(); @@ -12871,7 +12620,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyStatusTimestamp extends InputPrivacyKey { - public static int constructor = 0x4f96cb18; + public static final int constructor = 0x4f96cb18; public void serializeToStream(AbstractSerializedData stream) { @@ -12880,7 +12629,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyChatInvite extends InputPrivacyKey { - public static int constructor = 0xbdfb0426; + public static final int constructor = 0xbdfb0426; public void serializeToStream(AbstractSerializedData stream) { @@ -12889,7 +12638,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyPhoneCall extends InputPrivacyKey { - public static int constructor = 0xfabadc5f; + public static final int constructor = 0xfabadc5f; public void serializeToStream(AbstractSerializedData stream) { @@ -12898,7 +12647,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyForwards extends InputPrivacyKey { - public static int constructor = 0xa4dd4c08; + public static final int constructor = 0xa4dd4c08; public void serializeToStream(AbstractSerializedData stream) { @@ -12907,7 +12656,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyPhoneNumber extends InputPrivacyKey { - public static int constructor = 0x352dafa; + public static final int constructor = 0x352dafa; public void serializeToStream(AbstractSerializedData stream) { @@ -12916,7 +12665,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyAddedByPhone extends InputPrivacyKey { - public static int constructor = 0xd1219bdd; + public static final int constructor = 0xd1219bdd; public void serializeToStream(AbstractSerializedData stream) { @@ -12925,7 +12674,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyVoiceMessages extends InputPrivacyKey { - public static int constructor = 0xaee69d68; + public static final int constructor = 0xaee69d68; public void serializeToStream(AbstractSerializedData stream) { @@ -12934,7 +12683,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyAbout extends InputPrivacyKey { - public static int constructor = 0x3823cc40; + public static final int constructor = 0x3823cc40; public void serializeToStream(AbstractSerializedData stream) { @@ -12943,7 +12692,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyProfilePhoto extends InputPrivacyKey { - public static int constructor = 0x5719bacc; + public static final int constructor = 0x5719bacc; public void serializeToStream(AbstractSerializedData stream) { @@ -12952,7 +12701,7 @@ public class TLRPC { } public static class TL_inputPrivacyKeyPhoneP2P extends InputPrivacyKey { - public static int constructor = 0xdb9e70d2; + public static final int constructor = 0xdb9e70d2; public void serializeToStream(AbstractSerializedData stream) { @@ -12986,7 +12735,7 @@ public class TLRPC { } public static class TL_messages_exportedChatInviteReplaced extends messages_ExportedChatInvite { - public static int constructor = 0x222600ef; + public static final int constructor = 0x222600ef; public ExportedChatInvite new_invite; @@ -13024,7 +12773,7 @@ public class TLRPC { } public static class TL_messages_exportedChatInvite extends messages_ExportedChatInvite { - public static int constructor = 0x1871be50; + public static final int constructor = 0x1871be50; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13081,7 +12830,7 @@ public class TLRPC { } public static class TL_inputThemeSlug extends InputTheme { - public static int constructor = 0xf5890df1; + public static final int constructor = 0xf5890df1; public String slug; @@ -13096,7 +12845,7 @@ public class TLRPC { } public static class TL_inputTheme extends InputTheme { - public static int constructor = 0x3c5693e9; + public static final int constructor = 0x3c5693e9; public long id; public long access_hash; @@ -13139,7 +12888,7 @@ public class TLRPC { } public static class TL_photos_photos extends photos_Photos { - public static int constructor = 0x8dca6aa5; + public static final int constructor = 0x8dca6aa5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13193,7 +12942,7 @@ public class TLRPC { } public static class TL_photos_photosSlice extends photos_Photos { - public static int constructor = 0x15051f54; + public static final int constructor = 0x15051f54; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13303,7 +13052,7 @@ public class TLRPC { public boolean translations_disabled; public boolean stories_pinned_available; public ChatReactions available_reactions; - public PeerStories stories; + public TL_stories.PeerStories stories; public long inviterId; //custom public int invitesCount; //custom @@ -13453,7 +13202,7 @@ public class TLRPC { } public static class TL_channelFull_layer110 extends ChatFull { - public static int constructor = 0x2d895c74; + public static final int constructor = 0x2d895c74; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13613,7 +13362,7 @@ public class TLRPC { } public static class TL_chatFull_layer124 extends TL_chatFull { - public static int constructor = 0xf06c4018; + public static final int constructor = 0xf06c4018; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13700,7 +13449,7 @@ public class TLRPC { } public static class TL_channelFull_layer124 extends TL_channelFull { - public static int constructor = 0x2548c037; + public static final int constructor = 0x2548c037; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13902,7 +13651,7 @@ public class TLRPC { } public static class TL_chatFull_layer123 extends TL_chatFull { - public static int constructor = 0xf3474af6; + public static final int constructor = 0xf3474af6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -13983,7 +13732,7 @@ public class TLRPC { } public static class TL_channelFull_layer123 extends TL_channelFull { - public static int constructor = 0x7a7de4f7; + public static final int constructor = 0x7a7de4f7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -14158,7 +13907,7 @@ public class TLRPC { } public static class TL_chatFull_layer131 extends TL_chatFull { - public static int constructor = 0x8a1e2983; + public static final int constructor = 0x8a1e2983; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -14251,7 +14000,7 @@ public class TLRPC { } public static class TL_chatFull_layer132 extends TL_chatFull { - public static int constructor = 0x49a0a5d9; + public static final int constructor = 0x49a0a5d9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -14350,7 +14099,7 @@ public class TLRPC { } public static class TL_channelFull_layer132 extends TL_channelFull { - public static int constructor = 0x2f532f3c; + public static final int constructor = 0x2f532f3c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -14564,7 +14313,7 @@ public class TLRPC { } public static class TL_chatFull_layer133 extends ChatFull { - public static int constructor = 0x4dbdc099; + public static final int constructor = 0x4dbdc099; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -14663,7 +14412,7 @@ public class TLRPC { } public static class TL_chatFull_layer135 extends ChatFull { - public static int constructor = 0x46a6ffb4; + public static final int constructor = 0x46a6ffb4; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -14788,7 +14537,7 @@ public class TLRPC { } public static class TL_channelFull_layer135 extends ChatFull { - public static int constructor = 0x56662e2e; + public static final int constructor = 0x56662e2e; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15034,7 +14783,7 @@ public class TLRPC { } public static class TL_channelFull_layer134 extends ChatFull { - public static int constructor = 0x59cff963; + public static final int constructor = 0x59cff963; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15274,7 +15023,7 @@ public class TLRPC { } public static class TL_channelFull_layer133 extends ChatFull { - public static int constructor = 0xe9b27a17; + public static final int constructor = 0xe9b27a17; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -15488,7 +15237,7 @@ public class TLRPC { } public static class TL_chatFull extends ChatFull { - public static int constructor = 0xc9d31138; + public static final int constructor = 0xc9d31138; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15619,7 +15368,7 @@ public class TLRPC { } public static class TL_chatFull_layer144 extends ChatFull { - public static int constructor = 0xd18ee226; + public static final int constructor = 0xd18ee226; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15765,7 +15514,7 @@ public class TLRPC { } public static class TL_channelFull extends ChatFull { - public static int constructor = 0x723027bd; + public static final int constructor = 0x723027bd; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -15905,7 +15654,7 @@ public class TLRPC { available_reactions = ChatReactions.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags2 & 16) != 0) { - stories = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -16035,7 +15784,7 @@ public class TLRPC { } public static class TL_channelFull_layer162 extends TL_channelFull { - public static int constructor = 0xf2355507; + public static final int constructor = 0xf2355507; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16297,7 +16046,7 @@ public class TLRPC { } public static class TL_channelFull_layer144 extends ChatFull { - public static int constructor = 0xea68a619; + public static final int constructor = 0xea68a619; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16568,7 +16317,7 @@ public class TLRPC { } public static class TL_channelFull_layer139 extends ChatFull { - public static int constructor = 0xe13c3d20; + public static final int constructor = 0xe13c3d20; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -16835,7 +16584,7 @@ public class TLRPC { } public static class TL_channelFull_layer131 extends TL_channelFull { - public static int constructor = 0x548c3f93; + public static final int constructor = 0x548c3f93; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17043,7 +16792,7 @@ public class TLRPC { } public static class TL_channelFull_layer122 extends TL_channelFull { - public static int constructor = 0xef3a6acd; + public static final int constructor = 0xef3a6acd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17221,7 +16970,7 @@ public class TLRPC { } public static class TL_channelFull_layer121 extends TL_channelFull { - public static int constructor = 0xf0e6672a; + public static final int constructor = 0xf0e6672a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17389,7 +17138,7 @@ public class TLRPC { } public static class TL_channelFull_layer103 extends TL_channelFull { - public static int constructor = 0x10916653; + public static final int constructor = 0x10916653; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17535,7 +17284,7 @@ public class TLRPC { } public static class TL_channelFull_layer101 extends TL_channelFull { - public static int constructor = 0x9882e516; + public static final int constructor = 0x9882e516; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17673,7 +17422,7 @@ public class TLRPC { } public static class TL_channelFull_layer99 extends TL_channelFull { - public static int constructor = 0x3648977; + public static final int constructor = 0x3648977; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17805,7 +17554,7 @@ public class TLRPC { } public static class TL_channelFull_layer98 extends TL_channelFull { - public static int constructor = 0x1c87a71a; + public static final int constructor = 0x1c87a71a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17929,7 +17678,7 @@ public class TLRPC { } public static class TL_chatFull_layer87 extends TL_chatFull { - public static int constructor = 0x2e02a614; + public static final int constructor = 0x2e02a614; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -17975,7 +17724,7 @@ public class TLRPC { } public static class TL_channelFull_layer89 extends TL_channelFull { - public static int constructor = 0xcbb62890; + public static final int constructor = 0xcbb62890; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18097,7 +17846,7 @@ public class TLRPC { } public static class TL_channelFull_layer72 extends TL_channelFull { - public static int constructor = 0x76af5481; + public static final int constructor = 0x76af5481; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18213,7 +17962,7 @@ public class TLRPC { } public static class TL_channelFull_layer71 extends TL_channelFull { - public static int constructor = 0x17f45fcf; + public static final int constructor = 0x17f45fcf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18321,7 +18070,7 @@ public class TLRPC { } public static class TL_chatFull_layer122 extends TL_chatFull { - public static int constructor = 0xdc8c181; + public static final int constructor = 0xdc8c181; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18401,7 +18150,7 @@ public class TLRPC { } public static class TL_chatFull_layer121 extends TL_chatFull { - public static int constructor = 0x1b7c9db3; + public static final int constructor = 0x1b7c9db3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18475,7 +18224,7 @@ public class TLRPC { } public static class TL_chatFull_layer98 extends TL_chatFull { - public static int constructor = 0x22a235da; + public static final int constructor = 0x22a235da; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18541,7 +18290,7 @@ public class TLRPC { } public static class TL_chatFull_layer92 extends TL_chatFull { - public static int constructor = 0xedd2a791; + public static final int constructor = 0xedd2a791; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18603,7 +18352,7 @@ public class TLRPC { } public static class TL_channelFull_layer70 extends TL_channelFull { - public static int constructor = 0x95cb5f57; + public static final int constructor = 0x95cb5f57; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18703,7 +18452,7 @@ public class TLRPC { } public static class TL_channelFull_layer52 extends TL_channelFull { - public static int constructor = 0x97bee562; + public static final int constructor = 0x97bee562; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18797,7 +18546,7 @@ public class TLRPC { } public static class TL_channelFull_layer67 extends TL_channelFull { - public static int constructor = 0xc3d5512f; + public static final int constructor = 0xc3d5512f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18891,7 +18640,7 @@ public class TLRPC { } public static class TL_channelFull_layer48 extends TL_channelFull { - public static int constructor = 0x9e341ddf; + public static final int constructor = 0x9e341ddf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -18977,7 +18726,7 @@ public class TLRPC { } public static class TL_channelFull_old extends TL_channelFull { - public static int constructor = 0xfab31aa3; + public static final int constructor = 0xfab31aa3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19030,7 +18779,7 @@ public class TLRPC { } public static class TL_inputPeerNotifySettings extends TLObject { - public static int constructor = 0xcacb6ae2; + public static final int constructor = 0xcacb6ae2; public int flags; public boolean show_previews; @@ -19132,7 +18881,7 @@ public class TLRPC { } public static class TL_auth_loginToken extends auth_LoginToken { - public static int constructor = 0x629f1980; + public static final int constructor = 0x629f1980; public int expires; public byte[] token; @@ -19150,7 +18899,7 @@ public class TLRPC { } public static class TL_auth_loginTokenMigrateTo extends auth_LoginToken { - public static int constructor = 0x68e9916; + public static final int constructor = 0x68e9916; public int dc_id; public byte[] token; @@ -19168,7 +18917,7 @@ public class TLRPC { } public static class TL_auth_loginTokenSuccess extends auth_LoginToken { - public static int constructor = 0x390d5c5e; + public static final int constructor = 0x390d5c5e; public auth_Authorization authorization; @@ -19183,7 +18932,7 @@ public class TLRPC { } public static class TL_codeSettings extends TLObject { - public static int constructor = 0xad253d78; + public static final int constructor = 0xad253d78; public int flags; public boolean allow_flashcall; @@ -19287,7 +19036,7 @@ public class TLRPC { } public static class TL_account_emojiStatusesNotModified extends account_EmojiStatuses { - public static int constructor = 0xd08ce645; + public static final int constructor = 0xd08ce645; public void serializeToStream(AbstractSerializedData stream) { @@ -19296,7 +19045,7 @@ public class TLRPC { } public static class TL_account_emojiStatuses extends account_EmojiStatuses { - public static int constructor = 0x90c467d1; + public static final int constructor = 0x90c467d1; public void readParams(AbstractSerializedData stream, boolean exception) { hash = stream.readInt64(exception); @@ -19330,7 +19079,7 @@ public class TLRPC { } public static class TL_stats_messageStats extends TLObject { - public static int constructor = 0x8999f295; + public static final int constructor = 0x8999f295; public StatsGraph views_graph; @@ -19389,7 +19138,7 @@ public class TLRPC { } public static class TL_baseThemeArctic extends BaseTheme { - public static int constructor = 0x5b11125a; + public static final int constructor = 0x5b11125a; public void serializeToStream(AbstractSerializedData stream) { @@ -19398,7 +19147,7 @@ public class TLRPC { } public static class TL_baseThemeNight extends BaseTheme { - public static int constructor = 0xb7b31ea8; + public static final int constructor = 0xb7b31ea8; public void serializeToStream(AbstractSerializedData stream) { @@ -19407,7 +19156,7 @@ public class TLRPC { } public static class TL_baseThemeClassic extends BaseTheme { - public static int constructor = 0xc3a12462; + public static final int constructor = 0xc3a12462; public void serializeToStream(AbstractSerializedData stream) { @@ -19416,7 +19165,7 @@ public class TLRPC { } public static class TL_baseThemeTinted extends BaseTheme { - public static int constructor = 0x6d5f77ee; + public static final int constructor = 0x6d5f77ee; public void serializeToStream(AbstractSerializedData stream) { @@ -19425,7 +19174,7 @@ public class TLRPC { } public static class TL_baseThemeDay extends BaseTheme { - public static int constructor = 0xfbd81688; + public static final int constructor = 0xfbd81688; public void serializeToStream(AbstractSerializedData stream) { @@ -19434,7 +19183,7 @@ public class TLRPC { } public static class TL_null extends TLObject { - public static int constructor = 0x56730bcc; + public static final int constructor = 0x56730bcc; public static TL_null TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -19500,7 +19249,7 @@ public class TLRPC { } public static class TL_pagePart_layer67 extends TL_pagePart_layer82 { - public static int constructor = 0x8dee6c44; + public static final int constructor = 0x8dee6c44; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19575,7 +19324,7 @@ public class TLRPC { } public static class TL_pagePart_layer82 extends Page { - public static int constructor = 0x8e3f9ebe; + public static final int constructor = 0x8e3f9ebe; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19650,7 +19399,7 @@ public class TLRPC { } public static class TL_pageFull_layer67 extends TL_page { - public static int constructor = 0xd7a19d69; + public static final int constructor = 0xd7a19d69; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19725,7 +19474,7 @@ public class TLRPC { } public static class TL_pageFull_layer82 extends TL_page { - public static int constructor = 0x556ec7aa; + public static final int constructor = 0x556ec7aa; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19800,7 +19549,7 @@ public class TLRPC { } public static class TL_page_layer110 extends TL_page { - public static int constructor = 0xae891bec; + public static final int constructor = 0xae891bec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19883,7 +19632,7 @@ public class TLRPC { } public static class TL_page extends Page { - public static int constructor = 0x98657f0d; + public static final int constructor = 0x98657f0d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -19974,7 +19723,7 @@ public class TLRPC { } public static class TL_topPeerCategoryPeers extends TLObject { - public static int constructor = 0xfb834291; + public static final int constructor = 0xfb834291; public TopPeerCategory category; public int count; @@ -20058,7 +19807,7 @@ public class TLRPC { } public static class TL_inputUserSelf extends InputUser { - public static int constructor = 0xf7c1b13f; + public static final int constructor = 0xf7c1b13f; public void serializeToStream(AbstractSerializedData stream) { @@ -20067,7 +19816,7 @@ public class TLRPC { } public static class TL_inputUser extends InputUser { - public static int constructor = 0xf21158c6; + public static final int constructor = 0xf21158c6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20083,7 +19832,7 @@ public class TLRPC { } public static class TL_inputUserEmpty extends InputUser { - public static int constructor = 0xb98886cf; + public static final int constructor = 0xb98886cf; public void serializeToStream(AbstractSerializedData stream) { @@ -20092,7 +19841,7 @@ public class TLRPC { } public static class TL_inputUserFromMessage extends InputUser { - public static int constructor = 0x1da448e2; + public static final int constructor = 0x1da448e2; public InputPeer peer; public int msg_id; @@ -20197,7 +19946,7 @@ public class TLRPC { } public static class TL_keyboardButtonRequestPhone extends KeyboardButton { - public static int constructor = 0xb16a6c29; + public static final int constructor = 0xb16a6c29; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20211,7 +19960,7 @@ public class TLRPC { } public static class TL_keyboardButtonGame extends KeyboardButton { - public static int constructor = 0x50f41ccf; + public static final int constructor = 0x50f41ccf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20225,7 +19974,7 @@ public class TLRPC { } public static class TL_keyboardButtonUrl extends KeyboardButton { - public static int constructor = 0x258aff05; + public static final int constructor = 0x258aff05; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20241,7 +19990,7 @@ public class TLRPC { } public static class TL_keyboardButtonSwitchInline_layer157 extends KeyboardButton { - public static int constructor = 0x568a748; + public static final int constructor = 0x568a748; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -20260,7 +20009,7 @@ public class TLRPC { } public static class TL_keyboardButtonSwitchInline extends KeyboardButton { - public static int constructor = 0x93b9fbb5; + public static final int constructor = 0x93b9fbb5; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -20304,7 +20053,7 @@ public class TLRPC { } public static class TL_keyboardButtonRequestGeoLocation extends KeyboardButton { - public static int constructor = 0xfc796b3f; + public static final int constructor = 0xfc796b3f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20318,7 +20067,7 @@ public class TLRPC { } public static class TL_keyboardButtonUrlAuth extends KeyboardButton { - public static int constructor = 0x10b78d29; + public static final int constructor = 0x10b78d29; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20344,7 +20093,7 @@ public class TLRPC { } public static class TL_inputKeyboardButtonUrlAuth extends KeyboardButton { - public static int constructor = 0xd02e7fd4; + public static final int constructor = 0xd02e7fd4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20372,7 +20121,7 @@ public class TLRPC { } public static class TL_keyboardButtonRequestPoll extends KeyboardButton { - public static int constructor = 0xbbc7515d; + public static final int constructor = 0xbbc7515d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20394,7 +20143,7 @@ public class TLRPC { } public static class TL_keyboardButtonBuy extends KeyboardButton { - public static int constructor = 0xafd93fbb; + public static final int constructor = 0xafd93fbb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20408,7 +20157,7 @@ public class TLRPC { } public static class TL_inputKeyboardButtonUserProfile extends KeyboardButton { - public static int constructor = 0xe988037b; + public static final int constructor = 0xe988037b; public void readParams(AbstractSerializedData stream, boolean exception) { text = stream.readString(exception); @@ -20423,7 +20172,7 @@ public class TLRPC { } public static class TL_keyboardButtonUserProfile extends KeyboardButton { - public static int constructor = 0x308660c1; + public static final int constructor = 0x308660c1; public void readParams(AbstractSerializedData stream, boolean exception) { text = stream.readString(exception); @@ -20438,7 +20187,7 @@ public class TLRPC { } public static class TL_keyboardButtonCallback extends KeyboardButton { - public static int constructor = 0x35bbdb6b; + public static final int constructor = 0x35bbdb6b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20458,7 +20207,7 @@ public class TLRPC { } public static class TL_keyboardButtonCallback_layer117 extends TL_keyboardButtonCallback { - public static int constructor = 0x683a5e46; + public static final int constructor = 0x683a5e46; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20474,7 +20223,7 @@ public class TLRPC { } public static class TL_keyboardButton extends KeyboardButton { - public static int constructor = 0xa2fa4880; + public static final int constructor = 0xa2fa4880; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20488,7 +20237,7 @@ public class TLRPC { } public static class TL_videoSizeEmojiMarkup extends VideoSize { - public static int constructor = 0xf85c413c; + public static final int constructor = 0xf85c413c; public long emoji_id; @@ -20520,7 +20269,7 @@ public class TLRPC { } public static class TL_videoSizeStickerMarkup extends VideoSize { - public static int constructor = 0xda082fe; + public static final int constructor = 0xda082fe; public InputStickerSet stickerset; public long sticker_id; @@ -20609,7 +20358,7 @@ public class TLRPC { } public static class TL_videoSize_layer115 extends TL_videoSize { - public static int constructor = 0x435bb987; + public static final int constructor = 0x435bb987; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20631,7 +20380,7 @@ public class TLRPC { } public static class TL_videoSize_layer127 extends TL_videoSize { - public static int constructor = 0xe831c556; + public static final int constructor = 0xe831c556; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20661,7 +20410,7 @@ public class TLRPC { } public static class TL_videoSize extends VideoSize { - public static int constructor = 0xde33b094; + public static final int constructor = 0xde33b094; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20704,9 +20453,15 @@ public class TLRPC { public String last_name; public String vcard; public boolean no_webpage; + public boolean invert_media; + public boolean force_large_media; + public boolean force_small_media; + public boolean manual; + public boolean safe; public int period; public int heading; public int proximity_notification_radius; + public String url; public static BotInlineMessage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { BotInlineMessage result = null; @@ -20744,6 +20499,9 @@ public class TLRPC { case 0x354a9b09: result = new TL_botInlineMessageMediaInvoice(); break; + case 0x809ad9a6: + result = new TL_botInlineMessageMediaWebPage(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in BotInlineMessage", constructor)); @@ -20756,7 +20514,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaVenue_layer77 extends TL_botInlineMessageMediaVenue { - public static int constructor = 0x4366232e; + public static final int constructor = 0x4366232e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20786,7 +20544,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaVenue extends BotInlineMessage { - public static int constructor = 0x8a86659c; + public static final int constructor = 0x8a86659c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -20817,7 +20575,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaGeo_layer71 extends TL_botInlineMessageMediaGeo { - public static int constructor = 0x3a8fd8b8; + public static final int constructor = 0x3a8fd8b8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20839,7 +20597,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaAuto extends BotInlineMessage { - public static int constructor = 0x764cf810; + public static final int constructor = 0x764cf810; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20886,7 +20644,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaAuto_layer74 extends TL_botInlineMessageMediaAuto { - public static int constructor = 0xa74b15b; + public static final int constructor = 0xa74b15b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20908,7 +20666,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaContact_layer81 extends TL_botInlineMessageMediaContact { - public static int constructor = 0x35edb4d4; + public static final int constructor = 0x35edb4d4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -20934,7 +20692,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaContact extends BotInlineMessage { - public static int constructor = 0x18d1cdc2; + public static final int constructor = 0x18d1cdc2; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -20961,7 +20719,7 @@ public class TLRPC { } public static class TL_botInlineMessageText extends BotInlineMessage { - public static int constructor = 0x8c7f65e2; + public static final int constructor = 0x8c7f65e2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21010,7 +20768,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaGeo extends BotInlineMessage { - public static int constructor = 0x51846fd; + public static final int constructor = 0x51846fd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21050,7 +20808,7 @@ public class TLRPC { } public static class TL_botInlineMessageMediaGeo_layer119 extends TL_botInlineMessageMediaGeo { - public static int constructor = 0xb722de65; + public static final int constructor = 0xb722de65; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21073,8 +20831,63 @@ public class TLRPC { } } + public static class TL_botInlineMessageMediaWebPage extends BotInlineMessage { + public static final int constructor = 0x809ad9a6; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + invert_media = (flags & 8) != 0; + force_large_media = (flags & 16) != 0; + force_small_media = (flags & 32) != 0; + manual = (flags & 128) != 0; + safe = (flags & 256) != 0; + message = stream.readString(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++) { + entities.add(MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception)); + } + } + url = stream.readString(exception); + if ((flags & 4) != 0) { + reply_markup = ReplyMarkup.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = invert_media ? (flags | 8) : (flags &~ 8); + flags = force_large_media ? (flags | 8) : (flags &~ 16); + flags = force_small_media ? (flags | 32) : (flags &~ 32); + flags = manual ? (flags | 128) : (flags &~ 128); + flags = safe ? (flags | 256) : (flags &~ 256); + stream.writeInt32(flags); + stream.writeString(message); + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + final int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; ++a) { + entities.get(a).serializeToStream(stream); + } + } + stream.writeString(url); + if ((flags & 4) != 0) { + reply_markup.serializeToStream(stream); + } + } + } + public static class TL_botInlineMessageMediaInvoice extends BotInlineMessage { - public static int constructor = 0x354a9b09; + public static final int constructor = 0x354a9b09; public boolean shipping_address_requested; public boolean test; @@ -21118,7 +20931,7 @@ public class TLRPC { } public static class TL_keyboardButtonRow extends TLObject { - public static int constructor = 0x77608b83; + public static final int constructor = 0x77608b83; public ArrayList buttons = new ArrayList<>(); @@ -21187,7 +21000,7 @@ public class TLRPC { } public static class TL_boolTrue extends Bool { - public static int constructor = 0x997275b5; + public static final int constructor = 0x997275b5; public void serializeToStream(AbstractSerializedData stream) { @@ -21196,7 +21009,7 @@ public class TLRPC { } public static class TL_boolFalse extends Bool { - public static int constructor = 0xbc799737; + public static final int constructor = 0xbc799737; public void serializeToStream(AbstractSerializedData stream) { @@ -21205,7 +21018,7 @@ public class TLRPC { } public static class TL_messages_discussionMessage extends TLObject { - public static int constructor = 0xa6341782; + public static final int constructor = 0xa6341782; public int flags; public ArrayList messages = new ArrayList<>(); @@ -21323,7 +21136,7 @@ public class TLRPC { } public static class TL_messages_searchCounter extends TLObject { - public static int constructor = 0xe844ebff; + public static final int constructor = 0xe844ebff; public int flags; public boolean inexact; @@ -21360,7 +21173,7 @@ public class TLRPC { } public static class TL_inputAppEvent extends TLObject { - public static int constructor = 0x1d1b1245; + public static final int constructor = 0x1d1b1245; public double time; public String type; @@ -21397,7 +21210,7 @@ public class TLRPC { } public static class TL_auth_exportedAuthorization extends TLObject { - public static int constructor = 0xb434e2b8; + public static final int constructor = 0xb434e2b8; public long id; public byte[] bytes; @@ -21429,6 +21242,7 @@ public class TLRPC { public static abstract class WebPage extends TLObject { public int flags; + public boolean has_large_media; public long id; public String url; public String display_url; @@ -21465,18 +21279,24 @@ public class TLRPC { case 0xa31ea0b5: result = new TL_webPage_old(); break; - case 0xeb1477e8: + case 0x211a1788: result = new TL_webPageEmpty(); break; + case 0xeb1477e8: + result = new TL_webPageEmpty_layer165(); + break; case 0xd41a5167: result = new TL_webPageUrlPending(); break; case 0x7311ca11: result = new TL_webPageNotModified(); break; - case 0xc586da1c: + case 0xb0d13e47: result = new TL_webPagePending(); break; + case 0xc586da1c: + result = new TL_webPagePending_layer165(); + break; case 0x85849473: result = new TL_webPageNotModified_layer110(); break; @@ -21495,11 +21315,12 @@ public class TLRPC { } public static class TL_webPage extends WebPage { - public static int constructor = 0xe89c45b2; + public static final int constructor = 0xe89c45b2; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); + has_large_media = (flags & 8192) != 0; id = stream.readInt64(exception); url = stream.readString(exception); display_url = stream.readString(exception); @@ -21620,7 +21441,7 @@ public class TLRPC { } public static class TL_webPage_layer107 extends TL_webPage { - public static int constructor = 0xfa64e172; + public static final int constructor = 0xfa64e172; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21743,7 +21564,7 @@ public class TLRPC { } public static class TL_webPage_layer104 extends TL_webPage { - public static int constructor = 0x5f07b4bc; + public static final int constructor = 0x5f07b4bc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21843,7 +21664,7 @@ public class TLRPC { } public static class TL_webPage_old extends TL_webPage { - public static int constructor = 0xa31ea0b5; + public static final int constructor = 0xa31ea0b5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21929,7 +21750,29 @@ public class TLRPC { } public static class TL_webPageEmpty extends WebPage { - public static int constructor = 0xeb1477e8; + public static final int constructor = 0x211a1788; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + id = stream.readInt64(exception); + if ((flags & 1) != 0) { + url = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(id); + if ((flags & 1) != 0) { + stream.writeString(url); + } + } + } + + public static class TL_webPageEmpty_layer165 extends TL_webPageEmpty { + public static final int constructor = 0xeb1477e8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21943,7 +21786,7 @@ public class TLRPC { } public static class TL_webPageUrlPending extends WebPage { - public static int constructor = 0xd41a5167; + public static final int constructor = 0xd41a5167; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -21956,9 +21799,8 @@ public class TLRPC { } } - public static class TL_webPagePending extends WebPage { - public static int constructor = 0xc586da1c; - + public static class TL_webPagePending_layer165 extends TL_webPagePending { + public static final int constructor = 0xc586da1c; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); @@ -21972,8 +21814,32 @@ public class TLRPC { } } + public static class TL_webPagePending extends WebPage { + public static final int constructor = 0xb0d13e47; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + id = stream.readInt64(exception); + if ((flags & 1) != 0) { + url = stream.readString(exception); + } + date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(id); + if ((flags & 1) != 0) { + stream.writeString(url); + } + stream.writeInt32(date); + } + } + public static class TL_webPageNotModified_layer110 extends TL_webPageNotModified { - public static int constructor = 0x85849473; + public static final int constructor = 0x85849473; public void serializeToStream(AbstractSerializedData stream) { @@ -21982,7 +21848,7 @@ public class TLRPC { } public static class TL_webPageNotModified extends WebPage { - public static int constructor = 0x7311ca11; + public static final int constructor = 0x7311ca11; public int cached_page_views; @@ -22003,7 +21869,7 @@ public class TLRPC { } public static class TL_webPage_layer58 extends TL_webPage { - public static int constructor = 0xca820ed7; + public static final int constructor = 0xca820ed7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -22117,7 +21983,7 @@ public class TLRPC { } public static class TL_messages_featuredStickers extends messages_FeaturedStickers { - public static int constructor = 0xbe382906; + public static final int constructor = 0xbe382906; public int flags; public boolean premium; @@ -22181,7 +22047,7 @@ public class TLRPC { } public static class TL_messages_featuredStickersNotModified extends messages_FeaturedStickers { - public static int constructor = 0xc6dc0c66; + public static final int constructor = 0xc6dc0c66; public int count; @@ -22239,7 +22105,7 @@ public class TLRPC { } public static class TL_secureValueErrorFile extends SecureValueError { - public static int constructor = 0x7a700873; + public static final int constructor = 0x7a700873; public SecureValueType type; public byte[] file_hash; @@ -22260,7 +22126,7 @@ public class TLRPC { } public static class TL_secureValueErrorFrontSide extends SecureValueError { - public static int constructor = 0xbe3dfa; + public static final int constructor = 0xbe3dfa; public SecureValueType type; public byte[] file_hash; @@ -22281,7 +22147,7 @@ public class TLRPC { } public static class TL_secureValueErrorFiles extends SecureValueError { - public static int constructor = 0x666220e9; + public static final int constructor = 0x666220e9; public SecureValueType type; public ArrayList file_hash = new ArrayList<>(); @@ -22317,7 +22183,7 @@ public class TLRPC { } public static class TL_secureValueErrorReverseSide extends SecureValueError { - public static int constructor = 0x868a2aa5; + public static final int constructor = 0x868a2aa5; public SecureValueType type; public byte[] file_hash; @@ -22338,7 +22204,7 @@ public class TLRPC { } public static class TL_secureValueErrorTranslationFile extends SecureValueError { - public static int constructor = 0xa1144770; + public static final int constructor = 0xa1144770; public SecureValueType type; public byte[] file_hash; @@ -22359,7 +22225,7 @@ public class TLRPC { } public static class TL_secureValueError extends SecureValueError { - public static int constructor = 0x869d758f; + public static final int constructor = 0x869d758f; public SecureValueType type; public byte[] hash; @@ -22380,7 +22246,7 @@ public class TLRPC { } public static class TL_secureValueErrorData extends SecureValueError { - public static int constructor = 0xe8a40bd9; + public static final int constructor = 0xe8a40bd9; public SecureValueType type; public byte[] data_hash; @@ -22404,7 +22270,7 @@ public class TLRPC { } public static class TL_secureValueErrorTranslationFiles extends SecureValueError { - public static int constructor = 0x34636dd8; + public static final int constructor = 0x34636dd8; public SecureValueType type; public ArrayList file_hash = new ArrayList<>(); @@ -22440,7 +22306,7 @@ public class TLRPC { } public static class TL_secureValueErrorSelfie extends SecureValueError { - public static int constructor = 0xe537ced6; + public static final int constructor = 0xe537ced6; public SecureValueType type; public byte[] file_hash; @@ -22461,7 +22327,7 @@ public class TLRPC { } public static class TL_secureValue extends TLObject { - public static int constructor = 0x187fa0ca; + public static final int constructor = 0x187fa0ca; public int flags; public SecureValueType type; @@ -22611,7 +22477,7 @@ public class TLRPC { } public static class TL_phoneCallDiscardReasonHangup extends PhoneCallDiscardReason { - public static int constructor = 0x57adc690; + public static final int constructor = 0x57adc690; public void serializeToStream(AbstractSerializedData stream) { @@ -22620,7 +22486,7 @@ public class TLRPC { } public static class TL_phoneCallDiscardReasonBusy extends PhoneCallDiscardReason { - public static int constructor = 0xfaf7e8c9; + public static final int constructor = 0xfaf7e8c9; public void serializeToStream(AbstractSerializedData stream) { @@ -22629,7 +22495,7 @@ public class TLRPC { } public static class TL_phoneCallDiscardReasonMissed extends PhoneCallDiscardReason { - public static int constructor = 0x85e42301; + public static final int constructor = 0x85e42301; public void serializeToStream(AbstractSerializedData stream) { @@ -22638,7 +22504,7 @@ public class TLRPC { } public static class TL_phoneCallDiscardReasonDisconnect extends PhoneCallDiscardReason { - public static int constructor = 0xe095c1a0; + public static final int constructor = 0xe095c1a0; public void serializeToStream(AbstractSerializedData stream) { @@ -22689,7 +22555,7 @@ public class TLRPC { } public static class TL_dialogFilterChatlist extends DialogFilter { - public static int constructor = 0xd64a04a8; + public static final int constructor = 0xd64a04a8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -22756,7 +22622,7 @@ public class TLRPC { } public static class TL_dialogFilterDefault extends DialogFilter { - public static int constructor = 0x363293ae; + public static final int constructor = 0x363293ae; public void serializeToStream(AbstractSerializedData stream) { @@ -22765,7 +22631,7 @@ public class TLRPC { } public static class TL_dialogFilter extends DialogFilter { - public static int constructor = 0x7438f7e8; + public static final int constructor = 0x7438f7e8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -22867,7 +22733,7 @@ public class TLRPC { } public static class TL_auth_passwordRecovery extends TLObject { - public static int constructor = 0x137948a5; + public static final int constructor = 0x137948a5; public String email_pattern; @@ -22895,7 +22761,7 @@ public class TLRPC { } public static class TL_exportedContactToken extends TLObject { - public static int constructor = 0x41bf109b; + public static final int constructor = 0x41bf109b; public String url; public int expires; @@ -22926,7 +22792,7 @@ public class TLRPC { } public static class TL_botCommand extends TLObject { - public static int constructor = 0xc27ac8c7; + public static final int constructor = 0xc27ac8c7; public String command; public String description; @@ -22988,7 +22854,7 @@ public class TLRPC { } public static class TL_inputNotifyChats extends InputNotifyPeer { - public static int constructor = 0x4a95e84e; + public static final int constructor = 0x4a95e84e; public void serializeToStream(AbstractSerializedData stream) { @@ -22997,7 +22863,7 @@ public class TLRPC { } public static class TL_inputNotifyPeer extends InputNotifyPeer { - public static int constructor = 0xb8bc5b0c; + public static final int constructor = 0xb8bc5b0c; public InputPeer peer; @@ -23012,7 +22878,7 @@ public class TLRPC { } public static class TL_inputNotifyUsers extends InputNotifyPeer { - public static int constructor = 0x193b4417; + public static final int constructor = 0x193b4417; public void serializeToStream(AbstractSerializedData stream) { @@ -23021,7 +22887,7 @@ public class TLRPC { } public static class TL_inputNotifyBroadcasts extends InputNotifyPeer { - public static int constructor = 0xb1db7c7e; + public static final int constructor = 0xb1db7c7e; public void serializeToStream(AbstractSerializedData stream) { @@ -23030,7 +22896,7 @@ public class TLRPC { } public static class TL_inputNotifyForumTopic extends InputNotifyPeer { - public static int constructor = 0x5c467992; + public static final int constructor = 0x5c467992; public InputPeer peer; public int top_msg_id; @@ -23097,7 +22963,7 @@ public class TLRPC { } public static class TL_inputPhotoFileLocation extends InputFileLocation { - public static int constructor = 0x40181ffe; + public static final int constructor = 0x40181ffe; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23117,7 +22983,7 @@ public class TLRPC { } public static class TL_inputDocumentFileLocation extends InputFileLocation { - public static int constructor = 0xbad07584; + public static final int constructor = 0xbad07584; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23137,7 +23003,7 @@ public class TLRPC { } public static class TL_inputPeerPhotoFileLocation extends InputFileLocation { - public static int constructor = 0x37257e99; + public static final int constructor = 0x37257e99; public boolean big; public InputPeer peer; @@ -23160,7 +23026,7 @@ public class TLRPC { } public static class TL_inputEncryptedFileLocation extends InputFileLocation { - public static int constructor = 0xf5235d55; + public static final int constructor = 0xf5235d55; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23176,7 +23042,7 @@ public class TLRPC { } public static class TL_inputStickerSetThumb extends InputFileLocation { - public static int constructor = 0x9d84f3db; + public static final int constructor = 0x9d84f3db; public InputStickerSet stickerset; public int thumb_version; @@ -23194,7 +23060,7 @@ public class TLRPC { } public static class TL_inputGroupCallStream extends InputFileLocation { - public static int constructor = 0x598a92a; + public static final int constructor = 0x598a92a; public TL_inputGroupCall call; public long time_ms; @@ -23231,7 +23097,7 @@ public class TLRPC { } public static class TL_inputFileLocation extends InputFileLocation { - public static int constructor = 0xdfdaabe1; + public static final int constructor = 0xdfdaabe1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23251,7 +23117,7 @@ public class TLRPC { } public static class TL_inputSecureFileLocation extends InputFileLocation { - public static int constructor = 0xcbc7ee28; + public static final int constructor = 0xcbc7ee28; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23267,7 +23133,7 @@ public class TLRPC { } public static class TL_photos_photo extends TLObject { - public static int constructor = 0x20212ca8; + public static final int constructor = 0x20212ca8; public Photo photo; public ArrayList users = new ArrayList<>(); @@ -23339,7 +23205,7 @@ public class TLRPC { } public static class TL_help_termsOfServiceUpdate extends help_TermsOfServiceUpdate { - public static int constructor = 0x28ecf961; + public static final int constructor = 0x28ecf961; public int expires; public TL_help_termsOfService terms_of_service; @@ -23357,7 +23223,7 @@ public class TLRPC { } public static class TL_help_termsOfServiceUpdateEmpty extends help_TermsOfServiceUpdate { - public static int constructor = 0xe3309f7f; + public static final int constructor = 0xe3309f7f; public int expires; @@ -23372,7 +23238,7 @@ public class TLRPC { } public static class TL_messages_chatAdminsWithInvites extends TLObject { - public static int constructor = 0xb69b72d7; + public static final int constructor = 0xb69b72d7; public ArrayList admins = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -23441,7 +23307,7 @@ public class TLRPC { } public static class TL_phone_groupCall extends TLObject { - public static int constructor = 0x9e727aad; + public static final int constructor = 0x9e727aad; public GroupCall call; public ArrayList participants = new ArrayList<>(); @@ -23593,7 +23459,7 @@ public class TLRPC { } public static class TL_phoneCallRequested extends PhoneCall { - public static int constructor = 0x14b0ed0c; + public static final int constructor = 0x14b0ed0c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23623,7 +23489,7 @@ public class TLRPC { } public static class TL_phoneCall extends PhoneCall { - public static int constructor = 0x967f7c67; + public static final int constructor = 0x967f7c67; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23680,7 +23546,7 @@ public class TLRPC { } public static class TL_phoneCallEmpty extends PhoneCall { - public static int constructor = 0x5366c915; + public static final int constructor = 0x5366c915; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23694,7 +23560,7 @@ public class TLRPC { } public static class TL_phoneCallAccepted extends PhoneCall { - public static int constructor = 0x3660c311; + public static final int constructor = 0x3660c311; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23724,7 +23590,7 @@ public class TLRPC { } public static class TL_phoneCallWaiting extends PhoneCall { - public static int constructor = 0xc5226f17; + public static final int constructor = 0xc5226f17; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23758,7 +23624,7 @@ public class TLRPC { } public static class TL_phoneCallDiscarded extends PhoneCall { - public static int constructor = 0x50ca4de1; + public static final int constructor = 0x50ca4de1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -23814,7 +23680,7 @@ public class TLRPC { } public static class TL_help_countriesListNotModified extends help_CountriesList { - public static int constructor = 0x93cc1f32; + public static final int constructor = 0x93cc1f32; public void serializeToStream(AbstractSerializedData stream) { @@ -23823,7 +23689,7 @@ public class TLRPC { } public static class TL_help_countriesList extends help_CountriesList { - public static int constructor = 0x87d0759e; + public static final int constructor = 0x87d0759e; public ArrayList countries = new ArrayList<>(); public int hash; @@ -23902,10 +23768,18 @@ public class TLRPC { public EmojiStatus emoji_status; public ArrayList usernames = new ArrayList<>(); public int stories_max_id; + public int color; + public long background_emoji_id; public static User TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { User result = null; switch (constructor) { + case TL_user.constructor: + result = new TL_user(); + break; + case TL_user_layer165_2.constructor: + result = new TL_user_layer165_2(); + break; case 0xcab35e18: result = new TL_userContact_old2(); break; @@ -23915,8 +23789,8 @@ public class TLRPC { case 0xd3bc4b7a: result = new TL_userEmpty(); break; - case 0xabb5f120: - result = new TL_user(); + case TL_user_layer165.constructor: + result = new TL_user_layer165(); break; case 0x8f97c628: result = new TL_user_layer159(); @@ -24006,7 +23880,7 @@ public class TLRPC { } public static class TL_userContact_old2 extends User { - public static int constructor = 0xcab35e18; + public static final int constructor = 0xcab35e18; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24034,7 +23908,7 @@ public class TLRPC { } public static class TL_userContact_old extends TL_userContact_old2 { - public static int constructor = 0xf2fb8319; + public static final int constructor = 0xf2fb8319; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24060,7 +23934,7 @@ public class TLRPC { } public static class TL_userEmpty extends User { - public static int constructor = 0xd3bc4b7a; + public static final int constructor = 0xd3bc4b7a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24074,7 +23948,7 @@ public class TLRPC { } public static class TL_user extends User { - public static int constructor = 0xabb5f120; + public static final int constructor = 0xeb602f25; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -24176,6 +24050,407 @@ public class TLRPC { } catch (Throwable e) { FileLog.e(e); } + if ((flags2 & 128) != 0) { + color = stream.readInt32(exception); + } + if ((flags2 & 64) != 0) { + background_emoji_id = stream.readInt64(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + if (username == null) { + flags = flags & ~8; + } + stream.writeInt32(constructor); + flags = self ? (flags | 1024) : (flags &~ 1024); + flags = contact ? (flags | 2048) : (flags &~ 2048); + flags = mutual_contact ? (flags | 4096) : (flags &~ 4096); + flags = deleted ? (flags | 8192) : (flags &~ 8192); + flags = bot ? (flags | 16384) : (flags &~ 16384); + flags = bot_chat_history ? (flags | 32768) : (flags &~ 32768); + flags = bot_nochats ? (flags | 65536) : (flags &~ 65536); + flags = verified ? (flags | 131072) : (flags &~ 131072); + flags = restricted ? (flags | 262144) : (flags &~ 262144); + flags = min ? (flags | 1048576) : (flags &~ 1048576); + flags = bot_inline_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = support ? (flags | 8388608) : (flags &~ 8388608); + flags = scam ? (flags | 16777216) : (flags &~ 16777216); + flags = apply_min_photo ? (flags | 33554432) : (flags &~ 33554432); + flags = fake ? (flags | 67108864) : (flags &~ 67108864); + flags = bot_attach_menu ? (flags | 134217728) : (flags &~ 134217728); + flags = premium ? (flags | 268435456) : (flags &~ 268435456); + flags = attach_menu_enabled ? (flags | 536870912) : (flags &~ 536870912); + stream.writeInt32(flags); + flags2 = bot_can_edit ? (flags2 | 2) : (flags2 &~ 2); + flags2 = close_friend ? (flags2 | 4) : (flags2 &~ 4); + flags2 = stories_hidden ? (flags2 | 8) : (flags2 &~ 8); + flags2 = stories_unavailable ? (flags2 | 16) : (flags2 &~ 16); + stream.writeInt32(flags2); + stream.writeInt64(id); + if ((flags & 1) != 0) { + stream.writeInt64(access_hash); + } + if ((flags & 2) != 0) { + stream.writeString(first_name); + } + if ((flags & 4) != 0) { + stream.writeString(last_name); + } + if ((flags & 8) != 0) { + stream.writeString(username); + } + if ((flags & 16) != 0) { + stream.writeString(phone); + } + if ((flags & 32) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 64) != 0) { + status.serializeToStream(stream); + } + if ((flags & 16384) != 0) { + stream.writeInt32(bot_info_version); + } + if ((flags & 262144) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 524288) != 0) { + stream.writeString(bot_inline_placeholder); + } + if ((flags & 4194304) != 0) { + stream.writeString(lang_code); + } + if ((flags & 1073741824) != 0) { + emoji_status.serializeToStream(stream); + } + if ((flags2 & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = usernames.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + usernames.get(a).serializeToStream(stream); + } + } + if ((flags2 & 32) != 0) { + stream.writeInt32(stories_max_id); + } + if ((flags2 & 128) != 0) { + stream.writeInt32(color); + } + if ((flags2 & 64) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + + public static class TL_user_layer165_2 extends User { + public static final int constructor = 0x6fdee0df; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + self = (flags & 1024) != 0; + contact = (flags & 2048) != 0; + mutual_contact = (flags & 4096) != 0; + deleted = (flags & 8192) != 0; + bot = (flags & 16384) != 0; + bot_chat_history = (flags & 32768) != 0; + bot_nochats = (flags & 65536) != 0; + verified = (flags & 131072) != 0; + restricted = (flags & 262144) != 0; + min = (flags & 1048576) != 0; + bot_inline_geo = (flags & 2097152) != 0; + support = (flags & 8388608) != 0; + scam = (flags & 16777216) != 0; + apply_min_photo = (flags & 33554432) != 0; + fake = (flags & 67108864) != 0; + bot_attach_menu = (flags & 134217728) != 0; + premium = (flags & 268435456) != 0; + attach_menu_enabled = (flags & 536870912) != 0; + flags2 = stream.readInt32(exception); + bot_can_edit = (flags2 & 2) != 0; + close_friend = (flags2 & 4) != 0; + stories_hidden = (flags2 & 8) != 0; + stories_unavailable = (flags2 & 16) != 0; + id = stream.readInt64(exception); + if ((flags & 1) != 0) { + access_hash = stream.readInt64(exception); + } + if ((flags & 2) != 0) { + first_name = stream.readString(exception); + } + if ((flags & 4) != 0) { + last_name = stream.readString(exception); + } + if ((flags & 8) != 0) { + username = stream.readString(exception); + } + if ((flags & 16) != 0) { + phone = stream.readString(exception); + } + if ((flags & 32) != 0) { + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 64) != 0) { + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16384) != 0) { + bot_info_version = stream.readInt32(exception); + } + if ((flags & 262144) != 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_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 524288) != 0) { + bot_inline_placeholder = stream.readString(exception); + } + if ((flags & 4194304) != 0) { + lang_code = stream.readString(exception); + } + if ((flags & 1073741824) != 0) { + emoji_status = EmojiStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 1) != 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_username object = TL_username.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + usernames.add(object); + } + } + try { + if ((flags2 & 32) != 0) { + stories_max_id = stream.readInt32(exception); + } + } catch (Throwable e) { + FileLog.e(e); + } + color = stream.readInt32(exception); + if ((flags2 & 64) != 0) { + background_emoji_id = stream.readInt64(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + if (username == null) { + flags = flags & ~8; + } + stream.writeInt32(constructor); + flags = self ? (flags | 1024) : (flags &~ 1024); + flags = contact ? (flags | 2048) : (flags &~ 2048); + flags = mutual_contact ? (flags | 4096) : (flags &~ 4096); + flags = deleted ? (flags | 8192) : (flags &~ 8192); + flags = bot ? (flags | 16384) : (flags &~ 16384); + flags = bot_chat_history ? (flags | 32768) : (flags &~ 32768); + flags = bot_nochats ? (flags | 65536) : (flags &~ 65536); + flags = verified ? (flags | 131072) : (flags &~ 131072); + flags = restricted ? (flags | 262144) : (flags &~ 262144); + flags = min ? (flags | 1048576) : (flags &~ 1048576); + flags = bot_inline_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = support ? (flags | 8388608) : (flags &~ 8388608); + flags = scam ? (flags | 16777216) : (flags &~ 16777216); + flags = apply_min_photo ? (flags | 33554432) : (flags &~ 33554432); + flags = fake ? (flags | 67108864) : (flags &~ 67108864); + flags = bot_attach_menu ? (flags | 134217728) : (flags &~ 134217728); + flags = premium ? (flags | 268435456) : (flags &~ 268435456); + flags = attach_menu_enabled ? (flags | 536870912) : (flags &~ 536870912); + stream.writeInt32(flags); + flags2 = bot_can_edit ? (flags2 | 2) : (flags2 &~ 2); + flags2 = close_friend ? (flags2 | 4) : (flags2 &~ 4); + flags2 = stories_hidden ? (flags2 | 8) : (flags2 &~ 8); + flags2 = stories_unavailable ? (flags2 | 16) : (flags2 &~ 16); + stream.writeInt32(flags2); + stream.writeInt64(id); + if ((flags & 1) != 0) { + stream.writeInt64(access_hash); + } + if ((flags & 2) != 0) { + stream.writeString(first_name); + } + if ((flags & 4) != 0) { + stream.writeString(last_name); + } + if ((flags & 8) != 0) { + stream.writeString(username); + } + if ((flags & 16) != 0) { + stream.writeString(phone); + } + if ((flags & 32) != 0) { + photo.serializeToStream(stream); + } + if ((flags & 64) != 0) { + status.serializeToStream(stream); + } + if ((flags & 16384) != 0) { + stream.writeInt32(bot_info_version); + } + if ((flags & 262144) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 524288) != 0) { + stream.writeString(bot_inline_placeholder); + } + if ((flags & 4194304) != 0) { + stream.writeString(lang_code); + } + if ((flags & 1073741824) != 0) { + emoji_status.serializeToStream(stream); + } + if ((flags2 & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = usernames.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + usernames.get(a).serializeToStream(stream); + } + } + if ((flags2 & 32) != 0) { + stream.writeInt32(stories_max_id); + } + stream.writeInt32(color); + if ((flags2 & 64) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + + public static class TL_user_layer165 extends User { + public static final int constructor = 0xabb5f120; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + self = (flags & 1024) != 0; + contact = (flags & 2048) != 0; + mutual_contact = (flags & 4096) != 0; + deleted = (flags & 8192) != 0; + bot = (flags & 16384) != 0; + bot_chat_history = (flags & 32768) != 0; + bot_nochats = (flags & 65536) != 0; + verified = (flags & 131072) != 0; + restricted = (flags & 262144) != 0; + min = (flags & 1048576) != 0; + bot_inline_geo = (flags & 2097152) != 0; + support = (flags & 8388608) != 0; + scam = (flags & 16777216) != 0; + apply_min_photo = (flags & 33554432) != 0; + fake = (flags & 67108864) != 0; + bot_attach_menu = (flags & 134217728) != 0; + premium = (flags & 268435456) != 0; + attach_menu_enabled = (flags & 536870912) != 0; + flags2 = stream.readInt32(exception); + bot_can_edit = (flags2 & 2) != 0; + close_friend = (flags2 & 4) != 0; + stories_hidden = (flags2 & 8) != 0; + stories_unavailable = (flags2 & 16) != 0; + id = stream.readInt64(exception); + if ((flags & 1) != 0) { + access_hash = stream.readInt64(exception); + } + if ((flags & 2) != 0) { + first_name = stream.readString(exception); + } + if ((flags & 4) != 0) { + last_name = stream.readString(exception); + } + if ((flags & 8) != 0) { + username = stream.readString(exception); + } + if ((flags & 16) != 0) { + phone = stream.readString(exception); + } + if ((flags & 32) != 0) { + photo = UserProfilePhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 64) != 0) { + status = UserStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 16384) != 0) { + bot_info_version = stream.readInt32(exception); + } + if ((flags & 262144) != 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_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 524288) != 0) { + bot_inline_placeholder = stream.readString(exception); + } + if ((flags & 4194304) != 0) { + lang_code = stream.readString(exception); + } + if ((flags & 1073741824) != 0) { + emoji_status = EmojiStatus.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags2 & 1) != 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_username object = TL_username.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + usernames.add(object); + } + } + try { + if ((flags2 & 32) != 0) { + stories_max_id = stream.readInt32(exception); + } + } catch (Throwable e) { + FileLog.e(e); + } + color = (int) (id % 7); } public void serializeToStream(AbstractSerializedData stream) { @@ -24264,7 +24539,7 @@ public class TLRPC { } public static class TL_user_layer159 extends User { - public static int constructor = 0x8f97c628; + public static final int constructor = 0x8f97c628; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -24442,7 +24717,7 @@ public class TLRPC { } public static class TL_user_layer147 extends User { - public static int constructor = 0x5d99adee; + public static final int constructor = 0x5d99adee; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -24584,7 +24859,7 @@ public class TLRPC { } public static class TL_user_layer144 extends User { - public static int constructor = 0x3ff6ecb0; + public static final int constructor = 0x3ff6ecb0; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -24718,7 +24993,7 @@ public class TLRPC { } public static class TL_user_layer131 extends TL_user { - public static int constructor = 0x938458c1; + public static final int constructor = 0x938458c1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24849,7 +25124,7 @@ public class TLRPC { } public static class TL_user_layer104 extends TL_user { - public static int constructor = 0x2e13f4c3; + public static final int constructor = 0x2e13f4c3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24957,7 +25232,7 @@ public class TLRPC { } public static class TL_userSelf_old extends TL_userSelf_old3 { - public static int constructor = 0x720535ec; + public static final int constructor = 0x720535ec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -24983,7 +25258,7 @@ public class TLRPC { } public static class TL_userSelf_old3 extends User { - public static int constructor = 0x1c60e608; + public static final int constructor = 0x1c60e608; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25009,7 +25284,7 @@ public class TLRPC { } public static class TL_userDeleted_old2 extends User { - public static int constructor = 0xd6016d7a; + public static final int constructor = 0xd6016d7a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25029,7 +25304,7 @@ public class TLRPC { } public static class TL_userEmpty_layer131 extends TL_userEmpty { - public static int constructor = 0x200250ba; + public static final int constructor = 0x200250ba; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25043,7 +25318,7 @@ public class TLRPC { } public static class TL_userRequest_old extends TL_userRequest_old2 { - public static int constructor = 0x22e8ceb0; + public static final int constructor = 0x22e8ceb0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25069,7 +25344,7 @@ public class TLRPC { } public static class TL_userForeign_old extends TL_userForeign_old2 { - public static int constructor = 0x5214c89d; + public static final int constructor = 0x5214c89d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25093,7 +25368,7 @@ public class TLRPC { } public static class TL_userForeign_old2 extends User { - public static int constructor = 0x75cf7a8; + public static final int constructor = 0x75cf7a8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25119,7 +25394,7 @@ public class TLRPC { } public static class TL_userRequest_old2 extends User { - public static int constructor = 0xd9ccc4ef; + public static final int constructor = 0xd9ccc4ef; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25147,7 +25422,7 @@ public class TLRPC { } public static class TL_userDeleted_old extends TL_userDeleted_old2 { - public static int constructor = 0xb29ad7cc; + public static final int constructor = 0xb29ad7cc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25165,7 +25440,7 @@ public class TLRPC { } public static class TL_user_layer65 extends TL_user { - public static int constructor = 0xd10d979a; + public static final int constructor = 0xd10d979a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25263,7 +25538,7 @@ public class TLRPC { } public static class TL_user_old extends TL_user { - public static int constructor = 0x22e49072; + public static final int constructor = 0x22e49072; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25345,7 +25620,7 @@ public class TLRPC { } public static class TL_userSelf_old2 extends TL_userSelf_old3 { - public static int constructor = 0x7007b451; + public static final int constructor = 0x7007b451; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25373,7 +25648,7 @@ public class TLRPC { } public static class TL_phone_groupCallStreamRtmpUrl extends TLObject { - public static int constructor = 0x2dbf3432; + public static final int constructor = 0x2dbf3432; public String url; public String key; @@ -25441,7 +25716,7 @@ public class TLRPC { } public static class TL_recentMeUrlChat extends RecentMeUrl { - public static int constructor = 0xb2da71d2; + public static final int constructor = 0xb2da71d2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25457,7 +25732,7 @@ public class TLRPC { } public static class TL_recentMeUrlStickerSet extends RecentMeUrl { - public static int constructor = 0xbc0a57dc; + public static final int constructor = 0xbc0a57dc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25473,7 +25748,7 @@ public class TLRPC { } public static class TL_recentMeUrlUnknown extends RecentMeUrl { - public static int constructor = 0x46e1d13d; + public static final int constructor = 0x46e1d13d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25487,7 +25762,7 @@ public class TLRPC { } public static class TL_recentMeUrlChatInvite extends RecentMeUrl { - public static int constructor = 0xeb49081d; + public static final int constructor = 0xeb49081d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25503,7 +25778,7 @@ public class TLRPC { } public static class TL_recentMeUrlUser extends RecentMeUrl { - public static int constructor = 0xb92c09e2; + public static final int constructor = 0xb92c09e2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25519,7 +25794,7 @@ public class TLRPC { } public static class TL_statsGroupTopPoster extends TLObject { - public static int constructor = 0x9d04af9b; + public static final int constructor = 0x9d04af9b; public long user_id; public int messages; @@ -25553,7 +25828,7 @@ public class TLRPC { } public static class TL_statsDateRangeDays extends TLObject { - public static int constructor = 0xb637edaf; + public static final int constructor = 0xb637edaf; public int min_date; public int max_date; @@ -25584,7 +25859,7 @@ public class TLRPC { } public static class TL_payments_bankCardData extends TLObject { - public static int constructor = 0x3e24e573; + public static final int constructor = 0x3e24e573; public String title; public ArrayList open_urls = new ArrayList<>(); @@ -25634,7 +25909,7 @@ public class TLRPC { } public static class TL_messages_highScores extends TLObject { - public static int constructor = 0x9a3bfd99; + public static final int constructor = 0x9a3bfd99; public ArrayList scores = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -25703,7 +25978,7 @@ public class TLRPC { } public static class TL_phone_phoneCall extends TLObject { - public static int constructor = 0xec82e140; + public static final int constructor = 0xec82e140; public PhoneCall phone_call; public ArrayList users = new ArrayList<>(); @@ -25795,7 +26070,7 @@ public class TLRPC { } public static class TL_channelParticipantsMentions extends ChannelParticipantsFilter { - public static int constructor = 0xe04b5ceb; + public static final int constructor = 0xe04b5ceb; public int flags; public int top_msg_id; @@ -25823,7 +26098,7 @@ public class TLRPC { } public static class TL_channelParticipantsContacts extends ChannelParticipantsFilter { - public static int constructor = 0xbb6ae88d; + public static final int constructor = 0xbb6ae88d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25837,7 +26112,7 @@ public class TLRPC { } public static class TL_channelParticipantsAdmins extends ChannelParticipantsFilter { - public static int constructor = 0xb4608969; + public static final int constructor = 0xb4608969; public void serializeToStream(AbstractSerializedData stream) { @@ -25846,7 +26121,7 @@ public class TLRPC { } public static class TL_channelParticipantsKicked extends ChannelParticipantsFilter { - public static int constructor = 0xa3b54985; + public static final int constructor = 0xa3b54985; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25860,7 +26135,7 @@ public class TLRPC { } public static class TL_channelParticipantsSearch extends ChannelParticipantsFilter { - public static int constructor = 0x656ac4b; + public static final int constructor = 0x656ac4b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25874,7 +26149,7 @@ public class TLRPC { } public static class TL_channelParticipantsBots extends ChannelParticipantsFilter { - public static int constructor = 0xb0d1865b; + public static final int constructor = 0xb0d1865b; public void serializeToStream(AbstractSerializedData stream) { @@ -25883,7 +26158,7 @@ public class TLRPC { } public static class TL_channelParticipantsBanned extends ChannelParticipantsFilter { - public static int constructor = 0x1427a5e1; + public static final int constructor = 0x1427a5e1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -25897,7 +26172,7 @@ public class TLRPC { } public static class TL_channelParticipantsRecent extends ChannelParticipantsFilter { - public static int constructor = 0xde3f3c79; + public static final int constructor = 0xde3f3c79; public void serializeToStream(AbstractSerializedData stream) { @@ -25970,6 +26245,9 @@ public class TLRPC { case 0xe1037f92: result = new TL_messageActionChatMigrateTo(); break; + case 0x332ba9ed: + result = new TL_messageActionGiveawayLaunch(); + break; case 0xea3948e9: result = new TL_messageActionChannelMigrateFrom(); break; @@ -26015,6 +26293,9 @@ public class TLRPC { case 0x55555550: result = new TL_messageActionUserJoined(); break; + case 0xd2cfdb0e: + result = new TL_messageActionGiftCode(); + break; case 0xb18a431c: result = new TL_messageActionTopicEdit_layer149(); break; @@ -26126,7 +26407,7 @@ public class TLRPC { } public static class TL_messageActionLoginUnknownLocation extends MessageAction { - public static int constructor = 0x555555F5; + public static final int constructor = 0x555555F5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26142,7 +26423,7 @@ public class TLRPC { } public static class TL_messageEncryptedAction extends MessageAction { - public static int constructor = 0x555555F7; + public static final int constructor = 0x555555F7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26156,7 +26437,7 @@ public class TLRPC { } public static class TL_messageActionCustomAction extends MessageAction { - public static int constructor = 0xfae69f56; + public static final int constructor = 0xfae69f56; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26170,7 +26451,7 @@ public class TLRPC { } public static class TL_messageActionChatCreate extends MessageAction { - public static int constructor = 0xbd47cbad; + public static final int constructor = 0xbd47cbad; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26201,7 +26482,7 @@ public class TLRPC { } public static class TL_messageActionChatCreate_layer131 extends TL_messageActionChatCreate { - public static int constructor = 0xa6638b9a; + public static final int constructor = 0xa6638b9a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26232,7 +26513,7 @@ public class TLRPC { } public static class TL_messageActionInviteToGroupCall extends MessageAction { - public static int constructor = 0x502f92f7; + public static final int constructor = 0x502f92f7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26263,7 +26544,7 @@ public class TLRPC { } public static class TL_messageActionChannelMigrateFrom extends MessageAction { - public static int constructor = 0xea3948e9; + public static final int constructor = 0xea3948e9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26279,7 +26560,7 @@ public class TLRPC { } public static class TL_messageActionGroupCall extends MessageAction { - public static int constructor = 0x7a0d7f42; + public static final int constructor = 0x7a0d7f42; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26301,7 +26582,7 @@ public class TLRPC { } public static class TL_messageActionSetChatTheme extends MessageAction { - public static int constructor = 0xaa786345; + public static final int constructor = 0xaa786345; public String emoticon; @@ -26316,7 +26597,7 @@ public class TLRPC { } public static class TL_messages_getExtendedMedia extends TLObject { - public static int constructor = 0x84f80814; + public static final int constructor = 0x84f80814; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -26338,7 +26619,7 @@ public class TLRPC { } public static class TL_messages_getMessageReadParticipants extends TLObject { - public static int constructor = 0x31c1c44f; + public static final int constructor = 0x31c1c44f; public InputPeer peer; public int msg_id; @@ -26364,7 +26645,7 @@ public class TLRPC { } public static class TL_messageActionChatDeleteUser extends MessageAction { - public static int constructor = 0xa43f30cc; + public static final int constructor = 0xa43f30cc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26378,7 +26659,7 @@ public class TLRPC { } public static class TL_messageActionChatAddUser extends MessageAction { - public static int constructor = 0x15cefd00; + public static final int constructor = 0x15cefd00; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26407,7 +26688,7 @@ public class TLRPC { } public static class TL_messageActionChatMigrateTo_layer131 extends TL_messageActionChatMigrateTo { - public static int constructor = 0x51bdb021; + public static final int constructor = 0x51bdb021; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26421,7 +26702,7 @@ public class TLRPC { } public static class TL_messageActionHistoryClear extends MessageAction { - public static int constructor = 0x9fbab604; + public static final int constructor = 0x9fbab604; public void serializeToStream(AbstractSerializedData stream) { @@ -26430,7 +26711,7 @@ public class TLRPC { } public static class TL_messageActionChatEditPhoto extends MessageAction { - public static int constructor = 0x7fcb13a8; + public static final int constructor = 0x7fcb13a8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26444,7 +26725,7 @@ public class TLRPC { } public static class TL_messageActionScreenshotTaken extends MessageAction { - public static int constructor = 0x4792929b; + public static final int constructor = 0x4792929b; public void serializeToStream(AbstractSerializedData stream) { @@ -26453,7 +26734,7 @@ public class TLRPC { } public static class TL_messageActionPhoneNumberRequest extends MessageAction { - public static int constructor = 0x1baa035; + public static final int constructor = 0x1baa035; public void serializeToStream(AbstractSerializedData stream) { @@ -26462,7 +26743,7 @@ public class TLRPC { } public static class TL_messageActionSetSameChatWallPaper extends MessageAction { - public static int constructor = 0xc0787d6d; + public static final int constructor = 0xc0787d6d; public void readParams(AbstractSerializedData stream, boolean exception) { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -26475,7 +26756,7 @@ public class TLRPC { } public static class TL_messageActionTopicEdit extends MessageAction { - public static int constructor = 0xc0944820; + public static final int constructor = 0xc0944820; public long icon_emoji_id; public boolean closed; @@ -26516,7 +26797,7 @@ public class TLRPC { } public static class TL_messageActionTopicEdit_layer149 extends TL_messageActionTopicEdit { - public static int constructor = 0xb18a431c; + public static final int constructor = 0xb18a431c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -26547,7 +26828,7 @@ public class TLRPC { } public static class TL_messageActionChatJoinedByRequest extends MessageAction { - public static int constructor = 0xebbca3cb; + public static final int constructor = 0xebbca3cb; public void serializeToStream(AbstractSerializedData stream) { @@ -26556,7 +26837,7 @@ public class TLRPC { } public static class TL_messageActionChatMigrateTo extends MessageAction { - public static int constructor = 0xe1037f92; + public static final int constructor = 0xe1037f92; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26570,7 +26851,7 @@ public class TLRPC { } public static class TL_messageActionChatJoinedByLink extends MessageAction { - public static int constructor = 0x31224c3; + public static final int constructor = 0x31224c3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26584,7 +26865,7 @@ public class TLRPC { } public static class TL_messageActionChannelMigrateFrom_layer131 extends TL_messageActionChannelMigrateFrom { - public static int constructor = 0xb055eaee; + public static final int constructor = 0xb055eaee; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26600,7 +26881,7 @@ public class TLRPC { } public static class TL_messageActionChatAddUser_layer131 extends TL_messageActionChatAddUser { - public static int constructor = 0x488a7337; + public static final int constructor = 0x488a7337; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26629,7 +26910,7 @@ public class TLRPC { } public static class TL_messageActionChatDeleteUser_layer131 extends TL_messageActionChatDeleteUser { - public static int constructor = 0xb2ae9b0c; + public static final int constructor = 0xb2ae9b0c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26643,7 +26924,7 @@ public class TLRPC { } public static class TL_messageActionCreatedBroadcastList extends MessageAction { - public static int constructor = 0x55555557; + public static final int constructor = 0x55555557; public void serializeToStream(AbstractSerializedData stream) { @@ -26652,7 +26933,7 @@ public class TLRPC { } public static class TL_messageActionInviteToGroupCall_layer131 extends TL_messageActionInviteToGroupCall { - public static int constructor = 0x76b9f11a; + public static final int constructor = 0x76b9f11a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26683,7 +26964,7 @@ public class TLRPC { } public static class TL_messageActionWebViewDataSentMe extends MessageAction { - public static int constructor = 0x47dd8079; + public static final int constructor = 0x47dd8079; public String text; public String data; @@ -26701,7 +26982,7 @@ public class TLRPC { } public static class TL_messageActionWebViewDataSent extends MessageAction { - public static int constructor = 0xb4c38cb5; + public static final int constructor = 0xb4c38cb5; public String text; @@ -26716,7 +26997,7 @@ public class TLRPC { } public static class TL_messageActionSetChatWallPaper extends MessageAction { - public static int constructor = 0xbc44a927; + public static final int constructor = 0xbc44a927; public void readParams(AbstractSerializedData stream, boolean exception) { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -26729,7 +27010,7 @@ public class TLRPC { } public static class TL_messageActionUserJoined extends MessageAction { - public static int constructor = 0x55555550; + public static final int constructor = 0x55555550; public void serializeToStream(AbstractSerializedData stream) { @@ -26738,7 +27019,7 @@ public class TLRPC { } public static class TL_messageActionUserUpdatedPhoto extends MessageAction { - public static int constructor = 0x55555551; + public static final int constructor = 0x55555551; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26752,7 +27033,7 @@ public class TLRPC { } public static class TL_messageActionContactSignUp extends MessageAction { - public static int constructor = 0xf3f25f76; + public static final int constructor = 0xf3f25f76; public void serializeToStream(AbstractSerializedData stream) { @@ -26761,7 +27042,7 @@ public class TLRPC { } public static class TL_messageActionChatAddUser_old extends TL_messageActionChatAddUser { - public static int constructor = 0x5e3cfc4b; + public static final int constructor = 0x5e3cfc4b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26775,7 +27056,7 @@ public class TLRPC { } public static class TL_messageActionTTLChange extends MessageAction { - public static int constructor = 0x55555552; + public static final int constructor = 0x55555552; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26789,7 +27070,7 @@ public class TLRPC { } public static class TL_messageActionSetMessagesTTL extends MessageAction { - public static int constructor = 0x3c134d7b; + public static final int constructor = 0x3c134d7b; public int period; public long auto_setting_from; @@ -26813,7 +27094,7 @@ public class TLRPC { } public static class TL_messageActionSetMessagesTTL_layer149 extends TL_messageActionSetMessagesTTL { - public static int constructor = 0xaa1afbfd; + public static final int constructor = 0xaa1afbfd; public void readParams(AbstractSerializedData stream, boolean exception) { period = stream.readInt32(exception); @@ -26826,7 +27107,7 @@ public class TLRPC { } public static class TL_messageActionChatJoinedByLink_layer131 extends TL_messageActionChatJoinedByLink { - public static int constructor = 0xf89cf5e8; + public static final int constructor = 0xf89cf5e8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26840,7 +27121,7 @@ public class TLRPC { } public static class TL_messageActionChannelCreate extends MessageAction { - public static int constructor = 0x95d2ac92; + public static final int constructor = 0x95d2ac92; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26854,7 +27135,7 @@ public class TLRPC { } public static class TL_messageActionSecureValuesSent extends MessageAction { - public static int constructor = 0xd95c6154; + public static final int constructor = 0xd95c6154; public ArrayList types = new ArrayList<>(); @@ -26888,7 +27169,7 @@ public class TLRPC { } public static class TL_messageActionPinMessage extends MessageAction { - public static int constructor = 0x94bd38ed; + public static final int constructor = 0x94bd38ed; public void serializeToStream(AbstractSerializedData stream) { @@ -26897,7 +27178,7 @@ public class TLRPC { } public static class TL_messageActionGeoProximityReached extends MessageAction { - public static int constructor = 0x98e0d697; + public static final int constructor = 0x98e0d697; public Peer from_id; public Peer to_id; @@ -26918,7 +27199,7 @@ public class TLRPC { } public static class TL_messageActionChatDeletePhoto extends MessageAction { - public static int constructor = 0x95e3fbef; + public static final int constructor = 0x95e3fbef; public void serializeToStream(AbstractSerializedData stream) { @@ -26927,7 +27208,7 @@ public class TLRPC { } public static class TL_messageActionPhoneCall extends MessageAction { - public static int constructor = 0x80e11a7f; + public static final int constructor = 0x80e11a7f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26957,7 +27238,7 @@ public class TLRPC { } public static class TL_messageActionTopicCreate extends MessageAction { - public static int constructor = 0xd999256; + public static final int constructor = 0xd999256; public int icon_color; public long icon_emoji_id; @@ -26983,7 +27264,7 @@ public class TLRPC { } public static class TL_messageActionChatEditTitle extends MessageAction { - public static int constructor = 0xb5a1ce5a; + public static final int constructor = 0xb5a1ce5a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -26997,7 +27278,7 @@ public class TLRPC { } public static class TL_messageActionPaymentSent extends MessageAction { - public static int constructor = 0x96163f56; + public static final int constructor = 0x96163f56; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -27024,7 +27305,7 @@ public class TLRPC { } public static class TL_messageActionPaymentSent_layer140 extends TL_messageActionPaymentSent { - public static int constructor = 0x40699cd0; + public static final int constructor = 0x40699cd0; public void readParams(AbstractSerializedData stream, boolean exception) { currency = stream.readString(exception); @@ -27039,7 +27320,7 @@ public class TLRPC { } public static class TL_messageActionBotAllowed extends MessageAction { - public static int constructor = 0xc516d679; + public static final int constructor = 0xc516d679; public boolean attach_menu; public boolean from_request; @@ -27073,7 +27354,7 @@ public class TLRPC { } public static class TL_messageActionBotAllowed_layer153 extends MessageAction { - public static int constructor = 0xabe9affe; + public static final int constructor = 0xabe9affe; public String domain; @@ -27088,7 +27369,7 @@ public class TLRPC { } public static class TL_messageActionEmpty extends MessageAction { - public static int constructor = 0xb6aef7b0; + public static final int constructor = 0xb6aef7b0; public void serializeToStream(AbstractSerializedData stream) { @@ -27097,7 +27378,7 @@ public class TLRPC { } public static class TL_messageActionGameScore extends MessageAction { - public static int constructor = 0x92a72876; + public static final int constructor = 0x92a72876; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27113,7 +27394,7 @@ public class TLRPC { } public static class TL_messageActionGiftPremium extends MessageAction { - public static int constructor = 0xc83d6aec; + public static final int constructor = 0xc83d6aec; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -27140,7 +27421,7 @@ public class TLRPC { } public static class TL_messageActionPaymentSentMe extends MessageAction { - public static int constructor = 0x8f31b327; + public static final int constructor = 0x8f31b327; public int flags; public byte[] payload; @@ -27180,7 +27461,7 @@ public class TLRPC { } public static class TL_messageActionGroupCallScheduled extends MessageAction { - public static int constructor = 0xb3a07661; + public static final int constructor = 0xb3a07661; public int schedule_date; @@ -27237,7 +27518,7 @@ public class TLRPC { } public static class TL_inputReportReasonGeoIrrelevant extends ReportReason { - public static int constructor = 0xdbd4feed; + public static final int constructor = 0xdbd4feed; public void serializeToStream(AbstractSerializedData stream) { @@ -27246,7 +27527,7 @@ public class TLRPC { } public static class TL_inputReportReasonOther extends ReportReason { - public static int constructor = 0xc1e4a2b1; + public static final int constructor = 0xc1e4a2b1; public void serializeToStream(AbstractSerializedData stream) { @@ -27255,7 +27536,7 @@ public class TLRPC { } public static class TL_inputReportReasonFake extends ReportReason { - public static int constructor = 0xf5ddd6e7; + public static final int constructor = 0xf5ddd6e7; public void serializeToStream(AbstractSerializedData stream) { @@ -27264,7 +27545,7 @@ public class TLRPC { } public static class TL_inputReportReasonCopyright extends ReportReason { - public static int constructor = 0x9b89f93a; + public static final int constructor = 0x9b89f93a; public void serializeToStream(AbstractSerializedData stream) { @@ -27273,7 +27554,7 @@ public class TLRPC { } public static class TL_inputReportReasonSpam extends ReportReason { - public static int constructor = 0x58dbcab8; + public static final int constructor = 0x58dbcab8; public void serializeToStream(AbstractSerializedData stream) { @@ -27282,7 +27563,7 @@ public class TLRPC { } public static class TL_inputReportReasonViolence extends ReportReason { - public static int constructor = 0x1e22c78d; + public static final int constructor = 0x1e22c78d; public void serializeToStream(AbstractSerializedData stream) { @@ -27291,7 +27572,7 @@ public class TLRPC { } public static class TL_inputReportReasonChildAbuse extends ReportReason { - public static int constructor = 0xadf44ee3; + public static final int constructor = 0xadf44ee3; public void serializeToStream(AbstractSerializedData stream) { @@ -27300,7 +27581,7 @@ public class TLRPC { } public static class TL_inputReportReasonPornography extends ReportReason { - public static int constructor = 0x2e59d922; + public static final int constructor = 0x2e59d922; public void serializeToStream(AbstractSerializedData stream) { @@ -27309,7 +27590,7 @@ public class TLRPC { } public static class TL_inputReportReasonIllegalDrugs extends ReportReason { - public static int constructor = 0xa8eb2be; + public static final int constructor = 0xa8eb2be; public void serializeToStream(AbstractSerializedData stream) { @@ -27318,7 +27599,7 @@ public class TLRPC { } public static class TL_inputReportReasonPersonalDetails extends ReportReason { - public static int constructor = 0x9ec7863d; + public static final int constructor = 0x9ec7863d; public void serializeToStream(AbstractSerializedData stream) { @@ -27327,7 +27608,7 @@ public class TLRPC { } public static class TL_messages_archivedStickers extends TLObject { - public static int constructor = 0x4fcba9c8; + public static final int constructor = 0x4fcba9c8; public int count; public ArrayList sets = new ArrayList<>(); @@ -27423,7 +27704,7 @@ public class TLRPC { } public static class TL_decryptedMessage_layer17 extends TL_decryptedMessage { - public static int constructor = 0x204d3878; + public static final int constructor = 0x204d3878; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27443,7 +27724,7 @@ public class TLRPC { } public static class TL_decryptedMessageService extends DecryptedMessage { - public static int constructor = 0x73164160; + public static final int constructor = 0x73164160; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27459,7 +27740,7 @@ public class TLRPC { } public static class TL_decryptedMessageService_layer8 extends TL_decryptedMessageService { - public static int constructor = 0xaa48327d; + public static final int constructor = 0xaa48327d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27477,7 +27758,7 @@ public class TLRPC { } public static class TL_decryptedMessage_layer8 extends TL_decryptedMessage { - public static int constructor = 0x1f814f1f; + public static final int constructor = 0x1f814f1f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27497,7 +27778,7 @@ public class TLRPC { } public static class TL_decryptedMessage extends DecryptedMessage { - public static int constructor = 0x91cc4674; + public static final int constructor = 0x91cc4674; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27568,7 +27849,7 @@ public class TLRPC { } public static class TL_decryptedMessage_layer45 extends TL_decryptedMessage { - public static int constructor = 0x36b091de; + public static final int constructor = 0x36b091de; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -27653,7 +27934,7 @@ public class TLRPC { } public static class TL_account_themes extends account_Themes { - public static int constructor = 0x9a3d8c6d; + public static final int constructor = 0x9a3d8c6d; public long hash; public ArrayList themes = new ArrayList<>(); @@ -27690,7 +27971,7 @@ public class TLRPC { } public static class TL_account_themesNotModified extends account_Themes { - public static int constructor = 0xf41eb622; + public static final int constructor = 0xf41eb622; public void serializeToStream(AbstractSerializedData stream) { @@ -27699,7 +27980,7 @@ public class TLRPC { } public static class TL_invoice extends TLObject { - public static int constructor = 0x5db95a15; + public static final int constructor = 0x5db95a15; public int flags; public boolean test; @@ -27821,7 +28102,7 @@ public class TLRPC { } public static class TL_invoice_layer163 extends TL_invoice { - public static int constructor = 0x3e85a91b; + public static final int constructor = 0x3e85a91b; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -27930,7 +28211,7 @@ public class TLRPC { } public static class TL_account_wallPapersNotModified extends account_WallPapers { - public static int constructor = 0x1c199183; + public static final int constructor = 0x1c199183; public void serializeToStream(AbstractSerializedData stream) { @@ -27939,7 +28220,7 @@ public class TLRPC { } public static class TL_account_wallPapers extends account_WallPapers { - public static int constructor = 0xcdc3858c; + public static final int constructor = 0xcdc3858c; public long hash; public ArrayList wallpapers = new ArrayList<>(); @@ -28010,7 +28291,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypeBroadcast extends InlineQueryPeerType { - public static int constructor = 0x6334ee9a; + public static final int constructor = 0x6334ee9a; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28018,7 +28299,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypeChat extends InlineQueryPeerType { - public static int constructor = 0xd766c50a; + public static final int constructor = 0xd766c50a; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28026,7 +28307,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypePM extends InlineQueryPeerType { - public static int constructor = 0x833c0fac; + public static final int constructor = 0x833c0fac; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28034,7 +28315,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypeBotPM extends InlineQueryPeerType { - public static int constructor = 0xe3b2d0c; + public static final int constructor = 0xe3b2d0c; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28042,7 +28323,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypeMegagroup extends InlineQueryPeerType { - public static int constructor = 0x5ec4be43; + public static final int constructor = 0x5ec4be43; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28050,7 +28331,7 @@ public class TLRPC { } public static class TL_inlineQueryPeerTypeSameBotPM extends InlineQueryPeerType { - public static int constructor = 0x3081ed9d; + public static final int constructor = 0x3081ed9d; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -28059,7 +28340,7 @@ public class TLRPC { public static class TL_inputWebDocument extends TLObject { - public static int constructor = 0x9bed434d; + public static final int constructor = 0x9bed434d; public String url; public int size; @@ -28146,7 +28427,7 @@ public class TLRPC { } public static class TL_messageReactions extends MessageReactions { - public static int constructor = 0x4f2b9479; + public static final int constructor = 0x4f2b9479; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -28209,7 +28490,7 @@ public class TLRPC { } public static class TL_messageReactionsOld extends TL_messageReactions { - public static int constructor = 0x87b6e36; + public static final int constructor = 0x87b6e36; public static TL_messageReactions TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -28286,7 +28567,7 @@ public class TLRPC { } public static class TL_messageReactions_layer137 extends TL_messageReactions { - public static int constructor = 0xb87a24d1; + public static final int constructor = 0xb87a24d1; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -28370,7 +28651,7 @@ public class TLRPC { } public static class TL_video_old3 extends TL_video_layer45 { - public static int constructor = 0xee9f4a4d; + public static final int constructor = 0xee9f4a4d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28402,7 +28683,7 @@ public class TLRPC { } public static class TL_video_layer45 extends Video { - public static int constructor = 0xf72887d3; + public static final int constructor = 0xf72887d3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28434,7 +28715,7 @@ public class TLRPC { } public static class TL_videoEncrypted extends TL_video_layer45 { - public static int constructor = 0x55555553; + public static final int constructor = 0x55555553; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28472,7 +28753,7 @@ public class TLRPC { } public static class TL_video_old extends TL_video_layer45 { - public static int constructor = 0x5a04a49f; + public static final int constructor = 0x5a04a49f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28506,7 +28787,7 @@ public class TLRPC { } public static class TL_video_old2 extends TL_video_layer45 { - public static int constructor = 0x388fa391; + public static final int constructor = 0x388fa391; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28542,7 +28823,7 @@ public class TLRPC { } public static class TL_videoEmpty_layer45 extends Video { - public static int constructor = 0xc10658a8; + public static final int constructor = 0xc10658a8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28588,7 +28869,7 @@ public class TLRPC { } public static class TL_inputPaymentCredentials extends InputPaymentCredentials { - public static int constructor = 0x3417d728; + public static final int constructor = 0x3417d728; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28606,7 +28887,7 @@ public class TLRPC { } public static class TL_inputPaymentCredentialsGooglePay extends InputPaymentCredentials { - public static int constructor = 0x8ac32801; + public static final int constructor = 0x8ac32801; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28620,7 +28901,7 @@ public class TLRPC { } public static class TL_inputPaymentCredentialsSaved extends InputPaymentCredentials { - public static int constructor = 0xc10eb2cf; + public static final int constructor = 0xc10eb2cf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -28636,7 +28917,7 @@ public class TLRPC { } public static class TL_exportedMessageLink extends TLObject { - public static int constructor = 0x5dab1af4; + public static final int constructor = 0x5dab1af4; public String link; public String html; @@ -28667,7 +28948,7 @@ public class TLRPC { } public static class TL_groupCallParticipantVideo extends TLObject { - public static int constructor = 0x67753ac8; + public static final int constructor = 0x67753ac8; public int flags; public boolean paused; @@ -28770,7 +29051,7 @@ public class TLRPC { } public static class TL_topPeerCategoryChannels extends TopPeerCategory { - public static int constructor = 0x161d9628; + public static final int constructor = 0x161d9628; public void serializeToStream(AbstractSerializedData stream) { @@ -28779,7 +29060,7 @@ public class TLRPC { } public static class TL_topPeerCategoryPhoneCalls extends TopPeerCategory { - public static int constructor = 0x1e76a78c; + public static final int constructor = 0x1e76a78c; public void serializeToStream(AbstractSerializedData stream) { @@ -28788,7 +29069,7 @@ public class TLRPC { } public static class TL_topPeerCategoryGroups extends TopPeerCategory { - public static int constructor = 0xbd17a14a; + public static final int constructor = 0xbd17a14a; public void serializeToStream(AbstractSerializedData stream) { @@ -28797,7 +29078,7 @@ public class TLRPC { } public static class TL_topPeerCategoryBotsInline extends TopPeerCategory { - public static int constructor = 0x148677e2; + public static final int constructor = 0x148677e2; public void serializeToStream(AbstractSerializedData stream) { @@ -28806,7 +29087,7 @@ public class TLRPC { } public static class TL_topPeerCategoryForwardUsers extends TopPeerCategory { - public static int constructor = 0xa8406ca9; + public static final int constructor = 0xa8406ca9; public void serializeToStream(AbstractSerializedData stream) { @@ -28815,7 +29096,7 @@ public class TLRPC { } public static class TL_topPeerCategoryForwardChats extends TopPeerCategory { - public static int constructor = 0xfbeec0f0; + public static final int constructor = 0xfbeec0f0; public void serializeToStream(AbstractSerializedData stream) { @@ -28824,7 +29105,7 @@ public class TLRPC { } public static class TL_topPeerCategoryBotsPM extends TopPeerCategory { - public static int constructor = 0xab661b5b; + public static final int constructor = 0xab661b5b; public void serializeToStream(AbstractSerializedData stream) { @@ -28833,7 +29114,7 @@ public class TLRPC { } public static class TL_topPeerCategoryCorrespondents extends TopPeerCategory { - public static int constructor = 0x637b7ed; + public static final int constructor = 0x637b7ed; public void serializeToStream(AbstractSerializedData stream) { @@ -28846,10 +29127,15 @@ public class TLRPC { public int flags; public boolean reply_to_scheduled; public boolean forum_topic; + public boolean quote; public int reply_to_msg_id; public Peer reply_to_peer_id; public int reply_to_top_id; public long reply_to_random_id; //custom + public MessageFwdHeader reply_from; + public MessageMedia reply_media; + public String quote_text; + public ArrayList quote_entities = new ArrayList<>(); public long user_id; public int story_id; @@ -28857,12 +29143,18 @@ public class TLRPC { public static MessageReplyHeader TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageReplyHeader result = null; switch (constructor) { - case 0x9c98bfc1: + case TL_messageReplyStoryHeader.constructor: result = new TL_messageReplyStoryHeader(); break; - case 0xa6d57763: + case TL_messageReplyHeader.constructor: result = new TL_messageReplyHeader(); break; + case TL_messageReplyHeader_layer165_2.constructor: + result = new TL_messageReplyHeader_layer165_2(); + break; + case TL_messageReplyHeader_layer165.constructor: + result = new TL_messageReplyHeader_layer165(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in MessageReplyHeader", constructor)); @@ -28875,7 +29167,7 @@ public class TLRPC { } public static class TL_messageReplyStoryHeader extends MessageReplyHeader { - public static int constructor = 0x9c98bfc1; + public static final int constructor = 0x9c98bfc1; public void readParams(AbstractSerializedData stream, boolean exception) { user_id = stream.readInt64(exception); @@ -28890,7 +29182,159 @@ public class TLRPC { } public static class TL_messageReplyHeader extends MessageReplyHeader { - public static int constructor = 0xa6d57763; + public static final int constructor = 0x6eebcabd; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + reply_to_scheduled = (flags & 4) != 0; + forum_topic = (flags & 8) != 0; + quote = (flags & 512) != 0; + if ((flags & 16) != 0) { + reply_to_msg_id = stream.readInt32(exception); + } + if ((flags & 1) != 0) { + reply_to_peer_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + reply_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 256) != 0) { + reply_media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + reply_to_top_id = stream.readInt32(exception); + } + if ((flags & 64) != 0) { + quote_text = stream.readString(exception); + } + if ((flags & 128) != 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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + quote_entities.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = reply_to_scheduled ? (flags | 4) : (flags &~ 4); + flags = forum_topic ? (flags | 8) : (flags &~ 8); + flags = quote ? (flags | 512) : (flags &~ 512); + stream.writeInt32(flags); + if ((flags & 16) != 0) { + stream.writeInt32(reply_to_msg_id); + } + if ((flags & 1) != 0) { + reply_to_peer_id.serializeToStream(stream); + } + if ((flags & 32) != 0) { + reply_from.serializeToStream(stream); + } + if ((flags & 256) != 0) { + reply_media.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stream.writeInt32(reply_to_top_id); + } + if ((flags & 64) != 0) { + stream.writeString(quote_text); + } + if ((flags & 128) != 0) { + stream.writeInt32(0x1cb5c415); + int count = quote_entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; ++a) { + quote_entities.get(a).serializeToStream(stream); + } + } + } + } + + public static class TL_messageReplyHeader_layer165_2 extends TL_messageReplyHeader { + public static final int constructor = 0x3d5c1693; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + reply_to_scheduled = (flags & 4) != 0; + forum_topic = (flags & 8) != 0; + if ((flags & 16) != 0) { + reply_to_msg_id = stream.readInt32(exception); + } + if ((flags & 1) != 0) { + reply_to_peer_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + reply_from = MessageFwdHeader.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + reply_to_top_id = stream.readInt32(exception); + } + if ((flags & 64) != 0) { + quote_text = stream.readString(exception); + } + if ((flags & 128) != 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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + quote_entities.add(object); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = reply_to_scheduled ? (flags | 4) : (flags &~ 4); + flags = forum_topic ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + if ((flags & 16) != 0) { + stream.writeInt32(reply_to_msg_id); + } + if ((flags & 1) != 0) { + reply_to_peer_id.serializeToStream(stream); + } + if ((flags & 32) != 0) { + reply_from.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stream.writeInt32(reply_to_top_id); + } + if ((flags & 64) != 0) { + stream.writeString(quote_text); + } + if ((flags & 128) != 0) { + stream.writeInt32(0x1cb5c415); + int count = quote_entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; ++a) { + quote_entities.get(a).serializeToStream(stream); + } + } + } + } + + public static class TL_messageReplyHeader_layer165 extends TL_messageReplyHeader { + public static final int constructor = 0xa6d57763; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -28921,7 +29365,7 @@ public class TLRPC { } public static class TL_payments_validatedRequestedInfo extends TLObject { - public static int constructor = 0xd1451883; + public static final int constructor = 0xd1451883; public int flags; public String id; @@ -28982,7 +29426,7 @@ public class TLRPC { } public static class TL_jsonObjectValue extends TLObject { - public static int constructor = 0xc0de1bd9; + public static final int constructor = 0xc0de1bd9; public String key; public JSONValue value; @@ -29013,7 +29457,7 @@ public class TLRPC { } public static class TL_users_userFull extends TLObject { - public static int constructor = 0x3b6d152e; + public static final int constructor = 0x3b6d152e; public UserFull full_user; public ArrayList chats = new ArrayList<>(); @@ -29085,7 +29529,7 @@ public class TLRPC { } public static class TL_shippingOption extends TLObject { - public static int constructor = 0xb6213cdf; + public static final int constructor = 0xb6213cdf; public String id; public String title; @@ -29164,7 +29608,7 @@ public class TLRPC { } public static class TL_inputDocumentEmpty extends InputDocument { - public static int constructor = 0x72f0eaae; + public static final int constructor = 0x72f0eaae; public void serializeToStream(AbstractSerializedData stream) { @@ -29173,7 +29617,7 @@ public class TLRPC { } public static class TL_inputDocument extends InputDocument { - public static int constructor = 0x1abfb575; + public static final int constructor = 0x1abfb575; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -29191,7 +29635,7 @@ public class TLRPC { } public static class TL_folderPeer extends TLObject { - public static int constructor = 0xe9baa668; + public static final int constructor = 0xe9baa668; public Peer peer; public int folder_id; @@ -29222,7 +29666,7 @@ public class TLRPC { } public static class TL_stats_broadcastStats extends TLObject { - public static int constructor = 0xbdf78394; + public static final int constructor = 0xbdf78394; public TL_statsDateRangeDays period; public TL_statsAbsValueAndPrev followers; @@ -29366,7 +29810,7 @@ public class TLRPC { } public static class TL_secureValueTypeAddress extends SecureValueType { - public static int constructor = 0xcbe31e26; + public static final int constructor = 0xcbe31e26; public void serializeToStream(AbstractSerializedData stream) { @@ -29375,7 +29819,7 @@ public class TLRPC { } public static class TL_secureValueTypePassportRegistration extends SecureValueType { - public static int constructor = 0x99e3806a; + public static final int constructor = 0x99e3806a; public void serializeToStream(AbstractSerializedData stream) { @@ -29384,7 +29828,7 @@ public class TLRPC { } public static class TL_secureValueTypeIdentityCard extends SecureValueType { - public static int constructor = 0xa0d0744b; + public static final int constructor = 0xa0d0744b; public void serializeToStream(AbstractSerializedData stream) { @@ -29393,7 +29837,7 @@ public class TLRPC { } public static class TL_secureValueTypeUtilityBill extends SecureValueType { - public static int constructor = 0xfc36954e; + public static final int constructor = 0xfc36954e; public void serializeToStream(AbstractSerializedData stream) { @@ -29402,7 +29846,7 @@ public class TLRPC { } public static class TL_secureValueTypeBankStatement extends SecureValueType { - public static int constructor = 0x89137c0d; + public static final int constructor = 0x89137c0d; public void serializeToStream(AbstractSerializedData stream) { @@ -29411,7 +29855,7 @@ public class TLRPC { } public static class TL_secureValueTypeEmail extends SecureValueType { - public static int constructor = 0x8e3ca7ee; + public static final int constructor = 0x8e3ca7ee; public void serializeToStream(AbstractSerializedData stream) { @@ -29420,7 +29864,7 @@ public class TLRPC { } public static class TL_secureValueTypePersonalDetails extends SecureValueType { - public static int constructor = 0x9d2a81e3; + public static final int constructor = 0x9d2a81e3; public void serializeToStream(AbstractSerializedData stream) { @@ -29429,7 +29873,7 @@ public class TLRPC { } public static class TL_secureValueTypeTemporaryRegistration extends SecureValueType { - public static int constructor = 0xea02ec33; + public static final int constructor = 0xea02ec33; public void serializeToStream(AbstractSerializedData stream) { @@ -29438,7 +29882,7 @@ public class TLRPC { } public static class TL_secureValueTypePassport extends SecureValueType { - public static int constructor = 0x3dac6a00; + public static final int constructor = 0x3dac6a00; public void serializeToStream(AbstractSerializedData stream) { @@ -29447,7 +29891,7 @@ public class TLRPC { } public static class TL_secureValueTypeRentalAgreement extends SecureValueType { - public static int constructor = 0x8b883488; + public static final int constructor = 0x8b883488; public void serializeToStream(AbstractSerializedData stream) { @@ -29456,7 +29900,7 @@ public class TLRPC { } public static class TL_secureValueTypeDriverLicense extends SecureValueType { - public static int constructor = 0x6e425c4; + public static final int constructor = 0x6e425c4; public void serializeToStream(AbstractSerializedData stream) { @@ -29465,7 +29909,7 @@ public class TLRPC { } public static class TL_secureValueTypePhone extends SecureValueType { - public static int constructor = 0xb320aadb; + public static final int constructor = 0xb320aadb; public void serializeToStream(AbstractSerializedData stream) { @@ -29474,7 +29918,7 @@ public class TLRPC { } public static class TL_secureValueTypeInternalPassport extends SecureValueType { - public static int constructor = 0x99a48f23; + public static final int constructor = 0x99a48f23; public void serializeToStream(AbstractSerializedData stream) { @@ -29483,7 +29927,7 @@ public class TLRPC { } public static class TL_peerBlocked extends TLObject { - public static int constructor = 0xe8fd8014; + public static final int constructor = 0xe8fd8014; public Peer peer_id; public int date; @@ -29514,7 +29958,7 @@ public class TLRPC { } public static class TL_messages_affectedHistory extends TLObject { - public static int constructor = 0xb45c69d1; + public static final int constructor = 0xb45c69d1; public int pts; public int pts_count; @@ -29613,7 +30057,7 @@ public class TLRPC { } public static class TL_document_layer92 extends TL_document { - public static int constructor = 0x59534e4c; + public static final int constructor = 0x59534e4c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -29662,7 +30106,7 @@ public class TLRPC { } public static class TL_document_layer82 extends TL_document { - public static int constructor = 0x87232bc7; + public static final int constructor = 0x87232bc7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -29711,7 +30155,7 @@ public class TLRPC { } public static class TL_documentEncrypted_old extends TL_document { - public static int constructor = 0x55555556; + public static final int constructor = 0x55555556; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -29745,7 +30189,7 @@ public class TLRPC { } public static class TL_document extends Document { - public static int constructor = 0x8fd4c4d8; + public static final int constructor = 0x8fd4c4d8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -29843,7 +30287,7 @@ public class TLRPC { } public static class TL_document_layer142 extends TL_document { - public static int constructor = 0x1e87342b; + public static final int constructor = 0x1e87342b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -29942,7 +30386,7 @@ public class TLRPC { } public static class TL_document_layer113 extends TL_document { - public static int constructor = 0x9ba29cc1; + public static final int constructor = 0x9ba29cc1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -30016,7 +30460,7 @@ public class TLRPC { } public static class TL_document_old extends TL_document { - public static int constructor = 0x9efc6326; + public static final int constructor = 0x9efc6326; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -30046,7 +30490,7 @@ public class TLRPC { } public static class TL_documentEmpty extends Document { - public static int constructor = 0x36f8c871; + public static final int constructor = 0x36f8c871; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -30060,7 +30504,7 @@ public class TLRPC { } public static class TL_documentEncrypted extends Document { - public static int constructor = 0x55555558; + public static final int constructor = 0x55555558; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -30111,7 +30555,7 @@ public class TLRPC { } public static class TL_document_layer53 extends TL_document { - public static int constructor = 0xf9a39f4f; + public static final int constructor = 0xf9a39f4f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -30180,7 +30624,7 @@ public class TLRPC { } public static class TL_passwordKdfAlgoUnknown extends PasswordKdfAlgo { - public static int constructor = 0xd45ab096; + public static final int constructor = 0xd45ab096; public void serializeToStream(AbstractSerializedData stream) { @@ -30189,7 +30633,7 @@ public class TLRPC { } public static class TL_passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow extends PasswordKdfAlgo { - public static int constructor = 0x3a912d4a; + public static final int constructor = 0x3a912d4a; public byte[] salt1; public byte[] salt2; @@ -30353,7 +30797,7 @@ public class TLRPC { } public static class TL_pageBlockOrderedList extends PageBlock { - public static int constructor = 0x9a8ae1e1; + public static final int constructor = 0x9a8ae1e1; public ArrayList items = new ArrayList<>(); @@ -30387,7 +30831,7 @@ public class TLRPC { } public static class TL_pageBlockEmbedPost extends PageBlock { - public static int constructor = 0xf259a80b; + public static final int constructor = 0xf259a80b; public String url; public long webpage_id; @@ -30439,7 +30883,7 @@ public class TLRPC { } public static class TL_pageBlockParagraph extends PageBlock { - public static int constructor = 0x467a0766; + public static final int constructor = 0x467a0766; public RichText text; @@ -30454,7 +30898,7 @@ public class TLRPC { } public static class TL_pageBlockKicker extends PageBlock { - public static int constructor = 0x1e148390; + public static final int constructor = 0x1e148390; public RichText text; @@ -30469,7 +30913,7 @@ public class TLRPC { } public static class TL_pageBlockFooter extends PageBlock { - public static int constructor = 0x48870999; + public static final int constructor = 0x48870999; public RichText text; @@ -30484,7 +30928,7 @@ public class TLRPC { } public static class TL_pageBlockHeader extends PageBlock { - public static int constructor = 0xbfd064ec; + public static final int constructor = 0xbfd064ec; public RichText text; @@ -30499,7 +30943,7 @@ public class TLRPC { } public static class TL_pageBlockPreformatted extends PageBlock { - public static int constructor = 0xc070d93e; + public static final int constructor = 0xc070d93e; public RichText text; public String language; @@ -30517,7 +30961,7 @@ public class TLRPC { } public static class TL_pageBlockRelatedArticles extends PageBlock { - public static int constructor = 0x16115a96; + public static final int constructor = 0x16115a96; public RichText title; public ArrayList articles = new ArrayList<>(); @@ -30554,7 +30998,7 @@ public class TLRPC { } public static class TL_pageBlockSubheader extends PageBlock { - public static int constructor = 0xf12bb6e1; + public static final int constructor = 0xf12bb6e1; public RichText text; @@ -30569,7 +31013,7 @@ public class TLRPC { } public static class TL_pageBlockSlideshow extends PageBlock { - public static int constructor = 0x31f9590; + public static final int constructor = 0x31f9590; public ArrayList items = new ArrayList<>(); public TL_pageCaption caption; @@ -30606,7 +31050,7 @@ public class TLRPC { } public static class TL_pageBlockAnchor extends PageBlock { - public static int constructor = 0xce0d37b0; + public static final int constructor = 0xce0d37b0; public String name; @@ -30621,7 +31065,7 @@ public class TLRPC { } public static class TL_pageBlockMap extends PageBlock { - public static int constructor = 0xa44f3ef6; + public static final int constructor = 0xa44f3ef6; public GeoPoint geo; public int zoom; @@ -30648,7 +31092,7 @@ public class TLRPC { } public static class TL_pageBlockDivider extends PageBlock { - public static int constructor = 0xdb20b188; + public static final int constructor = 0xdb20b188; public void serializeToStream(AbstractSerializedData stream) { @@ -30657,7 +31101,7 @@ public class TLRPC { } public static class TL_pageBlockPhoto extends PageBlock { - public static int constructor = 0x1759c560; + public static final int constructor = 0x1759c560; public int flags; public long photo_id; @@ -30692,7 +31136,7 @@ public class TLRPC { } public static class TL_pageBlockList extends PageBlock { - public static int constructor = 0xe4e88011; + public static final int constructor = 0xe4e88011; public boolean ordered; public ArrayList items = new ArrayList<>(); @@ -30727,7 +31171,7 @@ public class TLRPC { } public static class TL_pageBlockUnsupported extends PageBlock { - public static int constructor = 0x13567e8a; + public static final int constructor = 0x13567e8a; public void serializeToStream(AbstractSerializedData stream) { @@ -30736,7 +31180,7 @@ public class TLRPC { } public static class TL_pageBlockCollage extends PageBlock { - public static int constructor = 0x65a0fa4d; + public static final int constructor = 0x65a0fa4d; public ArrayList items = new ArrayList<>(); public TL_pageCaption caption; @@ -30773,7 +31217,7 @@ public class TLRPC { } public static class TL_pageBlockEmbed extends PageBlock { - public static int constructor = 0xa8718dc5; + public static final int constructor = 0xa8718dc5; public int flags; public boolean full_width; @@ -30832,7 +31276,7 @@ public class TLRPC { } public static class TL_pageBlockSubtitle extends PageBlock { - public static int constructor = 0x8ffa9a1f; + public static final int constructor = 0x8ffa9a1f; public RichText text; @@ -30847,7 +31291,7 @@ public class TLRPC { } public static class TL_pageBlockBlockquote extends PageBlock { - public static int constructor = 0x263d7c26; + public static final int constructor = 0x263d7c26; public RichText text; public RichText caption; @@ -30865,7 +31309,7 @@ public class TLRPC { } public static class TL_pageBlockDetails extends PageBlock { - public static int constructor = 0x76768bed; + public static final int constructor = 0x76768bed; public int flags; public boolean open; @@ -30908,7 +31352,7 @@ public class TLRPC { } public static class TL_pageBlockChannel extends PageBlock { - public static int constructor = 0xef1751b5; + public static final int constructor = 0xef1751b5; public Chat channel; @@ -30923,7 +31367,7 @@ public class TLRPC { } public static class TL_pageBlockVideo extends PageBlock { - public static int constructor = 0x7c8fe7b6; + public static final int constructor = 0x7c8fe7b6; public int flags; public boolean autoplay; @@ -30950,7 +31394,7 @@ public class TLRPC { } public static class TL_pageBlockEmbed_layer60 extends TL_pageBlockEmbed { - public static int constructor = 0xd935d8fb; + public static final int constructor = 0xd935d8fb; public int flags; public boolean full_width; @@ -30994,7 +31438,7 @@ public class TLRPC { } public static class TL_pageBlockPullquote extends PageBlock { - public static int constructor = 0x4f4456d3; + public static final int constructor = 0x4f4456d3; public RichText text; public RichText caption; @@ -31012,7 +31456,7 @@ public class TLRPC { } public static class TL_pageBlockAudio extends PageBlock { - public static int constructor = 0x804361ea; + public static final int constructor = 0x804361ea; public long audio_id; public TL_pageCaption caption; @@ -31030,7 +31474,7 @@ public class TLRPC { } public static class TL_pageBlockTable extends PageBlock { - public static int constructor = 0xbf4dea82; + public static final int constructor = 0xbf4dea82; public int flags; public boolean bordered; @@ -31076,7 +31520,7 @@ public class TLRPC { } public static class TL_pageBlockTitle extends PageBlock { - public static int constructor = 0x70abc3fd; + public static final int constructor = 0x70abc3fd; public RichText text; @@ -31091,7 +31535,7 @@ public class TLRPC { } public static class TL_pageBlockCover extends PageBlock { - public static int constructor = 0x39f23300; + public static final int constructor = 0x39f23300; public PageBlock cover; @@ -31106,7 +31550,7 @@ public class TLRPC { } public static class TL_pageBlockAuthorDate extends PageBlock { - public static int constructor = 0xbaafe5e0; + public static final int constructor = 0xbaafe5e0; public RichText author; public int published_date; @@ -31167,7 +31611,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueDisallowAll extends InputPrivacyRule { - public static int constructor = 0xd66b66c9; + public static final int constructor = 0xd66b66c9; public void serializeToStream(AbstractSerializedData stream) { @@ -31176,7 +31620,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueDisallowUsers extends InputPrivacyRule { - public static int constructor = 0x90110467; + public static final int constructor = 0x90110467; public ArrayList users = new ArrayList<>(); @@ -31210,7 +31654,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueAllowContacts extends InputPrivacyRule { - public static int constructor = 0xd09e07b; + public static final int constructor = 0xd09e07b; public void serializeToStream(AbstractSerializedData stream) { @@ -31219,7 +31663,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueAllowChatParticipants extends InputPrivacyRule { - public static int constructor = 0x840649cf; + public static final int constructor = 0x840649cf; public ArrayList chats = new ArrayList<>(); @@ -31249,7 +31693,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueDisallowContacts extends InputPrivacyRule { - public static int constructor = 0xba52007; + public static final int constructor = 0xba52007; public void serializeToStream(AbstractSerializedData stream) { @@ -31258,7 +31702,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueAllowAll extends InputPrivacyRule { - public static int constructor = 0x184b35ce; + public static final int constructor = 0x184b35ce; public void serializeToStream(AbstractSerializedData stream) { @@ -31267,7 +31711,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueAllowUsers extends InputPrivacyRule { - public static int constructor = 0x131cc67f; + public static final int constructor = 0x131cc67f; public ArrayList users = new ArrayList<>(); @@ -31301,7 +31745,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueDisallowChatParticipants extends InputPrivacyRule { - public static int constructor = 0xe94f0f86; + public static final int constructor = 0xe94f0f86; public ArrayList chats = new ArrayList<>(); @@ -31331,7 +31775,7 @@ public class TLRPC { } public static class TL_inputPrivacyValueAllowCloseFriends extends InputPrivacyRule { - public static int constructor = 0x2f453e49; + public static final int constructor = 0x2f453e49; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -31339,7 +31783,7 @@ public class TLRPC { } public static class TL_maskCoords extends TLObject { - public static int constructor = 0xaed6dbb2; + public static final int constructor = 0xaed6dbb2; public int n; public double x; @@ -31376,7 +31820,7 @@ public class TLRPC { } public static class TL_messages_votesList extends TLObject { - public static int constructor = 0x4899484e; + public static final int constructor = 0x4899484e; public int flags; public int count; @@ -31480,7 +31924,7 @@ public class TLRPC { } public static class TL_highScore extends TLObject { - public static int constructor = 0x73a379eb; + public static final int constructor = 0x73a379eb; public int pos; public long user_id; @@ -31584,6 +32028,9 @@ public class TLRPC { case 0xb3ba0635: result = new TL_inputMediaPhoto(); break; + case 0xc21b8849: + result = new TL_inputMediaWebPage(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in InputMedia", constructor)); @@ -31596,7 +32043,7 @@ public class TLRPC { } public static class TL_inputMediaContact extends InputMedia { - public static int constructor = 0xf8ab7dfb; + public static final int constructor = 0xf8ab7dfb; public void readParams(AbstractSerializedData stream, boolean exception) { phone_number = stream.readString(exception); @@ -31615,7 +32062,7 @@ public class TLRPC { } public static class TL_inputMediaDocument extends InputMedia { - public static int constructor = 0x33473058; + public static final int constructor = 0x33473058; public InputDocument id; public String query; @@ -31647,7 +32094,7 @@ public class TLRPC { } public static class TL_inputMediaGame extends InputMedia { - public static int constructor = 0xd33f43f3; + public static final int constructor = 0xd33f43f3; public InputGame id; @@ -31662,7 +32109,7 @@ public class TLRPC { } public static class TL_inputMediaDice extends InputMedia { - public static int constructor = 0xe66fbf7b; + public static final int constructor = 0xe66fbf7b; public String emoticon; @@ -31677,7 +32124,7 @@ public class TLRPC { } public static class TL_inputMediaGeoPoint extends InputMedia { - public static int constructor = 0xf9c44144; + public static final int constructor = 0xf9c44144; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31691,7 +32138,7 @@ public class TLRPC { } public static class TL_inputMediaDocumentExternal extends InputMedia { - public static int constructor = 0xfb52dc99; + public static final int constructor = 0xfb52dc99; public String url; @@ -31716,7 +32163,7 @@ public class TLRPC { } public static class TL_inputMediaEmpty extends InputMedia { - public static int constructor = 0x9664f57f; + public static final int constructor = 0x9664f57f; public void serializeToStream(AbstractSerializedData stream) { @@ -31725,7 +32172,7 @@ public class TLRPC { } public static class TL_inputMediaPoll extends InputMedia { - public static int constructor = 0xf94e5f1; + public static final int constructor = 0xf94e5f1; public Poll poll; public ArrayList correct_answers = new ArrayList<>(); @@ -31797,7 +32244,7 @@ public class TLRPC { } public static class TL_inputMediaUploadedPhoto extends InputMedia { - public static int constructor = 0x1e287d04; + public static final int constructor = 0x1e287d04; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31846,7 +32293,7 @@ public class TLRPC { } public static class TL_inputMediaVenue extends InputMedia { - public static int constructor = 0xc13d1c11; + public static final int constructor = 0xc13d1c11; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31870,7 +32317,7 @@ public class TLRPC { } public static class TL_inputMediaGeoLive extends InputMedia { - public static int constructor = 0x971fa843; + public static final int constructor = 0x971fa843; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31906,7 +32353,7 @@ public class TLRPC { } public static class TL_inputMediaUploadedDocument extends InputMedia { - public static int constructor = 0x5b38c6c1; + public static final int constructor = 0x5b38c6c1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -31988,7 +32435,7 @@ public class TLRPC { } public static class TL_inputMediaPhotoExternal extends InputMedia { - public static int constructor = 0xe5bbfe1a; + public static final int constructor = 0xe5bbfe1a; public String url; @@ -32012,8 +32459,34 @@ public class TLRPC { } } + public static class TL_inputMediaWebPage extends InputMedia { + public static final int constructor = 0xc21b8849; + + public String url; + public boolean force_large_media; + public boolean force_small_media; + public boolean optional; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + force_large_media = (flags & 1) != 0; + force_small_media = (flags & 2) != 0; + optional = (flags & 4) != 0; + url = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = force_large_media ? (flags | 1) : (flags &~ 1); + flags = force_small_media ? (flags | 2) : (flags &~ 2); + flags = optional ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeString(url); + } + } + public static class TL_inputMediaPhoto extends InputMedia { - public static int constructor = 0xb3ba0635; + public static final int constructor = 0xb3ba0635; public InputPhoto id; @@ -32072,7 +32545,7 @@ public class TLRPC { } public static class TL_stickerSetMultiCovered extends StickerSetCovered { - public static int constructor = 0x3407e51b; + public static final int constructor = 0x3407e51b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32107,7 +32580,7 @@ public class TLRPC { } public static class TL_stickerKeyword extends TLObject { - public static int constructor = 0xfcfeb29c; + public static final int constructor = 0xfcfeb29c; public long document_id; public ArrayList keyword = new ArrayList<>(); @@ -32153,7 +32626,7 @@ public class TLRPC { } public static class TL_stickerSetFullCovered_layer146 extends TL_stickerSetFullCovered { - public static int constructor = 0x1aed5ee5; + public static final int constructor = 0x1aed5ee5; public void readParams(AbstractSerializedData stream, boolean exception) { set = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -32208,7 +32681,7 @@ public class TLRPC { } public static class TL_stickerSetNoCovered extends StickerSetCovered { - public static int constructor = 0x77b15d1c; + public static final int constructor = 0x77b15d1c; public void readParams(AbstractSerializedData stream, boolean exception) { set = StickerSet.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -32221,7 +32694,7 @@ public class TLRPC { } public static class TL_stickerSetFullCovered extends StickerSetCovered { - public static int constructor = 0x40d13c0e; + public static final int constructor = 0x40d13c0e; public ArrayList packs = new ArrayList<>(); public ArrayList keywords = new ArrayList<>(); @@ -32301,7 +32774,7 @@ public class TLRPC { } public static class TL_stickerSetCovered extends StickerSetCovered { - public static int constructor = 0x6410a5d2; + public static final int constructor = 0x6410a5d2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32344,7 +32817,7 @@ public class TLRPC { } public static class TL_encryptedMessageService extends EncryptedMessage { - public static int constructor = 0x23734b06; + public static final int constructor = 0x23734b06; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32364,7 +32837,7 @@ public class TLRPC { } public static class TL_encryptedMessage extends EncryptedMessage { - public static int constructor = 0xed18c118; + public static final int constructor = 0xed18c118; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32433,7 +32906,7 @@ public class TLRPC { } public static class TL_inputStickerSetPremiumGifts extends InputStickerSet { - public static int constructor = 0xc88b3b02; + public static final int constructor = 0xc88b3b02; public void serializeToStream(AbstractSerializedData stream) { @@ -32442,7 +32915,7 @@ public class TLRPC { } public static class TL_inputStickerSetEmojiDefaultStatuses extends InputStickerSet { - public static int constructor = 0x29d0f5ee; + public static final int constructor = 0x29d0f5ee; public void serializeToStream(AbstractSerializedData stream) { @@ -32451,7 +32924,7 @@ public class TLRPC { } public static class TL_inputStickerSetDice extends InputStickerSet { - public static int constructor = 0xe67f520e; + public static final int constructor = 0xe67f520e; public String emoticon; @@ -32466,7 +32939,7 @@ public class TLRPC { } public static class TL_inputStickerSetEmpty extends InputStickerSet { - public static int constructor = 0xffb62b95; + public static final int constructor = 0xffb62b95; public void serializeToStream(AbstractSerializedData stream) { @@ -32475,7 +32948,7 @@ public class TLRPC { } public static class TL_inputStickerSetID extends InputStickerSet { - public static int constructor = 0x9de7a269; + public static final int constructor = 0x9de7a269; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32491,7 +32964,7 @@ public class TLRPC { } public static class TL_inputStickerSetShortName extends InputStickerSet { - public static int constructor = 0x861cc8a0; + public static final int constructor = 0x861cc8a0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32505,7 +32978,7 @@ public class TLRPC { } public static class TL_inputStickerSetAnimatedEmoji extends InputStickerSet { - public static int constructor = 0x28703c8; + public static final int constructor = 0x28703c8; public void serializeToStream(AbstractSerializedData stream) { @@ -32514,7 +32987,7 @@ public class TLRPC { } public static class TL_inputStickerSetEmojiGenericAnimations extends InputStickerSet { - public static int constructor = 0x4c4d4ce; + public static final int constructor = 0x4c4d4ce; public void serializeToStream(AbstractSerializedData stream) { @@ -32523,7 +32996,7 @@ public class TLRPC { } public static class TL_inputStickerSetEmojiDefaultTopicIcons extends InputStickerSet { - public static int constructor = 0x44c1f8e9; + public static final int constructor = 0x44c1f8e9; public void serializeToStream(AbstractSerializedData stream) { @@ -32532,7 +33005,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventsFilter extends TLObject { - public static int constructor = 0xea107ae4; + public static final int constructor = 0xea107ae4; public int flags; public boolean join; @@ -32643,7 +33116,7 @@ public class TLRPC { } public static class TL_userStatusOffline extends UserStatus { - public static int constructor = 0x8c703f; + public static final int constructor = 0x8c703f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32657,7 +33130,7 @@ public class TLRPC { } public static class TL_userStatusLastWeek extends UserStatus { - public static int constructor = 0x7bf09fc; + public static final int constructor = 0x7bf09fc; public void serializeToStream(AbstractSerializedData stream) { @@ -32666,7 +33139,7 @@ public class TLRPC { } public static class TL_userStatusEmpty extends UserStatus { - public static int constructor = 0x9d05049; + public static final int constructor = 0x9d05049; public void serializeToStream(AbstractSerializedData stream) { @@ -32675,7 +33148,7 @@ public class TLRPC { } public static class TL_userStatusLastMonth extends UserStatus { - public static int constructor = 0x77ebc742; + public static final int constructor = 0x77ebc742; public void serializeToStream(AbstractSerializedData stream) { @@ -32684,7 +33157,7 @@ public class TLRPC { } public static class TL_userStatusOnline extends UserStatus { - public static int constructor = 0xedb93949; + public static final int constructor = 0xedb93949; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32698,7 +33171,7 @@ public class TLRPC { } public static class TL_userStatusRecently extends UserStatus { - public static int constructor = 0xe26f42f1; + public static final int constructor = 0xe26f42f1; public void serializeToStream(AbstractSerializedData stream) { @@ -32707,7 +33180,7 @@ public class TLRPC { } public static class TL_messages_peerSettings extends TLObject { - public static int constructor = 0x6880b94d; + public static final int constructor = 0x6880b94d; public TL_peerSettings settings; public ArrayList chats = new ArrayList<>(); @@ -32779,7 +33252,7 @@ public class TLRPC { } public static class TL_messages_checkedHistoryImportPeer extends TLObject { - public static int constructor = 0xa24de717; + public static final int constructor = 0xa24de717; public String confirm_text; @@ -32807,7 +33280,7 @@ public class TLRPC { } public static class TL_messages_messageEditData extends TLObject { - public static int constructor = 0x26b5dde6; + public static final int constructor = 0x26b5dde6; public int flags; public boolean caption; @@ -32866,7 +33339,7 @@ public class TLRPC { } public static class TL_messagePeerVoteMultiple extends MessagePeerVote { - public static int constructor = 0x4628f6e6; + public static final int constructor = 0x4628f6e6; public ArrayList options = new ArrayList<>(); @@ -32900,7 +33373,7 @@ public class TLRPC { } public static class TL_messagePeerVote extends MessagePeerVote { - public static int constructor = 0xb6cc2d5c; + public static final int constructor = 0xb6cc2d5c; public byte[] option; @@ -32919,7 +33392,7 @@ public class TLRPC { } public static class TL_messagePeerVoteInputOption extends MessagePeerVote { - public static int constructor = 0x74cda504; + public static final int constructor = 0x74cda504; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -32934,99 +33407,8 @@ public class TLRPC { } } - public static class TL_chatlists_chatlistUpdates extends TLObject { - public static int constructor = 0x93bd878d; - - public ArrayList missing_peers = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_chatlists_chatlistUpdates TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_chatlists_chatlistUpdates.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_chatlistUpdates", constructor)); - } else { - return null; - } - } - TL_chatlists_chatlistUpdates result = new TL_chatlists_chatlistUpdates(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Peer object = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - missing_peers.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = missing_peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - missing_peers.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - public static class TL_contacts_importedContacts extends TLObject { - public static int constructor = 0x77d01c3b; + public static final int constructor = 0x77d01c3b; public ArrayList imported = new ArrayList<>(); public ArrayList popular_invites = new ArrayList<>(); @@ -33135,7 +33517,7 @@ public class TLRPC { } public static class TL_dialogFilterSuggested extends TLObject { - public static int constructor = 0x77744d4a; + public static final int constructor = 0x77744d4a; public DialogFilter filter; public String description; @@ -33166,7 +33548,7 @@ public class TLRPC { } public static class TL_inlineBotSwitchPM extends TLObject { - public static int constructor = 0x3c20629f; + public static final int constructor = 0x3c20629f; public String text; public String start_param; @@ -33349,7 +33731,7 @@ public class TLRPC { result = new TL_updateUserTyping(); break; case 0xf74e932b: - result = new TL_updateReadStories(); + result = new TL_stories.TL_updateReadStories(); break; case 0xebe46819: result = new TL_updateServiceNotification(); @@ -33412,7 +33794,7 @@ public class TLRPC { result = new TL_updateSavedRingtones(); break; case 0x2c084dc1: - result = new TL_updateStoriesStealthMode(); + result = new TL_stories.TL_updateStoriesStealthMode(); break; case 0x84cd5a: result = new TL_updateTranscribedAudio(); @@ -33472,7 +33854,7 @@ public class TLRPC { result = new TL_updateRecentEmojiStatuses(); break; case 0x75b3b798: - result = new TL_updateStory(); + result = new TL_stories.TL_updateStory(); break; case 0x7063c3db: result = new TL_updatePendingJoinRequests(); @@ -33531,7 +33913,7 @@ public class TLRPC { } public static class TL_updateMessagePollVote extends Update { - public static int constructor = 0x24f40e77; + public static final int constructor = 0x24f40e77; public long poll_id; public Peer peer; @@ -33570,7 +33952,7 @@ public class TLRPC { } public static class TL_updateMoveStickerSetToTop extends Update { - public static int constructor = 0x86fccf85; + public static final int constructor = 0x86fccf85; public int flags; public boolean masks; @@ -33594,7 +33976,7 @@ public class TLRPC { } public static class TL_updateMessageExtendedMedia extends Update { - public static int constructor = 0x5a73a98c; + public static final int constructor = 0x5a73a98c; public Peer peer; public int msg_id; @@ -33615,7 +33997,7 @@ public class TLRPC { } public static class TL_updateMessagePoll extends Update { - public static int constructor = 0xaca1657b; + public static final int constructor = 0xaca1657b; public int flags; public long poll_id; @@ -33643,7 +34025,7 @@ public class TLRPC { } public static class TL_updatePeerHistoryTTL extends Update { - public static int constructor = 0xbb9bb9a5; + public static final int constructor = 0xbb9bb9a5; public int flags; public Peer peer; @@ -33668,7 +34050,7 @@ public class TLRPC { } public static class TL_updateChat extends Update { - public static int constructor = 0xf89a6a4e; + public static final int constructor = 0xf89a6a4e; public long chat_id; @@ -33683,7 +34065,7 @@ public class TLRPC { } public static class TL_updateDeleteMessages extends Update { - public static int constructor = 0xa20db0e5; + public static final int constructor = 0xa20db0e5; public ArrayList messages = new ArrayList<>(); public int pts; @@ -33719,7 +34101,7 @@ public class TLRPC { } public static class TL_updatePinnedChannelMessages extends Update { - public static int constructor = 0x5bb98608; + public static final int constructor = 0x5bb98608; public int flags; public boolean pinned; @@ -33764,7 +34146,7 @@ public class TLRPC { } public static class TL_updateGroupCallParticipants extends Update { - public static int constructor = 0xf2ebdb4e; + public static final int constructor = 0xf2ebdb4e; public TL_inputGroupCall call; public ArrayList participants = new ArrayList<>(); @@ -33804,7 +34186,7 @@ public class TLRPC { } public static class TL_updateReadFeaturedStickers extends Update { - public static int constructor = 0x571d2742; + public static final int constructor = 0x571d2742; public void serializeToStream(AbstractSerializedData stream) { @@ -33813,7 +34195,7 @@ public class TLRPC { } public static class TL_updateEncryptedChatTyping extends Update { - public static int constructor = 0x1710f156; + public static final int constructor = 0x1710f156; public int chat_id; @@ -33828,7 +34210,7 @@ public class TLRPC { } public static class TL_updateReadChannelDiscussionInbox extends Update { - public static int constructor = 0xd6b19546; + public static final int constructor = 0xd6b19546; public int flags; public long channel_id; @@ -33866,7 +34248,7 @@ public class TLRPC { } public static class TL_updateReadHistoryOutbox extends Update { - public static int constructor = 0x2f2f21bf; + public static final int constructor = 0x2f2f21bf; public Peer peer; public int max_id; @@ -33890,7 +34272,7 @@ public class TLRPC { } public static class TL_updateNewChannelMessage extends Update { - public static int constructor = 0x62ba04d9; + public static final int constructor = 0x62ba04d9; public Message message; public int pts; @@ -33911,7 +34293,7 @@ public class TLRPC { } public static class TL_updateDialogPinned extends Update { - public static int constructor = 0x6e6fe51c; + public static final int constructor = 0x6e6fe51c; public int flags; public boolean pinned; @@ -33939,7 +34321,7 @@ public class TLRPC { } public static class TL_updatePeerSettings extends Update { - public static int constructor = 0x6a7e7366; + public static final int constructor = 0x6a7e7366; public Peer peer; public TL_peerSettings settings; @@ -33957,7 +34339,7 @@ public class TLRPC { } public static class TL_updateUserPhone extends Update { - public static int constructor = 0x5492a13; + public static final int constructor = 0x5492a13; public long user_id; public String phone; @@ -33975,7 +34357,7 @@ public class TLRPC { } public static class TL_updateMessageID extends Update { - public static int constructor = 0x4e90bfd6; + public static final int constructor = 0x4e90bfd6; public int id; public long random_id; @@ -33993,7 +34375,7 @@ public class TLRPC { } public static class TL_updateReadChannelOutbox extends Update { - public static int constructor = 0xb75f99a9; + public static final int constructor = 0xb75f99a9; public long channel_id; public int max_id; @@ -34011,7 +34393,7 @@ public class TLRPC { } public static class TL_updateChannelUserTyping extends Update { - public static int constructor = 0x8c88c923; + public static final int constructor = 0x8c88c923; public int flags; public long channel_id; @@ -34042,7 +34424,7 @@ public class TLRPC { } public static class TL_updateStoryID extends Update { - public static int constructor = 0x1bf335b9; + public static final int constructor = 0x1bf335b9; public int id; public long random_id; @@ -34060,7 +34442,7 @@ public class TLRPC { } public static class TL_updateStickerSets extends Update { - public static int constructor = 0x31c24808; + public static final int constructor = 0x31c24808; public int flags; public boolean masks; @@ -34081,7 +34463,7 @@ public class TLRPC { } public static class TL_updateFolderPeers extends Update { - public static int constructor = 0x19360dc0; + public static final int constructor = 0x19360dc0; public ArrayList folder_peers = new ArrayList<>(); public int pts; @@ -34121,7 +34503,7 @@ public class TLRPC { } public static class TL_updateNewMessage extends Update { - public static int constructor = 0x1f2b0afd; + public static final int constructor = 0x1f2b0afd; public Message message; public int pts; @@ -34142,7 +34524,7 @@ public class TLRPC { } public static class TL_updateNewScheduledMessage extends Update { - public static int constructor = 0x39a51dfb; + public static final int constructor = 0x39a51dfb; public Message message; @@ -34157,7 +34539,7 @@ public class TLRPC { } public static class TL_updateNewEncryptedMessage extends Update { - public static int constructor = 0x12bcbd9a; + public static final int constructor = 0x12bcbd9a; public EncryptedMessage message; public int qts; @@ -34175,7 +34557,7 @@ public class TLRPC { } public static class TL_updateUserStatus extends Update { - public static int constructor = 0xe5bdf8de; + public static final int constructor = 0xe5bdf8de; public long user_id; public UserStatus status; @@ -34193,7 +34575,7 @@ public class TLRPC { } public static class TL_updateChannelMessageViews extends Update { - public static int constructor = 0xf226ac08; + public static final int constructor = 0xf226ac08; public long channel_id; public int id; @@ -34214,7 +34596,7 @@ public class TLRPC { } public static class TL_updateGroupCallConnection extends Update { - public static int constructor = 0xb783982; + public static final int constructor = 0xb783982; public int flags; public boolean presentation; @@ -34235,7 +34617,7 @@ public class TLRPC { } public static class TL_updateBotCommands extends Update { - public static int constructor = 0x4d712f2e; + public static final int constructor = 0x4d712f2e; public Peer peer; public long bot_id; @@ -34275,7 +34657,7 @@ public class TLRPC { } public static class TL_updateGeoLiveViewed extends Update { - public static int constructor = 0x871fb939; + public static final int constructor = 0x871fb939; public Peer peer; public int msg_id; @@ -34293,7 +34675,7 @@ public class TLRPC { } public static class TL_updateNotifySettings extends Update { - public static int constructor = 0xbec268ef; + public static final int constructor = 0xbec268ef; public NotifyPeer peer; public PeerNotifySettings notify_settings; @@ -34311,7 +34693,7 @@ public class TLRPC { } public static class TL_updateChannelParticipant extends Update { - public static int constructor = 0x985d3abb; + public static final int constructor = 0x985d3abb; public int flags; public long channel_id; @@ -34365,7 +34747,7 @@ public class TLRPC { } public static class TL_updateReadChannelDiscussionOutbox extends Update { - public static int constructor = 0x695c9e7c; + public static final int constructor = 0x695c9e7c; public long channel_id; public int top_msg_id; @@ -34386,7 +34768,7 @@ public class TLRPC { } public static class TL_updateChatParticipantDelete extends Update { - public static int constructor = 0xe32f3d77; + public static final int constructor = 0xe32f3d77; public long chat_id; public long user_id; @@ -34407,7 +34789,7 @@ public class TLRPC { } public static class TL_updateEditMessage extends Update { - public static int constructor = 0xe40370a3; + public static final int constructor = 0xe40370a3; public Message message; public int pts; @@ -34428,7 +34810,7 @@ public class TLRPC { } public static class TL_updateRecentReactions extends Update { - public static int constructor = 0x6f7863f4; + public static final int constructor = 0x6f7863f4; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -34436,7 +34818,7 @@ public class TLRPC { } public static class TL_updateWebPage extends Update { - public static int constructor = 0x7f891213; + public static final int constructor = 0x7f891213; public WebPage webpage; public int pts; @@ -34457,7 +34839,7 @@ public class TLRPC { } public static class TL_updateFavedStickers extends Update { - public static int constructor = 0xe511996d; + public static final int constructor = 0xe511996d; public void serializeToStream(AbstractSerializedData stream) { @@ -34466,7 +34848,7 @@ public class TLRPC { } public static class TL_updateChatParticipantAdd extends Update { - public static int constructor = 0x3dda5451; + public static final int constructor = 0x3dda5451; public long chat_id; public long user_id; @@ -34493,7 +34875,7 @@ public class TLRPC { } public static class TL_updateChatUserTyping extends Update { - public static int constructor = 0x83487af0; + public static final int constructor = 0x83487af0; public long chat_id; public Peer from_id; @@ -34514,7 +34896,7 @@ public class TLRPC { } public static class TL_updateLoginToken extends Update { - public static int constructor = 0x564fe691; + public static final int constructor = 0x564fe691; public void serializeToStream(AbstractSerializedData stream) { @@ -34523,7 +34905,7 @@ public class TLRPC { } public static class TL_updateEncryption extends Update { - public static int constructor = 0xb4a2e88d; + public static final int constructor = 0xb4a2e88d; public EncryptedChat chat; public int date; @@ -34541,7 +34923,7 @@ public class TLRPC { } public static class TL_updateGroupCall extends Update { - public static int constructor = 0x14b24500; + public static final int constructor = 0x14b24500; public long chat_id; public GroupCall call; @@ -34559,7 +34941,7 @@ public class TLRPC { } public static class TL_updateChannelTooLong extends Update { - public static int constructor = 0x108d941f; + public static final int constructor = 0x108d941f; public int flags; public long channel_id; @@ -34584,7 +34966,7 @@ public class TLRPC { } public static class TL_updateUserTyping extends Update { - public static int constructor = 0xc01e857f; + public static final int constructor = 0xc01e857f; public long user_id; public SendMessageAction action; @@ -34602,7 +34984,7 @@ public class TLRPC { } public static class TL_updateServiceNotification extends Update { - public static int constructor = 0xebe46819; + public static final int constructor = 0xebe46819; public int flags; public boolean popup; @@ -34611,6 +34993,7 @@ public class TLRPC { public String message; public MessageMedia media; public ArrayList entities = new ArrayList<>(); + public boolean invert_media; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -34618,6 +35001,7 @@ public class TLRPC { if ((flags & 2) != 0) { inbox_date = stream.readInt32(exception); } + invert_media = (flags & 4) != 0; type = stream.readString(exception); message = stream.readString(exception); media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -34641,6 +35025,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = popup ? (flags | 1) : (flags &~ 1); + flags = invert_media ? (flags | 4) : (flags &~ 4); stream.writeInt32(flags); if ((flags & 2) != 0) { stream.writeInt32(inbox_date); @@ -34658,7 +35043,7 @@ public class TLRPC { } public static class TL_updateSavedRingtones extends Update { - public static int constructor = 0x74d8be99; + public static final int constructor = 0x74d8be99; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -34666,7 +35051,7 @@ public class TLRPC { } public static class TL_updateTranscribedAudio extends Update { - public static int constructor = 0x84cd5a; + public static final int constructor = 0x84cd5a; public int flags; public boolean pending; @@ -34696,7 +35081,7 @@ public class TLRPC { } public static class TL_updateUserEmojiStatus extends Update { - public static int constructor = 0x28373599; + public static final int constructor = 0x28373599; public long user_id; public EmojiStatus emoji_status; @@ -34714,7 +35099,7 @@ public class TLRPC { } public static class TL_updateLangPack extends Update { - public static int constructor = 0x56022f4d; + public static final int constructor = 0x56022f4d; public TL_langPackDifference difference; @@ -34729,7 +35114,7 @@ public class TLRPC { } public static class TL_updateChannelAvailableMessages extends Update { - public static int constructor = 0xb23fc698; + public static final int constructor = 0xb23fc698; public long channel_id; public int available_min_id; @@ -34747,7 +35132,7 @@ public class TLRPC { } public static class TL_updateChatParticipantAdmin extends Update { - public static int constructor = 0xd7ca61a2; + public static final int constructor = 0xd7ca61a2; public long chat_id; public long user_id; @@ -34771,7 +35156,7 @@ public class TLRPC { } public static class TL_updateChannelReadMessagesContents extends Update { - public static int constructor = 0xea29055d; + public static final int constructor = 0xea29055d; public int flags; public long channel_id; @@ -34814,7 +35199,7 @@ public class TLRPC { } public static class TL_updatePrivacy extends Update { - public static int constructor = 0xee3b272a; + public static final int constructor = 0xee3b272a; public PrivacyKey key; public ArrayList rules = new ArrayList<>(); @@ -34851,7 +35236,7 @@ public class TLRPC { } public static class TL_updateConfig extends Update { - public static int constructor = 0xa229dd06; + public static final int constructor = 0xa229dd06; public void serializeToStream(AbstractSerializedData stream) { @@ -34860,7 +35245,7 @@ public class TLRPC { } public static class TL_updateDialogUnreadMark extends Update { - public static int constructor = 0xe16459c3; + public static final int constructor = 0xe16459c3; public int flags; public boolean unread; @@ -34881,7 +35266,7 @@ public class TLRPC { } public static class TL_updateDraftMessage extends Update { - public static int constructor = 0x1b49ec6d; + public static final int constructor = 0x1b49ec6d; public int flags; public Peer peer; @@ -34909,7 +35294,7 @@ public class TLRPC { } public static class TL_updateNewAuthorization extends Update { - public static int constructor = 0x8951abef; + public static final int constructor = 0x8951abef; public int flags; public boolean unconfirmed; @@ -34931,7 +35316,7 @@ public class TLRPC { } public static class TL_updateUserName extends Update { - public static int constructor = 0xa7848924; + public static final int constructor = 0xa7848924; public long user_id; public String first_name; @@ -34974,7 +35359,7 @@ public class TLRPC { } public static class TL_updateMessageReactions extends Update { - public static int constructor = 0x5e1b3cb8; + public static final int constructor = 0x5e1b3cb8; public int flags; public Peer peer; @@ -35006,7 +35391,7 @@ public class TLRPC { } public static class TL_updatePhoneCall extends Update { - public static int constructor = 0xab0f6b1e; + public static final int constructor = 0xab0f6b1e; public PhoneCall phone_call; @@ -35021,7 +35406,7 @@ public class TLRPC { } public static class TL_updateDialogFilter extends Update { - public static int constructor = 0x26ffde7d; + public static final int constructor = 0x26ffde7d; public int flags; public int id; @@ -35046,7 +35431,7 @@ public class TLRPC { } public static class TL_updatePeerBlocked extends Update { - public static int constructor = 0xebe07752; + public static final int constructor = 0xebe07752; public int flags; public boolean blocked; @@ -35070,7 +35455,7 @@ public class TLRPC { } public static class TL_updatePinnedMessages extends Update { - public static int constructor = 0xed85eab5; + public static final int constructor = 0xed85eab5; public int flags; public boolean pinned; @@ -35115,7 +35500,7 @@ public class TLRPC { } public static class TL_updatePhoneCallSignalingData extends Update { - public static int constructor = 0x2661bf09; + public static final int constructor = 0x2661bf09; public long phone_call_id; public byte[] data; @@ -35133,7 +35518,7 @@ public class TLRPC { } public static class TL_updateTranscribeAudio extends Update { - public static int constructor = 0x88617090; + public static final int constructor = 0x88617090; public int flags; public boolean isFinal; @@ -35157,7 +35542,7 @@ public class TLRPC { } public static class TL_updatePinnedDialogs extends Update { - public static int constructor = 0xfa0f3ca2; + public static final int constructor = 0xfa0f3ca2; public int flags; public int folder_id; @@ -35205,7 +35590,7 @@ public class TLRPC { } public static class TL_updatePeerLocated extends Update { - public static int constructor = 0xb4afcfb0; + public static final int constructor = 0xb4afcfb0; public ArrayList peers = new ArrayList<>(); @@ -35239,7 +35624,7 @@ public class TLRPC { } public static class TL_updateRecentStickers extends Update { - public static int constructor = 0x9a422c20; + public static final int constructor = 0x9a422c20; public void serializeToStream(AbstractSerializedData stream) { @@ -35248,7 +35633,7 @@ public class TLRPC { } public static class TL_updateReadHistoryInbox extends Update { - public static int constructor = 0x9c974fdf; + public static final int constructor = 0x9c974fdf; public int flags; public int folder_id; @@ -35285,7 +35670,7 @@ public class TLRPC { } public static class TL_updateDialogFilterOrder extends Update { - public static int constructor = 0xa5d72105; + public static final int constructor = 0xa5d72105; public ArrayList order = new ArrayList<>(); @@ -35315,7 +35700,7 @@ public class TLRPC { } public static class TL_updateSavedGifs extends Update { - public static int constructor = 0x9375341e; + public static final int constructor = 0x9375341e; public void serializeToStream(AbstractSerializedData stream) { @@ -35324,7 +35709,7 @@ public class TLRPC { } public static class TL_updateContactsReset extends Update { - public static int constructor = 0x7084a7be; + public static final int constructor = 0x7084a7be; public void serializeToStream(AbstractSerializedData stream) { @@ -35333,7 +35718,7 @@ public class TLRPC { } public static class TL_updateChannel extends Update { - public static int constructor = 0x635b4c09; + public static final int constructor = 0x635b4c09; public long channel_id; @@ -35348,7 +35733,7 @@ public class TLRPC { } public static class TL_updateChannelWebPage extends Update { - public static int constructor = 0x2f2ba99f; + public static final int constructor = 0x2f2ba99f; public long channel_id; public WebPage webpage; @@ -35372,7 +35757,7 @@ public class TLRPC { } public static class TL_updateDeleteScheduledMessages extends Update { - public static int constructor = 0x90866cee; + public static final int constructor = 0x90866cee; public Peer peer; public ArrayList messages = new ArrayList<>(); @@ -35405,7 +35790,7 @@ public class TLRPC { } public static class TL_updateSentStoryReaction extends Update { - public static int constructor = 0x7d627683; + public static final int constructor = 0x7d627683; public Peer peer; public int story_id; @@ -35426,7 +35811,7 @@ public class TLRPC { } public static class TL_updateChannelMessageForwards extends Update { - public static int constructor = 0xd29a27f4; + public static final int constructor = 0xd29a27f4; public long channel_id; public int id; @@ -35447,7 +35832,7 @@ public class TLRPC { } public static class TL_updateDeleteChannelMessages extends Update { - public static int constructor = 0xc32d5b12; + public static final int constructor = 0xc32d5b12; public long channel_id; public ArrayList messages = new ArrayList<>(); @@ -35486,7 +35871,7 @@ public class TLRPC { } public static class TL_updateUserPhoto extends Update { - public static int constructor = 0xf227868c; + public static final int constructor = 0xf227868c; public long user_id; public int date; @@ -35510,7 +35895,7 @@ public class TLRPC { } public static class TL_updateUser extends Update { - public static int constructor = 0x20529438; + public static final int constructor = 0x20529438; public long user_id; @@ -35525,7 +35910,7 @@ public class TLRPC { } public static class TL_updateDialogFilters extends Update { - public static int constructor = 0x3504914f; + public static final int constructor = 0x3504914f; public void serializeToStream(AbstractSerializedData stream) { @@ -35534,7 +35919,7 @@ public class TLRPC { } public static class TL_updateRecentEmojiStatuses extends Update { - public static int constructor = 0x30f443db; + public static final int constructor = 0x30f443db; public void serializeToStream(AbstractSerializedData stream) { @@ -35543,7 +35928,7 @@ public class TLRPC { } public static class TL_updatePendingJoinRequests extends Update { - public static int constructor = 0x7063c3db; + public static final int constructor = 0x7063c3db; public Peer peer; public int requests_pending; @@ -35579,7 +35964,7 @@ public class TLRPC { } public static class TL_updateDcOptions extends Update { - public static int constructor = 0x8e5e9873; + public static final int constructor = 0x8e5e9873; public ArrayList dc_options = new ArrayList<>(); @@ -35613,7 +35998,7 @@ public class TLRPC { } public static class TL_updateEditChannelMessage extends Update { - public static int constructor = 0x1b3f4df7; + public static final int constructor = 0x1b3f4df7; public Message message; public int pts; @@ -35634,7 +36019,7 @@ public class TLRPC { } public static class TL_updateNewStickerSet extends Update { - public static int constructor = 0x688a30aa; + public static final int constructor = 0x688a30aa; public TL_messages_stickerSet stickerset; @@ -35649,7 +36034,7 @@ public class TLRPC { } public static class TL_updateTheme extends Update { - public static int constructor = 0x8216fba3; + public static final int constructor = 0x8216fba3; public Theme theme; @@ -35664,7 +36049,7 @@ public class TLRPC { } public static class TL_updateLangPackTooLong extends Update { - public static int constructor = 0x46560264; + public static final int constructor = 0x46560264; public String lang_code; @@ -35679,7 +36064,7 @@ public class TLRPC { } public static class TL_updateEncryptedMessagesRead extends Update { - public static int constructor = 0x38fe25b7; + public static final int constructor = 0x38fe25b7; public int chat_id; public int max_date; @@ -35700,7 +36085,7 @@ public class TLRPC { } public static class TL_updateStickerSetsOrder extends Update { - public static int constructor = 0xbb2d201; + public static final int constructor = 0xbb2d201; public int flags; public boolean masks; @@ -35739,7 +36124,7 @@ public class TLRPC { } public static class TL_updateReadFeaturedEmojiStickers extends Update { - public static int constructor = 0xfb4c496c; + public static final int constructor = 0xfb4c496c; public void serializeToStream(AbstractSerializedData stream) { @@ -35748,7 +36133,7 @@ public class TLRPC { } public static class TL_updateReadChannelInbox extends Update { - public static int constructor = 0x922e6e10; + public static final int constructor = 0x922e6e10; public int flags; public int folder_id; @@ -35782,7 +36167,7 @@ public class TLRPC { } public static class TL_updateReadMessagesContents extends Update { - public static int constructor = 0xf8227181; + public static final int constructor = 0xf8227181; public int flags; public ArrayList messages = new ArrayList<>(); @@ -35827,7 +36212,7 @@ public class TLRPC { } public static class TL_updateChatParticipants extends Update { - public static int constructor = 0x7761198; + public static final int constructor = 0x7761198; public ChatParticipants participants; @@ -35842,7 +36227,7 @@ public class TLRPC { } public static class TL_updateChatDefaultBannedRights extends Update { - public static int constructor = 0x54c01850; + public static final int constructor = 0x54c01850; public Peer peer; public TL_chatBannedRights default_banned_rights; @@ -35863,7 +36248,7 @@ public class TLRPC { } public static class TL_updateChannelPinnedTopics extends Update { - public static int constructor = 0xfe198602; + public static final int constructor = 0xfe198602; public int flags; public long channel_id; @@ -35903,7 +36288,7 @@ public class TLRPC { } public static class TL_updateChannelPinnedTopic extends Update { - public static int constructor = 0x192efbe3; + public static final int constructor = 0x192efbe3; public int flags; public boolean pinned; @@ -35927,7 +36312,7 @@ public class TLRPC { } public static class TL_receivedNotifyMessage extends TLObject { - public static int constructor = 0xa384b779; + public static final int constructor = 0xa384b779; public int id; public int flags; @@ -35991,7 +36376,7 @@ public class TLRPC { } public static class TL_inputEncryptedFile extends InputEncryptedFile { - public static int constructor = 0x5a17b5e5; + public static final int constructor = 0x5a17b5e5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36007,7 +36392,7 @@ public class TLRPC { } public static class TL_inputEncryptedFileBigUploaded extends InputEncryptedFile { - public static int constructor = 0x2dc173c8; + public static final int constructor = 0x2dc173c8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36025,7 +36410,7 @@ public class TLRPC { } public static class TL_inputEncryptedFileEmpty extends InputEncryptedFile { - public static int constructor = 0x1837c364; + public static final int constructor = 0x1837c364; public void serializeToStream(AbstractSerializedData stream) { @@ -36034,7 +36419,7 @@ public class TLRPC { } public static class TL_inputEncryptedFileUploaded extends InputEncryptedFile { - public static int constructor = 0x64bd0306; + public static final int constructor = 0x64bd0306; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36080,7 +36465,7 @@ public class TLRPC { } public static class TL_messages_allStickers extends messages_AllStickers { - public static int constructor = 0xcdbbcebb; + public static final int constructor = 0xcdbbcebb; public long hash2; @@ -36116,7 +36501,7 @@ public class TLRPC { } public static class TL_messages_allStickersNotModified extends messages_AllStickers { - public static int constructor = 0xe86602c3; + public static final int constructor = 0xe86602c3; public void serializeToStream(AbstractSerializedData stream) { @@ -36125,7 +36510,7 @@ public class TLRPC { } public static class TL_messages_messageViews extends TLObject { - public static int constructor = 0xb6c4f543; + public static final int constructor = 0xb6c4f543; public ArrayList views = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -36281,7 +36666,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionSetMessageTTL extends DecryptedMessageAction { - public static int constructor = 0xa1733aec; + public static final int constructor = 0xa1733aec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36295,7 +36680,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionNotifyLayer extends DecryptedMessageAction { - public static int constructor = 0xf3048883; + public static final int constructor = 0xf3048883; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36309,7 +36694,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionDeleteMessages extends DecryptedMessageAction { - public static int constructor = 0x65614304; + public static final int constructor = 0x65614304; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36338,7 +36723,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionCommitKey extends DecryptedMessageAction { - public static int constructor = 0xec2e0b9b; + public static final int constructor = 0xec2e0b9b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36354,7 +36739,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionAbortKey extends DecryptedMessageAction { - public static int constructor = 0xdd05ec6b; + public static final int constructor = 0xdd05ec6b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36368,7 +36753,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionFlushHistory extends DecryptedMessageAction { - public static int constructor = 0x6719e45c; + public static final int constructor = 0x6719e45c; public void serializeToStream(AbstractSerializedData stream) { @@ -36377,7 +36762,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionTyping extends DecryptedMessageAction { - public static int constructor = 0xccb27641; + public static final int constructor = 0xccb27641; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36391,7 +36776,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionAcceptKey extends DecryptedMessageAction { - public static int constructor = 0x6fe1735b; + public static final int constructor = 0x6fe1735b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36409,7 +36794,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionReadMessages extends DecryptedMessageAction { - public static int constructor = 0xc4f40be; + public static final int constructor = 0xc4f40be; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36438,7 +36823,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionResend extends DecryptedMessageAction { - public static int constructor = 0x511110b0; + public static final int constructor = 0x511110b0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36454,7 +36839,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionRequestKey extends DecryptedMessageAction { - public static int constructor = 0xf3c9611b; + public static final int constructor = 0xf3c9611b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36470,7 +36855,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionScreenshotMessages extends DecryptedMessageAction { - public static int constructor = 0x8ac1f475; + public static final int constructor = 0x8ac1f475; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36499,7 +36884,7 @@ public class TLRPC { } public static class TL_decryptedMessageActionNoop extends DecryptedMessageAction { - public static int constructor = 0xa82fdd63; + public static final int constructor = 0xa82fdd63; public void serializeToStream(AbstractSerializedData stream) { @@ -36530,7 +36915,7 @@ public class TLRPC { } public static class TL_inputCheckPasswordEmpty extends InputCheckPasswordSRP { - public static int constructor = 0x9880f658; + public static final int constructor = 0x9880f658; public void serializeToStream(AbstractSerializedData stream) { @@ -36539,7 +36924,7 @@ public class TLRPC { } public static class TL_inputCheckPasswordSRP extends InputCheckPasswordSRP { - public static int constructor = 0xd27ff082; + public static final int constructor = 0xd27ff082; public long srp_id; public byte[] A; @@ -36597,7 +36982,7 @@ public class TLRPC { } public static class TL_account_password extends account_Password { - public static int constructor = 0x957b50fb; + public static final int constructor = 0x957b50fb; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -36664,7 +37049,7 @@ public class TLRPC { } public static class TL_account_password_layer144 extends account_Password { - public static int constructor = 0x185b184f; + public static final int constructor = 0x185b184f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -36725,7 +37110,7 @@ public class TLRPC { } public static class TL_chatAdminWithInvites extends TLObject { - public static int constructor = 0xf2ecef23; + public static final int constructor = 0xf2ecef23; public long admin_id; public int invites_count; @@ -36759,7 +37144,7 @@ public class TLRPC { } public static class TL_auth_loggedOut extends TLObject { - public static int constructor = 0xc3a2835f; + public static final int constructor = 0xc3a2835f; public int flags; public byte[] future_auth_token; @@ -36841,7 +37226,7 @@ public class TLRPC { } public static class TL_userProfilePhoto_layer126 extends TL_userProfilePhoto { - public static int constructor = 0x69d3ab26; + public static final int constructor = 0x69d3ab26; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36865,7 +37250,7 @@ public class TLRPC { } public static class TL_userProfilePhoto_layer127 extends TL_userProfilePhoto { - public static int constructor = 0xcc656077; + public static final int constructor = 0xcc656077; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36902,7 +37287,7 @@ public class TLRPC { } public static class TL_userProfilePhoto_layer115 extends TL_userProfilePhoto { - public static int constructor = 0xecd75d8c; + public static final int constructor = 0xecd75d8c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36922,7 +37307,7 @@ public class TLRPC { } public static class TL_userProfilePhotoEmpty extends UserProfilePhoto { - public static int constructor = 0x4f11bae1; + public static final int constructor = 0x4f11bae1; public void serializeToStream(AbstractSerializedData stream) { @@ -36931,7 +37316,7 @@ public class TLRPC { } public static class TL_userProfilePhoto_layer97 extends TL_userProfilePhoto { - public static int constructor = 0xd559d8c8; + public static final int constructor = 0xd559d8c8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36949,7 +37334,7 @@ public class TLRPC { } public static class TL_userProfilePhoto_old extends TL_userProfilePhoto { - public static int constructor = 0x990d1493; + public static final int constructor = 0x990d1493; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -36965,7 +37350,7 @@ public class TLRPC { } public static class TL_userProfilePhoto extends UserProfilePhoto { - public static int constructor = 0x82d1f706; + public static final int constructor = 0x82d1f706; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37048,9 +37433,6 @@ public class TLRPC { case 0x208e68c9: result = new TL_inputMessageEntityMentionName(); break; - case 0x5eef0214: - result = new TL_messageEntityAnimatedEmoji(); - break; case 0x4c4e743f: result = new TL_messageEntityCashtag(); break; @@ -37096,7 +37478,7 @@ public class TLRPC { } public static class TL_messageEntityTextUrl extends MessageEntity { - public static int constructor = 0x76a6d327; + public static final int constructor = 0x76a6d327; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37114,7 +37496,7 @@ public class TLRPC { } public static class TL_messageEntityBotCommand extends MessageEntity { - public static int constructor = 0x6cef8ac7; + public static final int constructor = 0x6cef8ac7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37130,7 +37512,7 @@ public class TLRPC { } public static class TL_messageEntityEmail extends MessageEntity { - public static int constructor = 0x64e475c2; + public static final int constructor = 0x64e475c2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37146,7 +37528,7 @@ public class TLRPC { } public static class TL_messageEntityPre extends MessageEntity { - public static int constructor = 0x73924be0; + public static final int constructor = 0x73924be0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37164,7 +37546,7 @@ public class TLRPC { } public static class TL_messageEntityUnknown extends MessageEntity { - public static int constructor = 0xbb92ba95; + public static final int constructor = 0xbb92ba95; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37180,7 +37562,7 @@ public class TLRPC { } public static class TL_messageEntityUrl extends MessageEntity { - public static int constructor = 0x6ed02538; + public static final int constructor = 0x6ed02538; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37196,7 +37578,7 @@ public class TLRPC { } public static class TL_messageEntityItalic extends MessageEntity { - public static int constructor = 0x826f8b60; + public static final int constructor = 0x826f8b60; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37212,7 +37594,7 @@ public class TLRPC { } public static class TL_messageEntityMention extends MessageEntity { - public static int constructor = 0xfa04579d; + public static final int constructor = 0xfa04579d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37228,7 +37610,7 @@ public class TLRPC { } public static class TL_messageEntitySpoiler extends MessageEntity { - public static int constructor = 0x32ca960f; + public static final int constructor = 0x32ca960f; public void readParams(AbstractSerializedData stream, boolean exception) { offset = stream.readInt32(exception); @@ -37243,7 +37625,7 @@ public class TLRPC { } public static class TL_messageEntityMentionName_layer131 extends TL_messageEntityMentionName { - public static int constructor = 0x352dca58; + public static final int constructor = 0x352dca58; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37261,7 +37643,7 @@ public class TLRPC { } public static class TL_inputMessageEntityMentionName extends MessageEntity { - public static int constructor = 0x208e68c9; + public static final int constructor = 0x208e68c9; public InputUser user_id; @@ -37280,25 +37662,7 @@ public class TLRPC { } public static class TL_messageEntityCashtag extends MessageEntity { - public static int constructor = 0x4c4e743f; - - public void readParams(AbstractSerializedData stream, boolean exception) { - offset = stream.readInt32(exception); - length = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(offset); - stream.writeInt32(length); - } - } - - public static class TL_messageEntityAnimatedEmoji extends MessageEntity { - public static int constructor = 0x5eef0214; - - public int offset; - public int length; + public static final int constructor = 0x4c4e743f; public void readParams(AbstractSerializedData stream, boolean exception) { offset = stream.readInt32(exception); @@ -37313,7 +37677,7 @@ public class TLRPC { } public static class TL_messageEntityBold extends MessageEntity { - public static int constructor = 0xbd610bc9; + public static final int constructor = 0xbd610bc9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37329,7 +37693,7 @@ public class TLRPC { } public static class TL_messageEntityHashtag extends MessageEntity { - public static int constructor = 0x6f635b0d; + public static final int constructor = 0x6f635b0d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37345,7 +37709,7 @@ public class TLRPC { } public static class TL_messageEntityCode extends MessageEntity { - public static int constructor = 0x28a20571; + public static final int constructor = 0x28a20571; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37361,7 +37725,7 @@ public class TLRPC { } public static class TL_messageEntityStrike extends MessageEntity { - public static int constructor = 0xbf0693d4; + public static final int constructor = 0xbf0693d4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37377,7 +37741,7 @@ public class TLRPC { } public static class TL_messageEntityBlockquote extends MessageEntity { - public static int constructor = 0x20df5d0; + public static final int constructor = 0x20df5d0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37393,7 +37757,7 @@ public class TLRPC { } public static class TL_messageEntityUnderline extends MessageEntity { - public static int constructor = 0x9c4e7e8b; + public static final int constructor = 0x9c4e7e8b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37409,7 +37773,7 @@ public class TLRPC { } public static class TL_messageEntityBankCard extends MessageEntity { - public static int constructor = 0x761e6af4; + public static final int constructor = 0x761e6af4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37425,7 +37789,7 @@ public class TLRPC { } public static class TL_messageEntityPhone extends MessageEntity { - public static int constructor = 0x9b69e34b; + public static final int constructor = 0x9b69e34b; public void readParams(AbstractSerializedData stream, boolean exception) { offset = stream.readInt32(exception); @@ -37440,7 +37804,7 @@ public class TLRPC { } public static class TL_messageEntityMentionName extends MessageEntity { - public static int constructor = 0xdc7b1140; + public static final int constructor = 0xdc7b1140; public long user_id; @@ -37481,7 +37845,7 @@ public class TLRPC { } public static class TL_channelLocationEmpty extends ChannelLocation { - public static int constructor = 0xbfb5ad8b; + public static final int constructor = 0xbfb5ad8b; public void serializeToStream(AbstractSerializedData stream) { @@ -37490,7 +37854,7 @@ public class TLRPC { } public static class TL_channelLocation extends ChannelLocation { - public static int constructor = 0x209b82db; + public static final int constructor = 0x209b82db; public GeoPoint geo_point; public String address; @@ -37561,7 +37925,7 @@ public class TLRPC { } public static class TL_photo_layer97 extends TL_photo { - public static int constructor = 0x9c477dd8; + public static final int constructor = 0x9c477dd8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37606,7 +37970,7 @@ public class TLRPC { } public static class TL_photo_layer55 extends TL_photo { - public static int constructor = 0xcded42fe; + public static final int constructor = 0xcded42fe; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37645,7 +38009,7 @@ public class TLRPC { } public static class TL_photo_old2 extends TL_photo { - public static int constructor = 0xc3838076; + public static final int constructor = 0xc3838076; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37688,7 +38052,7 @@ public class TLRPC { } public static class TL_photoEmpty extends Photo { - public static int constructor = 0x2331b22d; + public static final int constructor = 0x2331b22d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37702,7 +38066,7 @@ public class TLRPC { } public static class TL_photo_old extends TL_photo { - public static int constructor = 0x22b56751; + public static final int constructor = 0x22b56751; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37747,7 +38111,7 @@ public class TLRPC { } public static class TL_photo_layer115 extends TL_photo { - public static int constructor = 0xd07504a5; + public static final int constructor = 0xd07504a5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37794,7 +38158,7 @@ public class TLRPC { } public static class TL_photo extends Photo { - public static int constructor = 0xfb197a65; + public static final int constructor = 0xfb197a65; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37866,7 +38230,7 @@ public class TLRPC { } public static class TL_photo_layer82 extends TL_photo { - public static int constructor = 0x9288dd29; + public static final int constructor = 0x9288dd29; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37909,7 +38273,7 @@ public class TLRPC { } public static class TL_encryptedChatRequested_layer131 extends TL_encryptedChatRequested { - public static int constructor = 0x62718a82; + public static final int constructor = 0x62718a82; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37941,7 +38305,7 @@ public class TLRPC { } public static class TL_encryptedChatRequested_old extends TL_encryptedChatRequested { - public static int constructor = 0xfda9a7b7; + public static final int constructor = 0xfda9a7b7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37967,7 +38331,7 @@ public class TLRPC { } public static class TL_encryptedChatRequested_layer115 extends EncryptedChat { - public static int constructor = 0xc878527e; + public static final int constructor = 0xc878527e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -37991,7 +38355,7 @@ public class TLRPC { } public static class TL_encryptedChat_layer131 extends TL_encryptedChat { - public static int constructor = 0xfa56ce36; + public static final int constructor = 0xfa56ce36; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38017,7 +38381,7 @@ public class TLRPC { } public static class TL_encryptedChat_old extends TL_encryptedChat { - public static int constructor = 0x6601d14f; + public static final int constructor = 0x6601d14f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38045,7 +38409,7 @@ public class TLRPC { } public static class TL_encryptedChatEmpty extends EncryptedChat { - public static int constructor = 0xab7ec0a0; + public static final int constructor = 0xab7ec0a0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38059,7 +38423,7 @@ public class TLRPC { } public static class TL_encryptedChatWaiting_layer131 extends TL_encryptedChatWaiting { - public static int constructor = 0x3bf703dc; + public static final int constructor = 0x3bf703dc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38081,7 +38445,7 @@ public class TLRPC { } public static class TL_encryptedChatDiscarded_layer122 extends TL_encryptedChatDiscarded { - public static int constructor = 0x13d6dd27; + public static final int constructor = 0x13d6dd27; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38095,7 +38459,7 @@ public class TLRPC { } public static class TL_encryptedChatDiscarded extends EncryptedChat { - public static int constructor = 0x1e1c7c45; + public static final int constructor = 0x1e1c7c45; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38113,7 +38477,7 @@ public class TLRPC { } public static class TL_encryptedChat extends EncryptedChat { - public static int constructor = 0x61f0d4c7; + public static final int constructor = 0x61f0d4c7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38139,7 +38503,7 @@ public class TLRPC { } public static class TL_encryptedChatRequested extends EncryptedChat { - public static int constructor = 0x48f1d94c; + public static final int constructor = 0x48f1d94c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38171,7 +38535,7 @@ public class TLRPC { } public static class TL_encryptedChatWaiting extends EncryptedChat { - public static int constructor = 0x66b25953; + public static final int constructor = 0x66b25953; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38215,7 +38579,7 @@ public class TLRPC { } public static class TL_messages_foundStickerSetsNotModified extends messages_FoundStickerSets { - public static int constructor = 0xd54b65d; + public static final int constructor = 0xd54b65d; public void serializeToStream(AbstractSerializedData stream) { @@ -38224,7 +38588,7 @@ public class TLRPC { } public static class TL_messages_foundStickerSets extends messages_FoundStickerSets { - public static int constructor = 0x8af09dd2; + public static final int constructor = 0x8af09dd2; public long hash; public ArrayList sets = new ArrayList<>(); @@ -38261,7 +38625,7 @@ public class TLRPC { } public static class TL_contact extends TLObject { - public static int constructor = 0x145ade0b; + public static final int constructor = 0x145ade0b; public long user_id; public boolean mutual; @@ -38292,7 +38656,7 @@ public class TLRPC { } public static class TL_groupCallParticipantVideoSourceGroup extends TLObject { - public static int constructor = 0xdcb118b7; + public static final int constructor = 0xdcb118b7; public String semantics; public ArrayList sources = new ArrayList<>(); @@ -38338,7 +38702,7 @@ public class TLRPC { } public static class TL_help_countryCode extends TLObject { - public static int constructor = 0x4203c5ef; + public static final int constructor = 0x4203c5ef; public int flags; public String country_code; @@ -38413,7 +38777,7 @@ public class TLRPC { } public static class TL_secureData extends TLObject { - public static int constructor = 0x8aeabec3; + public static final int constructor = 0x8aeabec3; public byte[] data; public byte[] data_hash; @@ -38448,7 +38812,7 @@ public class TLRPC { public static class TL_config extends TLObject { - public static int constructor = 0xcc1a241e; + public static final int constructor = 0xcc1a241e; public int flags; public boolean default_p2p_contacts; @@ -38705,7 +39069,7 @@ public class TLRPC { } public static class TL_contacts_topPeers extends contacts_TopPeers { - public static int constructor = 0x70b772a8; + public static final int constructor = 0x70b772a8; public ArrayList categories = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -38783,7 +39147,7 @@ public class TLRPC { } public static class TL_contacts_topPeersDisabled extends contacts_TopPeers { - public static int constructor = 0xb52c939d; + public static final int constructor = 0xb52c939d; public void serializeToStream(AbstractSerializedData stream) { @@ -38792,7 +39156,7 @@ public class TLRPC { } public static class TL_contacts_topPeersNotModified extends contacts_TopPeers { - public static int constructor = 0xde266ef5; + public static final int constructor = 0xde266ef5; public void serializeToStream(AbstractSerializedData stream) { @@ -38801,7 +39165,7 @@ public class TLRPC { } public static class TL_help_support extends TLObject { - public static int constructor = 0x17c6b5f6; + public static final int constructor = 0x17c6b5f6; public String phone_number; public User user; @@ -38832,7 +39196,7 @@ public class TLRPC { } public static class TL_account_tmpPassword extends TLObject { - public static int constructor = 0xdb64fd34; + public static final int constructor = 0xdb64fd34; public byte[] tmp_password; public int valid_until; @@ -38888,7 +39252,7 @@ public class TLRPC { } public static class TL_messages_chats extends messages_Chats { - public static int constructor = 0x64ff9fd5; + public static final int constructor = 0x64ff9fd5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38921,7 +39285,7 @@ public class TLRPC { } public static class TL_messages_chatsSlice extends messages_Chats { - public static int constructor = 0x9cd81144; + public static final int constructor = 0x9cd81144; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -38990,7 +39354,7 @@ public class TLRPC { } public static class TL_inputChannelFromMessage_layer131 extends TL_inputChannelFromMessage { - public static int constructor = 0x2a286531; + public static final int constructor = 0x2a286531; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39008,7 +39372,7 @@ public class TLRPC { } public static class TL_inputChannel_layer131 extends TL_inputChannel { - public static int constructor = 0xafeb712e; + public static final int constructor = 0xafeb712e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39024,7 +39388,7 @@ public class TLRPC { } public static class TL_inputChannel extends InputChannel { - public static int constructor = 0xf35aec28; + public static final int constructor = 0xf35aec28; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39040,7 +39404,7 @@ public class TLRPC { } public static class TL_inputChannelEmpty extends InputChannel { - public static int constructor = 0xee8c1e86; + public static final int constructor = 0xee8c1e86; public void serializeToStream(AbstractSerializedData stream) { @@ -39049,7 +39413,7 @@ public class TLRPC { } public static class TL_inputChannelFromMessage extends InputChannel { - public static int constructor = 0x5b934f9d; + public static final int constructor = 0x5b934f9d; public InputPeer peer; public int msg_id; @@ -39069,7 +39433,7 @@ public class TLRPC { } public static class TL_messageRange extends TLObject { - public static int constructor = 0xae30253; + public static final int constructor = 0xae30253; public int min_id; public int max_id; @@ -39136,7 +39500,7 @@ public class TLRPC { } public static class TL_poll extends Poll { - public static int constructor = 0x86e18161; + public static final int constructor = 0x86e18161; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39195,7 +39559,7 @@ public class TLRPC { } public static class TL_poll_toDelete extends TL_poll { - public static int constructor = 0xaf746786; + public static final int constructor = 0xaf746786; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39248,7 +39612,7 @@ public class TLRPC { } public static class TL_poll_layer111 extends TL_poll { - public static int constructor = 0xd5529d06; + public static final int constructor = 0xd5529d06; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39329,7 +39693,7 @@ public class TLRPC { } public static class TL_messages_botResults_layer71 extends TL_messages_botResults_layer153 { - public static int constructor = 0xccd3563d; + public static final int constructor = 0xccd3563d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39382,7 +39746,7 @@ public class TLRPC { } public static class TL_messages_botResults extends messages_BotResults { - public static int constructor = 0xe021f2f6; + public static final int constructor = 0xe021f2f6; public static TL_messages_botResults TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -39475,7 +39839,7 @@ public class TLRPC { } public static class TL_messages_botResults_layer153 extends messages_BotResults { - public static int constructor = 0x947ca848; + public static final int constructor = 0x947ca848; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39549,7 +39913,7 @@ public class TLRPC { } public static class TL_inputFolderPeer extends TLObject { - public static int constructor = 0xfbd2c296; + public static final int constructor = 0xfbd2c296; public InputPeer peer; public int folder_id; @@ -39614,7 +39978,7 @@ public class TLRPC { } public static class TL_phoneConnection extends PhoneConnection { - public static int constructor = 0x9cc123c7; + public static final int constructor = 0x9cc123c7; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -39639,7 +40003,7 @@ public class TLRPC { } public static class TL_phoneConnectionWebrtc extends PhoneConnection { - public static int constructor = 0x635fe375; + public static final int constructor = 0x635fe375; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -39669,7 +40033,7 @@ public class TLRPC { } public static class TL_inputBotInlineMessageID extends TLObject { - public static int constructor = 0x890c3d89; + public static final int constructor = 0x890c3d89; public int dc_id; public long id; @@ -39725,7 +40089,7 @@ public class TLRPC { } public static class TL_securePlainEmail extends SecurePlainData { - public static int constructor = 0x21ec5a5f; + public static final int constructor = 0x21ec5a5f; public String email; @@ -39740,7 +40104,7 @@ public class TLRPC { } public static class TL_securePlainPhone extends SecurePlainData { - public static int constructor = 0x7d6099dd; + public static final int constructor = 0x7d6099dd; public String phone; @@ -39755,7 +40119,7 @@ public class TLRPC { } public static class TL_secureSecretSettings extends TLObject { - public static int constructor = 0x1527bcac; + public static final int constructor = 0x1527bcac; public SecurePasswordKdfAlgo secure_algo; public byte[] secure_secret; @@ -39789,7 +40153,7 @@ public class TLRPC { } public static class TL_emojiLanguage extends TLObject { - public static int constructor = 0xb3fb5361; + public static final int constructor = 0xb3fb5361; public String lang_code; @@ -39848,7 +40212,7 @@ public class TLRPC { } public static class TL_theme_layer133 extends TL_theme { - public static int constructor = 0xe802b8dc; + public static final int constructor = 0xe802b8dc; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -39894,7 +40258,7 @@ public class TLRPC { } public static class TL_theme extends Theme { - public static int constructor = 0xa00e67d6; + public static final int constructor = 0xa00e67d6; public int flags; public boolean creator; @@ -39977,7 +40341,7 @@ public class TLRPC { } public static class TL_theme_layer131 extends TL_theme { - public static int constructor = 0x28f1114; + public static final int constructor = 0x28f1114; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40017,7 +40381,7 @@ public class TLRPC { } public static class TL_theme_layer106 extends TL_theme { - public static int constructor = 0xf7d90ce0; + public static final int constructor = 0xf7d90ce0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40051,7 +40415,7 @@ public class TLRPC { } public static class TL_themeDocumentNotModified_layer106 extends TL_theme { - public static int constructor = 0x483d270c; + public static final int constructor = 0x483d270c; public void serializeToStream(AbstractSerializedData stream) { @@ -40096,7 +40460,7 @@ public class TLRPC { } public static class TL_updates_channelDifferenceEmpty extends updates_ChannelDifference { - public static int constructor = 0x3e11affb; + public static final int constructor = 0x3e11affb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40120,7 +40484,7 @@ public class TLRPC { } public static class TL_updates_channelDifference extends updates_ChannelDifference { - public static int constructor = 0x2064674e; + public static final int constructor = 0x2064674e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40228,7 +40592,7 @@ public class TLRPC { } public static class TL_updates_channelDifferenceTooLong extends updates_ChannelDifference { - public static int constructor = 0xa4bcc6fe; + public static final int constructor = 0xa4bcc6fe; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40340,7 +40704,7 @@ public class TLRPC { } public static class TL_sponsoredWebPage extends TLObject { - public static int constructor = 0x3db8ec63; + public static final int constructor = 0x3db8ec63; public int flags; public String url; @@ -40381,7 +40745,7 @@ public class TLRPC { } public static class TL_sponsoredMessage extends TLObject { - public static int constructor = 0xdaafff6b; + public static final int constructor = 0xdaafff6b; public int flags; public boolean recommended; @@ -40503,7 +40867,7 @@ public class TLRPC { } public static class TL_account_authorizationForm extends TLObject { - public static int constructor = 0xad2e1cd8; + public static final int constructor = 0xad2e1cd8; public int flags; public ArrayList required_types = new ArrayList<>(); @@ -40626,7 +40990,7 @@ public class TLRPC { } public static class TL_help_recentMeUrls extends TLObject { - public static int constructor = 0xe0310d7; + public static final int constructor = 0xe0310d7; public ArrayList urls = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -40717,7 +41081,7 @@ public class TLRPC { } public static class TL_channelMessagesFilterEmpty extends ChannelMessagesFilter { - public static int constructor = 0x94d42ee7; + public static final int constructor = 0x94d42ee7; public void serializeToStream(AbstractSerializedData stream) { @@ -40726,7 +41090,7 @@ public class TLRPC { } public static class TL_channelMessagesFilter extends ChannelMessagesFilter { - public static int constructor = 0xcd77d957; + public static final int constructor = 0xcd77d957; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -40763,7 +41127,7 @@ public class TLRPC { } public static class TL_bankCardOpenUrl extends TLObject { - public static int constructor = 0xf568028a; + public static final int constructor = 0xf568028a; public String url; public String name; @@ -40794,7 +41158,7 @@ public class TLRPC { } public static class TL_contacts_resolvedPeer extends TLObject { - public static int constructor = 0x7f077ad9; + public static final int constructor = 0x7f077ad9; public Peer peer; public ArrayList chats = new ArrayList<>(); @@ -40866,7 +41230,7 @@ public class TLRPC { } public static class TL_searchResultPosition extends TLObject { - public static int constructor = 0x7f648b67; + public static final int constructor = 0x7f648b67; public int msg_id; public int date; @@ -40900,7 +41264,7 @@ public class TLRPC { } public static class TL_messages_searchResultsPositions extends TLObject { - public static int constructor = 0x53b22baf; + public static final int constructor = 0x53b22baf; public int count; public ArrayList positions = new ArrayList<>(); @@ -40950,7 +41314,7 @@ public class TLRPC { } public static class TL_searchResultsCalendarPeriod extends TLObject { - public static int constructor = 0xc9b0539f; + public static final int constructor = 0xc9b0539f; public int date; public int min_msg_id; @@ -40987,7 +41351,7 @@ public class TLRPC { } public static class TL_inputSingleMedia extends TLObject { - public static int constructor = 0x1cc6e91f; + public static final int constructor = 0x1cc6e91f; public int flags; public InputMedia media; @@ -41050,7 +41414,7 @@ public class TLRPC { } public static class TL_inputPhoneCall extends TLObject { - public static int constructor = 0x1e36fded; + public static final int constructor = 0x1e36fded; public long id; public long access_hash; @@ -41111,7 +41475,7 @@ public class TLRPC { } public static class TL_webDocumentNoProxy extends WebDocument { - public static int constructor = 0xf9c8bcc6; + public static final int constructor = 0xf9c8bcc6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41150,7 +41514,7 @@ public class TLRPC { } public static class TL_webDocument_layer81 extends TL_webDocument { - public static int constructor = 0xc61acbd8; + public static final int constructor = 0xc61acbd8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41193,7 +41557,7 @@ public class TLRPC { } public static class TL_webDocument extends WebDocument { - public static int constructor = 0x1c570ed1; + public static final int constructor = 0x1c570ed1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41256,7 +41620,7 @@ public class TLRPC { } public static class TL_help_promoData extends help_PromoData { - public static int constructor = 0x8c39793f; + public static final int constructor = 0x8c39793f; public int flags; public boolean proxy; @@ -41338,7 +41702,7 @@ public class TLRPC { } public static class TL_help_promoDataEmpty extends help_PromoData { - public static int constructor = 0x98f6ac75; + public static final int constructor = 0x98f6ac75; public int expires; @@ -41451,7 +41815,7 @@ public class TLRPC { } public static class TL_channelParticipant extends ChannelParticipant { - public static int constructor = 0xc00c07c0; + public static final int constructor = 0xc00c07c0; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41468,7 +41832,7 @@ public class TLRPC { } public static class TL_channelParticipantSelf extends ChannelParticipant { - public static int constructor = 0x35a8bfa7; + public static final int constructor = 0x35a8bfa7; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -41489,7 +41853,7 @@ public class TLRPC { } public static class TL_channelParticipantSelf_layer133 extends ChannelParticipant { - public static int constructor = 0x28a8bc67; + public static final int constructor = 0x28a8bc67; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41508,7 +41872,7 @@ public class TLRPC { } public static class TL_channelParticipantCreator extends ChannelParticipant { - public static int constructor = 0x2fe601d3; + public static final int constructor = 0x2fe601d3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41533,7 +41897,7 @@ public class TLRPC { } public static class TL_channelParticipantAdmin extends ChannelParticipant { - public static int constructor = 0x34c3bb53; + public static final int constructor = 0x34c3bb53; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41572,7 +41936,7 @@ public class TLRPC { } public static class TL_channelParticipantBanned extends ChannelParticipant { - public static int constructor = 0x6df8014e; + public static final int constructor = 0x6df8014e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41596,7 +41960,7 @@ public class TLRPC { } public static class TL_channelParticipantBanned_layer125 extends TL_channelParticipantBanned { - public static int constructor = 0x1c0facaf; + public static final int constructor = 0x1c0facaf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41621,7 +41985,7 @@ public class TLRPC { } public static class TL_channelParticipantLeft extends ChannelParticipant { - public static int constructor = 0x1b03f006; + public static final int constructor = 0x1b03f006; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41635,7 +41999,7 @@ public class TLRPC { } public static class TL_channelParticipantLeft_layer125 extends TL_channelParticipantLeft { - public static int constructor = 0xc3c6796b; + public static final int constructor = 0xc3c6796b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41650,7 +42014,7 @@ public class TLRPC { } public static class TL_channelParticipantBanned_layer131 extends TL_channelParticipantBanned { - public static int constructor = 0x50a1dfd6; + public static final int constructor = 0x50a1dfd6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41674,7 +42038,7 @@ public class TLRPC { } public static class TL_channelParticipantCreator_layer103 extends TL_channelParticipantCreator { - public static int constructor = 0xe3e2e1f9; + public static final int constructor = 0xe3e2e1f9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41689,7 +42053,7 @@ public class TLRPC { } public static class TL_channelParticipant_layer131 extends TL_channelParticipant { - public static int constructor = 0x15ebac1d; + public static final int constructor = 0x15ebac1d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41706,7 +42070,7 @@ public class TLRPC { } public static class TL_channelParticipantKicked_layer67 extends ChannelParticipant { - public static int constructor = 0x8cc5e69a; + public static final int constructor = 0x8cc5e69a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41725,7 +42089,7 @@ public class TLRPC { } public static class TL_channelParticipantSelf_layer131 extends TL_channelParticipantSelf { - public static int constructor = 0xa3289a6d; + public static final int constructor = 0xa3289a6d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41744,7 +42108,7 @@ public class TLRPC { } public static class TL_channelParticipantAdmin_layer131 extends TL_channelParticipantAdmin { - public static int constructor = 0xccbebbaf; + public static final int constructor = 0xccbebbaf; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41783,7 +42147,7 @@ public class TLRPC { } public static class TL_channelParticipantCreator_layer118 extends TL_channelParticipantCreator { - public static int constructor = 0x808d15a4; + public static final int constructor = 0x808d15a4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41806,7 +42170,7 @@ public class TLRPC { } public static class TL_channelParticipantCreator_layer131 extends TL_channelParticipantCreator { - public static int constructor = 0x447dca4b; + public static final int constructor = 0x447dca4b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41831,7 +42195,7 @@ public class TLRPC { } public static class TL_channelParticipantModerator_layer67 extends TL_channelParticipantAdmin { - public static int constructor = 0x91057fef; + public static final int constructor = 0x91057fef; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41850,7 +42214,7 @@ public class TLRPC { } public static class TL_channelParticipantEditor_layer67 extends TL_channelParticipantAdmin { - public static int constructor = 0x98192d61; + public static final int constructor = 0x98192d61; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41869,7 +42233,7 @@ public class TLRPC { } public static class TL_channelParticipantAdmin_layer92 extends TL_channelParticipantAdmin { - public static int constructor = 0xa82fa898; + public static final int constructor = 0xa82fa898; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41897,7 +42261,7 @@ public class TLRPC { } public static class TL_channelParticipantAdmin_layer103 extends TL_channelParticipantAdmin { - public static int constructor = 0x5daa6e23; + public static final int constructor = 0x5daa6e23; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -41952,7 +42316,7 @@ public class TLRPC { } public static class TL_inputStickeredMediaDocument extends InputStickeredMedia { - public static int constructor = 0x438865b; + public static final int constructor = 0x438865b; public InputDocument id; @@ -41967,7 +42331,7 @@ public class TLRPC { } public static class TL_inputStickeredMediaPhoto extends InputStickeredMedia { - public static int constructor = 0x4a992157; + public static final int constructor = 0x4a992157; public InputPhoto id; @@ -42008,7 +42372,7 @@ public class TLRPC { } public static class TL_channels_channelParticipants extends channels_ChannelParticipants { - public static int constructor = 0x9ab0feaf; + public static final int constructor = 0x9ab0feaf; public void readParams(AbstractSerializedData stream, boolean exception) { count = stream.readInt32(exception); @@ -42084,7 +42448,7 @@ public class TLRPC { } public static class TL_channels_channelParticipantsNotModified extends channels_ChannelParticipants { - public static int constructor = 0xf0173fe9; + public static final int constructor = 0xf0173fe9; public void serializeToStream(AbstractSerializedData stream) { @@ -42128,7 +42492,7 @@ public class TLRPC { } public static class TL_wallPaperSettings_layer106 extends TL_wallPaperSettings { - public static int constructor = 0xa12f40b8; + public static final int constructor = 0xa12f40b8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42158,7 +42522,7 @@ public class TLRPC { } public static class TL_wallPaperSettings_layer128 extends TL_wallPaperSettings { - public static int constructor = 0x5086cf8; + public static final int constructor = 0x5086cf8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42200,7 +42564,7 @@ public class TLRPC { } public static class TL_wallPaperSettings extends WallPaperSettings { - public static int constructor = 0x1dc1bca4; + public static final int constructor = 0x1dc1bca4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42254,7 +42618,7 @@ public class TLRPC { } public static class TL_contacts_found extends TLObject { - public static int constructor = 0xb3134d9d; + public static final int constructor = 0xb3134d9d; public ArrayList my_results = new ArrayList<>(); public ArrayList results = new ArrayList<>(); @@ -42407,7 +42771,7 @@ public class TLRPC { } public static class TL_chatParticipantsForbidden_layer131 extends TL_chatParticipantsForbidden { - public static int constructor = 0xfc900c2b; + public static final int constructor = 0xfc900c2b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42429,7 +42793,7 @@ public class TLRPC { } public static class TL_chatParticipants_layer131 extends TL_chatParticipants { - public static int constructor = 0x3f460fed; + public static final int constructor = 0x3f460fed; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42466,7 +42830,7 @@ public class TLRPC { } public static class TL_chatParticipantsForbidden extends ChatParticipants { - public static int constructor = 0x8763d3e1; + public static final int constructor = 0x8763d3e1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42488,7 +42852,7 @@ public class TLRPC { } public static class TL_chatParticipants extends ChatParticipants { - public static int constructor = 0x3cbc93f8; + public static final int constructor = 0x3cbc93f8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42525,7 +42889,7 @@ public class TLRPC { } public static class TL_chatParticipants_old extends TL_chatParticipants { - public static int constructor = 0x7841b415; + public static final int constructor = 0x7841b415; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42564,7 +42928,7 @@ public class TLRPC { } public static class TL_chatParticipantsForbidden_old extends TL_chatParticipantsForbidden { - public static int constructor = 0xfd2bb8a; + public static final int constructor = 0xfd2bb8a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42578,7 +42942,7 @@ public class TLRPC { } public static class TL_game extends TLObject { - public static int constructor = 0xbdf9653b; + public static final int constructor = 0xbdf9653b; public int flags; public long id; @@ -42722,7 +43086,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaAudio extends DecryptedMessageMedia { - public static int constructor = 0x57e0a9cb; + public static final int constructor = 0x57e0a9cb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42744,7 +43108,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaGeoPoint extends DecryptedMessageMedia { - public static int constructor = 0x35480a59; + public static final int constructor = 0x35480a59; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42760,7 +43124,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaContact extends DecryptedMessageMedia { - public static int constructor = 0x588a0a97; + public static final int constructor = 0x588a0a97; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42780,7 +43144,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaEmpty extends DecryptedMessageMedia { - public static int constructor = 0x89f5c4a; + public static final int constructor = 0x89f5c4a; public void serializeToStream(AbstractSerializedData stream) { @@ -42789,7 +43153,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaDocument extends DecryptedMessageMedia { - public static int constructor = 0x6abd9782; + public static final int constructor = 0x6abd9782; public byte[] thumb; @@ -42839,7 +43203,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaDocument_layer101 extends TL_decryptedMessageMediaDocument { - public static int constructor = 0x7afe8ae2; + public static final int constructor = 0x7afe8ae2; public byte[] thumb; @@ -42889,7 +43253,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaWebPage extends DecryptedMessageMedia { - public static int constructor = 0xe50511d8; + public static final int constructor = 0xe50511d8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -42903,7 +43267,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaPhoto extends DecryptedMessageMedia { - public static int constructor = 0xf1fa8d78; + public static final int constructor = 0xf1fa8d78; public byte[] thumb; @@ -42934,7 +43298,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaVideo extends DecryptedMessageMedia { - public static int constructor = 0x970c8c0e; + public static final int constructor = 0x970c8c0e; public byte[] thumb; @@ -42969,7 +43333,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaDocument_layer8 extends TL_decryptedMessageMediaDocument { - public static int constructor = 0xb095434b; + public static final int constructor = 0xb095434b; public byte[] thumb; @@ -42998,7 +43362,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaVideo_layer8 extends TL_decryptedMessageMediaVideo { - public static int constructor = 0x4cee6ef3; + public static final int constructor = 0x4cee6ef3; public byte[] thumb; @@ -43029,7 +43393,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaVenue extends DecryptedMessageMedia { - public static int constructor = 0x8a0df56f; + public static final int constructor = 0x8a0df56f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43053,7 +43417,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaExternalDocument extends DecryptedMessageMedia { - public static int constructor = 0xfa95b0dd; + public static final int constructor = 0xfa95b0dd; public PhotoSize thumb; @@ -43101,7 +43465,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaVideo_layer17 extends TL_decryptedMessageMediaVideo { - public static int constructor = 0x524a415d; + public static final int constructor = 0x524a415d; public byte[] thumb; @@ -43134,7 +43498,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaAudio_layer8 extends TL_decryptedMessageMediaAudio { - public static int constructor = 0x6080758f; + public static final int constructor = 0x6080758f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43154,7 +43518,7 @@ public class TLRPC { } public static class TL_decryptedMessageMediaPhoto_layer8 extends TL_decryptedMessageMediaPhoto { - public static int constructor = 0x32798a8c; + public static final int constructor = 0x32798a8c; public byte[] thumb; @@ -43205,7 +43569,7 @@ public class TLRPC { } public static class TL_emojiKeywordDeleted extends EmojiKeyword { - public static int constructor = 0x236df622; + public static final int constructor = 0x236df622; public String keyword; public ArrayList emoticons = new ArrayList<>(); @@ -43260,7 +43624,7 @@ public class TLRPC { } public static class TL_messages_emojiGroupsNotModified extends messages_EmojiGroups { - public static int constructor = 0x6fb4ad87; + public static final int constructor = 0x6fb4ad87; public void serializeToStream(AbstractSerializedData stream) { @@ -43269,7 +43633,7 @@ public class TLRPC { } public static class TL_messages_emojiGroups extends messages_EmojiGroups { - public static int constructor = 0x881fb94b; + public static final int constructor = 0x881fb94b; public int hash; public ArrayList groups = new ArrayList<>(); @@ -43306,7 +43670,7 @@ public class TLRPC { } public static class TL_emojiGroup extends TLObject { - public static int constructor = 0x7a9abda9; + public static final int constructor = 0x7a9abda9; public String title; public long icon_emoji_id; @@ -43355,7 +43719,7 @@ public class TLRPC { } public static class TL_emojiKeyword extends EmojiKeyword { - public static int constructor = 0xd5b3b9f9; + public static final int constructor = 0xd5b3b9f9; public String keyword; public ArrayList emoticons = new ArrayList<>(); @@ -43388,7 +43752,7 @@ public class TLRPC { } public static class TL_account_autoDownloadSettings extends TLObject { - public static int constructor = 0x63cacf26; + public static final int constructor = 0x63cacf26; public TL_autoDownloadSettings low; public TL_autoDownloadSettings medium; @@ -43460,7 +43824,7 @@ public class TLRPC { } public static class TL_chatParticipantAdmin_layer131 extends TL_chatParticipantAdmin { - public static int constructor = 0xe2d6e436; + public static final int constructor = 0xe2d6e436; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43478,7 +43842,7 @@ public class TLRPC { } public static class TL_chatParticipantAdmin extends ChatParticipant { - public static int constructor = 0xa0933f5b; + public static final int constructor = 0xa0933f5b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43496,7 +43860,7 @@ public class TLRPC { } public static class TL_chatParticipant_layer131 extends TL_chatParticipant { - public static int constructor = 0xc8d7493e; + public static final int constructor = 0xc8d7493e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43514,7 +43878,7 @@ public class TLRPC { } public static class TL_chatParticipantCreator_layer131 extends TL_chatParticipantCreator { - public static int constructor = 0xda13538a; + public static final int constructor = 0xda13538a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43528,7 +43892,7 @@ public class TLRPC { } public static class TL_chatParticipant extends ChatParticipant { - public static int constructor = 0xc02d4007; + public static final int constructor = 0xc02d4007; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43546,7 +43910,7 @@ public class TLRPC { } public static class TL_chatParticipantCreator extends ChatParticipant { - public static int constructor = 0xe46bcee4; + public static final int constructor = 0xe46bcee4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -43560,7 +43924,7 @@ public class TLRPC { } public static class TL_availableReaction extends TLObject { - public static int constructor = 0xc077ec01; + public static final int constructor = 0xc077ec01; public int flags; public boolean inactive; @@ -43630,7 +43994,7 @@ public class TLRPC { } public static class TL_webAuthorization extends TLObject { - public static int constructor = 0xa6f8f452; + public static final int constructor = 0xa6f8f452; public long hash; public long bot_id; @@ -43704,7 +44068,7 @@ public class TLRPC { } public static class TL_inputSecureFileUploaded extends InputSecureFile { - public static int constructor = 0x3334b0f0; + public static final int constructor = 0x3334b0f0; public long id; public int parts; @@ -43731,7 +44095,7 @@ public class TLRPC { } public static class TL_inputSecureFile extends InputSecureFile { - public static int constructor = 0x5367e5be; + public static final int constructor = 0x5367e5be; public long id; public long access_hash; @@ -43749,7 +44113,7 @@ public class TLRPC { } public static class TL_postAddress extends TLObject { - public static int constructor = 0x1e8caaeb; + public static final int constructor = 0x1e8caaeb; public String street_line1; public String street_line2; @@ -43925,6 +44289,12 @@ public class TLRPC { case 0x64f36dfc: result = new TL_channelAdminLogEventActionToggleAntiSpam(); break; + case 0x3c2b247b: + result = new TL_channelAdminLogEventActionChangeColor(); + break; + case 0x445fc434: + result = new TL_channelAdminLogEventActionChangeBackgroundEmoji(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in ChannelAdminLogEventAction", constructor)); @@ -43937,7 +44307,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionDiscardGroupCall extends ChannelAdminLogEventAction { - public static int constructor = 0xdb9f9140; + public static final int constructor = 0xdb9f9140; public TL_inputGroupCall call; @@ -43952,7 +44322,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeStickerSet extends ChannelAdminLogEventAction { - public static int constructor = 0xb1c3caa7; + public static final int constructor = 0xb1c3caa7; public InputStickerSet prev_stickerset; public InputStickerSet new_stickerset; @@ -43970,7 +44340,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantMute extends ChannelAdminLogEventAction { - public static int constructor = 0xf92424d2; + public static final int constructor = 0xf92424d2; public TL_groupCallParticipant participant; @@ -43985,7 +44355,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionDefaultBannedRights extends ChannelAdminLogEventAction { - public static int constructor = 0x2df5fc0a; + public static final int constructor = 0x2df5fc0a; public TL_chatBannedRights prev_banned_rights; public TL_chatBannedRights new_banned_rights; @@ -44003,7 +44373,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeTheme extends ChannelAdminLogEventAction { - public static int constructor = 0xfe69018d; + public static final int constructor = 0xfe69018d; public String prev_value; public String new_value; @@ -44021,7 +44391,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantLeave extends ChannelAdminLogEventAction { - public static int constructor = 0xf89777f2; + public static final int constructor = 0xf89777f2; public void serializeToStream(AbstractSerializedData stream) { @@ -44030,7 +44400,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionEditMessage extends ChannelAdminLogEventAction { - public static int constructor = 0x709b2405; + public static final int constructor = 0x709b2405; public Message prev_message; public Message new_message; @@ -44048,7 +44418,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionExportedInviteEdit extends ChannelAdminLogEventAction { - public static int constructor = 0xe90ebb59; + public static final int constructor = 0xe90ebb59; public TL_chatInviteExported prev_invite; public TL_chatInviteExported new_invite; @@ -44066,7 +44436,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeUsername extends ChannelAdminLogEventAction { - public static int constructor = 0x6a4afc38; + public static final int constructor = 0x6a4afc38; public String prev_value; public String new_value; @@ -44084,7 +44454,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeLocation extends ChannelAdminLogEventAction { - public static int constructor = 0xe6b76ae; + public static final int constructor = 0xe6b76ae; public ChannelLocation prev_value; public ChannelLocation new_value; @@ -44102,7 +44472,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangePhoto extends ChannelAdminLogEventAction { - public static int constructor = 0x434bd2af; + public static final int constructor = 0x434bd2af; public Photo prev_photo; public Photo new_photo; @@ -44120,7 +44490,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantToggleAdmin extends ChannelAdminLogEventAction { - public static int constructor = 0xd5676710; + public static final int constructor = 0xd5676710; public ChannelParticipant prev_participant; public ChannelParticipant new_participant; @@ -44138,7 +44508,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleSlowMode extends ChannelAdminLogEventAction { - public static int constructor = 0x53909779; + public static final int constructor = 0x53909779; public int prev_value; public int new_value; @@ -44156,7 +44526,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantJoinByInvite extends ChannelAdminLogEventAction { - public static int constructor = 0xfe9fc158; + public static final int constructor = 0xfe9fc158; public int flags; public TL_chatInviteExported invite; @@ -44177,7 +44547,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionExportedInviteRevoke extends ChannelAdminLogEventAction { - public static int constructor = 0x410a134e; + public static final int constructor = 0x410a134e; public TL_chatInviteExported invite; @@ -44192,7 +44562,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionStopPoll extends ChannelAdminLogEventAction { - public static int constructor = 0x8f079643; + public static final int constructor = 0x8f079643; public Message message; @@ -44207,7 +44577,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionExportedInviteDelete extends ChannelAdminLogEventAction { - public static int constructor = 0x5a50fca4; + public static final int constructor = 0x5a50fca4; public TL_chatInviteExported invite; @@ -44222,7 +44592,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleSignatures extends ChannelAdminLogEventAction { - public static int constructor = 0x26ae0971; + public static final int constructor = 0x26ae0971; public boolean new_value; @@ -44237,7 +44607,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantVolume extends ChannelAdminLogEventAction { - public static int constructor = 0x3e7f6847; + public static final int constructor = 0x3e7f6847; public TL_groupCallParticipant participant; @@ -44252,7 +44622,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleForum extends ChannelAdminLogEventAction { - public static int constructor = 0x2cc6383; + public static final int constructor = 0x2cc6383; public boolean new_value; @@ -44267,7 +44637,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionEditTopic extends ChannelAdminLogEventAction { - public static int constructor = 0xf06fe208; + public static final int constructor = 0xf06fe208; public ForumTopic prev_topic; public ForumTopic new_topic; @@ -44285,7 +44655,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantToggleBan extends ChannelAdminLogEventAction { - public static int constructor = 0xe6d83d7e; + public static final int constructor = 0xe6d83d7e; public ChannelParticipant prev_participant; public ChannelParticipant new_participant; @@ -44303,7 +44673,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantJoin extends ChannelAdminLogEventAction { - public static int constructor = 0x183040d3; + public static final int constructor = 0x183040d3; public void serializeToStream(AbstractSerializedData stream) { @@ -44312,7 +44682,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionTogglePreHistoryHidden extends ChannelAdminLogEventAction { - public static int constructor = 0x5f5c95f1; + public static final int constructor = 0x5f5c95f1; public boolean new_value; @@ -44327,7 +44697,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantJoinByRequest extends ChannelAdminLogEventAction { - public static int constructor = 0xafb6144a; + public static final int constructor = 0xafb6144a; public ExportedChatInvite invite; public long approved_by; @@ -44345,7 +44715,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionUpdatePinned extends ChannelAdminLogEventAction { - public static int constructor = 0xe9e82c18; + public static final int constructor = 0xe9e82c18; public Message message; @@ -44360,7 +44730,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleGroupCallSetting extends ChannelAdminLogEventAction { - public static int constructor = 0x56d6a247; + public static final int constructor = 0x56d6a247; public boolean join_muted; @@ -44375,7 +44745,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantInvite extends ChannelAdminLogEventAction { - public static int constructor = 0xe31c34d8; + public static final int constructor = 0xe31c34d8; public ChannelParticipant participant; @@ -44390,7 +44760,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeAbout extends ChannelAdminLogEventAction { - public static int constructor = 0x55188a2e; + public static final int constructor = 0x55188a2e; public String prev_value; public String new_value; @@ -44408,7 +44778,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionStartGroupCall extends ChannelAdminLogEventAction { - public static int constructor = 0x23209745; + public static final int constructor = 0x23209745; public TL_inputGroupCall call; @@ -44423,7 +44793,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeLinkedChat extends ChannelAdminLogEventAction { - public static int constructor = 0x50c7ac8; + public static final int constructor = 0x50c7ac8; public long prev_value; public long new_value; @@ -44441,7 +44811,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionSendMessage extends ChannelAdminLogEventAction { - public static int constructor = 0x278f2868; + public static final int constructor = 0x278f2868; public Message message; @@ -44456,7 +44826,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeAvailableReactions extends ChannelAdminLogEventAction { - public static int constructor = 0xbe4e0ef8; + public static final int constructor = 0xbe4e0ef8; public ChatReactions prev_value; public ChatReactions new_value; @@ -44474,7 +44844,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleInvites extends ChannelAdminLogEventAction { - public static int constructor = 0x1b7907ae; + public static final int constructor = 0x1b7907ae; public boolean new_value; @@ -44489,7 +44859,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionParticipantUnmute extends ChannelAdminLogEventAction { - public static int constructor = 0xe64429c0; + public static final int constructor = 0xe64429c0; public TL_groupCallParticipant participant; @@ -44504,7 +44874,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionDeleteMessage extends ChannelAdminLogEventAction { - public static int constructor = 0x42e047bb; + public static final int constructor = 0x42e047bb; public Message message; @@ -44519,7 +44889,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeTitle extends ChannelAdminLogEventAction { - public static int constructor = 0xe6dfb825; + public static final int constructor = 0xe6dfb825; public String prev_value; public String new_value; @@ -44537,7 +44907,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionPinTopic extends ChannelAdminLogEventAction { - public static int constructor = 0x5d8d353b; + public static final int constructor = 0x5d8d353b; public int flags; public ForumTopic prev_topic; @@ -44566,7 +44936,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeHistoryTTL extends ChannelAdminLogEventAction { - public static int constructor = 0x6e941a38; + public static final int constructor = 0x6e941a38; public int prev_value; public int new_value; @@ -44584,7 +44954,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionToggleNoForwards extends ChannelAdminLogEventAction { - public static int constructor = 0xcb2ac766; + public static final int constructor = 0xcb2ac766; public boolean new_value; @@ -44599,7 +44969,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionCreateTopic extends ChannelAdminLogEventAction { - public static int constructor = 0x58707d28; + public static final int constructor = 0x58707d28; public ForumTopic topic; @@ -44614,7 +44984,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionDeleteTopic extends ChannelAdminLogEventAction { - public static int constructor = 0xae168909; + public static final int constructor = 0xae168909; public ForumTopic topic; @@ -44629,7 +44999,7 @@ public class TLRPC { } public static class TL_channelAdminLogEventActionChangeUsernames extends ChannelAdminLogEventAction { - public static int constructor = 0xf04fb3a9; + public static final int constructor = 0xf04fb3a9; public ArrayList prev_value = new ArrayList<>(); public ArrayList new_value = new ArrayList<>(); @@ -44675,8 +45045,44 @@ public class TLRPC { } } + public static class TL_channelAdminLogEventActionChangeColor extends ChannelAdminLogEventAction { + public static final int constructor = 0x3c2b247b; + + public int prev_value; + public int new_value; + + public void readParams(AbstractSerializedData stream, boolean exception) { + prev_value = stream.readInt32(exception); + new_value = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(prev_value); + stream.writeInt32(new_value); + } + } + + public static class TL_channelAdminLogEventActionChangeBackgroundEmoji extends ChannelAdminLogEventAction { + public static final int constructor = 0x445fc434; + + public long prev_value; + public long new_value; + + public void readParams(AbstractSerializedData stream, boolean exception) { + prev_value = stream.readInt64(exception); + new_value = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(prev_value); + stream.writeInt64(new_value); + } + } + public static class TL_channelAdminLogEventActionToggleAntiSpam extends ChannelAdminLogEventAction { - public static int constructor = 0x64f36dfc; + public static final int constructor = 0x64f36dfc; public boolean new_value; @@ -44713,7 +45119,7 @@ public class TLRPC { } public static class TL_inputWebFileGeoPointLocation extends InputWebFileLocation { - public static int constructor = 0x9f2221c9; + public static final int constructor = 0x9f2221c9; public InputGeoPoint geo_point; public long access_hash; @@ -44743,7 +45149,7 @@ public class TLRPC { } public static class TL_inputWebFileLocation extends InputWebFileLocation { - public static int constructor = 0xc239d686; + public static final int constructor = 0xc239d686; public String url; public long access_hash; @@ -44783,7 +45189,7 @@ public class TLRPC { } public static class TL_peerSelfLocated extends PeerLocated { - public static int constructor = 0xf8ec284b; + public static final int constructor = 0xf8ec284b; public int expires; @@ -44798,7 +45204,7 @@ public class TLRPC { } public static class TL_peerLocated extends PeerLocated { - public static int constructor = 0xca461b5d; + public static final int constructor = 0xca461b5d; public Peer peer; public int expires; @@ -44819,7 +45225,7 @@ public class TLRPC { } public static class TL_statsPercentValue extends TLObject { - public static int constructor = 0xcbce2fe0; + public static final int constructor = 0xcbce2fe0; public double part; public double total; @@ -44850,7 +45256,7 @@ public class TLRPC { } public static class TL_autoDownloadSettings extends TLObject { - public static int constructor = 0xbaa57628; + public static final int constructor = 0xbaa57628; public int flags; public boolean disabled; @@ -44908,7 +45314,7 @@ public class TLRPC { } public static class TL_account_sentEmailCode extends TLObject { - public static int constructor = 0x811f854f; + public static final int constructor = 0x811f854f; public String email_pattern; public int length; @@ -44939,7 +45345,7 @@ public class TLRPC { } public static class TL_messages_inactiveChats extends TLObject { - public static int constructor = 0xa927fec5; + public static final int constructor = 0xa927fec5; public ArrayList dates = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -45026,7 +45432,7 @@ public class TLRPC { } public static class TL_channelAdminRights_layer92 extends TLObject { - public static int constructor = 0x5d7ceba5; + public static final int constructor = 0x5d7ceba5; public int flags; public boolean change_info; @@ -45127,6 +45533,8 @@ public class TLRPC { public boolean stories_hidden_min; public boolean stories_unavailable; public int stories_max_id; + public int color; + public long background_emoji_id; public ArrayList usernames = new ArrayList<>(); @@ -45149,9 +45557,15 @@ public class TLRPC { case 0x4df30834: result = new TL_channel_layer104(); break; - case 0x94f592db: + case TL_channel.constructor: result = new TL_channel(); break; + case TL_channel_layer165_2.constructor: + result = new TL_channel_layer165_2(); + break; + case TL_channel_layer165.constructor: + result = new TL_channel_layer165(); + break; case 0x450b7115: result = new TL_channel_layer77(); break; @@ -45290,7 +45704,7 @@ public class TLRPC { } public static class TL_chatForbidden_old extends TL_chatForbidden { - public static int constructor = 0xfb0ccc41; + public static final int constructor = 0xfb0ccc41; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45308,7 +45722,7 @@ public class TLRPC { } public static class TL_chat_old2 extends TL_chat { - public static int constructor = 0x7312bc48; + public static final int constructor = 0x7312bc48; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -45341,7 +45755,7 @@ public class TLRPC { } public static class TL_chat extends Chat { - public static int constructor = 0x41cbf256; + public static final int constructor = 0x41cbf256; public void readParams(AbstractSerializedData stream, boolean exception) { readParams(stream, exception, true); @@ -45402,7 +45816,7 @@ public class TLRPC { } public static class TL_chat_layer131 extends TL_chat { - public static int constructor = 0x3bda1bde; + public static final int constructor = 0x3bda1bde; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45458,7 +45872,7 @@ public class TLRPC { } public static class TL_channelForbidden extends Chat { - public static int constructor = 0x17d493d5; + public static final int constructor = 0x17d493d5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45488,7 +45902,7 @@ public class TLRPC { } public static class TL_channelForbidden_layer131 extends TL_channelForbidden { - public static int constructor = 0x289da732; + public static final int constructor = 0x289da732; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45518,7 +45932,7 @@ public class TLRPC { } public static class TL_channelForbidden_layer67 extends TL_channelForbidden { - public static int constructor = 0x8537784f; + public static final int constructor = 0x8537784f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45542,7 +45956,7 @@ public class TLRPC { } public static class TL_channel_layer48 extends TL_channel { - public static int constructor = 0x4b1b7506; + public static final int constructor = 0x4b1b7506; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -45597,7 +46011,7 @@ public class TLRPC { } public static class TL_channelForbidden_layer52 extends TL_channelForbidden { - public static int constructor = 0x2d85832c; + public static final int constructor = 0x2d85832c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -45615,7 +46029,349 @@ public class TLRPC { } public static class TL_channel extends Chat { - public static int constructor = 0x94f592db; + public static final int constructor = 0x1981ea7e; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + left = (flags & 4) != 0; + broadcast = (flags & 32) != 0; + verified = (flags & 128) != 0; + megagroup = (flags & 256) != 0; + restricted = (flags & 512) != 0; + signatures = (flags & 2048) != 0; + min = (flags & 4096) != 0; + scam = (flags & 524288) != 0; + has_link = (flags & 1048576) != 0; + has_geo = (flags & 2097152) != 0; + slowmode_enabled = (flags & 4194304) != 0; + call_active = (flags & 8388608) != 0; + call_not_empty = (flags & 16777216) != 0; + fake = (flags & 33554432) != 0; + gigagroup = (flags & 67108864) != 0; + noforwards = (flags & 134217728) != 0; + join_to_send = (flags & 268435456) != 0; + join_request = (flags & 536870912) != 0; + forum = (flags & 1073741824) != 0; + flags2 = stream.readInt32(exception); + stories_hidden = (flags2 & 2) != 0; + stories_hidden_min = (flags2 & 4) != 0; + stories_unavailable = (flags2 & 8) != 0; + id = stream.readInt64(exception); + if ((flags & 8192) != 0) { + access_hash = stream.readInt64(exception); + } + title = stream.readString(exception); + if ((flags & 64) != 0) { + username = stream.readString(exception); + } + photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + date = 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++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 16384) != 0) { + admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32768) != 0) { + banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 262144) != 0) { + default_banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 131072) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags2 & 1) != 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_username object = TL_username.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + usernames.add(object); + } + } + if ((flags2 & 16) != 0) { + stories_max_id = stream.readInt32(exception); + } + if ((flags2 & 64) != 0) { + color = stream.readInt32(exception); + } + if ((flags2 & 32) != 0) { + background_emoji_id = stream.readInt64(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = left ? (flags | 4) : (flags &~ 4); + flags = broadcast ? (flags | 32) : (flags &~ 32); + flags = verified ? (flags | 128) : (flags &~ 128); + flags = megagroup ? (flags | 256) : (flags &~ 256); + flags = restricted ? (flags | 512) : (flags &~ 512); + flags = signatures ? (flags | 2048) : (flags &~ 2048); + flags = min ? (flags | 4096) : (flags &~ 4096); + flags = scam ? (flags | 524288) : (flags &~ 524288); + flags = has_link ? (flags | 1048576) : (flags &~ 1048576); + flags = has_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = slowmode_enabled ? (flags | 4194304) : (flags &~ 4194304); + flags = call_active ? (flags | 8388608) : (flags &~ 8388608); + flags = call_not_empty ? (flags | 16777216) : (flags &~ 16777216); + flags = fake ? (flags | 33554432) : (flags &~ 33554432); + flags = gigagroup ? (flags | 67108864) : (flags &~ 67108864); + flags = noforwards ? (flags | 134217728) : (flags &~ 134217728); + flags = join_to_send ? (flags | 268435456) : (flags &~ 268435456); + flags = join_request ? (flags | 536870912) : (flags &~ 536870912); + flags = forum ? (flags | 1073741824) : (flags &~ 1073741824); + stream.writeInt32(flags); + flags2 = stories_hidden ? (flags2 | 2) : (flags2 &~ 2); + flags2 = stories_hidden_min ? (flags2 | 4) : (flags2 &~ 4); + flags2 = stories_unavailable ? (flags2 | 8) : (flags2 &~ 8); + stream.writeInt32(flags2); + stream.writeInt64(id); + if ((flags & 8192) != 0) { + stream.writeInt64(access_hash); + } + stream.writeString(title); + if ((flags & 64) != 0) { + stream.writeString(username); + } + photo.serializeToStream(stream); + stream.writeInt32(date); + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 16384) != 0) { + admin_rights.serializeToStream(stream); + } + if ((flags & 32768) != 0) { + banned_rights.serializeToStream(stream); + } + if ((flags & 262144) != 0) { + default_banned_rights.serializeToStream(stream); + } + if ((flags & 131072) != 0) { + stream.writeInt32(participants_count); + } + if ((flags2 & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = usernames.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + usernames.get(a).serializeToStream(stream); + } + } + if ((flags2 & 16) != 0) { + stream.writeInt32(stories_max_id); + } + if ((flags2 & 64) != 0) { + stream.writeInt32(color); + } + if ((flags2 & 32) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + + public static class TL_channel_layer165 extends TL_channel { + public static final int constructor = 0x2458af8c; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + creator = (flags & 1) != 0; + left = (flags & 4) != 0; + broadcast = (flags & 32) != 0; + verified = (flags & 128) != 0; + megagroup = (flags & 256) != 0; + restricted = (flags & 512) != 0; + signatures = (flags & 2048) != 0; + min = (flags & 4096) != 0; + scam = (flags & 524288) != 0; + has_link = (flags & 1048576) != 0; + has_geo = (flags & 2097152) != 0; + slowmode_enabled = (flags & 4194304) != 0; + call_active = (flags & 8388608) != 0; + call_not_empty = (flags & 16777216) != 0; + fake = (flags & 33554432) != 0; + gigagroup = (flags & 67108864) != 0; + noforwards = (flags & 134217728) != 0; + join_to_send = (flags & 268435456) != 0; + join_request = (flags & 536870912) != 0; + forum = (flags & 1073741824) != 0; + flags2 = stream.readInt32(exception); + stories_hidden = (flags2 & 2) != 0; + stories_hidden_min = (flags2 & 4) != 0; + stories_unavailable = (flags2 & 8) != 0; + id = stream.readInt64(exception); + if ((flags & 8192) != 0) { + access_hash = stream.readInt64(exception); + } + title = stream.readString(exception); + if ((flags & 64) != 0) { + username = stream.readString(exception); + } + photo = ChatPhoto.TLdeserialize(stream, stream.readInt32(exception), exception); + date = 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++) { + TL_restrictionReason object = TL_restrictionReason.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + restriction_reason.add(object); + } + } + if ((flags & 16384) != 0) { + admin_rights = TL_chatAdminRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32768) != 0) { + banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 262144) != 0) { + default_banned_rights = TL_chatBannedRights.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 131072) != 0) { + participants_count = stream.readInt32(exception); + } + if ((flags2 & 1) != 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_username object = TL_username.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + usernames.add(object); + } + } + if ((flags2 & 16) != 0) { + stories_max_id = stream.readInt32(exception); + } + color = stream.readInt32(exception); + if ((flags2 & 32) != 0) { + background_emoji_id = stream.readInt64(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = creator ? (flags | 1) : (flags &~ 1); + flags = left ? (flags | 4) : (flags &~ 4); + flags = broadcast ? (flags | 32) : (flags &~ 32); + flags = verified ? (flags | 128) : (flags &~ 128); + flags = megagroup ? (flags | 256) : (flags &~ 256); + flags = restricted ? (flags | 512) : (flags &~ 512); + flags = signatures ? (flags | 2048) : (flags &~ 2048); + flags = min ? (flags | 4096) : (flags &~ 4096); + flags = scam ? (flags | 524288) : (flags &~ 524288); + flags = has_link ? (flags | 1048576) : (flags &~ 1048576); + flags = has_geo ? (flags | 2097152) : (flags &~ 2097152); + flags = slowmode_enabled ? (flags | 4194304) : (flags &~ 4194304); + flags = call_active ? (flags | 8388608) : (flags &~ 8388608); + flags = call_not_empty ? (flags | 16777216) : (flags &~ 16777216); + flags = fake ? (flags | 33554432) : (flags &~ 33554432); + flags = gigagroup ? (flags | 67108864) : (flags &~ 67108864); + flags = noforwards ? (flags | 134217728) : (flags &~ 134217728); + flags = join_to_send ? (flags | 268435456) : (flags &~ 268435456); + flags = join_request ? (flags | 536870912) : (flags &~ 536870912); + flags = forum ? (flags | 1073741824) : (flags &~ 1073741824); + stream.writeInt32(flags); + flags2 = stories_hidden ? (flags2 | 2) : (flags2 &~ 2); + flags2 = stories_hidden_min ? (flags2 | 4) : (flags2 &~ 4); + flags2 = stories_unavailable ? (flags2 | 8) : (flags2 &~ 8); + stream.writeInt32(flags2); + stream.writeInt64(id); + if ((flags & 8192) != 0) { + stream.writeInt64(access_hash); + } + stream.writeString(title); + if ((flags & 64) != 0) { + stream.writeString(username); + } + photo.serializeToStream(stream); + stream.writeInt32(date); + if ((flags & 512) != 0) { + stream.writeInt32(0x1cb5c415); + int count = restriction_reason.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + restriction_reason.get(a).serializeToStream(stream); + } + } + if ((flags & 16384) != 0) { + admin_rights.serializeToStream(stream); + } + if ((flags & 32768) != 0) { + banned_rights.serializeToStream(stream); + } + if ((flags & 262144) != 0) { + default_banned_rights.serializeToStream(stream); + } + if ((flags & 131072) != 0) { + stream.writeInt32(participants_count); + } + if ((flags2 & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = usernames.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + usernames.get(a).serializeToStream(stream); + } + } + if ((flags2 & 16) != 0) { + stream.writeInt32(stories_max_id); + } + stream.writeInt32(color); + if ((flags2 & 32) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + + public static class TL_channel_layer165_2 extends TL_channel { + public static final int constructor = 0x94f592db; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -45776,7 +46532,7 @@ public class TLRPC { } public static class TL_channel_layer161 extends TL_channel { - public static int constructor = 0x83259464; + public static final int constructor = 0x83259464; public void readParams(AbstractSerializedData stream, boolean exception) { readParams(stream, exception, true); @@ -45933,7 +46689,7 @@ public class TLRPC { } public static class TL_channel_layer147 extends TL_channel { - public static int constructor = 0x8261ac61; + public static final int constructor = 0x8261ac61; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46056,7 +46812,7 @@ public class TLRPC { } public static class TL_chatForbidden extends Chat { - public static int constructor = 0x6592a1a7; + public static final int constructor = 0x6592a1a7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46072,7 +46828,7 @@ public class TLRPC { } public static class TL_chatForbidden_layer131 extends TL_chatForbidden { - public static int constructor = 0x7328bdb; + public static final int constructor = 0x7328bdb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46088,7 +46844,7 @@ public class TLRPC { } public static class TL_channel_layer67 extends TL_channel { - public static int constructor = 0xa14dca52; + public static final int constructor = 0xa14dca52; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46149,7 +46905,7 @@ public class TLRPC { } public static class TL_channel_old extends TL_channel { - public static int constructor = 0x678e9587; + public static final int constructor = 0x678e9587; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46196,7 +46952,7 @@ public class TLRPC { } public static class TL_chat_old extends TL_chat { - public static int constructor = 0x6e9c9bc7; + public static final int constructor = 0x6e9c9bc7; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt32(exception); @@ -46221,7 +46977,7 @@ public class TLRPC { } public static class TL_channel_layer131 extends TL_channel { - public static int constructor = 0xd31a961e; + public static final int constructor = 0xd31a961e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46338,7 +47094,7 @@ public class TLRPC { } public static class TL_channel_layer104 extends TL_channel { - public static int constructor = 0x4df30834; + public static final int constructor = 0x4df30834; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46428,7 +47184,7 @@ public class TLRPC { } public static class TL_channelParticipantBanned_layer92 extends TL_channelParticipantBanned { - public static int constructor = 0x222c1886; + public static final int constructor = 0x222c1886; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46454,7 +47210,7 @@ public class TLRPC { } public static class TL_channel_layer77 extends TL_channel { - public static int constructor = 0x450b7115; + public static final int constructor = 0x450b7115; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46531,7 +47287,7 @@ public class TLRPC { } public static class TL_channel_layer72 extends TL_channel { - public static int constructor = 0xcb44b1c; + public static final int constructor = 0xcb44b1c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46603,7 +47359,7 @@ public class TLRPC { } public static class TL_channel_layer92 extends TL_channel { - public static int constructor = 0xc88974ac; + public static final int constructor = 0xc88974ac; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46680,7 +47436,7 @@ public class TLRPC { } public static class TL_chat_layer92 extends TL_chat { - public static int constructor = 0xd91cdd54; + public static final int constructor = 0xd91cdd54; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46719,7 +47475,7 @@ public class TLRPC { } public static class TL_restrictionReason extends TLObject { - public static int constructor = 0xd072acb4; + public static final int constructor = 0xd072acb4; public String platform; public String reason; @@ -46762,6 +47518,7 @@ public class TLRPC { public boolean masks; public boolean videos; public boolean emojis; + public boolean text_color; public long id; public long access_hash; public String title; @@ -46814,7 +47571,7 @@ public class TLRPC { } public static class TL_stickerSet_old extends TL_stickerSet { - public static int constructor = 0xa7a43b17; + public static final int constructor = 0xa7a43b17; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -46834,7 +47591,7 @@ public class TLRPC { } public static class TL_stickerSet extends StickerSet { - public static int constructor = 0x2dd14edc; + public static final int constructor = 0x2dd14edc; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -46844,6 +47601,7 @@ public class TLRPC { animated = (flags & 32) != 0; videos = (flags & 64) != 0; emojis = (flags & 128) != 0; + text_color = (flags & 512) != 0; if ((flags & 1) != 0) { installed_date = stream.readInt32(exception); } @@ -46889,6 +47647,7 @@ public class TLRPC { flags = animated ? (flags | 32) : (flags &~ 32); flags = videos ? (flags | 64) : (flags &~ 64); flags = emojis ? (flags | 128) : (flags &~ 128); + flags = text_color ? (flags | 512) : (flags &~ 512); stream.writeInt32(flags); if ((flags & 1) != 0) { stream.writeInt32(installed_date); @@ -46920,7 +47679,7 @@ public class TLRPC { } public static class TL_stickerSet_layer143 extends TL_stickerSet { - public static int constructor = 0xd7df217a; + public static final int constructor = 0xd7df217a; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -47006,7 +47765,7 @@ public class TLRPC { } public static class TL_stickerSet_layer96 extends TL_stickerSet { - public static int constructor = 0x5585a139; + public static final int constructor = 0x5585a139; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47044,7 +47803,7 @@ public class TLRPC { } public static class TL_stickerSet_layer97 extends TL_stickerSet { - public static int constructor = 0x6a90bcb7; + public static final int constructor = 0x6a90bcb7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47091,7 +47850,7 @@ public class TLRPC { } public static class TL_stickerSet_layer126 extends TL_stickerSet { - public static int constructor = 0x40e237a8; + public static final int constructor = 0x40e237a8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47162,7 +47921,7 @@ public class TLRPC { } public static class TL_stickerSet_layer121 extends TL_stickerSet { - public static int constructor = 0xeeb46f27; + public static final int constructor = 0xeeb46f27; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47217,7 +47976,7 @@ public class TLRPC { } public static class TL_stickerSet_layer75 extends TL_stickerSet { - public static int constructor = 0xcd303b41; + public static final int constructor = 0xcd303b41; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47297,7 +48056,7 @@ public class TLRPC { } public static class TL_storage_fileUnknown extends storage_FileType { - public static int constructor = 0xaa963b05; + public static final int constructor = 0xaa963b05; public void serializeToStream(AbstractSerializedData stream) { @@ -47306,7 +48065,7 @@ public class TLRPC { } public static class TL_storage_fileMp4 extends storage_FileType { - public static int constructor = 0xb3cea0e4; + public static final int constructor = 0xb3cea0e4; public void serializeToStream(AbstractSerializedData stream) { @@ -47315,7 +48074,7 @@ public class TLRPC { } public static class TL_storage_fileWebp extends storage_FileType { - public static int constructor = 0x1081464c; + public static final int constructor = 0x1081464c; public void serializeToStream(AbstractSerializedData stream) { @@ -47324,7 +48083,7 @@ public class TLRPC { } public static class TL_storage_filePng extends storage_FileType { - public static int constructor = 0xa4f63c0; + public static final int constructor = 0xa4f63c0; public void serializeToStream(AbstractSerializedData stream) { @@ -47333,7 +48092,7 @@ public class TLRPC { } public static class TL_storage_fileGif extends storage_FileType { - public static int constructor = 0xcae1aadf; + public static final int constructor = 0xcae1aadf; public void serializeToStream(AbstractSerializedData stream) { @@ -47342,7 +48101,7 @@ public class TLRPC { } public static class TL_storage_filePdf extends storage_FileType { - public static int constructor = 0xae1e508d; + public static final int constructor = 0xae1e508d; public void serializeToStream(AbstractSerializedData stream) { @@ -47351,7 +48110,7 @@ public class TLRPC { } public static class TL_storage_fileMp3 extends storage_FileType { - public static int constructor = 0x528a0677; + public static final int constructor = 0x528a0677; public void serializeToStream(AbstractSerializedData stream) { @@ -47360,7 +48119,7 @@ public class TLRPC { } public static class TL_storage_fileJpeg extends storage_FileType { - public static int constructor = 0x7efe0e; + public static final int constructor = 0x7efe0e; public void serializeToStream(AbstractSerializedData stream) { @@ -47369,7 +48128,7 @@ public class TLRPC { } public static class TL_storage_fileMov extends storage_FileType { - public static int constructor = 0x4b09ebbc; + public static final int constructor = 0x4b09ebbc; public void serializeToStream(AbstractSerializedData stream) { @@ -47378,7 +48137,7 @@ public class TLRPC { } public static class TL_storage_filePartial extends storage_FileType { - public static int constructor = 0x40bc6f52; + public static final int constructor = 0x40bc6f52; public void serializeToStream(AbstractSerializedData stream) { @@ -47418,7 +48177,7 @@ public class TLRPC { } public static class TL_auth_codeTypeSms extends auth_CodeType { - public static int constructor = 0x72a3158c; + public static final int constructor = 0x72a3158c; public void serializeToStream(AbstractSerializedData stream) { @@ -47427,7 +48186,7 @@ public class TLRPC { } public static class TL_auth_codeTypeCall extends auth_CodeType { - public static int constructor = 0x741cd3e3; + public static final int constructor = 0x741cd3e3; public void serializeToStream(AbstractSerializedData stream) { @@ -47436,7 +48195,7 @@ public class TLRPC { } public static class TL_auth_codeTypeFlashCall extends auth_CodeType { - public static int constructor = 0x226ccefb; + public static final int constructor = 0x226ccefb; public void serializeToStream(AbstractSerializedData stream) { @@ -47445,7 +48204,7 @@ public class TLRPC { } public static class TL_auth_codeTypeMissedCall extends auth_CodeType { - public static int constructor = 0xd61ad6ee; + public static final int constructor = 0xd61ad6ee; public void serializeToStream(AbstractSerializedData stream) { @@ -47454,7 +48213,7 @@ public class TLRPC { } public static class TL_auth_codeTypeFragmentSms extends auth_CodeType { - public static int constructor = 0x6ed998c; + public static final int constructor = 0x6ed998c; public void serializeToStream(AbstractSerializedData stream) { @@ -47463,7 +48222,7 @@ public class TLRPC { } public static class TL_messages_translateResult extends TLObject { - public static int constructor = 0x33db32f8; + public static final int constructor = 0x33db32f8; public ArrayList result = new ArrayList<>(); @@ -47582,7 +48341,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterGif extends MessagesFilter { - public static int constructor = 0xffc86587; + public static final int constructor = 0xffc86587; public void serializeToStream(AbstractSerializedData stream) { @@ -47591,7 +48350,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterMusic extends MessagesFilter { - public static int constructor = 0x3751b49e; + public static final int constructor = 0x3751b49e; public void serializeToStream(AbstractSerializedData stream) { @@ -47600,7 +48359,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterChatPhotos extends MessagesFilter { - public static int constructor = 0x3a20ecb8; + public static final int constructor = 0x3a20ecb8; public void serializeToStream(AbstractSerializedData stream) { @@ -47609,7 +48368,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterPhotos extends MessagesFilter { - public static int constructor = 0x9609a51c; + public static final int constructor = 0x9609a51c; public void serializeToStream(AbstractSerializedData stream) { @@ -47618,7 +48377,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterUrl extends MessagesFilter { - public static int constructor = 0x7ef0dd87; + public static final int constructor = 0x7ef0dd87; public void serializeToStream(AbstractSerializedData stream) { @@ -47627,7 +48386,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterDocument extends MessagesFilter { - public static int constructor = 0x9eddf188; + public static final int constructor = 0x9eddf188; public void serializeToStream(AbstractSerializedData stream) { @@ -47636,7 +48395,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterPhotoVideo extends MessagesFilter { - public static int constructor = 0x56e9f0e4; + public static final int constructor = 0x56e9f0e4; public void serializeToStream(AbstractSerializedData stream) { @@ -47645,7 +48404,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterPhotoVideoDocuments extends MessagesFilter { - public static int constructor = 0xd95e73bb; + public static final int constructor = 0xd95e73bb; public void serializeToStream(AbstractSerializedData stream) { @@ -47654,7 +48413,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterGeo extends MessagesFilter { - public static int constructor = 0xe7026d0d; + public static final int constructor = 0xe7026d0d; public void serializeToStream(AbstractSerializedData stream) { @@ -47663,7 +48422,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterPinned extends MessagesFilter { - public static int constructor = 0x1bb00451; + public static final int constructor = 0x1bb00451; public void serializeToStream(AbstractSerializedData stream) { @@ -47672,7 +48431,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterMyMentions extends MessagesFilter { - public static int constructor = 0xc1f8e69a; + public static final int constructor = 0xc1f8e69a; public void serializeToStream(AbstractSerializedData stream) { @@ -47681,7 +48440,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterRoundVoice extends MessagesFilter { - public static int constructor = 0x7a7c17a4; + public static final int constructor = 0x7a7c17a4; public void serializeToStream(AbstractSerializedData stream) { @@ -47690,7 +48449,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterVoice extends MessagesFilter { - public static int constructor = 0x50f5c392; + public static final int constructor = 0x50f5c392; public void serializeToStream(AbstractSerializedData stream) { @@ -47699,7 +48458,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterContacts extends MessagesFilter { - public static int constructor = 0xe062db83; + public static final int constructor = 0xe062db83; public void serializeToStream(AbstractSerializedData stream) { @@ -47708,7 +48467,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterVideo extends MessagesFilter { - public static int constructor = 0x9fc00e65; + public static final int constructor = 0x9fc00e65; public void serializeToStream(AbstractSerializedData stream) { @@ -47717,7 +48476,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterPhoneCalls extends MessagesFilter { - public static int constructor = 0x80c99768; + public static final int constructor = 0x80c99768; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -47733,7 +48492,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterEmpty extends MessagesFilter { - public static int constructor = 0x57e2f66c; + public static final int constructor = 0x57e2f66c; public void serializeToStream(AbstractSerializedData stream) { @@ -47742,7 +48501,7 @@ public class TLRPC { } public static class TL_inputMessagesFilterRoundVideo extends MessagesFilter { - public static int constructor = 0xb549da53; + public static final int constructor = 0xb549da53; public void serializeToStream(AbstractSerializedData stream) { @@ -47751,7 +48510,7 @@ public class TLRPC { } public static class TL_phone_groupParticipants extends TLObject { - public static int constructor = 0xf47751b6; + public static final int constructor = 0xf47751b6; public int count; public ArrayList participants = new ArrayList<>(); @@ -47873,7 +48632,7 @@ public class TLRPC { } public static class TL_pageListOrderedItemText extends PageListOrderedItem { - public static int constructor = 0x5e068047; + public static final int constructor = 0x5e068047; public String num; public RichText text; @@ -47891,7 +48650,7 @@ public class TLRPC { } public static class TL_pageListOrderedItemBlocks extends PageListOrderedItem { - public static int constructor = 0x98dd8936; + public static final int constructor = 0x98dd8936; public String num; public ArrayList blocks = new ArrayList<>(); @@ -47928,7 +48687,7 @@ public class TLRPC { } public static class TL_messages_messageEmpty extends TLObject { - public static int constructor = 0x3f4e0648; + public static final int constructor = 0x3f4e0648; public static TL_messages_messageEmpty TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -47950,7 +48709,7 @@ public class TLRPC { } public static class TL_secureCredentialsEncrypted extends TLObject { - public static int constructor = 0x33f0ea47; + public static final int constructor = 0x33f0ea47; public byte[] data; public byte[] hash; @@ -48029,7 +48788,7 @@ public class TLRPC { } public static class TL_messageFwdHeader_layer68 extends TL_messageFwdHeader { - public static int constructor = 0xc786ddcb; + public static final int constructor = 0xc786ddcb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48065,7 +48824,7 @@ public class TLRPC { } public static class TL_messageFwdHeader extends MessageFwdHeader { - public static int constructor = 0x5f777dce; + public static final int constructor = 0x5f777dce; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48125,7 +48884,7 @@ public class TLRPC { } public static class TL_messageFwdHeader_layer118 extends TL_messageFwdHeader { - public static int constructor = 0x353a686b; + public static final int constructor = 0x353a686b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48191,7 +48950,7 @@ public class TLRPC { } public static class TL_messageFwdHeader_layer112 extends TL_messageFwdHeader { - public static int constructor = 0xec338270; + public static final int constructor = 0xec338270; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48251,7 +49010,7 @@ public class TLRPC { } public static class TL_messageFwdHeader_layer72 extends TL_messageFwdHeader { - public static int constructor = 0xfadff4ac; + public static final int constructor = 0xfadff4ac; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48293,7 +49052,7 @@ public class TLRPC { } public static class TL_messageFwdHeader_layer96 extends TL_messageFwdHeader { - public static int constructor = 0x559ebe6d; + public static final int constructor = 0x559ebe6d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48386,7 +49145,7 @@ public class TLRPC { } public static class TL_fileLocationUnavailable extends FileLocation { - public static int constructor = 0x7c596b46; + public static final int constructor = 0x7c596b46; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48404,7 +49163,7 @@ public class TLRPC { } public static class TL_fileLocation_layer82 extends TL_fileLocation_layer97 { - public static int constructor = 0x53d69076; + public static final int constructor = 0x53d69076; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48424,7 +49183,7 @@ public class TLRPC { } public static class TL_fileLocation_layer97 extends FileLocation { - public static int constructor = 0x91d11eb; + public static final int constructor = 0x91d11eb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48446,7 +49205,7 @@ public class TLRPC { } public static class TL_fileLocationToBeDeprecated extends FileLocation { - public static int constructor = 0xbc7fc6cd; + public static final int constructor = 0xbc7fc6cd; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48462,7 +49221,7 @@ public class TLRPC { } public static class TL_fileEncryptedLocation extends FileLocation { - public static int constructor = 0x55555554; + public static final int constructor = 0x55555554; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48510,7 +49269,7 @@ public class TLRPC { } public static class TL_messages_savedGifsNotModified extends messages_SavedGifs { - public static int constructor = 0xe8025ca2; + public static final int constructor = 0xe8025ca2; public void serializeToStream(AbstractSerializedData stream) { @@ -48519,7 +49278,7 @@ public class TLRPC { } public static class TL_messages_savedGifs extends messages_SavedGifs { - public static int constructor = 0x84a02a0d; + public static final int constructor = 0x84a02a0d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48622,7 +49381,7 @@ public class TLRPC { } public static class TL_photoStrippedSize extends PhotoSize { - public static int constructor = 0xe0b0bc2e; + public static final int constructor = 0xe0b0bc2e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48639,7 +49398,7 @@ public class TLRPC { } public static class TL_photoSizeProgressive_layer127 extends TL_photoSizeProgressive { - public static int constructor = 0x5aa86a51; + public static final int constructor = 0x5aa86a51; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48679,7 +49438,7 @@ public class TLRPC { } public static class TL_photoSize_layer127 extends TL_photoSize { - public static int constructor = 0x77bfb61b; + public static final int constructor = 0x77bfb61b; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48701,7 +49460,7 @@ public class TLRPC { } public static class TL_photoSizeEmpty extends PhotoSize { - public static int constructor = 0xe17e23c; + public static final int constructor = 0xe17e23c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48715,7 +49474,7 @@ public class TLRPC { } public static class TL_photoCachedSize_layer127 extends TL_photoCachedSize { - public static int constructor = 0xe9a734fa; + public static final int constructor = 0xe9a734fa; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48737,7 +49496,7 @@ public class TLRPC { } public static class TL_photoSize extends PhotoSize { - public static int constructor = 0x75c78e60; + public static final int constructor = 0x75c78e60; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48757,7 +49516,7 @@ public class TLRPC { } public static class TL_photoCachedSize extends PhotoSize { - public static int constructor = 0x21e1ad6; + public static final int constructor = 0x21e1ad6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -48777,7 +49536,7 @@ public class TLRPC { } public static class TL_photoSizeProgressive extends PhotoSize { - public static int constructor = 0xfa3efb95; + public static final int constructor = 0xfa3efb95; public ArrayList sizes = new ArrayList<>(); @@ -48850,7 +49609,7 @@ public class TLRPC { } public static class TL_chatInviteExported extends ExportedChatInvite { - public static int constructor = 0xab4a819; + public static final int constructor = 0xab4a819; public int flags; public boolean revoked; @@ -48927,7 +49686,7 @@ public class TLRPC { } public static class TL_chatInviteExported_layer133 extends TL_chatInviteExported { - public static int constructor = 0xb18105e8; + public static final int constructor = 0xb18105e8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -48974,7 +49733,7 @@ public class TLRPC { } public static class TL_chatInviteEmpty_layer122 extends TL_chatInviteExported { - public static int constructor = 0x69df3769; + public static final int constructor = 0x69df3769; public void serializeToStream(AbstractSerializedData stream) { @@ -48983,7 +49742,7 @@ public class TLRPC { } public static class TL_chatInviteExported_layer131 extends TL_chatInviteExported { - public static int constructor = 0x6e24fc9d; + public static final int constructor = 0x6e24fc9d; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -49031,7 +49790,7 @@ public class TLRPC { } public static class TL_chatInviteExported_layer122 extends TL_chatInviteExported { - public static int constructor = 0xfc2e05bc; + public static final int constructor = 0xfc2e05bc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -49071,7 +49830,7 @@ public class TLRPC { } public static class TL_inputFileBig extends InputFile { - public static int constructor = 0xfa4f0bb5; + public static final int constructor = 0xfa4f0bb5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -49089,7 +49848,7 @@ public class TLRPC { } public static class TL_inputFile extends InputFile { - public static int constructor = 0xf52ff27f; + public static final int constructor = 0xf52ff27f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -49109,7 +49868,7 @@ public class TLRPC { } public static class TL_textWithEntities extends TLObject { - public static int constructor = 0x751f3146; + public static final int constructor = 0x751f3146; public String text; public ArrayList entities = new ArrayList<>(); @@ -49159,7 +49918,7 @@ public class TLRPC { } public static class TL_account_webAuthorizations extends TLObject { - public static int constructor = 0xed56c9fc; + public static final int constructor = 0xed56c9fc; public ArrayList authorizations = new ArrayList<>(); public ArrayList users = new ArrayList<>(); @@ -49228,7 +49987,7 @@ public class TLRPC { } public static class TL_updates_state extends TLObject { - public static int constructor = 0xa56c2a3e; + public static final int constructor = 0xa56c2a3e; public int pts; public int qts; @@ -49294,7 +50053,7 @@ public class TLRPC { } public static class TL_reactionCount extends ReactionCount { - public static int constructor = 0xa3d1cb80; + public static final int constructor = 0xa3d1cb80; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -49339,7 +50098,7 @@ public class TLRPC { } public static class TL_messages_availableReactionsNotModified extends messages_AvailableReactions { - public static int constructor = 0x9f071957; + public static final int constructor = 0x9f071957; public void serializeToStream(AbstractSerializedData stream) { @@ -49348,7 +50107,7 @@ public class TLRPC { } public static class TL_messages_availableReactions extends messages_AvailableReactions { - public static int constructor = 0x768e3aad; + public static final int constructor = 0x768e3aad; public int hash; public ArrayList reactions = new ArrayList<>(); @@ -49417,7 +50176,7 @@ public class TLRPC { public ArrayList premium_gifts = new ArrayList<>(); public Photo fallback_photo; public WallPaper wallpaper; - public PeerStories stories; + public TL_stories.PeerStories stories; public static UserFull TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { UserFull result = null; @@ -49473,7 +50232,7 @@ public class TLRPC { } public static class TL_userFull extends UserFull { - public static int constructor = 0xb9b12c6c; + public static final int constructor = 0xb9b12c6c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -49548,7 +50307,7 @@ public class TLRPC { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 33554432) != 0) { - stories = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -49623,7 +50382,7 @@ public class TLRPC { } public static class TL_userFull_layer162 extends UserFull { - public static int constructor = 0x4fe1cc86; + public static final int constructor = 0x4fe1cc86; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -49698,7 +50457,7 @@ public class TLRPC { wallpaper = WallPaper.TLdeserialize(stream, stream.readInt32(exception), exception); } if ((flags & 33554432) != 0) { - stories = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + stories = TL_stories.PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -49773,7 +50532,7 @@ public class TLRPC { } public static class TL_userFull_layer159 extends UserFull { - public static int constructor = 0x93eadb53; + public static final int constructor = 0x93eadb53; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -49913,7 +50672,7 @@ public class TLRPC { } public static class TL_userFull_layer156 extends UserFull { - public static int constructor = 0xf8d32aed; + public static final int constructor = 0xf8d32aed; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -50047,7 +50806,7 @@ public class TLRPC { } public static class TL_userFull_layer150_rev2 extends UserFull { - public static int constructor = 0xec6d41e3; + public static final int constructor = 0xec6d41e3; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -50173,7 +50932,7 @@ public class TLRPC { } public static class TL_userFull_layer150 extends UserFull { - public static int constructor = 0xc4b1fc3f; + public static final int constructor = 0xc4b1fc3f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -50293,7 +51052,7 @@ public class TLRPC { } public static class TL_userFull_layer143 extends TL_userFull { - public static int constructor = 0x8c72ea81; + public static final int constructor = 0x8c72ea81; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -50386,7 +51145,7 @@ public class TLRPC { } public static class TL_userFull_layer139 extends UserFull { - public static int constructor = 0xcf366521; + public static final int constructor = 0xcf366521; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -50467,7 +51226,7 @@ public class TLRPC { } public static class TL_userFull_layer134 extends TL_userFull { - public static int constructor = 0xd697ff05; + public static final int constructor = 0xd697ff05; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50543,7 +51302,7 @@ public class TLRPC { } public static class TL_userFull_layer101 extends TL_userFull { - public static int constructor = 0x745559cc; + public static final int constructor = 0x745559cc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50603,7 +51362,7 @@ public class TLRPC { } public static class TL_userFull_layer98 extends TL_userFull { - public static int constructor = 0x8ea4a881; + public static final int constructor = 0x8ea4a881; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50657,7 +51416,7 @@ public class TLRPC { } public static class TL_userFull_layer131 extends TL_userFull { - public static int constructor = 0x139a9a77; + public static final int constructor = 0x139a9a77; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50727,7 +51486,7 @@ public class TLRPC { } public static class TL_userFull_layer123 extends TL_userFull { - public static int constructor = 0xedf17c12; + public static final int constructor = 0xedf17c12; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50852,7 +51611,7 @@ public class TLRPC { } public static class TL_updates extends Updates { - public static int constructor = 0x74ae4240; + public static final int constructor = 0x74ae4240; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50907,7 +51666,7 @@ public class TLRPC { } public static class TL_updateShortMessage extends Updates { - public static int constructor = 0x313bc7f8; + public static final int constructor = 0x313bc7f8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50955,7 +51714,7 @@ public class TLRPC { } public static class TL_updateShortSentMessage extends Updates { - public static int constructor = 0x9015e101; + public static final int constructor = 0x9015e101; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -50992,7 +51751,7 @@ public class TLRPC { } public static class TL_updateShort extends Updates { - public static int constructor = 0x78d4dec1; + public static final int constructor = 0x78d4dec1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51002,7 +51761,7 @@ public class TLRPC { } public static class TL_updateShortChatMessage extends Updates { - public static int constructor = 0x4d6deea5; + public static final int constructor = 0x4d6deea5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51051,7 +51810,7 @@ public class TLRPC { } public static class TL_updatesCombined extends Updates { - public static int constructor = 0x725b04c3; + public static final int constructor = 0x725b04c3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51107,7 +51866,7 @@ public class TLRPC { } public static class TL_updatesTooLong extends Updates { - public static int constructor = 0xe317af7e; + public static final int constructor = 0xe317af7e; } public static abstract class WallPaper extends TLObject { @@ -51152,7 +51911,7 @@ public class TLRPC { } public static class TL_wallPaper extends WallPaper { - public static int constructor = 0xa437c3ed; + public static final int constructor = 0xa437c3ed; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51188,7 +51947,7 @@ public class TLRPC { } public static class TL_wallPaper_layer94 extends TL_wallPaper { - public static int constructor = 0xf04f91ec; + public static final int constructor = 0xf04f91ec; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51214,7 +51973,7 @@ public class TLRPC { } public static class TL_wallPaperNoFile_layer128 extends TL_wallPaperNoFile { - public static int constructor = 0x8af40b25; + public static final int constructor = 0x8af40b25; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51238,7 +51997,7 @@ public class TLRPC { } public static class TL_wallPaperNoFile extends WallPaper { - public static int constructor = 0xe0804116; + public static final int constructor = 0xe0804116; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51264,7 +52023,7 @@ public class TLRPC { } public static class TL_paymentSavedCredentialsCard extends TLObject { - public static int constructor = 0xcdc27a1f; + public static final int constructor = 0xcdc27a1f; public String id; public String title; @@ -51317,7 +52076,7 @@ public class TLRPC { } public static class TL_pageListItemBlocks extends PageListItem { - public static int constructor = 0x25e073fc; + public static final int constructor = 0x25e073fc; public ArrayList blocks = new ArrayList<>(); @@ -51351,7 +52110,7 @@ public class TLRPC { } public static class TL_pageListItemText extends PageListItem { - public static int constructor = 0xb92fb6cd; + public static final int constructor = 0xb92fb6cd; public RichText text; @@ -51366,7 +52125,7 @@ public class TLRPC { } public static class TL_stickerPack extends TLObject { - public static int constructor = 0x12b299d4; + public static final int constructor = 0x12b299d4; public String emoticon; public ArrayList documents = new ArrayList<>(); @@ -51437,7 +52196,7 @@ public class TLRPC { } public static class TL_emojiStatusEmpty extends EmojiStatus { - public static int constructor = 0x2de11aae; + public static final int constructor = 0x2de11aae; public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); @@ -51445,7 +52204,7 @@ public class TLRPC { } public static class TL_emojiStatus extends EmojiStatus { - public static int constructor = 0x929b619d; + public static final int constructor = 0x929b619d; public long document_id; @@ -51460,7 +52219,7 @@ public class TLRPC { } public static class TL_emojiStatusUntil extends EmojiStatus { - public static int constructor = 0xfa30a8c7; + public static final int constructor = 0xfa30a8c7; public long document_id; public int until; @@ -51479,7 +52238,7 @@ public class TLRPC { public static class TL_inputEncryptedChat extends TLObject { - public static int constructor = 0xf141b5e1; + public static final int constructor = 0xf141b5e1; public int chat_id; public long access_hash; @@ -51535,7 +52294,7 @@ public class TLRPC { } public static class TL_inputChatPhoto extends InputChatPhoto { - public static int constructor = 0x8953ad37; + public static final int constructor = 0x8953ad37; public InputPhoto id; @@ -51550,7 +52309,7 @@ public class TLRPC { } public static class TL_inputChatPhotoEmpty extends InputChatPhoto { - public static int constructor = 0x1ca48f57; + public static final int constructor = 0x1ca48f57; public void serializeToStream(AbstractSerializedData stream) { @@ -51559,7 +52318,7 @@ public class TLRPC { } public static class TL_inputChatUploadedPhoto extends InputChatPhoto { - public static int constructor = 0xbdcdaec0; + public static final int constructor = 0xbdcdaec0; public int flags; public InputFile file; @@ -51602,7 +52361,7 @@ public class TLRPC { } public static class TL_nearestDc extends TLObject { - public static int constructor = 0x8e1a1775; + public static final int constructor = 0x8e1a1775; public String country; public int this_dc; @@ -51636,7 +52395,7 @@ public class TLRPC { } public static class TL_payments_savedInfo extends TLObject { - public static int constructor = 0xfb8fe43c; + public static final int constructor = 0xfb8fe43c; public int flags; public boolean has_saved_credentials; @@ -51699,7 +52458,7 @@ public class TLRPC { } public static class TL_inputPhotoEmpty extends InputPhoto { - public static int constructor = 0x1cd7bf0d; + public static final int constructor = 0x1cd7bf0d; public void serializeToStream(AbstractSerializedData stream) { @@ -51708,7 +52467,7 @@ public class TLRPC { } public static class TL_inputPhoto extends InputPhoto { - public static int constructor = 0x3bb3b94a; + public static final int constructor = 0x3bb3b94a; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -51726,7 +52485,7 @@ public class TLRPC { } public static class TL_messages_messageReactionsList extends TLObject { - public static int constructor = 0x31bd492d; + public static final int constructor = 0x31bd492d; public int flags; public int count; @@ -51830,7 +52589,7 @@ public class TLRPC { } public static class TL_importedContact extends TLObject { - public static int constructor = 0xc13e3c50; + public static final int constructor = 0xc13e3c50; public long user_id; public long client_id; @@ -51861,7 +52620,7 @@ public class TLRPC { } public static class TL_chatOnlines extends TLObject { - public static int constructor = 0xf041e250; + public static final int constructor = 0xf041e250; public int onlines; @@ -51911,7 +52670,7 @@ public class TLRPC { } public static class TL_messages_recentStickers extends messages_RecentStickers { - public static int constructor = 0x88d37c56; + public static final int constructor = 0x88d37c56; public long hash; public ArrayList packs = new ArrayList<>(); @@ -51988,7 +52747,7 @@ public class TLRPC { } public static class TL_messages_recentStickersNotModified extends messages_RecentStickers { - public static int constructor = 0xb17f890; + public static final int constructor = 0xb17f890; public void serializeToStream(AbstractSerializedData stream) { @@ -51997,7 +52756,7 @@ public class TLRPC { } public static class TL_pageRelatedArticle extends TLObject { - public static int constructor = 0xb390dc08; + public static final int constructor = 0xb390dc08; public int flags; public String url; @@ -52066,7 +52825,7 @@ public class TLRPC { } public static class TL_accountDaysTTL extends TLObject { - public static int constructor = 0xb8d0afdf; + public static final int constructor = 0xb8d0afdf; public int days; @@ -52116,7 +52875,7 @@ public class TLRPC { } public static class TL_messages_stickersNotModified extends messages_Stickers { - public static int constructor = 0xf1749a22; + public static final int constructor = 0xf1749a22; public void serializeToStream(AbstractSerializedData stream) { @@ -52125,7 +52884,7 @@ public class TLRPC { } public static class TL_messages_stickers extends messages_Stickers { - public static int constructor = 0x30a6ec7e; + public static final int constructor = 0x30a6ec7e; public long hash; public ArrayList stickers = new ArrayList<>(); @@ -52221,7 +52980,7 @@ public class TLRPC { } public static class TL_inputPeerSelf extends InputPeer { - public static int constructor = 0x7da07ec9; + public static final int constructor = 0x7da07ec9; public void serializeToStream(AbstractSerializedData stream) { @@ -52230,7 +52989,7 @@ public class TLRPC { } public static class TL_inputPeerUserFromMessage extends InputPeer { - public static int constructor = 0xa87b0a1c; + public static final int constructor = 0xa87b0a1c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52248,7 +53007,7 @@ public class TLRPC { } public static class TL_inputPeerUser extends InputPeer { - public static int constructor = 0xdde8a54c; + public static final int constructor = 0xdde8a54c; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52264,7 +53023,7 @@ public class TLRPC { } public static class TL_inputPeerChat_layer131 extends TL_inputPeerChat { - public static int constructor = 0x179be863; + public static final int constructor = 0x179be863; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52278,7 +53037,7 @@ public class TLRPC { } public static class TL_inputPeerChannel extends InputPeer { - public static int constructor = 0x27bcbbfc; + public static final int constructor = 0x27bcbbfc; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52294,7 +53053,7 @@ public class TLRPC { } public static class TL_inputPeerUser_layer131 extends TL_inputPeerUser { - public static int constructor = 0x7b8e7de6; + public static final int constructor = 0x7b8e7de6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52310,7 +53069,7 @@ public class TLRPC { } public static class TL_inputPeerEmpty extends InputPeer { - public static int constructor = 0x7f3b18ea; + public static final int constructor = 0x7f3b18ea; public void serializeToStream(AbstractSerializedData stream) { @@ -52319,7 +53078,7 @@ public class TLRPC { } public static class TL_inputPeerChannelFromMessage extends InputPeer { - public static int constructor = 0xbd2a0840; + public static final int constructor = 0xbd2a0840; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52337,7 +53096,7 @@ public class TLRPC { } public static class TL_inputPeerChat extends InputPeer { - public static int constructor = 0x35a95cb9; + public static final int constructor = 0x35a95cb9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52351,7 +53110,7 @@ public class TLRPC { } public static class TL_inputPeerChannel_layer131 extends TL_inputPeerChannel { - public static int constructor = 0x20adaef8; + public static final int constructor = 0x20adaef8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52367,7 +53126,7 @@ public class TLRPC { } public static class TL_inputPeerChannelFromMessage_layer131 extends TL_inputPeerChannelFromMessage { - public static int constructor = 0x9c95f7bb; + public static final int constructor = 0x9c95f7bb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52385,7 +53144,7 @@ public class TLRPC { } public static class TL_inputPeerUserFromMessage_layer131 extends TL_inputPeerUserFromMessage { - public static int constructor = 0x17bae2e6; + public static final int constructor = 0x17bae2e6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -52425,7 +53184,7 @@ public class TLRPC { } public static class TL_help_passportConfigNotModified extends help_PassportConfig { - public static int constructor = 0xbfb9f457; + public static final int constructor = 0xbfb9f457; public void serializeToStream(AbstractSerializedData stream) { @@ -52434,7 +53193,7 @@ public class TLRPC { } public static class TL_help_passportConfig extends help_PassportConfig { - public static int constructor = 0xa098d6af; + public static final int constructor = 0xa098d6af; public int hash; public TL_dataJSON countries_langs; @@ -52452,7 +53211,7 @@ public class TLRPC { } public static class TL_phone_exportedGroupCallInvite extends TLObject { - public static int constructor = 0x204bd158; + public static final int constructor = 0x204bd158; public String link; @@ -52480,7 +53239,7 @@ public class TLRPC { } public static class TL_account_passwordInputSettings extends TLObject { - public static int constructor = 0xc23727c9; + public static final int constructor = 0xc23727c9; public int flags; public PasswordKdfAlgo new_algo; @@ -52543,7 +53302,7 @@ public class TLRPC { } public static class TL_dcOption extends TLObject { - public static int constructor = 0x18b7a10d; + public static final int constructor = 0x18b7a10d; public int flags; public boolean ipv6; @@ -52602,7 +53361,7 @@ public class TLRPC { } public static class TL_pageTableRow extends TLObject { - public static int constructor = 0xe0c0c5e5; + public static final int constructor = 0xe0c0c5e5; public ArrayList cells = new ArrayList<>(); @@ -52649,7 +53408,7 @@ public class TLRPC { } public static class TL_emojiURL extends TLObject { - public static int constructor = 0xa575739d; + public static final int constructor = 0xa575739d; public String url; @@ -52677,7 +53436,7 @@ public class TLRPC { } public static class TL_decryptedMessageLayer extends TLObject { - public static int constructor = 0x1be31789; + public static final int constructor = 0x1be31789; public byte[] random_bytes; public int layer; @@ -52717,7 +53476,7 @@ public class TLRPC { } public static class TL_groupCallParticipant extends TLObject { - public static int constructor = 0xeba636fe; + public static final int constructor = 0xeba636fe; public int flags; public boolean muted; @@ -52840,7 +53599,7 @@ public class TLRPC { } public static class TL_fileHash extends TLObject { - public static int constructor = 0xf39b035c; + public static final int constructor = 0xf39b035c; public long offset; public int limit; @@ -52874,7 +53633,7 @@ public class TLRPC { } public static class TL_messages_peerDialogs extends TLObject { - public static int constructor = 0x3371c354; + public static final int constructor = 0x3371c354; public ArrayList dialogs = new ArrayList<>(); public ArrayList messages = new ArrayList<>(); @@ -52990,7 +53749,7 @@ public class TLRPC { } public static class TL_topPeer extends TLObject { - public static int constructor = 0xedcdc05b; + public static final int constructor = 0xedcdc05b; public Peer peer; public double rating; @@ -53046,7 +53805,7 @@ public class TLRPC { } public static class TL_account_resetPasswordFailedWait extends account_ResetPasswordResult { - public static int constructor = 0xe3779861; + public static final int constructor = 0xe3779861; public int retry_date; @@ -53061,7 +53820,7 @@ public class TLRPC { } public static class TL_account_resetPasswordRequestedWait extends account_ResetPasswordResult { - public static int constructor = 0xe9effc7d; + public static final int constructor = 0xe9effc7d; public int until_date; @@ -53076,7 +53835,7 @@ public class TLRPC { } public static class TL_account_resetPasswordOk extends account_ResetPasswordResult { - public static int constructor = 0xe926d63e; + public static final int constructor = 0xe926d63e; public void serializeToStream(AbstractSerializedData stream) { @@ -53116,7 +53875,7 @@ public class TLRPC { } public static class TL_messages_dialogs extends messages_Dialogs { - public static int constructor = 0x15ba6c40; + public static final int constructor = 0x15ba6c40; public void readParams(AbstractSerializedData stream, boolean exception) { int magic = stream.readInt32(exception); @@ -53211,7 +53970,7 @@ public class TLRPC { } public static class TL_messages_dialogsSlice extends messages_Dialogs { - public static int constructor = 0x71e094f3; + public static final int constructor = 0x71e094f3; public void readParams(AbstractSerializedData stream, boolean exception) { count = stream.readInt32(exception); @@ -53308,7 +54067,7 @@ public class TLRPC { } public static class TL_messages_dialogsNotModified extends messages_Dialogs { - public static int constructor = 0xf0e3e596; + public static final int constructor = 0xf0e3e596; public void readParams(AbstractSerializedData stream, boolean exception) { count = stream.readInt32(exception); @@ -53321,7 +54080,7 @@ public class TLRPC { } public static class TL_account_authorizations extends TLObject { - public static int constructor = 0x4bff8ea0; + public static final int constructor = 0x4bff8ea0; public int authorization_ttl_days; public ArrayList authorizations = new ArrayList<>(); @@ -53371,7 +54130,7 @@ public class TLRPC { } public static class TL_paymentRequestedInfo extends TLObject { - public static int constructor = 0x909c3f94; + public static final int constructor = 0x909c3f94; public int flags; public String name; @@ -53464,7 +54223,7 @@ public class TLRPC { } public static class TL_reactionCustomEmoji extends Reaction { - public static int constructor = 0x8935fc73; + public static final int constructor = 0x8935fc73; public long document_id; @@ -53479,7 +54238,7 @@ public class TLRPC { } public static class TL_reactionEmpty extends Reaction { - public static int constructor = 0x79f5d419; + public static final int constructor = 0x79f5d419; public void serializeToStream(AbstractSerializedData stream) { @@ -53488,7 +54247,7 @@ public class TLRPC { } public static class TL_reactionEmoji extends Reaction { - public static int constructor = 0x1b2286b8; + public static final int constructor = 0x1b2286b8; public String emoticon; @@ -53503,7 +54262,7 @@ public class TLRPC { } public static class TL_messages_getEmojiGroups extends TLObject { - public static int constructor = 0x7488ce5b; + public static final int constructor = 0x7488ce5b; public int hash; @@ -53518,7 +54277,7 @@ public class TLRPC { } public static class TL_messages_getEmojiProfilePhotoGroups extends TLObject { - public static int constructor = 0x21a548f3; + public static final int constructor = 0x21a548f3; public int hash; @@ -53533,7 +54292,7 @@ public class TLRPC { } public static class TL_messages_getEmojiStatusGroups extends TLObject { - public static int constructor = 0x2ecd56cd; + public static final int constructor = 0x2ecd56cd; public int hash; @@ -53548,7 +54307,7 @@ public class TLRPC { } public static class TL_messages_searchCustomEmoji extends TLObject { - public static int constructor = 0x2c11c0d7; + public static final int constructor = 0x2c11c0d7; public String emoticon; public long hash; @@ -53565,7 +54324,7 @@ public class TLRPC { } public static class TL_messages_togglePeerTranslations extends TLObject { - public static int constructor = 0xe47cb579; + public static final int constructor = 0xe47cb579; public int flags; public boolean disabled; @@ -53584,7 +54343,7 @@ public class TLRPC { } public static class TL_auth_sendCode extends TLObject { - public static int constructor = 0xa677244f; + public static final int constructor = 0xa677244f; public String phone_number; public int api_id; @@ -53605,7 +54364,7 @@ public class TLRPC { } public static class TL_auth_signUp extends TLObject { - public static int constructor = 0x80eee427; + public static final int constructor = 0x80eee427; public String phone_number; public String phone_code_hash; @@ -53626,7 +54385,7 @@ public class TLRPC { } public static class TL_auth_signInOld extends TLObject { - public static int constructor = 0xbcd51581; + public static final int constructor = 0xbcd51581; public String phone_number; public String phone_code_hash; @@ -53645,7 +54404,7 @@ public class TLRPC { } public static class TL_auth_signIn extends TLObject { - public static int constructor = 0x8d52a951; + public static final int constructor = 0x8d52a951; public int flags; public String phone_number; @@ -53672,7 +54431,7 @@ public class TLRPC { } public static class TL_auth_logOut extends TLObject { - public static int constructor = 0x3e72ba19; + public static final int constructor = 0x3e72ba19; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -53685,7 +54444,7 @@ public class TLRPC { } public static class TL_auth_resetLoginEmail extends TLObject { - public static int constructor = 0x7e960193; + public static final int constructor = 0x7e960193; public String phone_number; public String phone_code_hash; @@ -53702,7 +54461,7 @@ public class TLRPC { } public static class TL_auth_resetAuthorizations extends TLObject { - public static int constructor = 0x9fab0d1a; + public static final int constructor = 0x9fab0d1a; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -53715,7 +54474,7 @@ public class TLRPC { } public static class TL_auth_exportAuthorization extends TLObject { - public static int constructor = 0xe5bfffcd; + public static final int constructor = 0xe5bfffcd; public int dc_id; @@ -53730,7 +54489,7 @@ public class TLRPC { } public static class TL_auth_importAuthorization extends TLObject { - public static int constructor = 0xa57a7dad; + public static final int constructor = 0xa57a7dad; public long id; public byte[] bytes; @@ -53747,7 +54506,7 @@ public class TLRPC { } public static class TL_auth_exportLoginToken extends TLObject { - public static int constructor = 0xb7e085fe; + public static final int constructor = 0xb7e085fe; public int api_id; public String api_hash; @@ -53771,7 +54530,7 @@ public class TLRPC { } public static class TL_auth_importLoginToken extends TLObject { - public static int constructor = 0x95ac5ce4; + public static final int constructor = 0x95ac5ce4; public byte[] token; @@ -53786,7 +54545,7 @@ public class TLRPC { } public static class TL_auth_acceptLoginToken extends TLObject { - public static int constructor = 0xe894ad4d; + public static final int constructor = 0xe894ad4d; public byte[] token; @@ -53801,7 +54560,7 @@ public class TLRPC { } public static class TL_auth_checkRecoveryPassword extends TLObject { - public static int constructor = 0xd36bf79; + public static final int constructor = 0xd36bf79; public String code; @@ -53816,7 +54575,7 @@ public class TLRPC { } public static class TL_auth_requestFirebaseSms extends TLObject { - public static int constructor = 0x89464b50; + public static final int constructor = 0x89464b50; public int flags; public String phone_number; @@ -53843,7 +54602,7 @@ public class TLRPC { } public static class TL_account_registerDevice extends TLObject { - public static int constructor = 0xec86017a; + public static final int constructor = 0xec86017a; public int flags; public boolean no_muted; @@ -53875,7 +54634,7 @@ public class TLRPC { } public static class TL_account_unregisterDevice extends TLObject { - public static int constructor = 0x6a0d3206; + public static final int constructor = 0x6a0d3206; public int token_type; public String token; @@ -53899,7 +54658,7 @@ public class TLRPC { } public static class TL_account_updateNotifySettings extends TLObject { - public static int constructor = 0x84be5b93; + public static final int constructor = 0x84be5b93; public InputNotifyPeer peer; public TL_inputPeerNotifySettings settings; @@ -53916,7 +54675,7 @@ public class TLRPC { } public static class TL_account_getNotifySettings extends TLObject { - public static int constructor = 0x12b3ad31; + public static final int constructor = 0x12b3ad31; public InputNotifyPeer peer; @@ -53931,7 +54690,7 @@ public class TLRPC { } public static class TL_account_resetNotifySettings extends TLObject { - public static int constructor = 0xdb7e1747; + public static final int constructor = 0xdb7e1747; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -53944,7 +54703,7 @@ public class TLRPC { } public static class TL_account_updateProfile extends TLObject { - public static int constructor = 0x78515775; + public static final int constructor = 0x78515775; public int flags; public String first_name; @@ -53971,7 +54730,7 @@ public class TLRPC { } public static class TL_account_updateStatus extends TLObject { - public static int constructor = 0x6628562c; + public static final int constructor = 0x6628562c; public boolean offline; @@ -53986,7 +54745,7 @@ public class TLRPC { } public static class TL_account_getWallPapers extends TLObject { - public static int constructor = 0x7967d36; + public static final int constructor = 0x7967d36; public long hash; @@ -54001,7 +54760,7 @@ public class TLRPC { } public static class TL_users_getUsers extends TLObject { - public static int constructor = 0xd91a548; + public static final int constructor = 0xd91a548; public ArrayList id = new ArrayList<>(); @@ -54030,7 +54789,7 @@ public class TLRPC { } public static class TL_account_reportPeer extends TLObject { - public static int constructor = 0xc5ba3d86; + public static final int constructor = 0xc5ba3d86; public InputPeer peer; public ReportReason reason; @@ -54049,7 +54808,7 @@ public class TLRPC { } public static class TL_account_resetPassword extends TLObject { - public static int constructor = 0x9308ce1b; + public static final int constructor = 0x9308ce1b; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54062,7 +54821,7 @@ public class TLRPC { } public static class TL_account_declinePasswordReset extends TLObject { - public static int constructor = 0x4c9409f6; + public static final int constructor = 0x4c9409f6; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54075,7 +54834,7 @@ public class TLRPC { } public static class TL_account_getChatThemes extends TLObject { - public static int constructor = 0xd638de89; + public static final int constructor = 0xd638de89; public long hash; @@ -54090,7 +54849,7 @@ public class TLRPC { } public static class TL_account_setAuthorizationTTL extends TLObject { - public static int constructor = 0xbf899aa0; + public static final int constructor = 0xbf899aa0; public int authorization_ttl_days; @@ -54105,7 +54864,7 @@ public class TLRPC { } public static class TL_account_changeAuthorizationSettings extends TLObject { - public static int constructor = 0x40f48462; + public static final int constructor = 0x40f48462; public int flags; public boolean confirmed; @@ -54132,7 +54891,7 @@ public class TLRPC { } public static class TL_users_getFullUser extends TLObject { - public static int constructor = 0xb60f5918; + public static final int constructor = 0xb60f5918; public InputUser id; @@ -54147,7 +54906,7 @@ public class TLRPC { } public static class TL_contacts_getStatuses extends TLObject { - public static int constructor = 0xc4a353ee; + public static final int constructor = 0xc4a353ee; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54169,7 +54928,7 @@ public class TLRPC { } public static class TL_contacts_getContacts extends TLObject { - public static int constructor = 0x5dd69e12; + public static final int constructor = 0x5dd69e12; public long hash; @@ -54184,7 +54943,7 @@ public class TLRPC { } public static class TL_contacts_importContacts extends TLObject { - public static int constructor = 0x2c800be5; + public static final int constructor = 0x2c800be5; public ArrayList contacts = new ArrayList<>(); @@ -54204,7 +54963,7 @@ public class TLRPC { } public static class TL_contacts_deleteContacts extends TLObject { - public static int constructor = 0x96a0e00; + public static final int constructor = 0x96a0e00; public ArrayList id = new ArrayList<>(); @@ -54224,7 +54983,7 @@ public class TLRPC { } public static class TL_contacts_deleteByPhones extends TLObject { - public static int constructor = 0x1013fd9e; + public static final int constructor = 0x1013fd9e; public ArrayList phones = new ArrayList<>(); @@ -54244,7 +55003,7 @@ public class TLRPC { } public static class TL_contacts_block extends TLObject { - public static int constructor = 0x2e2e8734; + public static final int constructor = 0x2e2e8734; public int flags; public boolean my_stories_from; @@ -54263,7 +55022,7 @@ public class TLRPC { } public static class TL_contacts_unblock extends TLObject { - public static int constructor = 0xb550d328; + public static final int constructor = 0xb550d328; public int flags; public boolean my_stories_from; @@ -54282,7 +55041,7 @@ public class TLRPC { } public static class TL_contacts_getBlocked extends TLObject { - public static int constructor = 0x9a868f80; + public static final int constructor = 0x9a868f80; public int flags; public boolean my_stories_from; @@ -54303,7 +55062,7 @@ public class TLRPC { } public static class TL_contacts_exportCard extends TLObject { - public static int constructor = 0x84e53737; + public static final int constructor = 0x84e53737; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54321,7 +55080,7 @@ public class TLRPC { } public static class TL_contacts_importCard extends TLObject { - public static int constructor = 0x4fe196fe; + public static final int constructor = 0x4fe196fe; public ArrayList export_card = new ArrayList<>(); @@ -54341,7 +55100,7 @@ public class TLRPC { } public static class TL_contacts_resetSaved extends TLObject { - public static int constructor = 0x879537f1; + public static final int constructor = 0x879537f1; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54354,7 +55113,7 @@ public class TLRPC { } public static class TL_contacts_toggleTopPeers extends TLObject { - public static int constructor = 0x8514bdda; + public static final int constructor = 0x8514bdda; public boolean enabled; @@ -54369,7 +55128,7 @@ public class TLRPC { } public static class TL_contacts_addContact extends TLObject { - public static int constructor = 0xe8f463d0; + public static final int constructor = 0xe8f463d0; public int flags; public boolean add_phone_privacy_exception; @@ -54394,7 +55153,7 @@ public class TLRPC { } public static class TL_contacts_acceptContact extends TLObject { - public static int constructor = 0xf831a20f; + public static final int constructor = 0xf831a20f; public InputUser id; @@ -54409,7 +55168,7 @@ public class TLRPC { } public static class TL_contacts_getLocated extends TLObject { - public static int constructor = 0xd348bc44; + public static final int constructor = 0xd348bc44; public int flags; public boolean background; @@ -54432,7 +55191,7 @@ public class TLRPC { } public static class TL_contacts_blockFromReplies extends TLObject { - public static int constructor = 0x29a8962c; + public static final int constructor = 0x29a8962c; public int flags; public boolean delete_message; @@ -54455,7 +55214,7 @@ public class TLRPC { } public static class TL_contacts_resolvePhone extends TLObject { - public static int constructor = 0x8af94344; + public static final int constructor = 0x8af94344; public String phone; @@ -54470,7 +55229,7 @@ public class TLRPC { } public static class TL_messages_getMessages extends TLObject { - public static int constructor = 0x4222fa74; + public static final int constructor = 0x4222fa74; public ArrayList id = new ArrayList<>(); @@ -54490,7 +55249,7 @@ public class TLRPC { } public static class TL_messages_getDialogs extends TLObject { - public static int constructor = 0xa0f4cb4f; + public static final int constructor = 0xa0f4cb4f; public int flags; public boolean exclude_pinned; @@ -54521,7 +55280,7 @@ public class TLRPC { } public static class TL_messages_getHistory extends TLObject { - public static int constructor = 0x4423e6c5; + public static final int constructor = 0x4423e6c5; public InputPeer peer; public int offset_id; @@ -54550,7 +55309,7 @@ public class TLRPC { } public static class TL_messages_search extends TLObject { - public static int constructor = 0xa0fda762; + public static final int constructor = 0xa0fda762; public int flags; public InputPeer peer; @@ -54595,7 +55354,7 @@ public class TLRPC { } public static class TL_help_getTermsOfServiceUpdate extends TLObject { - public static int constructor = 0x2ca51fd1; + public static final int constructor = 0x2ca51fd1; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54608,7 +55367,7 @@ public class TLRPC { } public static class TL_help_acceptTermsOfService extends TLObject { - public static int constructor = 0xee72f79a; + public static final int constructor = 0xee72f79a; public TL_dataJSON id; @@ -54623,7 +55382,7 @@ public class TLRPC { } public static class TL_help_getPassportConfig extends TLObject { - public static int constructor = 0xc661ad08; + public static final int constructor = 0xc661ad08; public int hash; @@ -54638,7 +55397,7 @@ public class TLRPC { } public static class TL_help_getSupportName extends TLObject { - public static int constructor = 0xd360e72c; + public static final int constructor = 0xd360e72c; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54651,7 +55410,7 @@ public class TLRPC { } public static class TL_help_getPremiumPromo extends TLObject { - public static int constructor = 0xb81b93d4; + public static final int constructor = 0xb81b93d4; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54664,7 +55423,7 @@ public class TLRPC { } public static class TL_help_getUserInfo extends TLObject { - public static int constructor = 0x38a08d3; + public static final int constructor = 0x38a08d3; public InputUser user_id; @@ -54679,7 +55438,7 @@ public class TLRPC { } public static class TL_help_editUserInfo extends TLObject { - public static int constructor = 0x66b91b70; + public static final int constructor = 0x66b91b70; public InputUser user_id; public String message; @@ -54703,7 +55462,7 @@ public class TLRPC { } public static class TL_help_getPromoData extends TLObject { - public static int constructor = 0xc0977421; + public static final int constructor = 0xc0977421; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54716,7 +55475,7 @@ public class TLRPC { } public static class TL_help_hidePromoData extends TLObject { - public static int constructor = 0x1e251c95; + public static final int constructor = 0x1e251c95; public InputPeer peer; @@ -54731,7 +55490,7 @@ public class TLRPC { } public static class TL_help_dismissSuggestion extends TLObject { - public static int constructor = 0xf50dbaa1; + public static final int constructor = 0xf50dbaa1; public InputPeer peer; public String suggestion; @@ -54748,7 +55507,7 @@ public class TLRPC { } public static class TL_help_getCountriesList extends TLObject { - public static int constructor = 0x735787a8; + public static final int constructor = 0x735787a8; public String lang_code; public int hash; @@ -54765,7 +55524,7 @@ public class TLRPC { } public static class TL_messages_readHistory extends TLObject { - public static int constructor = 0xe306d3a; + public static final int constructor = 0xe306d3a; public InputPeer peer; public int max_id; @@ -54782,7 +55541,7 @@ public class TLRPC { } public static class TL_messages_deleteHistory extends TLObject { - public static int constructor = 0xb08f922a; + public static final int constructor = 0xb08f922a; public int flags; public boolean just_clear; @@ -54813,7 +55572,7 @@ public class TLRPC { } public static class TL_channels_togglePreHistoryHidden extends TLObject { - public static int constructor = 0xeabbb94c; + public static final int constructor = 0xeabbb94c; public InputChannel channel; public boolean enabled; @@ -54830,7 +55589,7 @@ public class TLRPC { } public static class TL_channels_getGroupsForDiscussion extends TLObject { - public static int constructor = 0xf5dad378; + public static final int constructor = 0xf5dad378; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -54843,7 +55602,7 @@ public class TLRPC { } public static class TL_channels_setDiscussionGroup extends TLObject { - public static int constructor = 0x40582bb2; + public static final int constructor = 0x40582bb2; public InputChannel broadcast; public InputChannel group; @@ -54860,7 +55619,7 @@ public class TLRPC { } public static class TL_channels_editCreator extends TLObject { - public static int constructor = 0x8f38cd1f; + public static final int constructor = 0x8f38cd1f; public InputChannel channel; public InputUser user_id; @@ -54879,7 +55638,7 @@ public class TLRPC { } public static class TL_channels_editLocation extends TLObject { - public static int constructor = 0x58e63f6d; + public static final int constructor = 0x58e63f6d; public InputChannel channel; public InputGeoPoint geo_point; @@ -54898,7 +55657,7 @@ public class TLRPC { } public static class TL_messages_editChatAdmin extends TLObject { - public static int constructor = 0xa85bd1c2; + public static final int constructor = 0xa85bd1c2; public long chat_id; public InputUser user_id; @@ -54917,7 +55676,7 @@ public class TLRPC { } public static class TL_messages_migrateChat extends TLObject { - public static int constructor = 0xa2875319; + public static final int constructor = 0xa2875319; public long chat_id; @@ -54932,7 +55691,7 @@ public class TLRPC { } public static class TL_messages_searchGlobal extends TLObject { - public static int constructor = 0x4bc6589a; + public static final int constructor = 0x4bc6589a; public int flags; public int folder_id; @@ -54969,7 +55728,7 @@ public class TLRPC { } public static class TL_messages_deleteMessages extends TLObject { - public static int constructor = 0xe58e95d2; + public static final int constructor = 0xe58e95d2; public int flags; public boolean revoke; @@ -55022,7 +55781,7 @@ public class TLRPC { } public static class TL_messages_receivedMessages extends TLObject { - public static int constructor = 0x5a954c0; + public static final int constructor = 0x5a954c0; public int max_id; @@ -55046,7 +55805,7 @@ public class TLRPC { } public static class TL_messages_setTyping extends TLObject { - public static int constructor = 0x58943ee2; + public static final int constructor = 0x58943ee2; public int flags; public InputPeer peer; @@ -55069,7 +55828,7 @@ public class TLRPC { } public static class TL_messages_sendMessage extends TLObject { - public static int constructor = 0x280d096f; + public static final int constructor = 0x280d096f; public int flags; public boolean no_webpage; @@ -55078,6 +55837,7 @@ public class TLRPC { public boolean clear_draft; public boolean noforwards; public boolean update_stickersets_order; + public boolean invert_media; public InputPeer peer; public InputReplyTo reply_to; public String message; @@ -55099,6 +55859,7 @@ public class TLRPC { flags = clear_draft ? (flags | 128) : (flags &~ 128); flags = noforwards ? (flags | 16384) : (flags &~ 16384); flags = update_stickersets_order ? (flags | 32768) : (flags &~ 32768); + flags = invert_media ? (flags | 65536) : (flags &~ 65536); stream.writeInt32(flags); peer.serializeToStream(stream); if ((flags & 1) != 0) { @@ -55127,7 +55888,7 @@ public class TLRPC { } public static class TL_messages_sendMedia extends TLObject { - public static int constructor = 0x72ccc23d; + public static final int constructor = 0x72ccc23d; public int flags; public boolean silent; @@ -55135,6 +55896,7 @@ public class TLRPC { public boolean clear_draft; public boolean noforwards; public boolean update_stickersets_order; + public boolean invert_media; public InputPeer peer; public InputReplyTo reply_to; public InputMedia media; @@ -55156,6 +55918,7 @@ public class TLRPC { flags = clear_draft ? (flags | 128) : (flags &~ 128); flags = noforwards ? (flags | 16384) : (flags &~ 16384); flags = update_stickersets_order ? (flags | 32768) : (flags &~ 32768); + flags = invert_media ? (flags | 65536) : (flags &~ 65536); stream.writeInt32(flags); peer.serializeToStream(stream); if ((flags & 1) != 0) { @@ -55185,7 +55948,7 @@ public class TLRPC { } public static class TL_messages_forwardMessages extends TLObject { - public static int constructor = 0xc661bbc4; + public static final int constructor = 0xc661bbc4; public int flags; public boolean silent; @@ -55242,7 +56005,7 @@ public class TLRPC { } public static class TL_messages_reportSpam extends TLObject { - public static int constructor = 0xcf1592db; + public static final int constructor = 0xcf1592db; public InputPeer peer; @@ -55257,7 +56020,7 @@ public class TLRPC { } public static class TL_messages_getPeerSettings extends TLObject { - public static int constructor = 0xefd9a6a2; + public static final int constructor = 0xefd9a6a2; public InputPeer peer; @@ -55272,7 +56035,7 @@ public class TLRPC { } public static class TL_messages_report extends TLObject { - public static int constructor = 0x8953ab4e; + public static final int constructor = 0x8953ab4e; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -55298,7 +56061,7 @@ public class TLRPC { } public static class TL_messages_getChats extends TLObject { - public static int constructor = 0x49e9528f; + public static final int constructor = 0x49e9528f; public ArrayList id = new ArrayList<>(); @@ -55318,7 +56081,7 @@ public class TLRPC { } public static class TL_messages_getFullChat extends TLObject { - public static int constructor = 0xaeb00b34; + public static final int constructor = 0xaeb00b34; public long chat_id; @@ -55333,7 +56096,7 @@ public class TLRPC { } public static class TL_messages_editChatTitle extends TLObject { - public static int constructor = 0x73783ffd; + public static final int constructor = 0x73783ffd; public long chat_id; public String title; @@ -55350,7 +56113,7 @@ public class TLRPC { } public static class TL_messages_editChatPhoto extends TLObject { - public static int constructor = 0x35ddd674; + public static final int constructor = 0x35ddd674; public long chat_id; public InputChatPhoto photo; @@ -55367,7 +56130,7 @@ public class TLRPC { } public static class TL_messages_addChatUser extends TLObject { - public static int constructor = 0xf24753e3; + public static final int constructor = 0xf24753e3; public long chat_id; public InputUser user_id; @@ -55386,7 +56149,7 @@ public class TLRPC { } public static class TL_messages_deleteChatUser extends TLObject { - public static int constructor = 0xa2185cab; + public static final int constructor = 0xa2185cab; public int flags; public boolean revoke_history; @@ -55407,7 +56170,7 @@ public class TLRPC { } public static class TL_messages_createChat extends TLObject { - public static int constructor = 0x34a818; + public static final int constructor = 0x34a818; public int flags; public ArrayList users = new ArrayList<>(); @@ -55435,7 +56198,7 @@ public class TLRPC { } public static class TL_messages_getSearchResultsCalendar extends TLObject { - public static int constructor = 0x49f0bde9; + public static final int constructor = 0x49f0bde9; public InputPeer peer; public MessagesFilter filter; @@ -55456,7 +56219,7 @@ public class TLRPC { } public static class TL_updates_getState extends TLObject { - public static int constructor = 0xedd4882a; + public static final int constructor = 0xedd4882a; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -55469,7 +56232,7 @@ public class TLRPC { } public static class TL_updates_getDifference extends TLObject { - public static int constructor = 0x25939651; + public static final int constructor = 0x25939651; public int flags; public int pts; @@ -55494,7 +56257,7 @@ public class TLRPC { } public static class TL_updates_getChannelDifference extends TLObject { - public static int constructor = 0x3173d78; + public static final int constructor = 0x3173d78; public int flags; public boolean force; @@ -55519,7 +56282,7 @@ public class TLRPC { } public static class TL_photos_updateProfilePhoto extends TLObject { - public static int constructor = 0x9e82039; + public static final int constructor = 0x9e82039; public int flags; public boolean fallback; @@ -55542,7 +56305,7 @@ public class TLRPC { } public static class TL_photos_uploadProfilePhoto extends TLObject { - public static int constructor = 0x388a3b5; + public static final int constructor = 0x388a3b5; public int flags; public boolean fallback; @@ -55579,7 +56342,7 @@ public class TLRPC { } public static class TL_photos_deletePhotos extends TLObject { - public static int constructor = 0x87cf7f2f; + public static final int constructor = 0x87cf7f2f; public ArrayList id = new ArrayList<>(); @@ -55604,7 +56367,7 @@ public class TLRPC { } public static class TL_upload_getFile extends TLObject { - public static int constructor = 0xbe5335be; + public static final int constructor = 0xbe5335be; public int flags; public boolean precise; @@ -55629,7 +56392,7 @@ public class TLRPC { } public static class TL_help_getConfig extends TLObject { - public static int constructor = 0xc4f9186b; + public static final int constructor = 0xc4f9186b; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -55642,7 +56405,7 @@ public class TLRPC { } public static class TL_help_getNearestDc extends TLObject { - public static int constructor = 0x1fb33026; + public static final int constructor = 0x1fb33026; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -55655,7 +56418,7 @@ public class TLRPC { } public static class TL_help_getAppUpdate extends TLObject { - public static int constructor = 0x522d5a7d; + public static final int constructor = 0x522d5a7d; public String source; @@ -55670,7 +56433,7 @@ public class TLRPC { } public static class TL_help_getAppConfig extends TLObject { - public static int constructor = 0x61e3f854; + public static final int constructor = 0x61e3f854; public int hash; @@ -55686,7 +56449,7 @@ public class TLRPC { public static class TL_help_saveAppLog extends TLObject { - public static int constructor = 0x6f02f748; + public static final int constructor = 0x6f02f748; public ArrayList events = new ArrayList<>(); @@ -55706,7 +56469,7 @@ public class TLRPC { } public static class TL_help_getInviteText extends TLObject { - public static int constructor = 0x4d392343; + public static final int constructor = 0x4d392343; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -55719,7 +56482,7 @@ public class TLRPC { } public static class TL_photos_getUserPhotos extends TLObject { - public static int constructor = 0x91cd32a8; + public static final int constructor = 0x91cd32a8; public InputUser user_id; public int offset; @@ -55740,7 +56503,7 @@ public class TLRPC { } public static class TL_messages_forwardMessage extends TLObject { - public static int constructor = 0x33963bf9; + public static final int constructor = 0x33963bf9; public InputPeer peer; public int id; @@ -55759,7 +56522,7 @@ public class TLRPC { } public static class TL_messages_getDhConfig extends TLObject { - public static int constructor = 0x26cf8950; + public static final int constructor = 0x26cf8950; public int version; public int random_length; @@ -55776,7 +56539,7 @@ public class TLRPC { } public static class TL_messages_requestEncryption extends TLObject { - public static int constructor = 0xf64daf43; + public static final int constructor = 0xf64daf43; public InputUser user_id; public int random_id; @@ -55795,7 +56558,7 @@ public class TLRPC { } public static class TL_messages_acceptEncryption extends TLObject { - public static int constructor = 0x3dbc0415; + public static final int constructor = 0x3dbc0415; public TL_inputEncryptedChat peer; public byte[] g_b; @@ -55814,7 +56577,7 @@ public class TLRPC { } public static class TL_messages_discardEncryption extends TLObject { - public static int constructor = 0xf393aea0; + public static final int constructor = 0xf393aea0; public int flags; public boolean delete_history; @@ -55833,7 +56596,7 @@ public class TLRPC { } public static class TL_messages_setEncryptedTyping extends TLObject { - public static int constructor = 0x791451ed; + public static final int constructor = 0x791451ed; public TL_inputEncryptedChat peer; public boolean typing; @@ -55850,7 +56613,7 @@ public class TLRPC { } public static class TL_messages_readEncryptedHistory extends TLObject { - public static int constructor = 0x7f4b690a; + public static final int constructor = 0x7f4b690a; public TL_inputEncryptedChat peer; public int max_date; @@ -55867,7 +56630,7 @@ public class TLRPC { } public static class TL_messages_receivedQueue extends TLObject { - public static int constructor = 0x55a5bb66; + public static final int constructor = 0x55a5bb66; public int max_qts; @@ -55887,7 +56650,7 @@ public class TLRPC { } public static class TL_messages_reportEncryptedSpam extends TLObject { - public static int constructor = 0x4b0c8c0f; + public static final int constructor = 0x4b0c8c0f; public TL_inputEncryptedChat peer; @@ -55902,7 +56665,7 @@ public class TLRPC { } public static class TL_help_getSupport extends TLObject { - public static int constructor = 0x9cdf08cd; + public static final int constructor = 0x9cdf08cd; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -55915,7 +56678,7 @@ public class TLRPC { } public static class TL_messages_readMessageContents extends TLObject { - public static int constructor = 0x36a73f77; + public static final int constructor = 0x36a73f77; public ArrayList id = new ArrayList<>(); @@ -55935,7 +56698,7 @@ public class TLRPC { } public static class TL_account_checkUsername extends TLObject { - public static int constructor = 0x2714d86c; + public static final int constructor = 0x2714d86c; public String username; @@ -55950,7 +56713,7 @@ public class TLRPC { } public static class TL_account_updateUsername extends TLObject { - public static int constructor = 0x3e0bdd7c; + public static final int constructor = 0x3e0bdd7c; public String username; @@ -55965,7 +56728,7 @@ public class TLRPC { } public static class TL_contacts_search extends TLObject { - public static int constructor = 0x11f812d8; + public static final int constructor = 0x11f812d8; public String q; public int limit; @@ -55982,7 +56745,7 @@ public class TLRPC { } public static class TL_account_getPrivacy extends TLObject { - public static int constructor = 0xdadbc950; + public static final int constructor = 0xdadbc950; public InputPrivacyKey key; @@ -55997,7 +56760,7 @@ public class TLRPC { } public static class TL_account_setPrivacy extends TLObject { - public static int constructor = 0xc9f81ce8; + public static final int constructor = 0xc9f81ce8; public InputPrivacyKey key; public ArrayList rules = new ArrayList<>(); @@ -56019,7 +56782,7 @@ public class TLRPC { } public static class TL_account_deleteAccount extends TLObject { - public static int constructor = 0x418d4e0b; + public static final int constructor = 0x418d4e0b; public String reason; @@ -56034,7 +56797,7 @@ public class TLRPC { } public static class TL_account_getAccountTTL extends TLObject { - public static int constructor = 0x8fc711d; + public static final int constructor = 0x8fc711d; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56047,7 +56810,7 @@ public class TLRPC { } public static class TL_account_setAccountTTL extends TLObject { - public static int constructor = 0x2442485e; + public static final int constructor = 0x2442485e; public TL_accountDaysTTL ttl; @@ -56062,7 +56825,7 @@ public class TLRPC { } public static class TL_contacts_resolveUsername extends TLObject { - public static int constructor = 0xf93ccba3; + public static final int constructor = 0xf93ccba3; public String username; @@ -56077,7 +56840,7 @@ public class TLRPC { } public static class TL_contacts_getTopPeers extends TLObject { - public static int constructor = 0x973478b6; + public static final int constructor = 0x973478b6; public int flags; public boolean correspondents; @@ -56114,7 +56877,7 @@ public class TLRPC { } public static class TL_contacts_resetTopPeerRating extends TLObject { - public static int constructor = 0x1ae373ac; + public static final int constructor = 0x1ae373ac; public TopPeerCategory category; public InputPeer peer; @@ -56131,7 +56894,7 @@ public class TLRPC { } public static class TL_account_sendChangePhoneCode extends TLObject { - public static int constructor = 0x82574ae5; + public static final int constructor = 0x82574ae5; public String phone_number; public TL_codeSettings settings; @@ -56148,7 +56911,7 @@ public class TLRPC { } public static class TL_account_changePhone extends TLObject { - public static int constructor = 0x70c32edb; + public static final int constructor = 0x70c32edb; public String phone_number; public String phone_code_hash; @@ -56167,7 +56930,7 @@ public class TLRPC { } public static class TL_account_getWebAuthorizations extends TLObject { - public static int constructor = 0x182e6d6f; + public static final int constructor = 0x182e6d6f; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56180,7 +56943,7 @@ public class TLRPC { } public static class TL_account_resetWebAuthorization extends TLObject { - public static int constructor = 0x2d01b9ef; + public static final int constructor = 0x2d01b9ef; public long hash; @@ -56195,7 +56958,7 @@ public class TLRPC { } public static class TL_account_resetWebAuthorizations extends TLObject { - public static int constructor = 0x682d2594; + public static final int constructor = 0x682d2594; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56208,7 +56971,7 @@ public class TLRPC { } public static class TL_account_getMultiWallPapers extends TLObject { - public static int constructor = 0x65ad71dc; + public static final int constructor = 0x65ad71dc; public ArrayList wallpapers = new ArrayList<>(); @@ -56237,7 +57000,7 @@ public class TLRPC { } public static class TL_account_getGlobalPrivacySettings extends TLObject { - public static int constructor = 0xeb2b4cf6; + public static final int constructor = 0xeb2b4cf6; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56250,7 +57013,7 @@ public class TLRPC { } public static class TL_account_setGlobalPrivacySettings extends TLObject { - public static int constructor = 0x1edaaac2; + public static final int constructor = 0x1edaaac2; public TL_globalPrivacySettings settings; @@ -56265,7 +57028,7 @@ public class TLRPC { } public static class TL_account_reportProfilePhoto extends TLObject { - public static int constructor = 0xfa8cc6f5; + public static final int constructor = 0xfa8cc6f5; public InputPeer peer; public InputPhoto photo_id; @@ -56286,7 +57049,7 @@ public class TLRPC { } public static class TL_account_getAllSecureValues extends TLObject { - public static int constructor = 0xb288bc7d; + public static final int constructor = 0xb288bc7d; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56308,7 +57071,7 @@ public class TLRPC { } public static class TL_account_getSecureValue extends TLObject { - public static int constructor = 0x73665bc2; + public static final int constructor = 0x73665bc2; public ArrayList types = new ArrayList<>(); @@ -56337,7 +57100,7 @@ public class TLRPC { } public static class TL_account_saveSecureValue extends TLObject { - public static int constructor = 0x899fe31d; + public static final int constructor = 0x899fe31d; public TL_inputSecureValue value; public long secure_secret_id; @@ -56354,7 +57117,7 @@ public class TLRPC { } public static class TL_account_deleteSecureValue extends TLObject { - public static int constructor = 0xb880bc4b; + public static final int constructor = 0xb880bc4b; public ArrayList types = new ArrayList<>(); @@ -56374,7 +57137,7 @@ public class TLRPC { } public static class TL_account_getAuthorizationForm extends TLObject { - public static int constructor = 0xa929597a; + public static final int constructor = 0xa929597a; public long bot_id; public String scope; @@ -56393,7 +57156,7 @@ public class TLRPC { } public static class TL_account_acceptAuthorization extends TLObject { - public static int constructor = 0xf3ed4c73; + public static final int constructor = 0xf3ed4c73; public long bot_id; public String scope; @@ -56421,7 +57184,7 @@ public class TLRPC { } public static class TL_account_sendVerifyPhoneCode extends TLObject { - public static int constructor = 0xa5a356f9; + public static final int constructor = 0xa5a356f9; public String phone_number; public TL_codeSettings settings; @@ -56438,7 +57201,7 @@ public class TLRPC { } public static class TL_account_verifyPhone extends TLObject { - public static int constructor = 0x4dd3a7f6; + public static final int constructor = 0x4dd3a7f6; public String phone_number; public String phone_code_hash; @@ -56457,7 +57220,7 @@ public class TLRPC { } public static class TL_account_sendVerifyEmailCode extends TLObject { - public static int constructor = 0x98e037bb; + public static final int constructor = 0x98e037bb; public EmailVerifyPurpose purpose; public String email; @@ -56474,7 +57237,7 @@ public class TLRPC { } public static class TL_account_verifyEmail extends TLObject { - public static int constructor = 0x32da4cf; + public static final int constructor = 0x32da4cf; public EmailVerifyPurpose purpose; public EmailVerification verification; @@ -56491,7 +57254,7 @@ public class TLRPC { } public static class TL_account_confirmPasswordEmail extends TLObject { - public static int constructor = 0x8fdf1920; + public static final int constructor = 0x8fdf1920; public String code; @@ -56506,7 +57269,7 @@ public class TLRPC { } public static class TL_account_resendPasswordEmail extends TLObject { - public static int constructor = 0x7a7f2a15; + public static final int constructor = 0x7a7f2a15; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56519,7 +57282,7 @@ public class TLRPC { } public static class TL_account_cancelPasswordEmail extends TLObject { - public static int constructor = 0xc1cbd5b6; + public static final int constructor = 0xc1cbd5b6; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56532,7 +57295,7 @@ public class TLRPC { } public static class TL_account_getContactSignUpNotification extends TLObject { - public static int constructor = 0x9f07c728; + public static final int constructor = 0x9f07c728; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56545,7 +57308,7 @@ public class TLRPC { } public static class TL_account_setContactSignUpNotification extends TLObject { - public static int constructor = 0xcff43f61; + public static final int constructor = 0xcff43f61; public boolean silent; @@ -56560,7 +57323,7 @@ public class TLRPC { } public static class TL_account_getNotifyExceptions extends TLObject { - public static int constructor = 0x53577479; + public static final int constructor = 0x53577479; public int flags; public boolean compare_sound; @@ -56581,7 +57344,7 @@ public class TLRPC { } public static class TL_account_getWallPaper extends TLObject { - public static int constructor = 0xfc8ddbea; + public static final int constructor = 0xfc8ddbea; public InputWallPaper wallpaper; @@ -56596,7 +57359,7 @@ public class TLRPC { } public static class TL_account_uploadWallPaper extends TLObject { - public static int constructor = 0xdd853661; + public static final int constructor = 0xdd853661; public InputFile file; public String mime_type; @@ -56615,7 +57378,7 @@ public class TLRPC { } public static class TL_account_saveWallPaper extends TLObject { - public static int constructor = 0x6c5a5b37; + public static final int constructor = 0x6c5a5b37; public InputWallPaper wallpaper; public boolean unsave; @@ -56634,7 +57397,7 @@ public class TLRPC { } public static class TL_account_installWallPaper extends TLObject { - public static int constructor = 0xfeed5769; + public static final int constructor = 0xfeed5769; public InputWallPaper wallpaper; public TL_wallPaperSettings settings; @@ -56651,7 +57414,7 @@ public class TLRPC { } public static class TL_account_resetWallPapers extends TLObject { - public static int constructor = 0xbb3b9804; + public static final int constructor = 0xbb3b9804; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56664,7 +57427,7 @@ public class TLRPC { } public static class TL_account_getAutoDownloadSettings extends TLObject { - public static int constructor = 0x56da0b3f; + public static final int constructor = 0x56da0b3f; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56677,7 +57440,7 @@ public class TLRPC { } public static class TL_account_saveAutoDownloadSettings extends TLObject { - public static int constructor = 0x76f36233; + public static final int constructor = 0x76f36233; public int flags; public boolean low; @@ -56698,7 +57461,7 @@ public class TLRPC { } public static class TL_account_uploadTheme extends TLObject { - public static int constructor = 0x1c3db333; + public static final int constructor = 0x1c3db333; public int flags; public InputFile file; @@ -56723,7 +57486,7 @@ public class TLRPC { } public static class TL_account_createTheme extends TLObject { - public static int constructor = 0x8432c21f; + public static final int constructor = 0x8432c21f; public int flags; public String slug; @@ -56750,7 +57513,7 @@ public class TLRPC { } public static class TL_account_updateTheme extends TLObject { - public static int constructor = 0x5cb367d5; + public static final int constructor = 0x5cb367d5; public int flags; public String format; @@ -56785,7 +57548,7 @@ public class TLRPC { } public static class TL_account_saveTheme extends TLObject { - public static int constructor = 0xf257106c; + public static final int constructor = 0xf257106c; public InputTheme theme; public boolean unsave; @@ -56802,7 +57565,7 @@ public class TLRPC { } public static class TL_account_installTheme extends TLObject { - public static int constructor = 0x7ae43737; + public static final int constructor = 0x7ae43737; public int flags; public boolean dark; @@ -56827,7 +57590,7 @@ public class TLRPC { } public static class TL_account_getTheme extends TLObject { - public static int constructor = 0x8d9d742b; + public static final int constructor = 0x8d9d742b; public String format; public InputTheme theme; @@ -56846,7 +57609,7 @@ public class TLRPC { } public static class TL_account_getThemes extends TLObject { - public static int constructor = 0x7206e458; + public static final int constructor = 0x7206e458; public String format; public long hash; @@ -56863,7 +57626,7 @@ public class TLRPC { } public static class TL_account_updateEmojiStatus extends TLObject { - public static int constructor = 0xfbd3de6b; + public static final int constructor = 0xfbd3de6b; public EmojiStatus emoji_status; @@ -56877,8 +57640,23 @@ public class TLRPC { } } + public static class TL_account_getDefaultBackgroundEmojis extends TLObject { + public static final int constructor = 0xa60ab9ce; + + public long hash; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return EmojiList.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(hash); + } + } + public static class TL_account_getDefaultEmojiStatuses extends TLObject { - public static int constructor = 0xd6753386; + public static final int constructor = 0xd6753386; public long hash; @@ -56893,7 +57671,7 @@ public class TLRPC { } public static class TL_account_getRecentEmojiStatuses extends TLObject { - public static int constructor = 0xf578105; + public static final int constructor = 0xf578105; public long hash; @@ -56908,7 +57686,7 @@ public class TLRPC { } public static class TL_account_clearRecentEmojiStatuses extends TLObject { - public static int constructor = 0x18201aae; + public static final int constructor = 0x18201aae; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56921,7 +57699,7 @@ public class TLRPC { } public static class TL_account_updateDeviceLocked extends TLObject { - public static int constructor = 0x38df3532; + public static final int constructor = 0x38df3532; public int period; @@ -56936,7 +57714,7 @@ public class TLRPC { } public static class TL_messages_getWebPagePreview extends TLObject { - public static int constructor = 0x8b68b0cc; + public static final int constructor = 0x8b68b0cc; public int flags; public String message; @@ -56962,7 +57740,7 @@ public class TLRPC { } public static class TL_account_getAuthorizations extends TLObject { - public static int constructor = 0xe320c158; + public static final int constructor = 0xe320c158; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -56975,7 +57753,7 @@ public class TLRPC { } public static class TL_account_resetAuthorization extends TLObject { - public static int constructor = 0xdf77f3bc; + public static final int constructor = 0xdf77f3bc; public long hash; @@ -56990,7 +57768,7 @@ public class TLRPC { } public static class TL_account_getPassword extends TLObject { - public static int constructor = 0x548a30f5; + public static final int constructor = 0x548a30f5; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -57003,7 +57781,7 @@ public class TLRPC { } public static class TL_account_getPasswordSettings extends TLObject { - public static int constructor = 0x9cd4eaf9; + public static final int constructor = 0x9cd4eaf9; public InputCheckPasswordSRP password; @@ -57018,7 +57796,7 @@ public class TLRPC { } public static class TL_account_updatePasswordSettings extends TLObject { - public static int constructor = 0xa59b102f; + public static final int constructor = 0xa59b102f; public InputCheckPasswordSRP password; public TL_account_passwordInputSettings new_settings; @@ -57035,7 +57813,7 @@ public class TLRPC { } public static class TL_account_sendConfirmPhoneCode extends TLObject { - public static int constructor = 0x1b3faa88; + public static final int constructor = 0x1b3faa88; public String hash; public TL_codeSettings settings; @@ -57052,7 +57830,7 @@ public class TLRPC { } public static class TL_account_confirmPhone extends TLObject { - public static int constructor = 0x5f2178c3; + public static final int constructor = 0x5f2178c3; public String phone_code_hash; public String phone_code; @@ -57069,7 +57847,7 @@ public class TLRPC { } public static class TL_account_getTmpPassword extends TLObject { - public static int constructor = 0x449e0b51; + public static final int constructor = 0x449e0b51; public InputCheckPasswordSRP password; public int period; @@ -57086,7 +57864,7 @@ public class TLRPC { } public static class TL_auth_checkPassword extends TLObject { - public static int constructor = 0xd18b4d16; + public static final int constructor = 0xd18b4d16; public InputCheckPasswordSRP password; @@ -57101,7 +57879,7 @@ public class TLRPC { } public static class TL_auth_requestPasswordRecovery extends TLObject { - public static int constructor = 0xd897bc66; + public static final int constructor = 0xd897bc66; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -57114,7 +57892,7 @@ public class TLRPC { } public static class TL_auth_recoverPassword extends TLObject { - public static int constructor = 0x37096c70; + public static final int constructor = 0x37096c70; public int flags; public String code; @@ -57135,7 +57913,7 @@ public class TLRPC { } public static class TL_auth_resendCode extends TLObject { - public static int constructor = 0x3ef1a9bf; + public static final int constructor = 0x3ef1a9bf; public String phone_number; public String phone_code_hash; @@ -57152,7 +57930,7 @@ public class TLRPC { } public static class TL_auth_cancelCode extends TLObject { - public static int constructor = 0x1f040578; + public static final int constructor = 0x1f040578; public String phone_number; public String phone_code_hash; @@ -57169,7 +57947,7 @@ public class TLRPC { } public static class TL_messages_exportChatInvite extends TLObject { - public static int constructor = 0xa02ce5d5; + public static final int constructor = 0xa02ce5d5; public int flags; public boolean legacy_revoke_permanent; @@ -57202,7 +57980,7 @@ public class TLRPC { } public static class TL_messages_checkChatInvite extends TLObject { - public static int constructor = 0x3eadb1bb; + public static final int constructor = 0x3eadb1bb; public String hash; @@ -57217,7 +57995,7 @@ public class TLRPC { } public static class TL_messages_importChatInvite extends TLObject { - public static int constructor = 0x6c50051c; + public static final int constructor = 0x6c50051c; public String hash; @@ -57232,7 +58010,7 @@ public class TLRPC { } public static class TL_messages_getStickerSet extends TLObject { - public static int constructor = 0xc8a0ec74; + public static final int constructor = 0xc8a0ec74; public InputStickerSet stickerset; public int hash; @@ -57249,7 +58027,7 @@ public class TLRPC { } public static class TL_messages_installStickerSet extends TLObject { - public static int constructor = 0xc78fe460; + public static final int constructor = 0xc78fe460; public InputStickerSet stickerset; public boolean archived; @@ -57266,7 +58044,7 @@ public class TLRPC { } public static class TL_messages_uninstallStickerSet extends TLObject { - public static int constructor = 0xf96e55de; + public static final int constructor = 0xf96e55de; public InputStickerSet stickerset; @@ -57281,7 +58059,7 @@ public class TLRPC { } public static class TL_messages_startBot extends TLObject { - public static int constructor = 0xe6df7378; + public static final int constructor = 0xe6df7378; public InputUser bot; public InputPeer peer; @@ -57302,7 +58080,7 @@ public class TLRPC { } public static class TL_messages_getMessagesViews extends TLObject { - public static int constructor = 0x5784d3e1; + public static final int constructor = 0x5784d3e1; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -57326,7 +58104,7 @@ public class TLRPC { } public static class TL_messages_getSavedGifs extends TLObject { - public static int constructor = 0x5cf09635; + public static final int constructor = 0x5cf09635; public long hash; @@ -57341,7 +58119,7 @@ public class TLRPC { } public static class TL_messages_saveGif extends TLObject { - public static int constructor = 0x327a30cb; + public static final int constructor = 0x327a30cb; public InputDocument id; public boolean unsave; @@ -57358,7 +58136,7 @@ public class TLRPC { } public static class TL_messages_getInlineBotResults extends TLObject { - public static int constructor = 0x514e999d; + public static final int constructor = 0x514e999d; public int flags; public InputUser bot; @@ -57385,7 +58163,7 @@ public class TLRPC { } public static class TL_messages_sendInlineBotResult extends TLObject { - public static int constructor = 0xf7bc68ba; + public static final int constructor = 0xf7bc68ba; public int flags; public boolean silent; @@ -57428,7 +58206,7 @@ public class TLRPC { } public static class TL_messages_getMessageEditData extends TLObject { - public static int constructor = 0xfda68d36; + public static final int constructor = 0xfda68d36; public InputPeer peer; public int id; @@ -57445,10 +58223,11 @@ public class TLRPC { } public static class TL_messages_editMessage extends TLObject { - public static int constructor = 0x48f71778; + public static final int constructor = 0x48f71778; public int flags; public boolean no_webpage; + public boolean invert_media; public InputPeer peer; public int id; public String message; @@ -57464,6 +58243,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = no_webpage ? (flags | 2) : (flags &~ 2); + flags = invert_media ? (flags | 65536) : (flags &~ 65536); stream.writeInt32(flags); peer.serializeToStream(stream); stream.writeInt32(id); @@ -57491,7 +58271,7 @@ public class TLRPC { } public static class TL_messages_getBotCallbackAnswer extends TLObject { - public static int constructor = 0x9342ca07; + public static final int constructor = 0x9342ca07; public int flags; public boolean game; @@ -57520,7 +58300,7 @@ public class TLRPC { } public static class TL_messages_setBotCallbackAnswer extends TLObject { - public static int constructor = 0xd58f130a; + public static final int constructor = 0xd58f130a; public int flags; public boolean alert; @@ -57549,7 +58329,7 @@ public class TLRPC { } public static class TL_messages_getPeerDialogs extends TLObject { - public static int constructor = 0xe470bcfd; + public static final int constructor = 0xe470bcfd; public ArrayList peers = new ArrayList<>(); @@ -57569,15 +58349,16 @@ public class TLRPC { } public static class TL_messages_saveDraft extends TLObject { - public static int constructor = 0xb4331e3f; + public static final int constructor = 0x7ff3b806; public int flags; public boolean no_webpage; - public int reply_to_msg_id; - public int top_msg_id; + public boolean invert_media; + public InputReplyTo reply_to; public InputPeer peer; public String message; public ArrayList entities = new ArrayList<>(); + public InputMedia media; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); @@ -57586,12 +58367,10 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = no_webpage ? (flags | 2) : (flags &~ 2); + flags = invert_media ? (flags | 64) : (flags &~ 64); stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(reply_to_msg_id); - } - if ((flags & 4) != 0) { - stream.writeInt32(top_msg_id); + if ((flags & 16) != 0) { + reply_to.serializeToStream(stream); } peer.serializeToStream(stream); stream.writeString(message); @@ -57603,11 +58382,14 @@ public class TLRPC { entities.get(a).serializeToStream(stream); } } + if ((flags & 32) != 0) { + media.serializeToStream(stream); + } } } public static class TL_messages_getAllDrafts extends TLObject { - public static int constructor = 0x6a3f8d65; + public static final int constructor = 0x6a3f8d65; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -57620,7 +58402,7 @@ public class TLRPC { } public static class TL_messages_getFeaturedStickers extends TLObject { - public static int constructor = 0x64780b14; + public static final int constructor = 0x64780b14; public long hash; @@ -57635,7 +58417,7 @@ public class TLRPC { } public static class TL_messages_readFeaturedStickers extends TLObject { - public static int constructor = 0x5b118126; + public static final int constructor = 0x5b118126; public ArrayList id = new ArrayList<>(); @@ -57655,7 +58437,7 @@ public class TLRPC { } public static class TL_messages_getRecentStickers extends TLObject { - public static int constructor = 0x9da9403b; + public static final int constructor = 0x9da9403b; public int flags; public boolean attached; @@ -57674,7 +58456,7 @@ public class TLRPC { } public static class TL_messages_saveRecentSticker extends TLObject { - public static int constructor = 0x392718f8; + public static final int constructor = 0x392718f8; public int flags; public boolean attached; @@ -57695,7 +58477,7 @@ public class TLRPC { } public static class TL_messages_clearRecentStickers extends TLObject { - public static int constructor = 0x8999602d; + public static final int constructor = 0x8999602d; public int flags; public boolean attached; @@ -57712,7 +58494,7 @@ public class TLRPC { } public static class TL_messages_getArchivedStickers extends TLObject { - public static int constructor = 0x57f17692; + public static final int constructor = 0x57f17692; public int flags; public boolean masks; @@ -57735,7 +58517,7 @@ public class TLRPC { } public static class TL_messages_setGameScore extends TLObject { - public static int constructor = 0x8ef8ecc0; + public static final int constructor = 0x8ef8ecc0; public int flags; public boolean edit_message; @@ -57762,7 +58544,7 @@ public class TLRPC { } public static class TL_messages_setInlineGameScore extends TLObject { - public static int constructor = 0x15ad9f64; + public static final int constructor = 0x15ad9f64; public int flags; public boolean edit_message; @@ -57787,7 +58569,7 @@ public class TLRPC { } public static class TL_messages_getMaskStickers extends TLObject { - public static int constructor = 0x640f82b8; + public static final int constructor = 0x640f82b8; public long hash; @@ -57802,7 +58584,7 @@ public class TLRPC { } public static class TL_messages_getGameHighScores extends TLObject { - public static int constructor = 0xe822649d; + public static final int constructor = 0xe822649d; public InputPeer peer; public int id; @@ -57821,7 +58603,7 @@ public class TLRPC { } public static class TL_messages_getInlineGameHighScores extends TLObject { - public static int constructor = 0xf635e1b; + public static final int constructor = 0xf635e1b; public TL_inputBotInlineMessageID id; public InputUser user_id; @@ -57838,7 +58620,7 @@ public class TLRPC { } public static class TL_messages_getAttachedStickers extends TLObject { - public static int constructor = 0xcc5b67cc; + public static final int constructor = 0xcc5b67cc; public InputStickeredMedia media; @@ -57862,7 +58644,7 @@ public class TLRPC { } public static class TL_messages_getCommonChats extends TLObject { - public static int constructor = 0xe40ca104; + public static final int constructor = 0xe40ca104; public InputUser user_id; public long max_id; @@ -57881,7 +58663,7 @@ public class TLRPC { } public static class TL_messages_getAllChats extends TLObject { - public static int constructor = 0x875f74be; + public static final int constructor = 0x875f74be; public ArrayList except_ids = new ArrayList<>(); @@ -57901,13 +58683,13 @@ public class TLRPC { } public static class TL_messages_getWebPage extends TLObject { - public static int constructor = 0x32ca8f91; + public static final int constructor = 0x8d9692a3; public String url; public int hash; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return WebPage.TLdeserialize(stream, constructor, exception); + return TL_messages_webPage.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -57918,7 +58700,7 @@ public class TLRPC { } public static class TL_messages_toggleDialogPin extends TLObject { - public static int constructor = 0xa731e257; + public static final int constructor = 0xa731e257; public int flags; public boolean pinned; @@ -57937,7 +58719,7 @@ public class TLRPC { } public static class TL_messages_reorderPinnedDialogs extends TLObject { - public static int constructor = 0x3b1adf37; + public static final int constructor = 0x3b1adf37; public int flags; public boolean force; @@ -57963,7 +58745,7 @@ public class TLRPC { } public static class TL_messages_getPinnedDialogs extends TLObject { - public static int constructor = 0xd6b94df2; + public static final int constructor = 0xd6b94df2; public int folder_id; @@ -57978,7 +58760,7 @@ public class TLRPC { } public static class TL_messages_uploadMedia extends TLObject { - public static int constructor = 0x519bc2b1; + public static final int constructor = 0x519bc2b1; public InputPeer peer; public InputMedia media; @@ -57995,7 +58777,7 @@ public class TLRPC { } public static class TL_messages_sendScreenshotNotification extends TLObject { - public static int constructor = 0xa1405817; + public static final int constructor = 0xa1405817; public InputPeer peer; public InputReplyTo reply_to; @@ -58014,7 +58796,7 @@ public class TLRPC { } public static class TL_messages_getFavedStickers extends TLObject { - public static int constructor = 0x4f1aaa9; + public static final int constructor = 0x4f1aaa9; public long hash; @@ -58029,7 +58811,7 @@ public class TLRPC { } public static class TL_messages_faveSticker extends TLObject { - public static int constructor = 0xb9ffc55b; + public static final int constructor = 0xb9ffc55b; public InputDocument id; public boolean unfave; @@ -58046,7 +58828,7 @@ public class TLRPC { } public static class TL_messages_getUnreadMentions extends TLObject { - public static int constructor = 0xf107e790; + public static final int constructor = 0xf107e790; public int flags; public InputPeer peer; @@ -58077,7 +58859,7 @@ public class TLRPC { } public static class TL_messages_readMentions extends TLObject { - public static int constructor = 0x36e5bf4d; + public static final int constructor = 0x36e5bf4d; public int flags; public InputPeer peer; @@ -58098,7 +58880,7 @@ public class TLRPC { } public static class TL_messages_getRecentLocations extends TLObject { - public static int constructor = 0x702a40e0; + public static final int constructor = 0x702a40e0; public InputPeer peer; public int limit; @@ -58117,7 +58899,7 @@ public class TLRPC { } public static class TL_messages_sendMultiMedia extends TLObject { - public static int constructor = 0x456e8987; + public static final int constructor = 0x456e8987; public int flags; public boolean silent; @@ -58125,6 +58907,7 @@ public class TLRPC { public boolean clear_draft; public boolean noforwards; public boolean update_stickersets_order; + public boolean invert_media; public InputPeer peer; public InputReplyTo reply_to; public ArrayList multi_media = new ArrayList<>(); @@ -58142,6 +58925,7 @@ public class TLRPC { flags = clear_draft ? (flags | 128) : (flags &~ 128); flags = noforwards ? (flags | 16384) : (flags &~ 16384); flags = update_stickersets_order ? (flags | 32768) : (flags &~ 32768); + flags = invert_media ? (flags | 65536) : (flags &~ 65536); stream.writeInt32(flags); peer.serializeToStream(stream); if ((flags & 1) != 0) { @@ -58163,7 +58947,7 @@ public class TLRPC { } public static class TL_messages_clearAllDrafts extends TLObject { - public static int constructor = 0x7e58ee9c; + public static final int constructor = 0x7e58ee9c; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -58176,7 +58960,7 @@ public class TLRPC { } public static class TL_messages_updatePinnedMessage extends TLObject { - public static int constructor = 0xd2aaf7ec; + public static final int constructor = 0xd2aaf7ec; public int flags; public boolean silent; @@ -58201,7 +58985,7 @@ public class TLRPC { } public static class TL_messages_sendVote extends TLObject { - public static int constructor = 0x10ea6184; + public static final int constructor = 0x10ea6184; public InputPeer peer; public int msg_id; @@ -58225,7 +59009,7 @@ public class TLRPC { } public static class TL_messages_getPollResults extends TLObject { - public static int constructor = 0x73bb643b; + public static final int constructor = 0x73bb643b; public InputPeer peer; public int msg_id; @@ -58242,7 +59026,7 @@ public class TLRPC { } public static class TL_messages_getOnlines extends TLObject { - public static int constructor = 0x6e2be050; + public static final int constructor = 0x6e2be050; public InputPeer peer; @@ -58257,7 +59041,7 @@ public class TLRPC { } public static class TL_messages_getStatsURL extends TLObject { - public static int constructor = 0x812c2ae6; + public static final int constructor = 0x812c2ae6; public int flags; public boolean dark; @@ -58278,7 +59062,7 @@ public class TLRPC { } public static class TL_messages_editChatAbout extends TLObject { - public static int constructor = 0xdef60797; + public static final int constructor = 0xdef60797; public InputPeer peer; public String about; @@ -58295,7 +59079,7 @@ public class TLRPC { } public static class TL_messages_editChatDefaultBannedRights extends TLObject { - public static int constructor = 0xa5866b41; + public static final int constructor = 0xa5866b41; public InputPeer peer; public TL_chatBannedRights banned_rights; @@ -58312,7 +59096,7 @@ public class TLRPC { } public static class TL_messages_getEmojiKeywords extends TLObject { - public static int constructor = 0x35a0e062; + public static final int constructor = 0x35a0e062; public String lang_code; @@ -58327,7 +59111,7 @@ public class TLRPC { } public static class TL_messages_getEmojiKeywordsDifference extends TLObject { - public static int constructor = 0x1508b6af; + public static final int constructor = 0x1508b6af; public String lang_code; public int from_version; @@ -58344,7 +59128,7 @@ public class TLRPC { } public static class TL_messages_getEmojiKeywordsLanguages extends TLObject { - public static int constructor = 0x4e9963b2; + public static final int constructor = 0x4e9963b2; public ArrayList lang_codes = new ArrayList<>(); @@ -58373,7 +59157,7 @@ public class TLRPC { } public static class TL_messages_getEmojiURL extends TLObject { - public static int constructor = 0xd5b10c26; + public static final int constructor = 0xd5b10c26; public String lang_code; @@ -58388,7 +59172,7 @@ public class TLRPC { } public static class TL_messages_getSearchCounters extends TLObject { - public static int constructor = 0xae7cc1; + public static final int constructor = 0xae7cc1; public int flags; public InputPeer peer; @@ -58425,7 +59209,7 @@ public class TLRPC { } public static class TL_messages_requestUrlAuth extends TLObject { - public static int constructor = 0x198fb446; + public static final int constructor = 0x198fb446; public int flags; public InputPeer peer; @@ -58456,7 +59240,7 @@ public class TLRPC { } public static class TL_messages_acceptUrlAuth extends TLObject { - public static int constructor = 0xb12c7125; + public static final int constructor = 0xb12c7125; public int flags; public boolean write_allowed; @@ -58489,7 +59273,7 @@ public class TLRPC { } public static class TL_messages_hidePeerSettingsBar extends TLObject { - public static int constructor = 0x4facb138; + public static final int constructor = 0x4facb138; public InputPeer peer; @@ -58504,7 +59288,7 @@ public class TLRPC { } public static class TL_messages_getScheduledHistory extends TLObject { - public static int constructor = 0xf516760b; + public static final int constructor = 0xf516760b; public InputPeer peer; public long hash; @@ -58521,7 +59305,7 @@ public class TLRPC { } public static class TL_messages_getScheduledMessages extends TLObject { - public static int constructor = 0xbdbb0464; + public static final int constructor = 0xbdbb0464; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -58543,7 +59327,7 @@ public class TLRPC { } public static class TL_messages_sendScheduledMessages extends TLObject { - public static int constructor = 0xbd38850a; + public static final int constructor = 0xbd38850a; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -58565,7 +59349,7 @@ public class TLRPC { } public static class TL_messages_deleteScheduledMessages extends TLObject { - public static int constructor = 0x59ae2b16; + public static final int constructor = 0x59ae2b16; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -58615,7 +59399,7 @@ public class TLRPC { } public static class TL_messages_sendReaction extends TLObject { - public static int constructor = 0xd30d78d4; + public static final int constructor = 0xd30d78d4; public int flags; public boolean big; @@ -58647,7 +59431,7 @@ public class TLRPC { } public static class TL_messages_setDefaultReaction extends TLObject { - public static int constructor = 0x4f47a016; + public static final int constructor = 0x4f47a016; public Reaction reaction; @@ -58662,7 +59446,7 @@ public class TLRPC { } public static class TL_messages_translateText extends TLObject { - public static int constructor = 0x63183030; + public static final int constructor = 0x63183030; public int flags; public InputPeer peer; @@ -58701,7 +59485,7 @@ public class TLRPC { } public static class TL_messages_getUnreadReactions extends TLObject { - public static int constructor = 0x3223495b; + public static final int constructor = 0x3223495b; public int flags; public InputPeer peer; @@ -58732,7 +59516,7 @@ public class TLRPC { } public static class TL_messages_readReactions extends TLObject { - public static int constructor = 0x54aa7f8e; + public static final int constructor = 0x54aa7f8e; public int flags; public InputPeer peer; @@ -58753,7 +59537,7 @@ public class TLRPC { } public static class TL_messages_sendWebViewData extends TLObject { - public static int constructor = 0xdc0242c8; + public static final int constructor = 0xdc0242c8; public InputUser bot; public long random_id; @@ -58774,7 +59558,7 @@ public class TLRPC { } public static class TL_messages_getMessagesReactions extends TLObject { - public static int constructor = 0x8bba90e6; + public static final int constructor = 0x8bba90e6; public InputPeer peer; public ArrayList id = new ArrayList<>(); @@ -58796,7 +59580,7 @@ public class TLRPC { } public static class TL_messages_getMessageReactionsList extends TLObject { - public static int constructor = 0x461b3f48; + public static final int constructor = 0x461b3f48; public int flags; public InputPeer peer; @@ -58825,7 +59609,7 @@ public class TLRPC { } public static class TL_messages_setChatAvailableReactions extends TLObject { - public static int constructor = 0xfeb16771; + public static final int constructor = 0xfeb16771; public InputPeer peer; public ChatReactions available_reactions; @@ -58842,7 +59626,7 @@ public class TLRPC { } public static class TL_messages_getAvailableReactions extends TLObject { - public static int constructor = 0x18dea0ac; + public static final int constructor = 0x18dea0ac; public int hash; @@ -58858,7 +59642,7 @@ public class TLRPC { public static class TL_messages_searchResultsCalendar extends TLObject { - public static int constructor = 0x147ee23c; + public static final int constructor = 0x147ee23c; public int flags; public boolean inexact; @@ -58993,7 +59777,7 @@ public class TLRPC { } public static class TL_messages_getPollVotes extends TLObject { - public static int constructor = 0xb86e380e; + public static final int constructor = 0xb86e380e; public int flags; public InputPeer peer; @@ -59022,7 +59806,7 @@ public class TLRPC { } public static class TL_messages_getDialogFilters extends TLObject { - public static int constructor = 0xf19ed96d; + public static final int constructor = 0xf19ed96d; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -59044,7 +59828,7 @@ public class TLRPC { } public static class TL_messages_getSuggestedDialogFilters extends TLObject { - public static int constructor = 0xa29cd42c; + public static final int constructor = 0xa29cd42c; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -59066,7 +59850,7 @@ public class TLRPC { } public static class TL_messages_updateDialogFilter extends TLObject { - public static int constructor = 0x1ad4a04a; + public static final int constructor = 0x1ad4a04a; public int flags; public int id; @@ -59087,7 +59871,7 @@ public class TLRPC { } public static class TL_messages_updateDialogFiltersOrder extends TLObject { - public static int constructor = 0xc563c1e4; + public static final int constructor = 0xc563c1e4; public ArrayList order = new ArrayList<>(); @@ -59107,7 +59891,7 @@ public class TLRPC { } public static class TL_messages_getOldFeaturedStickers extends TLObject { - public static int constructor = 0x7ed094a1; + public static final int constructor = 0x7ed094a1; public int offset; public int limit; @@ -59126,7 +59910,7 @@ public class TLRPC { } public static class TL_messages_getReplies extends TLObject { - public static int constructor = 0x22ddd30c; + public static final int constructor = 0x22ddd30c; public InputPeer peer; public int msg_id; @@ -59157,7 +59941,7 @@ public class TLRPC { } public static class TL_messages_getDiscussionMessage extends TLObject { - public static int constructor = 0x446972fd; + public static final int constructor = 0x446972fd; public InputPeer peer; public int msg_id; @@ -59174,7 +59958,7 @@ public class TLRPC { } public static class TL_messages_readDiscussion extends TLObject { - public static int constructor = 0xf731a9f4; + public static final int constructor = 0xf731a9f4; public InputPeer peer; public int msg_id; @@ -59193,7 +59977,7 @@ public class TLRPC { } public static class TL_messages_unpinAllMessages extends TLObject { - public static int constructor = 0xf025bc8b; + public static final int constructor = 0xf025bc8b; public InputPeer peer; @@ -59208,7 +59992,7 @@ public class TLRPC { } public static class TL_messages_getExportedChatInvites extends TLObject { - public static int constructor = 0xa2b5a3f6; + public static final int constructor = 0xa2b5a3f6; public int flags; public boolean revoked; @@ -59239,7 +60023,7 @@ public class TLRPC { } public static class TL_messages_getExportedChatInvite extends TLObject { - public static int constructor = 0x73746f5c; + public static final int constructor = 0x73746f5c; public InputPeer peer; public String link; @@ -59256,7 +60040,7 @@ public class TLRPC { } public static class TL_messages_editExportedChatInvite extends TLObject { - public static int constructor = 0xbdca2f75; + public static final int constructor = 0xbdca2f75; public int flags; public boolean revoked; @@ -59293,7 +60077,7 @@ public class TLRPC { } public static class TL_messages_deleteRevokedExportedChatInvites extends TLObject { - public static int constructor = 0x56987bd5; + public static final int constructor = 0x56987bd5; public InputPeer peer; public InputUser admin_id; @@ -59310,7 +60094,7 @@ public class TLRPC { } public static class TL_messages_deleteExportedChatInvite extends TLObject { - public static int constructor = 0xd464a42b; + public static final int constructor = 0xd464a42b; public InputPeer peer; public String link; @@ -59327,7 +60111,7 @@ public class TLRPC { } public static class TL_messages_getAdminsWithInvites extends TLObject { - public static int constructor = 0x3920e6ef; + public static final int constructor = 0x3920e6ef; public InputPeer peer; @@ -59342,7 +60126,7 @@ public class TLRPC { } public static class TL_messages_getChatInviteImporters extends TLObject { - public static int constructor = 0xdf04dd4e; + public static final int constructor = 0xdf04dd4e; public int flags; public boolean requested; @@ -59375,7 +60159,7 @@ public class TLRPC { } public static class TL_messages_hideChatJoinRequest extends TLObject { - public static int constructor = 0x7fe7e815; + public static final int constructor = 0x7fe7e815; public int flags; public boolean approved; @@ -59396,7 +60180,7 @@ public class TLRPC { } public static class TL_messages_hideAllChatJoinRequests extends TLObject { - public static int constructor = 0xe085f4ea; + public static final int constructor = 0xe085f4ea; public int flags; public boolean approved; @@ -59419,7 +60203,7 @@ public class TLRPC { } public static class TL_messages_toggleNoForwards extends TLObject { - public static int constructor = 0xb11eafa2; + public static final int constructor = 0xb11eafa2; public InputPeer peer; public boolean enabled; @@ -59436,7 +60220,7 @@ public class TLRPC { } public static class TL_messages_saveDefaultSendAs extends TLObject { - public static int constructor = 0xccfddf96; + public static final int constructor = 0xccfddf96; public InputPeer peer; public InputPeer send_as; @@ -59453,7 +60237,7 @@ public class TLRPC { } public static class TL_messages_setHistoryTTL extends TLObject { - public static int constructor = 0xb80e5fe4; + public static final int constructor = 0xb80e5fe4; public InputPeer peer; public int period; @@ -59470,7 +60254,7 @@ public class TLRPC { } public static class TL_messages_deleteChat extends TLObject { - public static int constructor = 0x5bd0ee50; + public static final int constructor = 0x5bd0ee50; public long chat_id; @@ -59485,7 +60269,7 @@ public class TLRPC { } public static class TL_messages_deletePhoneCallHistory extends TLObject { - public static int constructor = 0xf9cbe409; + public static final int constructor = 0xf9cbe409; public int flags; public boolean revoke; @@ -59502,7 +60286,7 @@ public class TLRPC { } public static class TL_messages_checkHistoryImport extends TLObject { - public static int constructor = 0x43fe19f3; + public static final int constructor = 0x43fe19f3; public String import_head; @@ -59517,7 +60301,7 @@ public class TLRPC { } public static class TL_messages_initHistoryImport extends TLObject { - public static int constructor = 0x34090c3b; + public static final int constructor = 0x34090c3b; public InputPeer peer; public InputFile file; @@ -59536,7 +60320,7 @@ public class TLRPC { } public static class TL_messages_uploadImportedMedia extends TLObject { - public static int constructor = 0x2a862092; + public static final int constructor = 0x2a862092; public InputPeer peer; public long import_id; @@ -59557,7 +60341,7 @@ public class TLRPC { } public static class TL_messages_startHistoryImport extends TLObject { - public static int constructor = 0xb43df344; + public static final int constructor = 0xb43df344; public InputPeer peer; public long import_id; @@ -59574,7 +60358,7 @@ public class TLRPC { } public static class TL_messages_checkHistoryImportPeer extends TLObject { - public static int constructor = 0x5dc60f03; + public static final int constructor = 0x5dc60f03; public InputPeer peer; @@ -59589,7 +60373,7 @@ public class TLRPC { } public static class TL_messages_setChatTheme extends TLObject { - public static int constructor = 0xe63be13f; + public static final int constructor = 0xe63be13f; public InputPeer peer; public String emoticon; @@ -59606,7 +60390,7 @@ public class TLRPC { } public static class TL_help_getAppChangelog extends TLObject { - public static int constructor = 0x9010ef6f; + public static final int constructor = 0x9010ef6f; public String prev_app_version; @@ -59621,7 +60405,7 @@ public class TLRPC { } public static class TL_messages_toggleStickerSets extends TLObject { - public static int constructor = 0xb5052fea; + public static final int constructor = 0xb5052fea; public int flags; public boolean uninstall; @@ -59649,7 +60433,7 @@ public class TLRPC { } public static class TL_messages_uploadEncryptedFile extends TLObject { - public static int constructor = 0x5057c497; + public static final int constructor = 0x5057c497; public TL_inputEncryptedChat peer; public InputEncryptedFile file; @@ -59666,7 +60450,7 @@ public class TLRPC { } public static class TL_messages_searchStickerSets extends TLObject { - public static int constructor = 0x35705b8a; + public static final int constructor = 0x35705b8a; public int flags; public boolean exclude_featured; @@ -59687,7 +60471,7 @@ public class TLRPC { } public static class TL_messages_markDialogUnread extends TLObject { - public static int constructor = 0xc286d98f; + public static final int constructor = 0xc286d98f; public int flags; public boolean unread; @@ -59706,7 +60490,7 @@ public class TLRPC { } public static class TL_messages_getDialogUnreadMarks extends TLObject { - public static int constructor = 0x22e24e22; + public static final int constructor = 0x22e24e22; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -59728,7 +60512,7 @@ public class TLRPC { } public static class TL_help_setBotUpdatesStatus extends TLObject { - public static int constructor = 0xec22cfcd; + public static final int constructor = 0xec22cfcd; public int pending_updates_count; public String message; @@ -59745,7 +60529,7 @@ public class TLRPC { } public static class TL_messages_reorderStickerSets extends TLObject { - public static int constructor = 0x78337739; + public static final int constructor = 0x78337739; public int flags; public boolean masks; @@ -59771,7 +60555,7 @@ public class TLRPC { } public static class TL_messages_getEmojiStickers extends TLObject { - public static int constructor = 0xfbfca18f; + public static final int constructor = 0xfbfca18f; public long hash; @@ -59786,7 +60570,7 @@ public class TLRPC { } public static class TL_messages_getFeaturedEmojiStickers extends TLObject { - public static int constructor = 0xecf6736; + public static final int constructor = 0xecf6736; public long hash; @@ -59801,7 +60585,7 @@ public class TLRPC { } public static class TL_messages_getDocumentByHash extends TLObject { - public static int constructor = 0x338e2464; + public static final int constructor = 0x338e2464; public byte[] sha256; public int size; @@ -59820,7 +60604,7 @@ public class TLRPC { } public static class TL_help_getRecentMeUrls extends TLObject { - public static int constructor = 0x3dc0f114; + public static final int constructor = 0x3dc0f114; public String referer; @@ -59835,7 +60619,7 @@ public class TLRPC { } public static class TL_help_getDeepLinkInfo extends TLObject { - public static int constructor = 0x3fedc75f; + public static final int constructor = 0x3fedc75f; public String path; @@ -59850,7 +60634,7 @@ public class TLRPC { } public static class TL_channels_readHistory extends TLObject { - public static int constructor = 0xcc104937; + public static final int constructor = 0xcc104937; public InputChannel channel; public int max_id; @@ -59867,7 +60651,7 @@ public class TLRPC { } public static class TL_channels_deleteMessages extends TLObject { - public static int constructor = 0x84c1fd4e; + public static final int constructor = 0x84c1fd4e; public InputChannel channel; public ArrayList id = new ArrayList<>(); @@ -59917,7 +60701,7 @@ public class TLRPC { } public static class TL_channels_deleteParticipantHistory extends TLObject { - public static int constructor = 0x367544db; + public static final int constructor = 0x367544db; public InputChannel channel; public InputPeer participant; @@ -59934,7 +60718,7 @@ public class TLRPC { } public static class TL_channels_reportSpam extends TLObject { - public static int constructor = 0xf44a8315; + public static final int constructor = 0xf44a8315; public InputChannel channel; public InputPeer participant; @@ -59958,7 +60742,7 @@ public class TLRPC { } public static class TL_channels_getMessages extends TLObject { - public static int constructor = 0x93d7b347; + public static final int constructor = 0x93d7b347; public InputChannel channel; public ArrayList id = new ArrayList<>(); @@ -59980,7 +60764,7 @@ public class TLRPC { } public static class TL_channels_getParticipants extends TLObject { - public static int constructor = 0x77ced9d0; + public static final int constructor = 0x77ced9d0; public InputChannel channel; public ChannelParticipantsFilter filter; @@ -60003,7 +60787,7 @@ public class TLRPC { } public static class TL_channels_getParticipant extends TLObject { - public static int constructor = 0xa0ab6cc6; + public static final int constructor = 0xa0ab6cc6; public InputChannel channel; public InputPeer participant; @@ -60020,7 +60804,7 @@ public class TLRPC { } public static class TL_channels_getChannels extends TLObject { - public static int constructor = 0xa7f6bbb; + public static final int constructor = 0xa7f6bbb; public ArrayList id = new ArrayList<>(); @@ -60040,7 +60824,7 @@ public class TLRPC { } public static class TL_channels_getFullChannel extends TLObject { - public static int constructor = 0x8736a09; + public static final int constructor = 0x8736a09; public InputChannel channel; @@ -60055,7 +60839,7 @@ public class TLRPC { } public static class TL_channels_createChannel extends TLObject { - public static int constructor = 0x91006707; + public static final int constructor = 0x91006707; public int flags; public boolean broadcast; @@ -60094,7 +60878,7 @@ public class TLRPC { } public static class TL_channels_editAdmin extends TLObject { - public static int constructor = 0xd33c8902; + public static final int constructor = 0xd33c8902; public InputChannel channel; public InputUser user_id; @@ -60115,7 +60899,7 @@ public class TLRPC { } public static class TL_channels_editTitle extends TLObject { - public static int constructor = 0x566decd0; + public static final int constructor = 0x566decd0; public InputChannel channel; public String title; @@ -60132,7 +60916,7 @@ public class TLRPC { } public static class TL_channels_editPhoto extends TLObject { - public static int constructor = 0xf12e57c9; + public static final int constructor = 0xf12e57c9; public InputChannel channel; public InputChatPhoto photo; @@ -60149,7 +60933,7 @@ public class TLRPC { } public static class TL_channels_checkUsername extends TLObject { - public static int constructor = 0x10e6bd2c; + public static final int constructor = 0x10e6bd2c; public InputChannel channel; public String username; @@ -60166,7 +60950,7 @@ public class TLRPC { } public static class TL_channels_updateUsername extends TLObject { - public static int constructor = 0x3514b3de; + public static final int constructor = 0x3514b3de; public InputChannel channel; public String username; @@ -60183,7 +60967,7 @@ public class TLRPC { } public static class TL_channels_joinChannel extends TLObject { - public static int constructor = 0x24b524c5; + public static final int constructor = 0x24b524c5; public InputChannel channel; @@ -60198,7 +60982,7 @@ public class TLRPC { } public static class TL_channels_leaveChannel extends TLObject { - public static int constructor = 0xf836aa95; + public static final int constructor = 0xf836aa95; public InputChannel channel; @@ -60213,7 +60997,7 @@ public class TLRPC { } public static class TL_channels_inviteToChannel extends TLObject { - public static int constructor = 0x199f3a6c; + public static final int constructor = 0x199f3a6c; public InputChannel channel; public ArrayList users = new ArrayList<>(); @@ -60235,7 +61019,7 @@ public class TLRPC { } public static class TL_channels_deleteChannel extends TLObject { - public static int constructor = 0xc0111fe3; + public static final int constructor = 0xc0111fe3; public InputChannel channel; @@ -60250,7 +61034,7 @@ public class TLRPC { } public static class TL_channels_exportMessageLink extends TLObject { - public static int constructor = 0xe63fadeb; + public static final int constructor = 0xe63fadeb; public int flags; public boolean grouped; @@ -60273,7 +61057,7 @@ public class TLRPC { } public static class TL_channels_toggleSignatures extends TLObject { - public static int constructor = 0x1f69b606; + public static final int constructor = 0x1f69b606; public InputChannel channel; public boolean enabled; @@ -60290,7 +61074,7 @@ public class TLRPC { } public static class TL_channels_getAdminedPublicChannels extends TLObject { - public static int constructor = 0xf8b036af; + public static final int constructor = 0xf8b036af; public int flags; public boolean by_location; @@ -60309,7 +61093,7 @@ public class TLRPC { } public static class TL_channels_editBanned extends TLObject { - public static int constructor = 0x96e6cd81; + public static final int constructor = 0x96e6cd81; public InputChannel channel; public InputPeer participant; @@ -60328,7 +61112,7 @@ public class TLRPC { } public static class TL_channels_getAdminLog extends TLObject { - public static int constructor = 0x33ddf480; + public static final int constructor = 0x33ddf480; public int flags; public InputChannel channel; @@ -60366,7 +61150,7 @@ public class TLRPC { } public static class TL_channels_setStickers extends TLObject { - public static int constructor = 0xea8ca4f9; + public static final int constructor = 0xea8ca4f9; public InputChannel channel; public InputStickerSet stickerset; @@ -60383,7 +61167,7 @@ public class TLRPC { } public static class TL_channels_readMessageContents extends TLObject { - public static int constructor = 0xeab5dc38; + public static final int constructor = 0xeab5dc38; public InputChannel channel; public ArrayList id = new ArrayList<>(); @@ -60405,7 +61189,7 @@ public class TLRPC { } public static class TL_channels_deleteHistory extends TLObject { - public static int constructor = 0x9baa9647; + public static final int constructor = 0x9baa9647; public int flags; public boolean for_everyone; @@ -60426,7 +61210,7 @@ public class TLRPC { } public static class TL_channels_searchPosts extends TLObject { - public static int constructor = 0x43a0a7e2; + public static final int constructor = 0x43a0a7e2; public String q; public int offset_rate; @@ -60449,7 +61233,7 @@ public class TLRPC { } public static class TL_channels_toggleSlowMode extends TLObject { - public static int constructor = 0xedd49ef0; + public static final int constructor = 0xedd49ef0; public InputChannel channel; public int seconds; @@ -60466,7 +61250,7 @@ public class TLRPC { } public static class TL_channels_getInactiveChannels extends TLObject { - public static int constructor = 0x11e831ee; + public static final int constructor = 0x11e831ee; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -60479,7 +61263,7 @@ public class TLRPC { } public static class TL_channels_convertToGigagroup extends TLObject { - public static int constructor = 0xb290c69; + public static final int constructor = 0xb290c69; public InputChannel channel; @@ -60494,7 +61278,7 @@ public class TLRPC { } public static class TL_channels_viewSponsoredMessage extends TLObject { - public static int constructor = 0xbeaedb94; + public static final int constructor = 0xbeaedb94; public InputChannel channel; public byte[] random_id; @@ -60511,7 +61295,7 @@ public class TLRPC { } public static class TL_channels_getSponsoredMessages extends TLObject { - public static int constructor = 0xec210fbf; + public static final int constructor = 0xec210fbf; public InputChannel channel; @@ -60526,7 +61310,7 @@ public class TLRPC { } public static class TL_channels_getSendAs extends TLObject { - public static int constructor = 0xdc770ee; + public static final int constructor = 0xdc770ee; public InputPeer peer; @@ -60541,7 +61325,7 @@ public class TLRPC { } public static class TL_stickers_createStickerSet extends TLObject { - public static int constructor = 0x9021ab67; + public static final int constructor = 0x9021ab67; public int flags; public boolean masks; @@ -60585,7 +61369,7 @@ public class TLRPC { } public static class TL_stickers_checkShortName extends TLObject { - public static int constructor = 0x284b3639; + public static final int constructor = 0x284b3639; public String short_name; @@ -60600,7 +61384,7 @@ public class TLRPC { } public static class TL_stickers_suggestShortName extends TLObject { - public static int constructor = 0x4dafc503; + public static final int constructor = 0x4dafc503; public String title; @@ -60615,7 +61399,7 @@ public class TLRPC { } public static class TL_phone_getCallConfig extends TLObject { - public static int constructor = 0x55451fa9; + public static final int constructor = 0x55451fa9; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -60628,7 +61412,7 @@ public class TLRPC { } public static class TL_phone_requestCall extends TLObject { - public static int constructor = 0x42ff96ed; + public static final int constructor = 0x42ff96ed; public int flags; public boolean video; @@ -60653,7 +61437,7 @@ public class TLRPC { } public static class TL_phone_acceptCall extends TLObject { - public static int constructor = 0x3bd2b4a0; + public static final int constructor = 0x3bd2b4a0; public TL_inputPhoneCall peer; public byte[] g_b; @@ -60672,7 +61456,7 @@ public class TLRPC { } public static class TL_phone_confirmCall extends TLObject { - public static int constructor = 0x2efe1722; + public static final int constructor = 0x2efe1722; public TL_inputPhoneCall peer; public byte[] g_a; @@ -60693,7 +61477,7 @@ public class TLRPC { } public static class TL_phone_receivedCall extends TLObject { - public static int constructor = 0x17d54f61; + public static final int constructor = 0x17d54f61; public TL_inputPhoneCall peer; @@ -60708,7 +61492,7 @@ public class TLRPC { } public static class TL_phone_discardCall extends TLObject { - public static int constructor = 0xb2cbc1c0; + public static final int constructor = 0xb2cbc1c0; public int flags; public boolean video; @@ -60733,7 +61517,7 @@ public class TLRPC { } public static class TL_phone_setCallRating extends TLObject { - public static int constructor = 0x59ead627; + public static final int constructor = 0x59ead627; public int flags; public boolean user_initiative; @@ -60756,7 +61540,7 @@ public class TLRPC { } public static class TL_phone_saveCallDebug extends TLObject { - public static int constructor = 0x277add7e; + public static final int constructor = 0x277add7e; public TL_inputPhoneCall peer; public TL_dataJSON debug; @@ -60773,7 +61557,7 @@ public class TLRPC { } public static class TL_phone_sendSignalingData extends TLObject { - public static int constructor = 0xff7a9383; + public static final int constructor = 0xff7a9383; public TL_inputPhoneCall peer; public byte[] data; @@ -60790,7 +61574,7 @@ public class TLRPC { } public static class TL_phone_createGroupCall extends TLObject { - public static int constructor = 0x48cdc6d8; + public static final int constructor = 0x48cdc6d8; public int flags; public InputPeer peer; @@ -60817,7 +61601,7 @@ public class TLRPC { } public static class TL_phone_joinGroupCall extends TLObject { - public static int constructor = 0xb132ff7b; + public static final int constructor = 0xb132ff7b; public int flags; public boolean muted; @@ -60846,7 +61630,7 @@ public class TLRPC { } public static class TL_phone_leaveGroupCall extends TLObject { - public static int constructor = 0x500377f9; + public static final int constructor = 0x500377f9; public TL_inputGroupCall call; public int source; @@ -60863,7 +61647,7 @@ public class TLRPC { } public static class TL_phone_inviteToGroupCall extends TLObject { - public static int constructor = 0x7b393160; + public static final int constructor = 0x7b393160; public TL_inputGroupCall call; public ArrayList users = new ArrayList<>(); @@ -60885,7 +61669,7 @@ public class TLRPC { } public static class TL_phone_discardGroupCall extends TLObject { - public static int constructor = 0x7a777135; + public static final int constructor = 0x7a777135; public TL_inputGroupCall call; @@ -60900,7 +61684,7 @@ public class TLRPC { } public static class TL_phone_toggleGroupCallSettings extends TLObject { - public static int constructor = 0x74bbb43d; + public static final int constructor = 0x74bbb43d; public int flags; public boolean reset_invite_hash; @@ -60923,7 +61707,7 @@ public class TLRPC { } public static class TL_phone_getGroupCall extends TLObject { - public static int constructor = 0x41845db; + public static final int constructor = 0x41845db; public TL_inputGroupCall call; public int limit; @@ -60940,7 +61724,7 @@ public class TLRPC { } public static class TL_phone_getGroupParticipants extends TLObject { - public static int constructor = 0xc558d8ab; + public static final int constructor = 0xc558d8ab; public TL_inputGroupCall call; public ArrayList ids = new ArrayList<>(); @@ -60973,7 +61757,7 @@ public class TLRPC { } public static class TL_phone_checkGroupCall extends TLObject { - public static int constructor = 0xb59cf977; + public static final int constructor = 0xb59cf977; public TL_inputGroupCall call; public ArrayList sources = new ArrayList<>(); @@ -61000,7 +61784,7 @@ public class TLRPC { } public static class TL_phone_toggleGroupCallRecord extends TLObject { - public static int constructor = 0xf128c708; + public static final int constructor = 0xf128c708; public int flags; public boolean start; @@ -61029,7 +61813,7 @@ public class TLRPC { } public static class TL_phone_editGroupCallParticipant extends TLObject { - public static int constructor = 0xa5273abf; + public static final int constructor = 0xa5273abf; public int flags; public TL_inputGroupCall call; @@ -61072,7 +61856,7 @@ public class TLRPC { } public static class TL_phone_editGroupCallTitle extends TLObject { - public static int constructor = 0x1ca6ac0a; + public static final int constructor = 0x1ca6ac0a; public TL_inputGroupCall call; public String title; @@ -61089,7 +61873,7 @@ public class TLRPC { } public static class TL_phone_getGroupCallJoinAs extends TLObject { - public static int constructor = 0xef7c213a; + public static final int constructor = 0xef7c213a; public InputPeer peer; @@ -61104,7 +61888,7 @@ public class TLRPC { } public static class TL_phone_exportGroupCallInvite extends TLObject { - public static int constructor = 0xe6aa647f; + public static final int constructor = 0xe6aa647f; public int flags; public boolean can_self_unmute; @@ -61123,7 +61907,7 @@ public class TLRPC { } public static class TL_phone_toggleGroupCallStartSubscription extends TLObject { - public static int constructor = 0x219c34e6; + public static final int constructor = 0x219c34e6; public TL_inputGroupCall call; public boolean subscribed; @@ -61140,7 +61924,7 @@ public class TLRPC { } public static class TL_phone_startScheduledGroupCall extends TLObject { - public static int constructor = 0x5680e342; + public static final int constructor = 0x5680e342; public TL_inputGroupCall call; @@ -61155,7 +61939,7 @@ public class TLRPC { } public static class TL_phone_saveDefaultGroupCallJoinAs extends TLObject { - public static int constructor = 0x575e1f8c; + public static final int constructor = 0x575e1f8c; public InputPeer peer; public InputPeer join_as; @@ -61172,7 +61956,7 @@ public class TLRPC { } public static class TL_phone_joinGroupCallPresentation extends TLObject { - public static int constructor = 0xcbea6bc4; + public static final int constructor = 0xcbea6bc4; public TL_inputGroupCall call; public TL_dataJSON params; @@ -61189,7 +61973,7 @@ public class TLRPC { } public static class TL_groupCallStreamChannel extends TLObject { - public static int constructor = 0x80eb48af; + public static final int constructor = 0x80eb48af; public int channel; public int scale; @@ -61223,7 +62007,7 @@ public class TLRPC { } public static class TL_phone_groupCallStreamChannels extends TLObject { - public static int constructor = 0xd0e482b2; + public static final int constructor = 0xd0e482b2; public ArrayList channels = new ArrayList<>(); @@ -61270,7 +62054,7 @@ public class TLRPC { } public static class TL_phone_leaveGroupCallPresentation extends TLObject { - public static int constructor = 0x1c50d144; + public static final int constructor = 0x1c50d144; public TL_inputGroupCall call; @@ -61285,7 +62069,7 @@ public class TLRPC { } public static class TL_phone_getGroupCallStreamChannels extends TLObject { - public static int constructor = 0x1ab21940; + public static final int constructor = 0x1ab21940; public TL_inputGroupCall call; @@ -61300,7 +62084,7 @@ public class TLRPC { } public static class TL_phone_getGroupCallStreamRtmpUrl extends TLObject { - public static int constructor = 0xdeb3abbf; + public static final int constructor = 0xdeb3abbf; public InputPeer peer; public boolean revoke; @@ -61317,7 +62101,7 @@ public class TLRPC { } public static class TL_payments_getPaymentForm extends TLObject { - public static int constructor = 0x37148dbb; + public static final int constructor = 0x37148dbb; public int flags; public InputInvoice invoice; @@ -61338,7 +62122,7 @@ public class TLRPC { } public static class TL_payments_getPaymentReceipt extends TLObject { - public static int constructor = 0x2478d1cc; + public static final int constructor = 0x2478d1cc; public InputPeer peer; public int msg_id; @@ -61355,7 +62139,7 @@ public class TLRPC { } public static class TL_payments_validateRequestedInfo extends TLObject { - public static int constructor = 0xb6c8f12b; + public static final int constructor = 0xb6c8f12b; public int flags; public boolean save; @@ -61376,7 +62160,7 @@ public class TLRPC { } public static class TL_payments_sendPaymentForm extends TLObject { - public static int constructor = 0x2d03522f; + public static final int constructor = 0x2d03522f; public int flags; public long form_id; @@ -61409,7 +62193,7 @@ public class TLRPC { } public static class TL_help_supportName extends TLObject { - public static int constructor = 0x8c05f1c9; + public static final int constructor = 0x8c05f1c9; public String name; @@ -61437,7 +62221,7 @@ public class TLRPC { } public static class TL_inputThemeSettings extends TLObject { - public static int constructor = 0x8fde504f; + public static final int constructor = 0x8fde504f; public int flags; public boolean message_colors_animated; @@ -61517,7 +62301,7 @@ public class TLRPC { } public static class TL_payments_assignPlayMarketTransaction extends TLObject { - public static int constructor = 0xdffd50d3; + public static final int constructor = 0xdffd50d3; public TL_dataJSON receipt; public InputStorePaymentPurpose purpose; @@ -61538,11 +62322,17 @@ public class TLRPC { public static InputStorePaymentPurpose TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputStorePaymentPurpose result = null; switch (constructor) { + case 0x616f7fe8: + result = new TL_inputStorePaymentGiftPremium(); + break; + case 0xa3805f3f: + result = new TL_inputStorePaymentPremiumGiftCode(); + break; case 0xa6751e66: result = new TL_inputStorePaymentPremiumSubscription(); break; - case 0x616f7fe8: - result = new TL_inputStorePaymentGiftPremium(); + case 0x7c9375e6: + result = new TL_inputStorePaymentPremiumGiveaway(); break; } if (result == null && exception) { @@ -61556,7 +62346,7 @@ public class TLRPC { } public static class TL_inputStorePaymentPremiumSubscription extends InputStorePaymentPurpose { - public static int constructor = 0xa6751e66; + public static final int constructor = 0xa6751e66; public int flags; public boolean restore; @@ -61577,7 +62367,7 @@ public class TLRPC { } public static class TL_inputStorePaymentGiftPremium extends InputStorePaymentPurpose { - public static int constructor = 0x616f7fe8; + public static final int constructor = 0x616f7fe8; public InputUser user_id; public String currency; @@ -61598,7 +62388,7 @@ public class TLRPC { } public static class TL_payments_getSavedInfo extends TLObject { - public static int constructor = 0x227d824b; + public static final int constructor = 0x227d824b; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -61611,7 +62401,7 @@ public class TLRPC { } public static class TL_payments_clearSavedInfo extends TLObject { - public static int constructor = 0xd83d70c1; + public static final int constructor = 0xd83d70c1; public int flags; public boolean credentials; @@ -61630,7 +62420,7 @@ public class TLRPC { } public static class TL_payments_getBankCardData extends TLObject { - public static int constructor = 0x2e79d779; + public static final int constructor = 0x2e79d779; public String number; @@ -61645,7 +62435,7 @@ public class TLRPC { } public static class TL_langpack_getLangPack extends TLObject { - public static int constructor = 0x9ab5c58e; + public static final int constructor = 0x9ab5c58e; public String lang_code; @@ -61660,7 +62450,7 @@ public class TLRPC { } public static class TL_langpack_getStrings extends TLObject { - public static int constructor = 0x2e1ee318; + public static final int constructor = 0x2e1ee318; public String lang_code; public ArrayList keys = new ArrayList<>(); @@ -61691,7 +62481,7 @@ public class TLRPC { } public static class TL_langpack_getDifference extends TLObject { - public static int constructor = 0xcd984aa5; + public static final int constructor = 0xcd984aa5; public String lang_pack; public String lang_code; @@ -61710,7 +62500,7 @@ public class TLRPC { } public static class TL_langpack_getLanguages extends TLObject { - public static int constructor = 0x800fd57d; + public static final int constructor = 0x800fd57d; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -61732,7 +62522,7 @@ public class TLRPC { } public static class TL_langpack_getLanguage extends TLObject { - public static int constructor = 0x6a596502; + public static final int constructor = 0x6a596502; public String lang_pack; public String lang_code; @@ -61749,7 +62539,7 @@ public class TLRPC { } public static class TL_folders_editPeerFolders extends TLObject { - public static int constructor = 0x6847d0ab; + public static final int constructor = 0x6847d0ab; public ArrayList folder_peers = new ArrayList<>(); @@ -61769,7 +62559,7 @@ public class TLRPC { } public static class TL_folders_deleteFolder extends TLObject { - public static int constructor = 0x1c295881; + public static final int constructor = 0x1c295881; public int folder_id; @@ -61784,7 +62574,7 @@ public class TLRPC { } public static class TL_stats_getBroadcastStats extends TLObject { - public static int constructor = 0xab42441a; + public static final int constructor = 0xab42441a; public int flags; public boolean dark; @@ -61803,7 +62593,7 @@ public class TLRPC { } public static class TL_stats_loadAsyncGraph extends TLObject { - public static int constructor = 0x621d5fa0; + public static final int constructor = 0x621d5fa0; public int flags; public String token; @@ -61824,7 +62614,7 @@ public class TLRPC { } public static class TL_stats_getMegagroupStats extends TLObject { - public static int constructor = 0xdcdf8607; + public static final int constructor = 0xdcdf8607; public int flags; public boolean dark; @@ -61843,7 +62633,7 @@ public class TLRPC { } public static class TL_stats_getMessagePublicForwards extends TLObject { - public static int constructor = 0x5630281b; + public static final int constructor = 0x5630281b; public InputChannel channel; public int msg_id; @@ -61868,7 +62658,7 @@ public class TLRPC { } public static class TL_stats_getMessageStats extends TLObject { - public static int constructor = 0xb6e0a3f5; + public static final int constructor = 0xb6e0a3f5; public int flags; public boolean dark; @@ -61891,7 +62681,7 @@ public class TLRPC { //manually created public static class TL_photoPathSize extends PhotoSize { - public static int constructor = 0xd8214d41; + public static final int constructor = 0xd8214d41; public Path svgPath; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -61979,7 +62769,7 @@ public class TLRPC { } public static class TL_pageBlockList_layer82 extends TL_pageBlockList { - public static int constructor = 0x3a58c7f4; + public static final int constructor = 0x3a58c7f4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62018,7 +62808,7 @@ public class TLRPC { //RichText end public static class TL_channels_sendAsPeers extends TLObject { - public static int constructor = 0xf496b0c6; + public static final int constructor = 0xf496b0c6; public ArrayList peers = new ArrayList<>(); public ArrayList chats = new ArrayList<>(); @@ -62109,7 +62899,7 @@ public class TLRPC { } public static class TL_sendAsPeer extends TLObject { - public static int constructor = 0xb81c7034; + public static final int constructor = 0xb81c7034; public int flags; public boolean premium_required; @@ -62180,9 +62970,13 @@ public class TLRPC { public MessageExtendedMedia extended_media; public boolean spoiler; public int id; - public StoryItem storyItem; + public TL_stories.StoryItem storyItem; public boolean via_mention; public Peer peer; + public boolean force_large_media; + public boolean force_small_media; + public boolean manual; + public boolean safe; public static MessageMedia TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageMedia result = null; @@ -62256,6 +63050,9 @@ public class TLRPC { case 0x4bd6e798: result = new TL_messageMediaPoll(); break; + case 0x58260664: + result = new TL_messageMediaGiveaway(); + break; case 0xb5223b0f: result = new TL_messageMediaPhoto_layer74(); break; @@ -62275,6 +63072,9 @@ public class TLRPC { result = new TL_messageMediaGeo(); break; case 0xa32dd600: + result = new TL_messageMediaWebPage_layer165(); + break; + case 0xddf10c3b: result = new TL_messageMediaWebPage(); break; case 0x4cf4d72d: @@ -62369,7 +63169,7 @@ public class TLRPC { //PageBlock start public static class TL_pageBlockAuthorDate_layer60 extends TL_pageBlockAuthorDate { - public static int constructor = 0x3d5b64f2; + public static final int constructor = 0x3d5b64f2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62387,7 +63187,7 @@ public class TLRPC { } public static class TL_pageBlockEmbedPost_layer82 extends TL_pageBlockEmbedPost { - public static int constructor = 0x292c7be9; + public static final int constructor = 0x292c7be9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62434,7 +63234,7 @@ public class TLRPC { } public static class TL_pageBlockEmbed_layer82 extends TL_pageBlockEmbed { - public static int constructor = 0xcde200d1; + public static final int constructor = 0xcde200d1; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62478,7 +63278,7 @@ public class TLRPC { } public static class TL_pageBlockVideo_layer82 extends TL_pageBlockVideo { - public static int constructor = 0xd9d71866; + public static final int constructor = 0xd9d71866; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62502,7 +63302,7 @@ public class TLRPC { } public static class TL_pageBlockSlideshow_layer82 extends TL_pageBlockSlideshow { - public static int constructor = 0x130c8963; + public static final int constructor = 0x130c8963; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62539,7 +63339,7 @@ public class TLRPC { } public static class TL_pageBlockPhoto_layer82 extends TL_pageBlockPhoto { - public static int constructor = 0xe9c69982; + public static final int constructor = 0xe9c69982; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62557,7 +63357,7 @@ public class TLRPC { } public static class TL_pageBlockCollage_layer82 extends TL_pageBlockCollage { - public static int constructor = 0x8b31c4f; + public static final int constructor = 0x8b31c4f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62594,7 +63394,7 @@ public class TLRPC { } public static class TL_pageBlockAudio_layer82 extends TL_pageBlockAudio { - public static int constructor = 0x31b81a7f; + public static final int constructor = 0x31b81a7f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62731,7 +63531,7 @@ public class TLRPC { public ArrayList restriction_reason = new ArrayList<>(); public int ttl_period; public boolean noforwards; - public boolean topic_start; + public boolean invert_media; public int send_state = 0; //custom public int fwd_msg_id = 0; //custom public String attachPath = ""; //custom @@ -62741,6 +63541,7 @@ public class TLRPC { public long dialog_id; //custom public int ttl; //custom public int destroyTime; //custom + public long destroyTimeMillis; //custom public int layer; //custom public int seq_in; //custom public int seq_out; //custom @@ -62760,7 +63561,7 @@ public class TLRPC { public String originalLanguage; //custom public String translatedToLanguage; //custom public TL_textWithEntities translatedText; // custom - public StoryItem replyStory; //custom + public TL_stories.StoryItem replyStory; //custom public static Message TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Message result = null; @@ -62963,7 +63764,7 @@ public class TLRPC { } public static class TL_messageEmpty_layer122 extends TL_messageEmpty { - public static int constructor = 0x83e5de54; + public static final int constructor = 0x83e5de54; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -62978,7 +63779,7 @@ public class TLRPC { } public static class TL_messageEmpty extends Message { - public static int constructor = 0x90a6ca84; + public static final int constructor = 0x90a6ca84; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63001,7 +63802,7 @@ public class TLRPC { } public static class TL_messageService_old2 extends TL_messageService { - public static int constructor = 0x1d86f70e; + public static final int constructor = 0x1d86f70e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -63035,7 +63836,7 @@ public class TLRPC { } public static class TL_message_layer72 extends TL_message { - public static int constructor = 0x90dddc11; + public static final int constructor = 0x90dddc11; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63058,6 +63859,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -63154,7 +63956,7 @@ public class TLRPC { } public static class TL_message_layer68 extends TL_message { - public static int constructor = 0xc09be45f; + public static final int constructor = 0xc09be45f; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63182,6 +63984,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -63273,7 +64076,7 @@ public class TLRPC { } public static class TL_message_layer47 extends TL_message { - public static int constructor = 0xc992e15c; + public static final int constructor = 0xc992e15c; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63304,6 +64107,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -63389,7 +64193,7 @@ public class TLRPC { } public static class TL_message_old7 extends TL_message { - public static int constructor = 0x5ba66c13; + public static final int constructor = 0x5ba66c13; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63417,6 +64221,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -63499,7 +64304,7 @@ public class TLRPC { } public static class TL_messageForwarded_old2 extends Message { - public static int constructor = 0xa367e716; + public static final int constructor = 0xa367e716; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -63545,7 +64350,7 @@ public class TLRPC { } public static class TL_message extends Message { - public static int constructor = 0x38116ee0; + public static final int constructor = 0x38116ee0; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -63559,7 +64364,7 @@ public class TLRPC { edit_hide = (flags & 2097152) != 0; pinned = (flags & 16777216) != 0; noforwards = (flags & 67108864) != 0; - topic_start = (flags & 134217728) != 0; + invert_media = (flags & 134217728) != 0; id = stream.readInt32(exception); if ((flags & 256) != 0) { from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -63660,7 +64465,7 @@ public class TLRPC { flags = edit_hide ? (flags | 2097152) : (flags &~ 2097152); flags = pinned ? (flags | 16777216) : (flags &~ 16777216); flags = noforwards ? (flags | 67108864) : (flags &~ 67108864); - flags = topic_start ? (flags | 134217728) : (flags &~ 134217728); + flags = invert_media ? (flags | 134217728) : (flags &~ 134217728); stream.writeInt32(flags); stream.writeInt32(id); if ((flags & 256) != 0) { @@ -63729,7 +64534,7 @@ public class TLRPC { } public static class TL_message_layer135 extends TL_message { - public static int constructor = 0x85d6cbe2; + public static final int constructor = 0x85d6cbe2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -63906,7 +64711,7 @@ public class TLRPC { } public static class TL_message_layer131 extends TL_message { - public static int constructor = 0xbce383d2; + public static final int constructor = 0xbce383d2; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64081,7 +64886,7 @@ public class TLRPC { } public static class TL_message_layer123 extends TL_message { - public static int constructor = 0x58ae39c9; + public static final int constructor = 0x58ae39c9; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64250,7 +65055,7 @@ public class TLRPC { } public static class TL_message_layer118 extends TL_message { - public static int constructor = 0xf52e6b7f; + public static final int constructor = 0xf52e6b7f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64277,6 +65082,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -64413,7 +65219,7 @@ public class TLRPC { } public static class TL_message_layer117 extends TL_message { - public static int constructor = 0x452c0e65; + public static final int constructor = 0x452c0e65; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64440,6 +65246,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -64570,7 +65377,7 @@ public class TLRPC { } public static class TL_message_layer104_3 extends TL_message { - public static int constructor = 0x9789dac4; + public static final int constructor = 0x9789dac4; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64597,6 +65404,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -64733,7 +65541,7 @@ public class TLRPC { } public static class TL_message_layer104_2 extends TL_message { - public static int constructor = 0x1c9b1027; + public static final int constructor = 0x1c9b1027; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -64760,6 +65568,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -64877,7 +65686,7 @@ public class TLRPC { } public static class TL_message_layer104 extends TL_message { - public static int constructor = 0x44f9b43d; + public static final int constructor = 0x44f9b43d; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -64902,6 +65711,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65006,7 +65816,7 @@ public class TLRPC { } public static class TL_message_old6 extends TL_message { - public static int constructor = 0x2bebfa86; + public static final int constructor = 0x2bebfa86; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65028,6 +65838,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65100,7 +65911,7 @@ public class TLRPC { } public static class TL_message_old5 extends TL_message { - public static int constructor = 0xf07814c8; + public static final int constructor = 0xf07814c8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65122,6 +65933,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65188,7 +66000,7 @@ public class TLRPC { } public static class TL_messageService_layer48 extends TL_messageService { - public static int constructor = 0xc06b9607; + public static final int constructor = 0xc06b9607; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65232,7 +66044,7 @@ public class TLRPC { } public static class TL_message_old4 extends TL_message { - public static int constructor = 0xc3060325; + public static final int constructor = 0xc3060325; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65254,6 +66066,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65295,7 +66108,7 @@ public class TLRPC { } public static class TL_message_old3 extends TL_message { - public static int constructor = 0xa7ab1991; + public static final int constructor = 0xa7ab1991; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception) | MESSAGE_FLAG_HAS_FROM_ID | MESSAGE_FLAG_HAS_MEDIA; @@ -65316,6 +66129,7 @@ public class TLRPC { } if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65351,7 +66165,7 @@ public class TLRPC { } public static class TL_message_old2 extends TL_message { - public static int constructor = 0x567699b3; + public static final int constructor = 0x567699b3; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65390,7 +66204,7 @@ public class TLRPC { } public static class TL_messageService_old extends TL_messageService { - public static int constructor = 0x9f8d60bb; + public static final int constructor = 0x9f8d60bb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65418,7 +66232,7 @@ public class TLRPC { } public static class TL_messageForwarded_old extends TL_messageForwarded_old2 { - public static int constructor = 0x5f46804; + public static final int constructor = 0x5f46804; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65459,7 +66273,7 @@ public class TLRPC { } public static class TL_message_old extends TL_message { - public static int constructor = 0x22eb6aba; + public static final int constructor = 0x22eb6aba; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt32(exception); @@ -65492,7 +66306,7 @@ public class TLRPC { } public static class TL_message_secret extends TL_message { - public static int constructor = 0x555555fa; + public static final int constructor = 0x555555fa; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -65572,7 +66386,7 @@ public class TLRPC { } public static class TL_message_secret_layer72 extends TL_message { - public static int constructor = 0x555555f9; + public static final int constructor = 0x555555f9; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -65646,7 +66460,7 @@ public class TLRPC { } public static class TL_message_secret_old extends TL_message_secret { - public static int constructor = 0x555555F8; + public static final int constructor = 0x555555F8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception) | MESSAGE_FLAG_HAS_FROM_ID | MESSAGE_FLAG_HAS_MEDIA; @@ -65686,7 +66500,7 @@ public class TLRPC { } public static class TL_messageService_layer123 extends TL_messageService { - public static int constructor = 0x286fa604; + public static final int constructor = 0x286fa604; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65733,7 +66547,7 @@ public class TLRPC { } public static class TL_messageService extends Message { - public static int constructor = 0x2b085862; + public static final int constructor = 0x2b085862; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -65785,7 +66599,7 @@ public class TLRPC { } public static class TL_messageService_layer118 extends TL_messageService { - public static int constructor = 0x9e19a1f6; + public static final int constructor = 0x9e19a1f6; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -65804,6 +66618,7 @@ public class TLRPC { peer_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); if ((flags & 8) != 0) { reply_to = new TLRPC.TL_messageReplyHeader(); + reply_to.flags |= 16; reply_to.reply_to_msg_id = stream.readInt32(exception); } date = stream.readInt32(exception); @@ -65883,7 +66698,7 @@ public class TLRPC { } public static class TL_dialog extends Dialog { - public static int constructor = 0xd58a08c6; + public static final int constructor = 0xd58a08c6; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -65940,7 +66755,7 @@ public class TLRPC { } public static class TL_dialog_layer149 extends TL_dialog { - public static int constructor = 0xa8edd0f5; + public static final int constructor = 0xa8edd0f5; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -65997,7 +66812,7 @@ public class TLRPC { } public static class TL_dialogFolder extends Dialog { - public static int constructor = 0x71bd134c; + public static final int constructor = 0x71bd134c; public TL_folder folder; public int unread_muted_peers_count; @@ -66034,7 +66849,7 @@ public class TLRPC { //ChatParticipant start public static class TL_chatChannelParticipant extends ChatParticipant { - public static int constructor = 0xc8d7493e; + public static final int constructor = 0xc8d7493e; public ChannelParticipant channelParticipant; } @@ -66042,7 +66857,7 @@ public class TLRPC { //Chat start public static class TL_chatEmpty extends Chat { - public static int constructor = 0x29562865; + public static final int constructor = 0x29562865; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66058,7 +66873,7 @@ public class TLRPC { } public static class TL_chatEmpty_layer131 extends TL_chatEmpty { - public static int constructor = 0x9ba2d800; + public static final int constructor = 0x9ba2d800; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66076,7 +66891,7 @@ public class TLRPC { //functions memory optimize public static class TL_upload_saveFilePart extends TLObject { - public static int constructor = 0xb304a621; + public static final int constructor = 0xb304a621; public long file_id; public int file_part; @@ -66106,7 +66921,7 @@ public class TLRPC { } public static class TL_messages_getStickers extends TLObject { - public static int constructor = 0xd5a5d3a1; + public static final int constructor = 0xd5a5d3a1; public String emoticon; public long hash; @@ -66123,7 +66938,7 @@ public class TLRPC { } public static class TL_messages_getAllStickers extends TLObject { - public static int constructor = 0xb8a0a1a8; + public static final int constructor = 0xb8a0a1a8; public long hash; @@ -66138,7 +66953,7 @@ public class TLRPC { } public static class TL_upload_saveBigFilePart extends TLObject { - public static int constructor = 0xde7b673d; + public static final int constructor = 0xde7b673d; public long file_id; public int file_part; @@ -66170,7 +66985,7 @@ public class TLRPC { } public static class TL_upload_getWebFile extends TLObject { - public static int constructor = 0x24e6818d; + public static final int constructor = 0x24e6818d; public InputWebFileLocation location; public int offset; @@ -66189,7 +67004,7 @@ public class TLRPC { } public static class TL_upload_getCdnFile extends TLObject { - public static int constructor = 0x395f69da; + public static final int constructor = 0x395f69da; public byte[] file_token; public long offset; @@ -66208,7 +67023,7 @@ public class TLRPC { } public static class TL_upload_reuploadCdnFile extends TLObject { - public static int constructor = 0x9b2754a8; + public static final int constructor = 0x9b2754a8; public byte[] file_token; public byte[] request_token; @@ -66234,7 +67049,7 @@ public class TLRPC { } public static class TL_upload_getCdnFileHashes extends TLObject { - public static int constructor = 0x91dc3f31; + public static final int constructor = 0x91dc3f31; public byte[] file_token; public long offset; @@ -66260,7 +67075,7 @@ public class TLRPC { } public static class TL_upload_getFileHashes extends TLObject { - public static int constructor = 0xc7025931; + public static final int constructor = 0xc7025931; public InputFileLocation location; public int offset; @@ -66286,7 +67101,7 @@ public class TLRPC { } public static class TL_upload_webFile extends TLObject { - public static int constructor = 0x21e753bc; + public static final int constructor = 0x21e753bc; public int size; public String mime_type; @@ -66391,7 +67206,7 @@ public class TLRPC { } public static class TL_upload_cdnFile extends upload_CdnFile { - public static int constructor = 0xa99fca4f; + public static final int constructor = 0xa99fca4f; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66416,7 +67231,7 @@ public class TLRPC { } public static class TL_upload_cdnFileReuploadNeeded extends upload_CdnFile { - public static int constructor = 0xeea8e46e; + public static final int constructor = 0xeea8e46e; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66430,7 +67245,7 @@ public class TLRPC { } public static class TL_upload_file extends upload_File { - public static int constructor = 0x96a18d5; + public static final int constructor = 0x96a18d5; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66459,7 +67274,7 @@ public class TLRPC { } public static class TL_upload_fileCdnRedirect extends upload_File { - public static int constructor = 0xf18cda44; + public static final int constructor = 0xf18cda44; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66528,7 +67343,7 @@ public class TLRPC { } public static class TL_phoneCallProtocol extends PhoneCallProtocol { - public static int constructor = 0xfc878fc8; + public static final int constructor = 0xfc878fc8; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66567,7 +67382,7 @@ public class TLRPC { } public static class TL_phoneCallProtocol_layer110 extends TL_phoneCallProtocol { - public static int constructor = 0xa2bb35cb; + public static final int constructor = 0xa2bb35cb; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -66589,7 +67404,7 @@ public class TLRPC { } public static class TL_messages_sendEncryptedFile extends TLObject { - public static int constructor = 0x5559481d; + public static final int constructor = 0x5559481d; public int flags; public boolean silent; @@ -66622,7 +67437,7 @@ public class TLRPC { } public static class TL_messages_sendEncryptedMultiMedia extends TLObject { - public static int constructor = 0xcacacaca; + public static final int constructor = 0xcacacaca; public ArrayList messages = new ArrayList<>(); public ArrayList files = new ArrayList<>(); @@ -66642,7 +67457,7 @@ public class TLRPC { } public static class TL_messages_sendEncrypted extends TLObject { - public static int constructor = 0x44fa7a15; + public static final int constructor = 0x44fa7a15; public int flags; public boolean silent; @@ -66673,7 +67488,7 @@ public class TLRPC { } public static class TL_messages_sendEncryptedService extends TLObject { - public static int constructor = 0x32d439a4; + public static final int constructor = 0x32d439a4; public TL_inputEncryptedChat peer; public long random_id; @@ -66700,7 +67515,7 @@ public class TLRPC { } public static class TL_messages_getSearchResultsPositions extends TLObject { - public static int constructor = 0x6e9583a3; + public static final int constructor = 0x6e9583a3; public InputPeer peer; public MessagesFilter filter; @@ -66721,7 +67536,7 @@ public class TLRPC { } public static class TL_attachMenuBot_layer140 extends TL_attachMenuBot { - public static int constructor = 0xe93cb772; + public static final int constructor = 0xe93cb772; public static TL_attachMenuBot TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_attachMenuBot.constructor != constructor) { @@ -66774,7 +67589,7 @@ public class TLRPC { } public static class TL_attachMenuBot_layer162 extends TL_attachMenuBot { - public static int constructor = 0xc8aa2cd2; + public static final int constructor = 0xc8aa2cd2; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -66839,7 +67654,7 @@ public class TLRPC { } public static class TL_attachMenuBot extends AttachMenuBot { - public static int constructor = 0xd90d8dfe; + public static final int constructor = 0xd90d8dfe; public int flags; public boolean inactive; @@ -66969,7 +67784,7 @@ public class TLRPC { } public static class TL_attachMenuBotsNotModified extends AttachMenuBots { - public static int constructor = 0xf1d88a5c; + public static final int constructor = 0xf1d88a5c; public void serializeToStream(AbstractSerializedData stream) { @@ -66978,7 +67793,7 @@ public class TLRPC { } public static class TL_attachMenuBots extends AttachMenuBots { - public static int constructor = 0x3c4301c0; + public static final int constructor = 0x3c4301c0; public long hash; public ArrayList bots = new ArrayList<>(); @@ -67037,7 +67852,7 @@ public class TLRPC { } public static class TL_updateAttachMenuBots extends Update { - public static int constructor = 0x17b7a20b; + public static final int constructor = 0x17b7a20b; public void serializeToStream(AbstractSerializedData stream) { @@ -67046,7 +67861,7 @@ public class TLRPC { } public static class TL_messages_webViewResult extends TLObject { - public static int constructor = 0xaadf159b; + public static final int constructor = 0xaadf159b; public BotInlineResult result; public ArrayList users = new ArrayList<>(); @@ -67096,7 +67911,7 @@ public class TLRPC { } public static class TL_keyboardButtonWebView extends KeyboardButton { - public static int constructor = 0x13767230; + public static final int constructor = 0x13767230; public void readParams(AbstractSerializedData stream, boolean exception) { text = stream.readString(exception); @@ -67256,7 +68071,7 @@ public class TLRPC { } public static class TL_keyboardButtonRequestPeer extends KeyboardButton { - public static int constructor = 0xd0b468c; + public static final int constructor = 0xd0b468c; public RequestPeerType peer_type; @@ -67275,7 +68090,7 @@ public class TLRPC { } public static class TL_messages_getAttachMenuBots extends TLObject { - public static int constructor = 0x16fcc2cb; + public static final int constructor = 0x16fcc2cb; public long hash; @@ -67290,7 +68105,7 @@ public class TLRPC { } public static class TL_messages_toggleBotInAttachMenu extends TLObject { - public static int constructor = 0x69f59d69; + public static final int constructor = 0x69f59d69; public int flags; public boolean write_allowed; @@ -67311,7 +68126,7 @@ public class TLRPC { } public static class TL_webViewResultUrl extends TLObject { - public static int constructor = 0xc14557c; + public static final int constructor = 0xc14557c; public long query_id; public String url; @@ -67342,7 +68157,7 @@ public class TLRPC { } public static class TL_messages_requestWebView extends TLObject { - public static int constructor = 0x269dc2c1; + public static final int constructor = 0x269dc2c1; public int flags; public boolean from_bot_menu; @@ -67387,7 +68202,7 @@ public class TLRPC { } public static class TL_messages_prolongWebView extends TLObject { - public static int constructor = 0xb0d81a83; + public static final int constructor = 0xb0d81a83; public int flags; public boolean silent; @@ -67418,7 +68233,7 @@ public class TLRPC { } public static class TL_messages_getBotApp extends TLObject { - public static int constructor = 0x34fdc5c3; + public static final int constructor = 0x34fdc5c3; public InputBotApp app; public long hash; @@ -67435,7 +68250,7 @@ public class TLRPC { } public static class TL_messages_requestAppWebView extends TLObject { - public static int constructor = 0x8c5a3b3c; + public static final int constructor = 0x8c5a3b3c; public int flags; public boolean write_allowed; @@ -67466,7 +68281,7 @@ public class TLRPC { } public static class TL_messages_requestSimpleWebView extends TLObject { - public static int constructor = 0x1a46500a; + public static final int constructor = 0x1a46500a; public int flags; public boolean from_switch_webview; @@ -67501,7 +68316,7 @@ public class TLRPC { } public static class TL_messages_sendWebViewResultMessage extends TLObject { - public static int constructor = 0xddcf50eb; + public static final int constructor = 0xddcf50eb; public long query_id; @@ -67516,7 +68331,7 @@ public class TLRPC { } public static class TL_messages_setWebViewResult extends TLObject { - public static int constructor = 0xe41cd11d; + public static final int constructor = 0xe41cd11d; public long query_id; @@ -67531,7 +68346,7 @@ public class TLRPC { } public static class TL_messages_getWebViewResult extends TLObject { - public static int constructor = 0x22b6c214; + public static final int constructor = 0x22b6c214; public InputPeer peer; public InputUser bot; @@ -67550,7 +68365,7 @@ public class TLRPC { } public static class TL_attachMenuBotsBot extends TLObject { - public static int constructor = 0x93bf667f; + public static final int constructor = 0x93bf667f; public TL_attachMenuBot bot; public ArrayList users = new ArrayList<>(); @@ -67600,7 +68415,7 @@ public class TLRPC { } public static class TL_simpleWebViewResultUrl extends TLObject { - public static int constructor = 0x882f76bb; + public static final int constructor = 0x882f76bb; public String url; @@ -67628,7 +68443,7 @@ public class TLRPC { } public static class TL_webViewMessageSent extends TLObject { - public static int constructor = 0xc94511c; + public static final int constructor = 0xc94511c; public int flags; public TL_inputBotInlineMessageID msg_id; @@ -67663,7 +68478,7 @@ public class TLRPC { } public static class TL_updateWebViewResultSent extends Update { - public static int constructor = 0x1592b79d; + public static final int constructor = 0x1592b79d; public long query_id; @@ -67678,7 +68493,7 @@ public class TLRPC { } public static class TL_keyboardButtonSimpleWebView extends KeyboardButton { - public static int constructor = 0xa0c0505c; + public static final int constructor = 0xa0c0505c; public void readParams(AbstractSerializedData stream, boolean exception) { text = stream.readString(exception); @@ -67693,7 +68508,7 @@ public class TLRPC { } public static class TL_messages_getAttachMenuBot extends TLObject { - public static int constructor = 0x77216192; + public static final int constructor = 0x77216192; public InputUser bot; @@ -67730,7 +68545,7 @@ public class TLRPC { } public static class TL_account_savedRingtonesNotModified extends account_SavedRingtones { - public static int constructor = 0xfbf6e8b1; + public static final int constructor = 0xfbf6e8b1; public void serializeToStream(AbstractSerializedData stream) { @@ -67739,7 +68554,7 @@ public class TLRPC { } public static class TL_account_savedRingtones extends account_SavedRingtones { - public static int constructor = 0xc1e92cc5; + public static final int constructor = 0xc1e92cc5; public long hash; public ArrayList ringtones = new ArrayList<>(); @@ -67776,7 +68591,7 @@ public class TLRPC { } public static class TL_account_uploadRingtone extends TLObject { - public static int constructor = 0x831a83a2; + public static final int constructor = 0x831a83a2; public InputFile file; public String file_name; @@ -67795,7 +68610,7 @@ public class TLRPC { } public static class TL_account_getSavedRingtones extends TLObject { - public static int constructor = 0xe1902288; + public static final int constructor = 0xe1902288; public long hash; @@ -67810,7 +68625,7 @@ public class TLRPC { } public static class TL_account_saveRingtone extends TLObject { - public static int constructor = 0x3dea5b03; + public static final int constructor = 0x3dea5b03; public InputDocument id; public boolean unsave; @@ -67827,7 +68642,7 @@ public class TLRPC { } public static class TL_attachMenuBotIconColor extends TLObject { - public static int constructor = 0x4576f3f0; + public static final int constructor = 0x4576f3f0; public String name; public int color; @@ -67858,7 +68673,7 @@ public class TLRPC { } public static class TL_attachMenuBotIcon extends TLObject { - public static int constructor = 0xb2a7386b; + public static final int constructor = 0xb2a7386b; public int flags; public String name; @@ -67943,7 +68758,7 @@ public class TLRPC { } public static class TL_botMenuButton extends BotMenuButton { - public static int constructor = 0xc7b57ce6; + public static final int constructor = 0xc7b57ce6; public String text; public String url; @@ -67961,7 +68776,7 @@ public class TLRPC { } public static class TL_botMenuButtonDefault extends BotMenuButton { - public static int constructor = 0x7533a588; + public static final int constructor = 0x7533a588; public void serializeToStream(AbstractSerializedData stream) { @@ -67970,7 +68785,7 @@ public class TLRPC { } public static class TL_botMenuButtonCommands extends BotMenuButton { - public static int constructor = 0x4258c205; + public static final int constructor = 0x4258c205; public void serializeToStream(AbstractSerializedData stream) { @@ -67979,7 +68794,7 @@ public class TLRPC { } public static class TL_updateBotMenuButton extends Update { - public static int constructor = 0x14b85813; + public static final int constructor = 0x14b85813; public long bot_id; public BotMenuButton button; @@ -67997,7 +68812,7 @@ public class TLRPC { } public static class TL_bots_setBotMenuButton extends TLObject { - public static int constructor = 0x4504d54f; + public static final int constructor = 0x4504d54f; public InputUser user_id; public BotMenuButton button; @@ -68014,7 +68829,7 @@ public class TLRPC { } public static class TL_bots_getBotMenuButton extends TLObject { - public static int constructor = 0x9c60eb28; + public static final int constructor = 0x9c60eb28; public InputUser user_id; @@ -68051,7 +68866,7 @@ public class TLRPC { } public static class TL_inputBotAppID extends InputBotApp { - public static int constructor = 0xa920bd7a; + public static final int constructor = 0xa920bd7a; public long id; public long access_hash; @@ -68069,7 +68884,7 @@ public class TLRPC { } public static class TL_inputBotAppShortName extends InputBotApp { - public static int constructor = 0x908c0407; + public static final int constructor = 0x908c0407; public InputUser bot_id; public String short_name; @@ -68118,7 +68933,7 @@ public class TLRPC { } public static class TL_botAppNotModified extends BotApp { - public static int constructor = 0x5da674b7; + public static final int constructor = 0x5da674b7; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -68130,7 +68945,7 @@ public class TLRPC { } public static class TL_botApp extends BotApp { - public static int constructor = 0x95fcd1d6; + public static final int constructor = 0x95fcd1d6; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -68164,7 +68979,7 @@ public class TLRPC { } public static class TL_messages_botApp extends TLObject { - public static int constructor = 0xeb50adf5; + public static final int constructor = 0xeb50adf5; public int flags; public boolean inactive; @@ -68201,7 +69016,7 @@ public class TLRPC { } public static class TL_appWebViewResultUrl extends TLObject { - public static int constructor = 0x3c1b4f0d; + public static final int constructor = 0x3c1b4f0d; public String url; @@ -68229,7 +69044,7 @@ public class TLRPC { } public static class TL_inlineBotWebView extends TLObject { - public static int constructor = 0xb57295d5; + public static final int constructor = 0xb57295d5; public String text; public String url; @@ -68282,7 +69097,7 @@ public class TLRPC { } public static class TL_account_savedRingtoneConverted extends account_SavedRingtone { - public static int constructor = 0x1f307eb7; + public static final int constructor = 0x1f307eb7; public Document document; @@ -68297,7 +69112,7 @@ public class TLRPC { } public static class TL_account_savedRingtone extends account_SavedRingtone { - public static int constructor = 0xb7263f6d; + public static final int constructor = 0xb7263f6d; public void serializeToStream(AbstractSerializedData stream) { @@ -68306,7 +69121,7 @@ public class TLRPC { } public static class TL_channels_toggleJoinToSend extends TLObject { - public static int constructor = 0xe4cb9580; + public static final int constructor = 0xe4cb9580; public InputChannel channel; public boolean enabled; @@ -68323,7 +69138,7 @@ public class TLRPC { } public static class TL_channels_toggleJoinRequest extends TLObject { - public static int constructor = 0x4c2985b6; + public static final int constructor = 0x4c2985b6; public InputChannel channel; public boolean enabled; @@ -68340,7 +69155,7 @@ public class TLRPC { } public static class TL_chatInvitePublicJoinRequests extends TL_chatInviteExported { - public static int constructor = 0xed107ab7; + public static final int constructor = 0xed107ab7; public void serializeToStream(AbstractSerializedData stream) { @@ -68353,7 +69168,7 @@ public class TLRPC { } public static class TL_phone_saveCallLog extends TLObject { - public static int constructor = 0x41248786; + public static final int constructor = 0x41248786; public TL_inputPhoneCall peer; public InputFile file; @@ -68401,7 +69216,7 @@ public class TLRPC { } public static class TL_attachMenuPeerTypeBotPM extends AttachMenuPeerType { - public static int constructor = 0xc32bfa1a; + public static final int constructor = 0xc32bfa1a; public void serializeToStream(AbstractSerializedData stream) { @@ -68410,7 +69225,7 @@ public class TLRPC { } public static class TL_attachMenuPeerTypePM extends AttachMenuPeerType { - public static int constructor = 0xf146d31f; + public static final int constructor = 0xf146d31f; public void serializeToStream(AbstractSerializedData stream) { @@ -68419,7 +69234,7 @@ public class TLRPC { } public static class TL_attachMenuPeerTypeBroadcast extends AttachMenuPeerType { - public static int constructor = 0x7bfbdefc; + public static final int constructor = 0x7bfbdefc; public void serializeToStream(AbstractSerializedData stream) { @@ -68428,7 +69243,7 @@ public class TLRPC { } public static class TL_attachMenuPeerTypeChat extends AttachMenuPeerType { - public static int constructor = 0x509113f; + public static final int constructor = 0x509113f; public void serializeToStream(AbstractSerializedData stream) { @@ -68437,7 +69252,7 @@ public class TLRPC { } public static class TL_attachMenuPeerTypeSameBotPM extends AttachMenuPeerType { - public static int constructor = 0x7d6be90e; + public static final int constructor = 0x7d6be90e; public void serializeToStream(AbstractSerializedData stream) { @@ -68450,6 +69265,9 @@ public class TLRPC { public static InputInvoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputInvoice result = null; switch (constructor) { + case 0x98986c0d: + result = new TL_inputInvoicePremiumGiftCode(); + break; case 0xc5b56859: result = new TL_inputInvoiceMessage(); break; @@ -68468,7 +69286,7 @@ public class TLRPC { } public static class TL_inputInvoiceMessage extends InputInvoice { - public static int constructor = 0xc5b56859; + public static final int constructor = 0xc5b56859; public InputPeer peer; public int msg_id; @@ -68486,7 +69304,7 @@ public class TLRPC { } public static class TL_inputInvoiceSlug extends InputInvoice { - public static int constructor = 0xc326caef; + public static final int constructor = 0xc326caef; public String slug; @@ -68501,7 +69319,7 @@ public class TLRPC { } public static class TL_payments_exportedInvoice extends TLObject { - public static int constructor = 0xaed0cbd9; + public static final int constructor = 0xaed0cbd9; public String url; @@ -68529,7 +69347,7 @@ public class TLRPC { } public static class TL_payments_exportInvoice extends TLObject { - public static int constructor = 0xf91b065; + public static final int constructor = 0xf91b065; public InputMedia invoice_media; @@ -68544,7 +69362,7 @@ public class TLRPC { } public static class TL_messages_transcribeAudio extends TLObject { - public static int constructor = 0x269e9a49; + public static final int constructor = 0x269e9a49; public InputPeer peer; public int msg_id; @@ -68561,7 +69379,7 @@ public class TLRPC { } public static class TL_messages_rateTranscribedAudio extends TLObject { - public static int constructor = 0x7f1d072f; + public static final int constructor = 0x7f1d072f; public InputPeer peer; public int msg_id; @@ -68582,7 +69400,7 @@ public class TLRPC { } public static class TL_messages_transcribedAudio extends TLObject { - public static int constructor = 0x93752c52; + public static final int constructor = 0x93752c52; public int flags; public boolean pending; @@ -68619,7 +69437,7 @@ public class TLRPC { } public static class TL_payments_canPurchasePremium extends TLObject { - public static int constructor = 0x9fc19eb6; + public static final int constructor = 0x9fc19eb6; public InputStorePaymentPurpose purpose; @@ -68634,7 +69452,7 @@ public class TLRPC { } public static class TL_payments_requestRecurringPayment extends TLObject { - public static int constructor = 0x146e958d; + public static final int constructor = 0x146e958d; public InputUser user_id; public String recurring_init_charge; @@ -68653,7 +69471,7 @@ public class TLRPC { } public static class TL_messageEntityCustomEmoji extends MessageEntity { - public static int constructor = 0xc8cf05f8; + public static final int constructor = 0xc8cf05f8; public long document_id; public TLRPC.Document document; //custom @@ -68673,7 +69491,7 @@ public class TLRPC { } public static class TL_messages_getCustomEmojiDocuments extends TLObject { - public static int constructor = 0xd9ab0f54; + public static final int constructor = 0xd9ab0f54; public ArrayList document_id = new ArrayList<>(); @@ -68727,7 +69545,7 @@ public class TLRPC { } public static class TL_chatReactionsSome extends ChatReactions { - public static int constructor = 0x661d4037; + public static final int constructor = 0x661d4037; public ArrayList reactions = new ArrayList<>(); @@ -68761,7 +69579,7 @@ public class TLRPC { } public static class TL_chatReactionsNone extends ChatReactions { - public static int constructor = 0xeafc32bc; + public static final int constructor = 0xeafc32bc; public void serializeToStream(AbstractSerializedData stream) { @@ -68770,7 +69588,7 @@ public class TLRPC { } public static class TL_chatReactionsAll extends ChatReactions { - public static int constructor = 0x52928bca; + public static final int constructor = 0x52928bca; public int flags; public boolean allow_custom; @@ -68788,7 +69606,7 @@ public class TLRPC { } public static class TL_messages_reportReaction extends TLObject { - public static int constructor = 0x61422a48; + public static final int constructor = 0x61422a48; public InputPeer peer; public int id; @@ -68807,7 +69625,7 @@ public class TLRPC { } public static class TL_messages_clearRecentReactions extends TLObject { - public static int constructor = 0x9dfeefb4; + public static final int constructor = 0x9dfeefb4; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -68842,7 +69660,7 @@ public class TLRPC { } public static class TL_messages_reactionsNotModified extends messages_Reactions { - public static int constructor = 0xb06fdbdf; + public static final int constructor = 0xb06fdbdf; public void serializeToStream(AbstractSerializedData stream) { @@ -68851,7 +69669,7 @@ public class TLRPC { } public static class TL_messages_reactions extends messages_Reactions { - public static int constructor = 0xeafdf716; + public static final int constructor = 0xeafdf716; public long hash; public ArrayList reactions = new ArrayList<>(); @@ -68888,7 +69706,7 @@ public class TLRPC { } public static class TL_messages_getTopReactions extends TLObject { - public static int constructor = 0xbb8125ba; + public static final int constructor = 0xbb8125ba; public int limit; public long hash; @@ -68905,7 +69723,7 @@ public class TLRPC { } public static class TL_messages_getRecentReactions extends TLObject { - public static int constructor = 0x39461db2; + public static final int constructor = 0x39461db2; public int limit; public long hash; @@ -68947,7 +69765,7 @@ public class TLRPC { } public static class TL_forumTopicDeleted extends TL_forumTopic { - public static int constructor = 0x23f109b; + public static final int constructor = 0x23f109b; public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt32(exception); @@ -68960,7 +69778,7 @@ public class TLRPC { } public static class TL_forumTopic_layer147 extends TL_forumTopic { - public static int constructor = 0x5920d6dc; + public static final int constructor = 0x5920d6dc; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -69009,7 +69827,7 @@ public class TLRPC { } public static class TL_forumTopic extends ForumTopic { - public static int constructor = 0x71701da9; + public static final int constructor = 0x71701da9; public int flags; public boolean my; @@ -69117,7 +69935,7 @@ public class TLRPC { } public static class TL_messages_forumTopics extends TLObject { - public static int constructor = 0x367617d3; + public static final int constructor = 0x367617d3; public int flags; public boolean order_by_create_date; @@ -69242,7 +70060,7 @@ public class TLRPC { } public static class TL_channels_toggleForum extends TLObject { - public static int constructor = 0xa4298b29; + public static final int constructor = 0xa4298b29; public InputChannel channel; public boolean enabled; @@ -69259,7 +70077,7 @@ public class TLRPC { } public static class TL_channels_createForumTopic extends TLObject { - public static int constructor = 0xf40c0224; + public static final int constructor = 0xf40c0224; public int flags; public InputChannel channel; @@ -69292,7 +70110,7 @@ public class TLRPC { } public static class TL_channels_editForumTopic extends TLObject { - public static int constructor = 0xf4dfa185; + public static final int constructor = 0xf4dfa185; public int flags; public InputChannel channel; @@ -69327,7 +70145,7 @@ public class TLRPC { } public static class TL_channels_updatePinnedForumTopic extends TLObject { - public static int constructor = 0x6c2d9026; + public static final int constructor = 0x6c2d9026; public InputChannel channel; public int topic_id; @@ -69346,7 +70164,7 @@ public class TLRPC { } public static class TL_channels_getForumTopics extends TLObject { - public static int constructor = 0xde560d1; + public static final int constructor = 0xde560d1; public int flags; public InputChannel channel; @@ -69375,7 +70193,7 @@ public class TLRPC { } public static class TL_channels_getForumTopicsByID extends TLObject { - public static int constructor = 0xb0831eb9; + public static final int constructor = 0xb0831eb9; public InputChannel channel; public ArrayList topics = new ArrayList<>(); @@ -69397,7 +70215,7 @@ public class TLRPC { } public static class TL_username extends TLObject { - public static int constructor = 0xb4073647; + public static final int constructor = 0xb4073647; public int flags; public boolean editable; @@ -69433,7 +70251,7 @@ public class TLRPC { } } public static class TL_channels_deleteTopicHistory extends TLObject { - public static int constructor = 0x34435f2d; + public static final int constructor = 0x34435f2d; public InputChannel channel; public int top_msg_id; @@ -69450,7 +70268,7 @@ public class TLRPC { } public static class TL_account_reorderUsernames extends TLObject { - public static int constructor = 0xef500eab; + public static final int constructor = 0xef500eab; public ArrayList order = new ArrayList<>(); @@ -69470,7 +70288,7 @@ public class TLRPC { } public static class TL_account_toggleUsername extends TLObject { - public static int constructor = 0x58d6b376; + public static final int constructor = 0x58d6b376; public String username; public boolean active; @@ -69487,7 +70305,7 @@ public class TLRPC { } public static class TL_channels_reorderUsernames extends TLObject { - public static int constructor = 0xb45ced1d; + public static final int constructor = 0xb45ced1d; public InputChannel channel; public ArrayList order = new ArrayList<>(); @@ -69509,7 +70327,7 @@ public class TLRPC { } public static class TL_channels_toggleUsername extends TLObject { - public static int constructor = 0x50f24105; + public static final int constructor = 0x50f24105; public InputChannel channel; public String username; @@ -69528,7 +70346,7 @@ public class TLRPC { } public static class TL_channels_deactivateAllUsernames extends TLObject { - public static int constructor = 0xa245dd3; + public static final int constructor = 0xa245dd3; public InputChannel channel; @@ -69543,7 +70361,7 @@ public class TLRPC { } public static class TL_channels_reorderPinnedForumTopics extends TLObject { - public static int constructor = 0x2950a18f; + public static final int constructor = 0x2950a18f; public int flags; public boolean force; @@ -69569,7 +70387,7 @@ public class TLRPC { } public static class TL_channels_toggleAntiSpam extends TLObject { - public static int constructor = 0x68f3e4eb; + public static final int constructor = 0x68f3e4eb; public InputChannel channel; public boolean enabled; @@ -69586,7 +70404,7 @@ public class TLRPC { } public static class TL_channels_reportAntiSpamFalsePositive extends TLObject { - public static int constructor = 0xa850a693; + public static final int constructor = 0xa850a693; public InputChannel channel; public int msg_id; @@ -69603,7 +70421,7 @@ public class TLRPC { } public static class TL_channels_toggleParticipantsHidden extends TLObject { - public static int constructor = 0x6a6e7854; + public static final int constructor = 0x6a6e7854; public InputChannel channel; public boolean enabled; @@ -69620,7 +70438,7 @@ public class TLRPC { } public static class TL_channels_clickSponsoredMessage extends TLObject { - public static int constructor = 0x18afbc93; + public static final int constructor = 0x18afbc93; public InputChannel channel; public byte[] random_id; @@ -69637,7 +70455,7 @@ public class TLRPC { } public static class TL_messages_setDefaultHistoryTTL extends TLObject { - public static int constructor = 0x9eb51445; + public static final int constructor = 0x9eb51445; public int period; @@ -69652,7 +70470,7 @@ public class TLRPC { } public static class TL_messages_getDefaultHistoryTTL extends TLObject { - public static int constructor = 0x658b7188; + public static final int constructor = 0x658b7188; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -69665,7 +70483,7 @@ public class TLRPC { } public static class TL_defaultHistoryTTL extends TLObject { - public static int constructor = 0x43b46b20; + public static final int constructor = 0x43b46b20; public int period; @@ -69693,7 +70511,7 @@ public class TLRPC { } public static class TL_messages_sendBotRequestedPeer extends TLObject { - public static int constructor = 0xfe38d01b; + public static final int constructor = 0xfe38d01b; public InputPeer peer; public int msg_id; @@ -69714,7 +70532,7 @@ public class TLRPC { } public static class TL_contacts_exportContactToken extends TLObject { - public static int constructor = 0xf8654027; + public static final int constructor = 0xf8654027; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -69727,7 +70545,7 @@ public class TLRPC { } public static class TL_contacts_importContactToken extends TLObject { - public static int constructor = 0x13005788; + public static final int constructor = 0x13005788; public String token; @@ -69742,7 +70560,7 @@ public class TLRPC { } public static class TL_messageActionSuggestProfilePhoto extends MessageAction { - public static int constructor = 0x57de635e; + public static final int constructor = 0x57de635e; public void readParams(AbstractSerializedData stream, boolean exception) { photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -69755,7 +70573,7 @@ public class TLRPC { } public static class TL_messageActionAttachMenuBotAllowed extends MessageAction { - public static int constructor = 0xe7e75f97; + public static final int constructor = 0xe7e75f97; public void readParams(AbstractSerializedData stream, boolean exception) { @@ -69767,7 +70585,7 @@ public class TLRPC { } public static class TL_messageActionRequestedPeer extends MessageAction { - public static int constructor = 0xfe77345d; + public static final int constructor = 0xfe77345d; public int button_id; public TLRPC.Peer peer; @@ -69785,7 +70603,7 @@ public class TLRPC { } public static class TL_photos_uploadContactProfilePhoto extends TLObject { - public static int constructor = 0xe14c4a71; + public static final int constructor = 0xe14c4a71; public int flags; public boolean suggest; @@ -69844,7 +70662,7 @@ public class TLRPC { } public static class TL_emojiList extends EmojiList { - public static int constructor = 0x7a1e11d1; + public static final int constructor = 0x7a1e11d1; public long hash; public ArrayList document_id = new ArrayList<>(); @@ -69877,7 +70695,7 @@ public class TLRPC { } public static class TL_emojiListNotModified extends EmojiList { - public static int constructor = 0x481eadfa; + public static final int constructor = 0x481eadfa; public void serializeToStream(AbstractSerializedData stream) { @@ -69886,7 +70704,7 @@ public class TLRPC { } public static class TL_account_getDefaultProfilePhotoEmojis extends TLObject { - public static int constructor = 0xe2750328; + public static final int constructor = 0xe2750328; public long hash; @@ -69901,7 +70719,7 @@ public class TLRPC { } public static class TL_account_getDefaultGroupPhotoEmojis extends TLObject { - public static int constructor = 0x915860ae; + public static final int constructor = 0x915860ae; public long hash; @@ -69915,8 +70733,52 @@ public class TLRPC { } } + public static class TL_channels_updateColor extends TLObject { + public static final int constructor = 0x621a201f; + + public int flags; + public InputChannel channel; + public int color; + public long background_emoji_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + channel.serializeToStream(stream); + stream.writeInt32(color); + if ((flags & 1) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + + public static class TL_account_updateColor extends TLObject { + public static final int constructor = 0xa001cc43; + + public int flags; + public int color; + public long background_emoji_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(color); + if ((flags & 1) != 0) { + stream.writeInt64(background_emoji_id); + } + } + } + public static class TL_updateGroupInvitePrivacyForbidden extends Update { - public static int constructor = 0xccf08ad6; + public static final int constructor = 0xccf08ad6; public long user_id; @@ -69930,233 +70792,8 @@ public class TLRPC { } } - public static class TL_chatlists_exportChatlistInvite extends TLObject { - public static int constructor = 0x8472478e; - - public TL_inputChatlistDialogFilter chatlist; - public String title; - public ArrayList peers = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_chatlists_exportedChatlistInvite.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - stream.writeString(title); - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - - public static class TL_chatlists_deleteExportedInvite extends TLObject { - public static int constructor = 0x719c5c5e; - - public TL_inputChatlistDialogFilter chatlist; - public String slug; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - stream.writeString(slug); - } - } - - public static class TL_chatlists_editExportedInvite extends TLObject { - public static int constructor = 0x653db63d; - - public int flags; - public boolean revoked; - public TL_inputChatlistDialogFilter chatlist; - public String slug; - public String title; - public ArrayList peers = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_exportedChatlistInvite.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = revoked ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - chatlist.serializeToStream(stream); - stream.writeString(slug); - if ((flags & 2) != 0) { - stream.writeString(title); - } - if ((flags & 4) != 0) { - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - } - - public static class TL_chatlists_getExportedInvites extends TLObject { - public static int constructor = 0xce03da83; - - public TL_inputChatlistDialogFilter chatlist; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_chatlists_exportedInvites.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - } - } - - public static class TL_chatlists_checkChatlistInvite extends TLObject { - public static int constructor = 0x41c10fff; - - public String slug; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return chatlist_ChatlistInvite.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(slug); - } - } - - public static class TL_chatlists_joinChatlistInvite extends TLObject { - public static int constructor = 0xa6b1e39a; - - public String slug; - public ArrayList peers = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(slug); - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - - public static class TL_chatlists_getChatlistUpdates extends TLObject { - public static int constructor = 0x89419521; - - public TL_inputChatlistDialogFilter chatlist; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_chatlists_chatlistUpdates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - } - } - - public static class TL_chatlists_joinChatlistUpdates extends TLObject { - public static int constructor = 0xe089f8f5; - - public TL_inputChatlistDialogFilter chatlist; - public ArrayList peers = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - - public static class TL_chatlists_hideChatlistUpdates extends TLObject { - public static int constructor = 0x66e486fb; - - public TL_inputChatlistDialogFilter chatlist; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Bool.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - } - } - - public static class TL_chatlists_getLeaveChatlistSuggestions extends TLObject { - public static int constructor = 0xfdbcd714; - - public TL_inputChatlistDialogFilter chatlist; - - 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++) { - Peer object = Peer.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); - chatlist.serializeToStream(stream); - } - } - - public static class TL_chatlists_leaveChatlist extends TLObject { - public static int constructor = 0x74fae13a; - - public TL_inputChatlistDialogFilter chatlist; - public ArrayList peers = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - chatlist.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = peers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peers.get(a).serializeToStream(stream); - } - } - } - public static class TL_messages_setChatWallPaper extends TLObject { - public static int constructor = 0x8ffacae1; + public static final int constructor = 0x8ffacae1; public int flags; public InputPeer peer; @@ -70184,1355 +70821,14 @@ public class TLRPC { } } - public static abstract class StoryItem extends TLObject { - - public int flags; - public boolean pinned; - public boolean isPublic; - public boolean close_friends; - public boolean contacts; - public boolean selected_contacts; - public boolean noforwards; - public boolean min; - public boolean out; - public int id; - public int date; - public int expire_date; - public String caption; - public boolean edited; - public ArrayList entities = new ArrayList<>(); - public MessageMedia media; - public ArrayList media_areas = new ArrayList(); - public ArrayList privacy = new ArrayList<>(); - public StoryViews views; - public Reaction sent_reaction; - public long lastUpdateTime; //custom - public String attachPath; //custom - public String firstFramePath; //custom - public long dialogId;// custom - public boolean justUploaded;// custom - public int messageId;//custom - public int messageType;//custom - public int fileReference; - public String detectedLng; //custom - public String translatedLng; //custom - public boolean translated; //custom - public TLRPC.TL_textWithEntities translatedText; //custom - public StoryPrivacyBottomSheet.StoryPrivacy parsedPrivacy; //custom - - public static StoryItem TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StoryItem result = null; - switch (constructor) { - case 0x44c457ce: - result = new TL_storyItem(); - break; - case 0x562aa637: - result = new TL_storyItem_layer160(); - break; - case 0x51e6ee4f: - result = new TL_storyItemDeleted(); - break; - case 0xffadc913: - result = new TL_storyItemSkipped(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StoryItem", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static abstract class StoryViews extends TLObject { - - public int flags; - public int views_count; - public int reactions_count; - public ArrayList recent_viewers = new ArrayList<>(); - public boolean has_viewers; - public int forwards_count; - public ArrayList reactions = new ArrayList<>(); - - public static StoryViews TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - StoryViews result = null; - switch (constructor) { - case 0xd36760cf: - result = new TL_storyViews_layer160(); - break; - case 0xc64c0b97: - result = new TL_storyViews_layer161(); - break; - case 0x8d595cd6: - result = new TL_storyViews(); - break; - - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in StoryViews", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_storyViews_layer160 extends StoryViews { - public static int constructor = 0xd36760cf; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - views_count = stream.readInt32(exception); - if ((flags & 1) != 0) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - recent_viewers.add(stream.readInt64(exception)); - } - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt32(views_count); - if ((flags & 1) != 0) { - stream.writeInt32(0x1cb5c415); - int count = recent_viewers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt64(recent_viewers.get(a)); - } - } - } - } - - public static class TL_storyViews_layer161 extends StoryViews { - public static int constructor = 0xc64c0b97; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - views_count = stream.readInt32(exception); - reactions_count = stream.readInt32(exception); - if ((flags & 1) != 0) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - recent_viewers.add(stream.readInt64(exception)); - } - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt32(views_count); - stream.writeInt32(reactions_count); - if ((flags & 1) != 0) { - stream.writeInt32(0x1cb5c415); - int count = recent_viewers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt64(recent_viewers.get(a)); - } - } - } - } - - public static class TL_storyViews extends StoryViews { - public static int constructor = 0x8d595cd6; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - has_viewers = (flags & 2) != 0; - views_count = stream.readInt32(exception); - if ((flags & 4) != 0) { - forwards_count = stream.readInt32(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++) { - ReactionCount object = ReactionCount.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - reactions.add(object); - } - } - if ((flags & 16) != 0) { - reactions_count = stream.readInt32(exception); - } - if ((flags & 1) != 0) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - recent_viewers.add(stream.readInt64(exception)); - } - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = has_viewers ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - stream.writeInt32(views_count); - if ((flags & 4) != 0) { - stream.writeInt32(forwards_count); - } - if ((flags & 8) != 0) { - stream.writeInt32(0x1cb5c415); - int count = reactions.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - reactions.get(a).serializeToStream(stream); - } - } - if ((flags & 16) != 0) { - stream.writeInt32(reactions_count); - } - if ((flags & 1) != 0) { - stream.writeInt32(0x1cb5c415); - int count = recent_viewers.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt64(recent_viewers.get(a)); - } - } - } - } - - public static class TL_storyItem extends StoryItem { - public static int constructor = 0x44c457ce; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - pinned = (flags & 32) != 0; - isPublic = (flags & 128) != 0; - close_friends = (flags & 256) != 0; - min = (flags & 512) != 0; - noforwards = (flags & 1024) != 0; - edited = (flags & 2048) != 0; - contacts = (flags & 4096) != 0; - selected_contacts = (flags & 8192) != 0; - out = (flags & 65536) != 0; - id = stream.readInt32(exception); - date = stream.readInt32(exception); - expire_date = stream.readInt32(exception); - if ((flags & 1) != 0) { - caption = stream.readString(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++) { - MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - entities.add(object); - } - } - media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 16384) != 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++) { - MediaArea object = MediaArea.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - media_areas.add(object); - } - } - if ((flags & 4) != 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++) { - PrivacyRule object = PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - privacy.add(object); - } - } - if ((flags & 8) != 0) { - views = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); - } - if ((flags & 32768) != 0) { - sent_reaction = Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = pinned ? (flags | 32) : (flags &~ 32); - flags = isPublic ? (flags | 128) : (flags &~ 128); - flags = close_friends ? (flags | 256) : (flags &~ 256); - flags = min ? (flags | 512) : (flags &~ 512); - flags = noforwards ? (flags | 1024) : (flags &~ 1024); - flags = edited ? (flags | 2048) : (flags &~ 2048); - flags = contacts ? (flags | 4096) : (flags &~ 4096); - flags = selected_contacts ? (flags | 8192) : (flags &~ 8192); - flags = out ? (flags | 65536) : (flags &~ 65536); - stream.writeInt32(flags); - stream.writeInt32(id); - stream.writeInt32(date); - stream.writeInt32(expire_date); - if ((flags & 1) != 0) { - stream.writeString(caption); - } - if ((flags & 2) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - media.serializeToStream(stream); - if ((flags & 16384) != 0) { - stream.writeInt32(0x1cb5c415); - int count = media_areas.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - media_areas.get(a).serializeToStream(stream); - } - } - if ((flags & 4) != 0) { - stream.writeInt32(0x1cb5c415); - int count = privacy.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - privacy.get(a).serializeToStream(stream); - } - } - if ((flags & 8) != 0) { - views.serializeToStream(stream); - } - if ((flags & 32768) != 0) { - sent_reaction.serializeToStream(stream); - } - } - } - - public static class TL_storyItem_layer160 extends TL_storyItem { - public static int constructor = 0x562aa637; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - pinned = (flags & 32) != 0; - isPublic = (flags & 128) != 0; - close_friends = (flags & 256) != 0; - min = (flags & 512) != 0; - noforwards = (flags & 1024) != 0; - edited = (flags & 2048) != 0; - contacts = (flags & 4096) != 0; - selected_contacts = (flags & 8192) != 0; - id = stream.readInt32(exception); - date = stream.readInt32(exception); - expire_date = stream.readInt32(exception); - if ((flags & 1) != 0) { - caption = stream.readString(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++) { - MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - entities.add(object); - } - } - media = MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 4) != 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++) { - PrivacyRule object = PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - privacy.add(object); - } - } - if ((flags & 8) != 0) { - views = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = pinned ? (flags | 32) : (flags &~ 32); - flags = isPublic ? (flags | 128) : (flags &~ 128); - flags = close_friends ? (flags | 256) : (flags &~ 256); - flags = min ? (flags | 512) : (flags &~ 512); - flags = noforwards ? (flags | 1024) : (flags &~ 1024); - flags = edited ? (flags | 2048) : (flags &~ 2048); - flags = contacts ? (flags | 4096) : (flags &~ 4096); - flags = selected_contacts ? (flags | 8192) : (flags &~ 8192); - stream.writeInt32(flags); - stream.writeInt32(id); - stream.writeInt32(date); - stream.writeInt32(expire_date); - if ((flags & 1) != 0) { - stream.writeString(caption); - } - if ((flags & 2) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - media.serializeToStream(stream); - if ((flags & 4) != 0) { - stream.writeInt32(0x1cb5c415); - int count = privacy.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - privacy.get(a).serializeToStream(stream); - } - } - if ((flags & 8) != 0) { - views.serializeToStream(stream); - } - } - } - - public static class TL_storyItemDeleted extends StoryItem { - public static int constructor = 0x51e6ee4f; - - public void readParams(AbstractSerializedData stream, boolean exception) { - id = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(id); - } - } - - public static class TL_storyItemSkipped extends StoryItem { - public static int constructor = 0xffadc913; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - close_friends = (flags & 256) != 0; - id = stream.readInt32(exception); - date = stream.readInt32(exception); - expire_date = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = close_friends ? (flags | 256) : (flags &~ 256); - stream.writeInt32(flags); - stream.writeInt32(id); - stream.writeInt32(date); - stream.writeInt32(expire_date); - } - } - - public static class TL_mediaAreaCoordinates extends TLObject { - public static final int constructor = 0x3d1ea4e; - - public double x; - public double y; - public double w; - public double h; - public double rotation; - - public static TL_mediaAreaCoordinates TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_mediaAreaCoordinates.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_mediaAreaCoordinates", constructor)); - } else { - return null; - } - } - TL_mediaAreaCoordinates result = new TL_mediaAreaCoordinates(); - result.readParams(stream, exception); - return result; - } - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - x = stream.readDouble(exception); - y = stream.readDouble(exception); - w = stream.readDouble(exception); - h = stream.readDouble(exception); - rotation = stream.readDouble(exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeDouble(x); - stream.writeDouble(y); - stream.writeDouble(w); - stream.writeDouble(h); - stream.writeDouble(rotation); - } - } - - public static class MediaArea extends TLObject { - public TL_mediaAreaCoordinates coordinates; - public Reaction reaction; - public int flags; - public boolean dark; - public boolean flipped; - - public static MediaArea TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - MediaArea result = null; - switch (constructor) { - case TL_mediaAreaVenue.constructor: - result = new TL_mediaAreaVenue(); - break; - case TL_mediaAreaGeoPoint.constructor: - result = new TL_mediaAreaGeoPoint(); - break; - case TL_inputMediaAreaVenue.constructor: - result = new TL_inputMediaAreaVenue(); - break; - case TL_mediaAreaSuggestedReaction.constructor: - result = new TL_mediaAreaSuggestedReaction(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in MediaArea", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_mediaAreaSuggestedReaction extends MediaArea { - public static final int constructor = 0x14455871; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - dark = (flags & 1) != 0; - flipped = (flags & 2) != 0; - coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); - reaction = Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = dark ? (flags | 1) : (flags &~ 1); - flags = flipped ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - coordinates.serializeToStream(stream); - reaction.serializeToStream(stream); - } - } - - public static class TL_mediaAreaVenue extends MediaArea { - public static final int constructor = 0xbe82db9c; - - public GeoPoint geo; - public String title; - public String address; - public String provider; - public String venue_id; - public String venue_type; - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); - geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); - title = stream.readString(exception); - address = stream.readString(exception); - provider = stream.readString(exception); - venue_id = stream.readString(exception); - venue_type = stream.readString(exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - coordinates.serializeToStream(stream); - geo.serializeToStream(stream); - stream.writeString(title); - stream.writeString(address); - stream.writeString(provider); - stream.writeString(venue_id); - stream.writeString(venue_type); - } - } - - public static class TL_inputMediaAreaVenue extends MediaArea { - public static final int constructor = 0xb282217f; - - public long query_id; - public String result_id; - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); - query_id = stream.readInt64(exception); - result_id = stream.readString(exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - coordinates.serializeToStream(stream); - stream.writeInt64(query_id); - stream.writeString(result_id); - } - } - - public static class TL_mediaAreaGeoPoint extends MediaArea { - public static final int constructor = 0xdf8b3b22; - - public GeoPoint geo; - - @Override - public void readParams(AbstractSerializedData stream, boolean exception) { - coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); - geo = GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - @Override - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - coordinates.serializeToStream(stream); - geo.serializeToStream(stream); - } - } - - public static class TL_stories_storyViews extends TLObject { - public static int constructor = 0xde9eed1d; - - public ArrayList views = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_stories_storyViews TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_storyViews.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_storyViews", constructor)); - } else { - return null; - } - } - TL_stories_storyViews result = new TL_stories_storyViews(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - StoryViews object = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - views.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = views.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - views.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static class TL_storyView extends TLObject { - public static int constructor = 0xb0bdeac5; - - public int flags; - public boolean blocked; - public boolean blocked_my_stories_from; - public long user_id; - public int date; - public Reaction reaction; - - public static TL_storyView TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_storyView.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_storyView", constructor)); - } else { - return null; - } - } - TL_storyView result = new TL_storyView(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - blocked = (flags & 1) != 0; - blocked_my_stories_from = (flags & 2) != 0; - user_id = stream.readInt64(exception); - date = stream.readInt32(exception); - if ((flags & 4) != 0) { - reaction = Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = blocked ? (flags | 1) : (flags &~ 1); - flags = blocked_my_stories_from ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - stream.writeInt64(user_id); - stream.writeInt32(date); - if ((flags & 4) != 0) { - reaction.serializeToStream(stream); - } - } - } - - public static abstract class PeerStories extends TLObject { - - public int flags; - public Peer peer; - public int max_read_id; - public ArrayList stories = new ArrayList<>(); - - public static PeerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - PeerStories result = null; - switch (constructor) { - case 0x9a35e999: - result = new TL_peerStories(); - break; - case 0x8611a200: - result = new TL_peerStories_layer162(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in PeerStories", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_peerStories extends PeerStories { - public static int constructor = 0x9a35e999; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - if ((flags & 1) != 0) { - max_read_id = stream.readInt32(exception); - } - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - stories.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - peer.serializeToStream(stream); - if ((flags & 1) != 0) { - stream.writeInt32(max_read_id); - } - stream.writeInt32(0x1cb5c415); - int count = stories.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stories.get(a).serializeToStream(stream); - } - } - } - - public static class TL_peerStories_layer162 extends TL_peerStories { - public static int constructor = 0x8611a200; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - long user_id = stream.readInt64(exception); - peer = new TL_peerUser(); - peer.user_id = user_id; - if ((flags & 1) != 0) { - max_read_id = stream.readInt32(exception); - } - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - stories.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt64(peer.user_id); - if ((flags & 1) != 0) { - stream.writeInt32(max_read_id); - } - stream.writeInt32(0x1cb5c415); - int count = stories.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stories.get(a).serializeToStream(stream); - } - } - } - - public static class TL_stories_peerStories extends TLObject { - public static int constructor = 0xcae68768; - - public PeerStories stories; - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_stories_peerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_peerStories.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_peerStories", constructor)); - } else { - return null; - } - } - TL_stories_peerStories result = new TL_stories_peerStories(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - stories = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); - int magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - int count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - 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); - stories.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static abstract class stories_AllStories extends TLObject { - - public static stories_AllStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - stories_AllStories result = null; - switch (constructor) { - case 0x1158fe3e: - result = new TL_stories_allStoriesNotModified(); - break; - case 0x6efc5e81: - result = new TL_stories_allStories(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in stories_AllStories", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_stories_allStoriesNotModified extends stories_AllStories { - public static int constructor = 0x1158fe3e; - - public int flags; - public String state; - public TL_storiesStealthMode stealth_mode; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - state = stream.readString(exception); - stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeString(state); - stealth_mode.serializeToStream(stream); - } - } - - public static class TL_stories_allStories extends stories_AllStories { - public static int constructor = 0x6efc5e81; - - public int flags; - public boolean has_more; - public int count; - public String state; - public ArrayList peer_stories = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - public TL_storiesStealthMode stealth_mode; - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - has_more = (flags & 1) != 0; - count = stream.readInt32(exception); - state = 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++) { - PeerStories object = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - peer_stories.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = has_more ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - stream.writeInt32(count); - stream.writeString(state); - stream.writeInt32(0x1cb5c415); - int count = peer_stories.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - peer_stories.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - stealth_mode.serializeToStream(stream); - } - } - - public static class TL_stories_canSendStory extends TLObject { - public static int constructor = 0xc7dfdfdd; - - public InputPeer peer; - - 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); - } - } - - public static class TL_stories_sendStory extends TLObject { - public static int constructor = 0xbcb73644; - - public int flags; - public boolean pinned; - public boolean noforwards; - public InputPeer peer; - public InputMedia media; - public ArrayList media_areas = new ArrayList<>(); - public String caption; - public ArrayList entities = new ArrayList<>(); - public ArrayList privacy_rules = new ArrayList<>(); - public long random_id; - public int period; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = pinned ? (flags | 4) : (flags &~ 4); - flags = noforwards ? (flags | 16) : (flags &~ 16); - stream.writeInt32(flags); - peer.serializeToStream(stream); - media.serializeToStream(stream); - if ((flags & 32) != 0) { - stream.writeInt32(0x1cb5c415); - int count = media_areas.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - media_areas.get(a).serializeToStream(stream); - } - } - if ((flags & 1) != 0) { - stream.writeString(caption); - } - if ((flags & 2) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - stream.writeInt32(0x1cb5c415); - int count = privacy_rules.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - privacy_rules.get(a).serializeToStream(stream); - } - stream.writeInt64(random_id); - if ((flags & 8) != 0) { - stream.writeInt32(period); - } - } - } - - public static class TL_stories_deleteStories extends TLObject { - public static int constructor = 0xae59db5f; - - public InputPeer peer; - public ArrayList id = new ArrayList<>(); - - 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++) { - vector.objects.add(stream.readInt32(exception)); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt32(id.get(a)); - } - } - } - - public static class TL_stories_togglePinned extends TLObject { - public static int constructor = 0x9a75a1ef; - - public InputPeer peer; - public ArrayList id = new ArrayList<>(); - public boolean pinned; - - 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++) { - vector.objects.add(stream.readInt32(exception)); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt32(id.get(a)); - } - stream.writeBool(pinned); - } - } - - public static class TL_stories_editStory extends TLObject { - public static int constructor = 0xb583ba46; - - public int flags; - public InputPeer peer; - public int id; - public InputMedia media; - public ArrayList media_areas = new ArrayList<>(); - public String caption; - public ArrayList entities = new ArrayList<>(); - public ArrayList privacy_rules = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(id); - if ((flags & 1) != 0) { - media.serializeToStream(stream); - } - if ((flags & 8) != 0) { - stream.writeInt32(0x1cb5c415); - int count = media_areas.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - media_areas.get(a).serializeToStream(stream); - } - } - if ((flags & 2) != 0) { - stream.writeString(caption); - } - if ((flags & 2) != 0) { - stream.writeInt32(0x1cb5c415); - int count = entities.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - entities.get(a).serializeToStream(stream); - } - } - if ((flags & 4) != 0) { - stream.writeInt32(0x1cb5c415); - int count = privacy_rules.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - privacy_rules.get(a).serializeToStream(stream); - } - } - } - } - - public static class TL_stories_getAllStories extends TLObject { - public static int constructor = 0xeeb0d625; - - public int flags; - public boolean include_hidden; - public boolean next; - public String state; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return stories_AllStories.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = next ? (flags | 2) : (flags &~ 2); - flags = include_hidden ? (flags | 4) : (flags &~ 4); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeString(state); - } - } - } - - public static class TL_stories_togglePeerStoriesHidden extends TLObject { - public static int constructor = 0xbd0415c4; - - public InputPeer peer; - public boolean hidden; - - 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.writeBool(hidden); - } - } - public static class TL_contacts_setBlocked extends TLObject { - public static int constructor = 0x94c65c76; - + public static final int constructor = 0x94c65c76; + public int flags; public boolean my_stories_from; public ArrayList id = new ArrayList<>(); public int limit; - + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); } @@ -71550,332 +70846,11 @@ public class TLRPC { } } - public static class TL_stories_stories extends TLObject { - public static int constructor = 0x5dd8c3c8; - - public int count; - public ArrayList stories = new ArrayList<>(); - public ArrayList chats = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - - public static TL_stories_stories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_stories.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_stories", constructor)); - } else { - return null; - } - } - TL_stories_stories result = new TL_stories_stories(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean 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++) { - StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - stories.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - chats.add(object); - } - magic = stream.readInt32(exception); - if (magic != 0x1cb5c415) { - if (exception) { - throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); - } - return; - } - count = stream.readInt32(exception); - for (int a = 0; a < count; a++) { - User object = User.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - users.add(object); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(count); - stream.writeInt32(0x1cb5c415); - int count = stories.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stories.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = chats.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - chats.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - } - } - - public static class TL_stories_getPeerStories extends TLObject { - public static int constructor = 0x2c4ada50; - - public InputPeer peer; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_peerStories.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } - - public static class TL_updateStory extends Update { - public static int constructor = 0x75b3b798; - - public Peer peer; - public StoryItem story; - - public void readParams(AbstractSerializedData stream, boolean exception) { - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - story = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - story.serializeToStream(stream); - } - } - - public static class TL_stories_getPinnedStories extends TLObject { - public static int constructor = 0x5821a5dc; - - public InputPeer peer; - public int offset_id; - public int limit; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_stories.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(offset_id); - stream.writeInt32(limit); - } - } - - public static class TL_stories_getStoriesArchive extends TLObject { - public static int constructor = 0xb4352016; - - public InputPeer peer; - public int offset_id; - public int limit; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_stories.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(offset_id); - stream.writeInt32(limit); - } - } - - public static class TL_updateReadStories extends Update { - public static int constructor = 0xf74e932b; - - public Peer peer; - public int max_id; - - public void readParams(AbstractSerializedData stream, boolean exception) { - peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); - max_id = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(max_id); - } - } - - public static class TL_stories_storyViewsList extends TLObject { - public static int constructor = 0x46e9b9ec; - - public int flags; - public int count; - public int reactions_count; - public ArrayList views = new ArrayList<>(); - public ArrayList users = new ArrayList<>(); - public String next_offset = ""; - - public static TL_stories_storyViewsList TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_storyViewsList.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_storyViewsList", constructor)); - } else { - return null; - } - } - TL_stories_storyViewsList result = new TL_stories_storyViewsList(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - count = stream.readInt32(exception); - reactions_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++) { - TL_storyView object = TL_storyView.TLdeserialize(stream, stream.readInt32(exception), exception); - if (object == null) { - return; - } - views.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); - } - if ((flags & 1) != 0) { - next_offset = stream.readString(exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt32(count); - stream.writeInt32(reactions_count); - stream.writeInt32(0x1cb5c415); - int count = views.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - views.get(a).serializeToStream(stream); - } - stream.writeInt32(0x1cb5c415); - count = users.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - users.get(a).serializeToStream(stream); - } - if ((flags & 1) != 0) { - stream.writeString(next_offset); - } - } - } - - public static class TL_stories_readStories extends TLObject { - public static int constructor = 0xa556dac8; - - public InputPeer peer; - public int max_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++) { - vector.objects.add(stream.readInt32(exception)); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(max_id); - } - } - - public static class TL_stories_getStoryViewsList extends TLObject { - public static int constructor = 0x7ed23c57; - - public int flags; - public boolean just_contacts; - public boolean reactions_first; - public InputPeer peer; - public String q; - public int id; - public String offset; - public int limit; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_storyViewsList.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = just_contacts ? (flags | 1) : (flags &~ 1); - flags = reactions_first ? (flags | 4) : (flags &~ 4); - stream.writeInt32(flags); - peer.serializeToStream(stream); - if ((flags & 2) != 0) { - stream.writeString(q); - } - stream.writeInt32(id); - stream.writeString(offset); - stream.writeInt32(limit); - } - } - public static class TL_editCloseFriends extends TLObject { - public static int constructor = 0xba6705f0; + public static final int constructor = 0xba6705f0; public ArrayList id = new ArrayList<>(); - + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); } @@ -71891,59 +70866,25 @@ public class TLRPC { } } - public static class TL_stories_getStoriesByID extends TLObject { - public static int constructor = 0x5774ca74; - - public InputPeer peer; - public ArrayList id = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_stories.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt32(id.get(a)); - } - } - } - - public static class TL_stories_getStoriesViews extends TLObject { - public static int constructor = 0x28e16cc8; - - public InputPeer peer; - public ArrayList id = new ArrayList<>(); - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_storyViews.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt32(id.get(a)); - } - } - } - public static abstract class InputReplyTo extends TLObject { + public int flags; + public int reply_to_msg_id; + public int top_msg_id; + public InputPeer reply_to_peer_id; + public String quote_text; + public ArrayList quote_entities = new ArrayList<>(); + + public InputUser user_id; + public int story_id; + public static InputReplyTo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { InputReplyTo result = null; switch (constructor) { - case 0x9c5386e4: + case TL_inputReplyToMessage.constructor: result = new TL_inputReplyToMessage(); break; - case 0x15b0f283: + case TL_inputReplyToStory.constructor: result = new TL_inputReplyToStory(); break; } @@ -71958,11 +70899,7 @@ public class TLRPC { } public static class TL_inputReplyToMessage extends InputReplyTo { - public static int constructor = 0x9c5386e4; - - public int flags; - public int reply_to_msg_id; - public int top_msg_id; + public static final int constructor = 0x73ec805; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -71970,6 +70907,29 @@ public class TLRPC { if ((flags & 1) != 0) { top_msg_id = stream.readInt32(exception); } + if ((flags & 2) != 0) { + reply_to_peer_id = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 4) != 0) { + quote_text = stream.readString(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++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + quote_entities.add(object); + } + } } public void serializeToStream(AbstractSerializedData stream) { @@ -71979,14 +70939,25 @@ public class TLRPC { if ((flags & 1) != 0) { stream.writeInt32(top_msg_id); } + if ((flags & 2) != 0) { + reply_to_peer_id.serializeToStream(stream); + } + if ((flags & 4) != 0) { + stream.writeString(quote_text); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = quote_entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; ++a) { + quote_entities.get(a).serializeToStream(stream); + } + } } } public static class TL_inputReplyToStory extends InputReplyTo { - public static int constructor = 0x15b0f283; - - public InputUser user_id; - public int story_id; + public static final int constructor = 0x15b0f283; public void readParams(AbstractSerializedData stream, boolean exception) { user_id = InputUser.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -72000,53 +70971,8 @@ public class TLRPC { } } - public static class TL_exportedStoryLink extends TLObject { - public static int constructor = 0x3fc9053b; - - public String link; - - public static TL_exportedStoryLink TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_exportedStoryLink.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_exportedStoryLink", constructor)); - } else { - return null; - } - } - TL_exportedStoryLink result = new TL_exportedStoryLink(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - link = stream.readString(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeString(link); - } - } - - public static class TL_stories_exportStoryLink extends TLObject { - public static int constructor = 0x7b8def20; - - public InputPeer peer; - public int id; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_exportedStoryLink.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - stream.writeInt32(id); - } - } - public static class TL_inputMediaStory extends InputMedia { - public static int constructor = 0x89fdd778; + public static final int constructor = 0x89fdd778; public InputPeer peer; public int id; @@ -72064,7 +70990,7 @@ public class TLRPC { } public static class TL_messageMediaStory extends MessageMedia { - public static int constructor = 0x68cb6283; + public static final int constructor = 0x68cb6283; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -72072,7 +70998,7 @@ public class TLRPC { peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); id = stream.readInt32(exception); if ((flags & 1) != 0) { - storyItem = TLRPC.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -72089,7 +71015,7 @@ public class TLRPC { } public static class TL_messageMediaStory_layer162 extends MessageMedia { - public static int constructor = 0xcbb20d88; + public static final int constructor = 0xcbb20d88; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -72097,7 +71023,7 @@ public class TLRPC { user_id = stream.readInt64(exception); id = stream.readInt32(exception); if ((flags & 1) != 0) { - storyItem = TLRPC.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); } peer = new TL_peerUser(); peer.user_id = user_id; @@ -72120,171 +71046,8 @@ public class TLRPC { } } - public static class TL_stories_report extends TLObject { - public static int constructor = 0x1923fa8c; - - public InputPeer peer; - public ArrayList id = new ArrayList<>(); - public ReportReason reason; - public String message; - - 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.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - stream.writeInt32(id.get(a)); - } - reason.serializeToStream(stream); - stream.writeString(message); - } - } - - public static class TL_stories_getAllReadPeerStories extends TLObject { - public static int constructor = 0x9b5ae7f9; - - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_stories_getPeerMaxIDs extends TLObject { - public static int constructor = 0x535983c3; - - public ArrayList id = new ArrayList<>(); - - 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++) { - vector.objects.add(stream.readInt32(exception)); - } - return vector; - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(0x1cb5c415); - int count = id.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - id.get(a).serializeToStream(stream); - } - } - } - - public static class TL_updateStoriesStealthMode extends Update { - public static int constructor = 0x2c084dc1; - - public TL_storiesStealthMode stealth_mode; - - public void readParams(AbstractSerializedData stream, boolean exception) { - stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stealth_mode.serializeToStream(stream); - } - } - - public static class TL_storiesStealthMode extends TLObject { - public static int constructor = 0x712e27fd; - - public int flags; - public int active_until_date; - public int cooldown_until_date; - - public static TL_storiesStealthMode TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_storiesStealthMode.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_storiesStealthMode", constructor)); - } else { - return null; - } - } - TL_storiesStealthMode result = new TL_storiesStealthMode(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - if ((flags & 1) != 0) { - active_until_date = stream.readInt32(exception); - } - if ((flags & 2) != 0) { - cooldown_until_date = stream.readInt32(exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - if ((flags & 1) != 0) { - stream.writeInt32(active_until_date); - } - if ((flags & 2) != 0) { - stream.writeInt32(cooldown_until_date); - } - } - } - - public static class TL_stories_activateStealthMode extends TLObject { - public static int constructor = 0x57bbd166; - - public int flags; - public boolean past; - public boolean future; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = past ? (flags | 1) : (flags &~ 1); - flags = future ? (flags | 2) : (flags &~ 2); - stream.writeInt32(flags); - } - } - - public static class TL_stories_sendReaction extends TLObject { - public static int constructor = 0x7fd736b2; - - public int flags; - public boolean add_to_recent; - public InputPeer peer; - public int story_id; - public Reaction reaction; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return Updates.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - flags = add_to_recent ? (flags | 1) : (flags &~ 1); - stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(story_id); - reaction.serializeToStream(stream); - } - } - public static class TL_bots_canSendMessage extends TLObject { - public static int constructor = 0x1359f4e6; + public static final int constructor = 0x1359f4e6; public InputUser bot; @@ -72299,7 +71062,7 @@ public class TLRPC { } public static class TL_bots_allowSendMessage extends TLObject { - public static int constructor = 0xf132e3ef; + public static final int constructor = 0xf132e3ef; public InputUser bot; @@ -72314,7 +71077,7 @@ public class TLRPC { } public static class TL_bots_invokeWebViewCustomMethod extends TLObject { - public static int constructor = 0x87fc5e7; + public static final int constructor = 0x87fc5e7; public InputUser bot; public String custom_method; @@ -72332,99 +71095,29 @@ public class TLRPC { } } - public static class TL_stories_getChatsToSend extends TLObject { - public static int constructor = 0xa56a8b60; + public static class TL_messages_webPage extends TLObject { + public static final int constructor = 0xfd5e12bd; - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_messages_chats.TLdeserialize(stream, constructor, exception); - } + public WebPage webpage; + public ArrayList chats; + public ArrayList users; - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_stories_boostsStatus extends TLObject { - public static int constructor = 0x66ea1fef; - - public int flags; - public int level; - public int current_level_boosts; - public int boosts; - public int next_level_boosts; - public TL_statsPercentValue premium_audience; - - public static TL_stories_boostsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_boostsStatus.constructor != constructor) { + public static TL_messages_webPage TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messages_webPage.constructor != constructor) { if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_boostsStatus", constructor)); + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_webPage", constructor)); } else { return null; } } - TL_stories_boostsStatus result = new TL_stories_boostsStatus(); + TL_messages_webPage result = new TL_messages_webPage(); result.readParams(stream, exception); return result; } + @Override public void readParams(AbstractSerializedData stream, boolean exception) { - flags = stream.readInt32(exception); - level = stream.readInt32(exception); - current_level_boosts = stream.readInt32(exception); - boosts = stream.readInt32(exception); - if ((flags & 1) != 0) { - next_level_boosts = stream.readInt32(exception); - } - if ((flags & 2) != 0) { - premium_audience = TL_statsPercentValue.TLdeserialize(stream, stream.readInt32(exception), exception); - } - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt32(flags); - stream.writeInt32(level); - stream.writeInt32(current_level_boosts); - stream.writeInt32(boosts); - if ((flags & 1) != 0) { - stream.writeInt32(next_level_boosts); - } - if ((flags & 2) != 0) { - premium_audience.serializeToStream(stream); - } - } - } - - public static abstract class stories_CanApplyBoostResult extends TLObject { - - public static stories_CanApplyBoostResult TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - stories_CanApplyBoostResult result = null; - switch (constructor) { - case 0x712c4655: - result = new TL_stories_canApplyBoostReplace(); - break; - case 0xc3173587: - result = new TL_stories_canApplyBoostOk(); - break; - } - if (result == null && exception) { - throw new RuntimeException(String.format("can't parse magic %x in stories_CanApplyBoostResult", constructor)); - } - if (result != null) { - result.readParams(stream, exception); - } - return result; - } - } - - public static class TL_stories_canApplyBoostReplace extends stories_CanApplyBoostResult { - public static int constructor = 0x712c4655; - - public Peer current_boost; - public ArrayList chats = new ArrayList<>(); - - public void readParams(AbstractSerializedData stream, boolean exception) { - current_boost = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + webpage = WebPage.TLdeserialize(stream, stream.readInt32(exception), exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { if (exception) { @@ -72440,130 +71133,86 @@ public class TLRPC { } 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); + } } + @Override public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - current_boost.serializeToStream(stream); + webpage.serializeToStream(stream); stream.writeInt32(0x1cb5c415); int count = chats.size(); stream.writeInt32(count); for (int a = 0; a < count; a++) { chats.get(a).serializeToStream(stream); } - } - } - - public static class TL_stories_canApplyBoostOk extends stories_CanApplyBoostResult { - public static int constructor = 0xc3173587; - - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - } - } - - public static class TL_stories_getBoostsStatus extends TLObject { - public static int constructor = 0x4c449472; - - public InputPeer peer; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_boostsStatus.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } - - public static class TL_stories_canApplyBoost extends TLObject { - public static int constructor = 0xdb05c1bd; - - public InputPeer peer; - - public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return stories_CanApplyBoostResult.TLdeserialize(stream, constructor, exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - peer.serializeToStream(stream); - } - } - - public static class TL_stories_applyBoost extends TLObject { - public static int constructor = 0xf29d7c2b; - - public InputPeer peer; - - 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); - } - } - - public static class TL_booster extends TLObject { - public static int constructor = 0xe9e6380; - - public long user_id; - public int expires; - - public static TL_booster TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_booster.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_booster", constructor)); - } else { - return null; - } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); } - TL_booster result = new TL_booster(); - result.readParams(stream, exception); - return result; - } - - public void readParams(AbstractSerializedData stream, boolean exception) { - user_id = stream.readInt64(exception); - expires = stream.readInt32(exception); - } - - public void serializeToStream(AbstractSerializedData stream) { - stream.writeInt32(constructor); - stream.writeInt64(user_id); - stream.writeInt32(expires); } } - public static class TL_stories_boostersList extends TLObject { - public static int constructor = 0xf3dd3d1d; + public static class TL_messageActionGiftCode extends MessageAction { + public static int constructor = 0xd2cfdb0e; - public int flags; - public int count; - public ArrayList boosters = new ArrayList<>(); - public String next_offset; - public ArrayList users = new ArrayList<>(); - - public static TL_stories_boostersList TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_stories_boostersList.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_stories_boostersList", constructor)); - } else { - return null; - } - } - TL_stories_boostersList result = new TL_stories_boostersList(); - result.readParams(stream, exception); - return result; - } + public boolean via_giveaway; + public boolean unclaimed; + public Peer boost_peer; + public int months; + public String slug; + + 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); + } + + 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); + } + } + + public static class TL_inputStorePaymentPremiumGiftCode extends InputStorePaymentPurpose { + public static int constructor = 0xa3805f3f; + + public int flags; + public ArrayList users = new ArrayList<>(); + public InputPeer boost_peer; + public String currency; + public long amount; 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) { @@ -72573,14 +71222,495 @@ public class TLRPC { } int count = stream.readInt32(exception); for (int a = 0; a < count; a++) { - TL_booster object = TL_booster.TLdeserialize(stream, stream.readInt32(exception), exception); + InputUser object = InputUser.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return; } - boosters.add(object); + users.add(object); } if ((flags & 1) != 0) { - next_offset = stream.readString(exception); + boost_peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(0x1cb5c415); + int count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + if ((flags & 1) != 0) { + boost_peer.serializeToStream(stream); + } + stream.writeString(currency); + stream.writeInt64(amount); + } + } + + public static class TL_inputStorePaymentPremiumGiveaway extends InputStorePaymentPurpose { + public static int constructor = 0x7c9375e6; + + public int flags; + public boolean only_new_subscribers; + public InputPeer boost_peer; + public ArrayList additional_peers = new ArrayList<>(); + public ArrayList countries_iso2 = new ArrayList<>(); + public long random_id; + public int until_date; + public String currency; + public long amount; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + only_new_subscribers = (flags & 1) != 0; + boost_peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), 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++) { + InputPeer object = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + additional_peers.add(object); + } + } + if ((flags & 4) != 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++) { + countries_iso2.add(stream.readString(exception)); + } + } + random_id = stream.readInt64(exception); + until_date = stream.readInt32(exception); + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = only_new_subscribers ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + boost_peer.serializeToStream(stream); + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = additional_peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + additional_peers.get(a).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = countries_iso2.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(countries_iso2.get(a)); + } + } + stream.writeInt64(random_id); + stream.writeInt32(until_date); + stream.writeString(currency); + stream.writeInt64(amount); + } + } + + public static class TL_inputInvoicePremiumGiftCode extends InputInvoice { + public static int constructor = 0x98986c0d; + + public InputStorePaymentPurpose purpose; + public TL_premiumGiftCodeOption option; + + public void readParams(AbstractSerializedData stream, boolean exception) { + purpose = InputStorePaymentPurpose.TLdeserialize(stream, stream.readInt32(exception), exception); + option = TL_premiumGiftCodeOption.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + purpose.serializeToStream(stream); + option.serializeToStream(stream); + } + } + + public static class TL_messageMediaGiveaway extends MessageMedia { + public static int constructor = 0x58260664; + + public boolean only_new_subscribers; + public ArrayList channels = new ArrayList<>(); + public ArrayList countries_iso2 = new ArrayList<>(); + public int quantity; + public int months; + public int until_date; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + only_new_subscribers = (flags & 1) != 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++) { + channels.add(stream.readInt64(exception)); + } + if ((flags & 2) != 0) { + magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + countries_iso2.add(stream.readString(exception)); + } + } + quantity = stream.readInt32(exception); + months = stream.readInt32(exception); + until_date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = only_new_subscribers ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(0x1cb5c415); + int count = channels.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(channels.get(a)); + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + count = countries_iso2.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(countries_iso2.get(a)); + } + } + stream.writeInt32(quantity); + stream.writeInt32(months); + stream.writeInt32(until_date); + } + } + + public static class TL_premiumGiftCodeOption extends TLObject { + public static int constructor = 0x257e962b; + + public int flags; + public int users; + public int months; + public String store_product; + public int store_quantity; + public String currency; + public long amount; + + public static TL_premiumGiftCodeOption TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_premiumGiftCodeOption.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_premiumGiftCodeOption", constructor)); + } else { + return null; + } + } + TL_premiumGiftCodeOption result = new TL_premiumGiftCodeOption(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + users = stream.readInt32(exception); + months = stream.readInt32(exception); + if ((flags & 1) != 0) { + store_product = stream.readString(exception); + } + if ((flags & 2) != 0) { + store_quantity = stream.readInt32(exception); + } + currency = stream.readString(exception); + amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(users); + stream.writeInt32(months); + if ((flags & 1) != 0) { + stream.writeString(store_product); + } + if ((flags & 2) != 0) { + stream.writeInt32(store_quantity); + } + stream.writeString(currency); + stream.writeInt64(amount); + } + } + + public static class TL_payments_getPremiumGiftCodeOptions extends TLObject { + public static int constructor = 0x2757ba54; + + public int flags; + public InputPeer boost_peer; + + 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_premiumGiftCodeOption object = TL_premiumGiftCodeOption.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) { + boost_peer.serializeToStream(stream); + } + } + } + + public static class TL_payments_checkGiftCode extends TLObject { + public static int constructor = 0x8e51b4c1; + + public String slug; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_payments_checkedGiftCode.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + } + } + + public static class TL_payments_applyGiftCode extends TLObject { + public static int constructor = 0xf6e26854; + + public String slug; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + } + } + + public static class TL_payments_giveawayInfoResults extends payments_GiveawayInfo { + public static int constructor = 0xcd5570; + + public int flags; + public boolean winner; + public boolean refunded; + public int start_date; + public String gift_code_slug; + public int finish_date; + public int winners_count; + public int activated_count; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + winner = (flags & 1) != 0; + refunded = (flags & 2) != 0; + start_date = stream.readInt32(exception); + if ((flags & 1) != 0) { + gift_code_slug = stream.readString(exception); + } + finish_date = stream.readInt32(exception); + winners_count = stream.readInt32(exception); + activated_count = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = winner ? (flags | 1) : (flags &~ 1); + flags = refunded ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt32(start_date); + if ((flags & 1) != 0) { + stream.writeString(gift_code_slug); + } + stream.writeInt32(finish_date); + stream.writeInt32(winners_count); + stream.writeInt32(activated_count); + } + } + + public static class TL_payments_giveawayInfo extends payments_GiveawayInfo { + public static int constructor = 0x4367daa0; + + public int flags; + public boolean participating; + public boolean preparing_results; + public int start_date; + public int joined_too_early_date; + public long admin_disallowed_chat_id; + public String disallowed_country; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + participating = (flags & 1) != 0; + preparing_results = (flags & 8) != 0; + start_date = stream.readInt32(exception); + if ((flags & 2) != 0) { + joined_too_early_date = stream.readInt32(exception); + } + if ((flags & 4) != 0) { + admin_disallowed_chat_id = stream.readInt64(exception); + } + if ((flags & 16) != 0) { + disallowed_country = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = participating ? (flags | 1) : (flags &~ 1); + flags = preparing_results ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeInt32(start_date); + if ((flags & 2) != 0) { + stream.writeInt32(joined_too_early_date); + } + if ((flags & 4) != 0) { + stream.writeInt64(admin_disallowed_chat_id); + } + if ((flags & 16) != 0) { + stream.writeString(disallowed_country); + } + } + } + + public static abstract class payments_GiveawayInfo extends TLObject { + + public static payments_GiveawayInfo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + payments_GiveawayInfo result = null; + switch (constructor) { + case 0xcd5570: + result = new TL_payments_giveawayInfoResults(); + break; + case 0x4367daa0: + result = new TL_payments_giveawayInfo(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in payments_GiveawayInfo", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_payments_getGiveawayInfo extends TLObject { + public static int constructor = 0xf4239425; + + public InputPeer peer; + public int msg_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return payments_GiveawayInfo.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + } + } + + public static class TL_payments_checkedGiftCode extends TLObject { + public static int constructor = 0xb722f158; + public static final long NO_USER_ID = -1L; //custom + + public int flags; + public boolean via_giveaway; + public Peer from_id; + public int giveaway_msg_id; + public long to_id = NO_USER_ID; + public int date; + public int months; + public int used_date; + public TL_stories.TL_boost boost; //custom + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_payments_checkedGiftCode TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_payments_checkedGiftCode.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_payments_checkedGiftCode", constructor)); + } else { + return null; + } + } + TL_payments_checkedGiftCode result = new TL_payments_checkedGiftCode(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + via_giveaway = (flags & 4) != 0; + from_id = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 8) != 0) { + giveaway_msg_id = stream.readInt32(exception); + } + if ((flags & 1) != 0) { + to_id = stream.readInt64(exception); + } + date = stream.readInt32(exception); + months = stream.readInt32(exception); + if ((flags & 2) != 0) { + used_date = 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++) { + Chat object = Chat.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + chats.add(object); } magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -72601,16 +71731,25 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = via_giveaway ? (flags | 4) : (flags &~ 4); stream.writeInt32(flags); - stream.writeInt32(count); - stream.writeInt32(0x1cb5c415); - int count = boosters.size(); - stream.writeInt32(count); - for (int a = 0; a < count; a++) { - boosters.get(a).serializeToStream(stream); + from_id.serializeToStream(stream); + if ((flags & 8) != 0) { + stream.writeInt32(giveaway_msg_id); } if ((flags & 1) != 0) { - stream.writeString(next_offset); + stream.writeInt64(to_id); + } + stream.writeInt32(date); + stream.writeInt32(months); + if ((flags & 2) != 0) { + stream.writeInt32(used_date); + } + stream.writeInt32(0x1cb5c415); + int count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); } stream.writeInt32(0x1cb5c415); count = users.size(); @@ -72621,29 +71760,37 @@ public class TLRPC { } } - public static class TL_stories_getBoostersList extends TLObject { - public static int constructor = 0x337ef980; + public static class TL_payments_launchPrepaidGiveaway extends TLObject { + public static int constructor = 0x5ff58f20; public InputPeer peer; - public String offset; - public int limit; + public long giveaway_id; + public InputStorePaymentPurpose purpose; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { - return TL_stories_boostersList.TLdeserialize(stream, constructor, exception); + return Updates.TLdeserialize(stream, constructor, exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); peer.serializeToStream(stream); - stream.writeString(offset); - stream.writeInt32(limit); + stream.writeInt64(giveaway_id); + purpose.serializeToStream(stream); + } + } + + public static class TL_messageActionGiveawayLaunch extends MessageAction { + public static int constructor = 0x332ba9ed; + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); } } //functions public static class Vector extends TLObject { - public static int constructor = 0x1cb5c415; + public static final int constructor = 0x1cb5c415; public ArrayList objects = new ArrayList<>(); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_chatlists.java b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_chatlists.java new file mode 100644 index 000000000..4c76f6d96 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_chatlists.java @@ -0,0 +1,744 @@ +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_chatlists { + public static class TL_inputChatlistDialogFilter extends TLObject { + public static final int constructor = 0xf3e0da33; + + public int filter_id; + + public static TL_inputChatlistDialogFilter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_inputChatlistDialogFilter.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_inputChatlistDialogFilter", constructor)); + } else { + return null; + } + } + TL_inputChatlistDialogFilter result = new TL_inputChatlistDialogFilter(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + filter_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(filter_id); + } + } + + public static class TL_chatlists_exportedChatlistInvite extends TLObject { + public static final int constructor = 0x10e6e3a6; + + public TLRPC.DialogFilter filter; + public TL_exportedChatlistInvite invite; + + public static TL_chatlists_exportedChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_chatlists_exportedChatlistInvite.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_exportedChatlistInvite", constructor)); + } else { + return null; + } + } + TL_chatlists_exportedChatlistInvite result = new TL_chatlists_exportedChatlistInvite(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + filter = TLRPC.DialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); + invite = TL_exportedChatlistInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + filter.serializeToStream(stream); + invite.serializeToStream(stream); + } + } + + public static class TL_exportedChatlistInvite extends TLObject { + public static final int constructor = 0xc5181ac; + + public int flags; + public boolean revoked; + public String title; + public String url; + public ArrayList peers = new ArrayList<>(); + + public static TL_exportedChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_exportedChatlistInvite.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_exportedChatlistInvite", constructor)); + } else { + return null; + } + } + TL_exportedChatlistInvite result = new TL_exportedChatlistInvite(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + revoked = (flags & 1) != 0; + title = stream.readString(exception); + url = 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.Peer object = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + peers.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = revoked ? (flags | 1) : (flags & ~1); + stream.writeInt32(flags); + stream.writeString(title); + stream.writeString(url); + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_exportedInvites extends TLObject { + public static final int constructor = 0x10ab6dc7; + + public ArrayList invites = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_chatlists_exportedInvites TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_chatlists_exportedInvites.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_exportedInvites", constructor)); + } else { + return null; + } + } + TL_chatlists_exportedInvites result = new TL_chatlists_exportedInvites(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_exportedChatlistInvite object = TL_exportedChatlistInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + invites.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.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(0x1cb5c415); + int count = invites.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + invites.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static abstract class chatlist_ChatlistInvite extends TLObject { + + public static chatlist_ChatlistInvite TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + chatlist_ChatlistInvite result = null; + switch (constructor) { + case 0xfa87f659: + result = new TL_chatlists_chatlistInviteAlready(); + break; + case 0x1dcd839d: + result = new TL_chatlists_chatlistInvite(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in chatlist_ChatlistInvite", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_chatlists_chatlistInviteAlready extends chatlist_ChatlistInvite { + public static final int constructor = 0xfa87f659; + + public int filter_id; + public ArrayList missing_peers = new ArrayList<>(); + public ArrayList already_peers = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + filter_id = stream.readInt32(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TLRPC.Peer object = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + missing_peers.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.Peer object = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + already_peers.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.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(filter_id); + stream.writeInt32(0x1cb5c415); + int count = missing_peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + missing_peers.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_chatlistInvite extends chatlist_ChatlistInvite { + public static final int constructor = 0x1dcd839d; + + public int flags; + public String title; + public String emoticon; + public ArrayList peers = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + title = stream.readString(exception); + if ((flags & 1) > 0) { + emoticon = 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.Peer object = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + peers.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.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.writeString(title); + if ((flags & 1) > 0) { + stream.writeString(emoticon); + } + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_chatlistUpdates extends TLObject { + public static final int constructor = 0x93bd878d; + + public ArrayList missing_peers = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_chatlists_chatlistUpdates TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_chatlists_chatlistUpdates.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_chatlists_chatlistUpdates", constructor)); + } else { + return null; + } + } + TL_chatlists_chatlistUpdates result = new TL_chatlists_chatlistUpdates(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TLRPC.Peer object = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + missing_peers.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.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(0x1cb5c415); + int count = missing_peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + missing_peers.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_exportChatlistInvite extends TLObject { + public static final int constructor = 0x8472478e; + + public TL_inputChatlistDialogFilter chatlist; + public String title; + public ArrayList peers = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_chatlists_exportedChatlistInvite.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + stream.writeString(title); + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_deleteExportedInvite extends TLObject { + public static final int constructor = 0x719c5c5e; + + public TL_inputChatlistDialogFilter chatlist; + public String slug; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + stream.writeString(slug); + } + } + + public static class TL_chatlists_editExportedInvite extends TLObject { + public static final int constructor = 0x653db63d; + + public int flags; + public boolean revoked; + public TL_inputChatlistDialogFilter chatlist; + public String slug; + public String title; + public ArrayList peers = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_exportedChatlistInvite.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = revoked ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + chatlist.serializeToStream(stream); + stream.writeString(slug); + if ((flags & 2) != 0) { + stream.writeString(title); + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } + } + + public static class TL_chatlists_getExportedInvites extends TLObject { + public static final int constructor = 0xce03da83; + + public TL_inputChatlistDialogFilter chatlist; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_chatlists_exportedInvites.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + } + } + + public static class TL_chatlists_checkChatlistInvite extends TLObject { + public static final int constructor = 0x41c10fff; + + public String slug; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return chatlist_ChatlistInvite.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + } + } + + public static class TL_chatlists_joinChatlistInvite extends TLObject { + public static final int constructor = 0xa6b1e39a; + + public String slug; + public ArrayList peers = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_getChatlistUpdates extends TLObject { + public static final int constructor = 0x89419521; + + public TL_inputChatlistDialogFilter chatlist; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_chatlists_chatlistUpdates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + } + } + + public static class TL_chatlists_joinChatlistUpdates extends TLObject { + public static final int constructor = 0xe089f8f5; + + public TL_inputChatlistDialogFilter chatlist; + public ArrayList peers = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } + + public static class TL_chatlists_hideChatlistUpdates extends TLObject { + public static final int constructor = 0x66e486fb; + + public TL_inputChatlistDialogFilter chatlist; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + } + } + + public static class TL_chatlists_getLeaveChatlistSuggestions extends TLObject { + public static final int constructor = 0xfdbcd714; + + public TL_inputChatlistDialogFilter chatlist; + + 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++) { + TLRPC.Peer object = TLRPC.Peer.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); + chatlist.serializeToStream(stream); + } + } + + public static class TL_chatlists_leaveChatlist extends TLObject { + public static final int constructor = 0x74fae13a; + + public TL_inputChatlistDialogFilter chatlist; + public ArrayList peers = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + chatlist.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = peers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peers.get(a).serializeToStream(stream); + } + } + } +} 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 new file mode 100644 index 000000000..dbf55895c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/tl/TL_stories.java @@ -0,0 +1,2462 @@ +package org.telegram.tgnet.tl; + +import org.telegram.tgnet.AbstractSerializedData; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.TLRPC.TL_statsPercentValue; +import org.telegram.ui.Stories.recorder.StoryPrivacyBottomSheet; + +import java.util.ArrayList; + +public class TL_stories { + public static class TL_stories_storyViews extends TLObject { + public static final int constructor = 0xde9eed1d; + + public ArrayList views = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_stories_storyViews TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_stories_storyViews.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_stories_storyViews", constructor)); + } else { + return null; + } + } + TL_stories_storyViews result = new TL_stories_storyViews(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + StoryViews object = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + views.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(0x1cb5c415); + int count = views.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + views.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_storyView extends TLObject { + public static final int constructor = 0xb0bdeac5; + + public int flags; + public boolean blocked; + public boolean blocked_my_stories_from; + public long user_id; + public int date; + public TLRPC.Reaction reaction; + + public static TL_storyView TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_storyView.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_storyView", constructor)); + } else { + return null; + } + } + TL_storyView result = new TL_storyView(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + blocked = (flags & 1) != 0; + blocked_my_stories_from = (flags & 2) != 0; + user_id = stream.readInt64(exception); + date = stream.readInt32(exception); + if ((flags & 4) != 0) { + reaction = TLRPC.Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = blocked ? (flags | 1) : (flags &~ 1); + flags = blocked_my_stories_from ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt64(user_id); + stream.writeInt32(date); + if ((flags & 4) != 0) { + reaction.serializeToStream(stream); + } + } + } + + public static abstract class PeerStories extends TLObject { + + public int flags; + public TLRPC.Peer peer; + public int max_read_id; + public ArrayList stories = new ArrayList<>(); + + public static PeerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + PeerStories result = null; + switch (constructor) { + case 0x9a35e999: + result = new TL_peerStories(); + break; + case 0x8611a200: + result = new TL_peerStories_layer162(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in PeerStories", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_peerStories extends PeerStories { + public static final int constructor = 0x9a35e999; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 1) != 0) { + max_read_id = stream.readInt32(exception); + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stories.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + peer.serializeToStream(stream); + if ((flags & 1) != 0) { + stream.writeInt32(max_read_id); + } + stream.writeInt32(0x1cb5c415); + int count = stories.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stories.get(a).serializeToStream(stream); + } + } + } + + public static class TL_peerStories_layer162 extends TL_peerStories { + public static final int constructor = 0x8611a200; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + long user_id = stream.readInt64(exception); + peer = new TLRPC.TL_peerUser(); + peer.user_id = user_id; + if ((flags & 1) != 0) { + max_read_id = stream.readInt32(exception); + } + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stories.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(peer.user_id); + if ((flags & 1) != 0) { + stream.writeInt32(max_read_id); + } + stream.writeInt32(0x1cb5c415); + int count = stories.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stories.get(a).serializeToStream(stream); + } + } + } + + public static class TL_stories_peerStories extends TLObject { + public static final int constructor = 0xcae68768; + + public PeerStories stories; + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_stories_peerStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_stories_peerStories.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_stories_peerStories", constructor)); + } else { + return null; + } + } + TL_stories_peerStories result = new TL_stories_peerStories(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + stories = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + 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); + stories.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static abstract class stories_AllStories extends TLObject { + + public static stories_AllStories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + stories_AllStories result = null; + switch (constructor) { + case 0x1158fe3e: + result = new TL_stories_allStoriesNotModified(); + break; + case 0x6efc5e81: + result = new TL_stories_allStories(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in stories_AllStories", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_stories_allStoriesNotModified extends stories_AllStories { + public static final int constructor = 0x1158fe3e; + + public int flags; + public String state; + public TL_storiesStealthMode stealth_mode; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + state = stream.readString(exception); + stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeString(state); + stealth_mode.serializeToStream(stream); + } + } + + public static class TL_stories_allStories extends stories_AllStories { + public static final int constructor = 0x6efc5e81; + + public int flags; + public boolean has_more; + public int count; + public String state; + public ArrayList peer_stories = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + public TL_storiesStealthMode stealth_mode; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + has_more = (flags & 1) != 0; + count = stream.readInt32(exception); + state = 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++) { + PeerStories object = PeerStories.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + peer_stories.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.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); + } + stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = has_more ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt32(count); + stream.writeString(state); + stream.writeInt32(0x1cb5c415); + int count = peer_stories.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peer_stories.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + stealth_mode.serializeToStream(stream); + } + } + + public static class TL_stories_canSendStory extends TLObject { + public static final int constructor = 0xc7dfdfdd; + + public TLRPC.InputPeer peer; + + 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); + } + } + + public static class TL_stories_sendStory extends TLObject { + public static final int constructor = 0xbcb73644; + + public int flags; + public boolean pinned; + public boolean noforwards; + public TLRPC.InputPeer peer; + public TLRPC.InputMedia media; + public ArrayList media_areas = new ArrayList<>(); + public String caption; + public ArrayList entities = new ArrayList<>(); + public ArrayList privacy_rules = new ArrayList<>(); + public long random_id; + public int period; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 4) : (flags &~ 4); + flags = noforwards ? (flags | 16) : (flags &~ 16); + stream.writeInt32(flags); + peer.serializeToStream(stream); + media.serializeToStream(stream); + if ((flags & 32) != 0) { + stream.writeInt32(0x1cb5c415); + int count = media_areas.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + media_areas.get(a).serializeToStream(stream); + } + } + if ((flags & 1) != 0) { + stream.writeString(caption); + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + stream.writeInt32(0x1cb5c415); + int count = privacy_rules.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + privacy_rules.get(a).serializeToStream(stream); + } + stream.writeInt64(random_id); + if ((flags & 8) != 0) { + stream.writeInt32(period); + } + } + } + + public static class TL_stories_deleteStories extends TLObject { + public static final int constructor = 0xae59db5f; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + + 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++) { + vector.objects.add(stream.readInt32(exception)); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } + + public static class TL_stories_togglePinned extends TLObject { + public static final int constructor = 0x9a75a1ef; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + public boolean pinned; + + 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++) { + vector.objects.add(stream.readInt32(exception)); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + stream.writeBool(pinned); + } + } + + public static class TL_stories_editStory extends TLObject { + public static final int constructor = 0xb583ba46; + + public int flags; + public TLRPC.InputPeer peer; + public int id; + public TLRPC.InputMedia media; + public ArrayList media_areas = new ArrayList<>(); + public String caption; + public ArrayList entities = new ArrayList<>(); + public ArrayList privacy_rules = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(id); + if ((flags & 1) != 0) { + media.serializeToStream(stream); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = media_areas.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + media_areas.get(a).serializeToStream(stream); + } + } + if ((flags & 2) != 0) { + stream.writeString(caption); + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = privacy_rules.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + privacy_rules.get(a).serializeToStream(stream); + } + } + } + } + + public static class TL_stories_getAllStories extends TLObject { + public static final int constructor = 0xeeb0d625; + + public int flags; + public boolean include_hidden; + public boolean next; + public String state; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return stories_AllStories.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = next ? (flags | 2) : (flags &~ 2); + flags = include_hidden ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(state); + } + } + } + + public static class TL_stories_togglePeerStoriesHidden extends TLObject { + public static final int constructor = 0xbd0415c4; + + public TLRPC.InputPeer peer; + public boolean hidden; + + 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.writeBool(hidden); + } + } + + public static class TL_stories_stories extends TLObject { + public static final int constructor = 0x5dd8c3c8; + + public int count; + public ArrayList stories = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_stories_stories TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_stories_stories.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_stories_stories", constructor)); + } else { + return null; + } + } + TL_stories_stories result = new TL_stories_stories(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean 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++) { + StoryItem object = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + stories.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.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(count); + stream.writeInt32(0x1cb5c415); + int count = stories.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stories.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_stories_getPeerStories extends TLObject { + public static final int constructor = 0x2c4ada50; + + public TLRPC.InputPeer peer; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_peerStories.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } + + public static class TL_updateStory extends TLRPC.Update { + public static final int constructor = 0x75b3b798; + + public TLRPC.Peer peer; + public StoryItem story; + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + story = StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + story.serializeToStream(stream); + } + } + + public static class TL_stories_getPinnedStories extends TLObject { + public static final int constructor = 0x5821a5dc; + + public TLRPC.InputPeer peer; + public int offset_id; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_stories.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(offset_id); + stream.writeInt32(limit); + } + } + + public static class TL_stories_getStoriesArchive extends TLObject { + public static final int constructor = 0xb4352016; + + public TLRPC.InputPeer peer; + public int offset_id; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_stories.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(offset_id); + stream.writeInt32(limit); + } + } + + public static class TL_updateReadStories extends TLRPC.Update { + public static final int constructor = 0xf74e932b; + + public TLRPC.Peer peer; + public int max_id; + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + max_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(max_id); + } + } + + public static class TL_stories_storyViewsList extends TLObject { + public static final int constructor = 0x46e9b9ec; + + public int flags; + public int count; + public int reactions_count; + public ArrayList views = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + public String next_offset = ""; + + public static TL_stories_storyViewsList TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_stories_storyViewsList.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_stories_storyViewsList", constructor)); + } else { + return null; + } + } + TL_stories_storyViewsList result = new TL_stories_storyViewsList(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + count = stream.readInt32(exception); + reactions_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++) { + TL_storyView object = TL_storyView.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + views.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); + } + if ((flags & 1) != 0) { + next_offset = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(count); + stream.writeInt32(reactions_count); + stream.writeInt32(0x1cb5c415); + int count = views.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + views.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + if ((flags & 1) != 0) { + stream.writeString(next_offset); + } + } + } + + public static class TL_stories_readStories extends TLObject { + public static final int constructor = 0xa556dac8; + + public TLRPC.InputPeer peer; + public int max_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++) { + vector.objects.add(stream.readInt32(exception)); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(max_id); + } + } + + public static class TL_stories_getStoryViewsList extends TLObject { + public static final int constructor = 0x7ed23c57; + + public int flags; + public boolean just_contacts; + public boolean reactions_first; + public TLRPC.InputPeer peer; + public String q; + public int id; + public String offset; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_storyViewsList.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = just_contacts ? (flags | 1) : (flags &~ 1); + flags = reactions_first ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + peer.serializeToStream(stream); + if ((flags & 2) != 0) { + stream.writeString(q); + } + stream.writeInt32(id); + stream.writeString(offset); + stream.writeInt32(limit); + } + } + + public static class TL_stories_getStoriesByID extends TLObject { + public static final int constructor = 0x5774ca74; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_stories.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } + + public static class TL_stories_getStoriesViews extends TLObject { + public static final int constructor = 0x28e16cc8; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_stories_storyViews.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + } + } + + public static class TL_exportedStoryLink extends TLObject { + public static final int constructor = 0x3fc9053b; + + public String link; + + public static TL_exportedStoryLink TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_exportedStoryLink.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_exportedStoryLink", constructor)); + } else { + return null; + } + } + TL_exportedStoryLink result = new TL_exportedStoryLink(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + link = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(link); + } + } + + public static class TL_stories_exportStoryLink extends TLObject { + public static final int constructor = 0x7b8def20; + + public TLRPC.InputPeer peer; + public int id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_exportedStoryLink.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(id); + } + } + + public static class TL_stories_report extends TLObject { + public static final int constructor = 0x1923fa8c; + + public TLRPC.InputPeer peer; + public ArrayList id = new ArrayList<>(); + public TLRPC.ReportReason reason; + public String message; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(id.get(a)); + } + reason.serializeToStream(stream); + stream.writeString(message); + } + } + + public static class TL_stories_getAllReadPeerStories extends TLObject { + public static final int constructor = 0x9b5ae7f9; + + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_stories_getPeerMaxIDs extends TLObject { + public static final int constructor = 0x535983c3; + + public ArrayList id = new ArrayList<>(); + + 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++) { + vector.objects.add(stream.readInt32(exception)); + } + return vector; + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(0x1cb5c415); + int count = id.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + id.get(a).serializeToStream(stream); + } + } + } + + public static class TL_updateStoriesStealthMode extends TLRPC.Update { + public static final int constructor = 0x2c084dc1; + + public TL_storiesStealthMode stealth_mode; + + public void readParams(AbstractSerializedData stream, boolean exception) { + stealth_mode = TL_storiesStealthMode.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stealth_mode.serializeToStream(stream); + } + } + + public static class TL_storiesStealthMode extends TLObject { + public static final int constructor = 0x712e27fd; + + public int flags; + public int active_until_date; + public int cooldown_until_date; + + public static TL_storiesStealthMode TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_storiesStealthMode.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_storiesStealthMode", constructor)); + } else { + return null; + } + } + TL_storiesStealthMode result = new TL_storiesStealthMode(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + active_until_date = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + cooldown_until_date = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(active_until_date); + } + if ((flags & 2) != 0) { + stream.writeInt32(cooldown_until_date); + } + } + } + + public static class TL_stories_activateStealthMode extends TLObject { + public static final int constructor = 0x57bbd166; + + public int flags; + public boolean past; + public boolean future; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = past ? (flags | 1) : (flags &~ 1); + flags = future ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + } + } + + public static class TL_stories_sendReaction extends TLObject { + public static final int constructor = 0x7fd736b2; + + public int flags; + public boolean add_to_recent; + public TLRPC.InputPeer peer; + public int story_id; + public TLRPC.Reaction reaction; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = add_to_recent ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(story_id); + reaction.serializeToStream(stream); + } + } + + public static class TL_stories_getChatsToSend extends TLObject { + public static final int constructor = 0xa56a8b60; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TLRPC.TL_messages_chats.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_myBoost extends TLObject { + public static int constructor = 0xc448415c; + + public int flags; + public int slot; + public TLRPC.Peer peer; + public int date; + public int expires; + public int cooldown_until_date; + + public static TL_myBoost TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_myBoost.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_myBoost", constructor)); + } else { + return null; + } + } + TL_myBoost result = new TL_myBoost(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + slot = stream.readInt32(exception); + if ((flags & 1) != 0) { + peer = TLRPC.Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + } + date = stream.readInt32(exception); + expires = stream.readInt32(exception); + if ((flags & 2) != 0) { + cooldown_until_date = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(slot); + if ((flags & 1) != 0) { + peer.serializeToStream(stream); + } + stream.writeInt32(date); + stream.writeInt32(expires); + if ((flags & 2) != 0) { + stream.writeInt32(cooldown_until_date); + } + } + } + + public static class TL_premium_myBoosts extends TLObject { + public static int constructor = 0x9ae228e2; + + public ArrayList my_boosts = new ArrayList<>(); + public ArrayList chats = new ArrayList<>(); + public ArrayList users = new ArrayList<>(); + + public static TL_premium_myBoosts TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_premium_myBoosts.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_premium_myBoosts", constructor)); + } else { + return null; + } + } + TL_premium_myBoosts result = new TL_premium_myBoosts(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + TL_myBoost object = TL_myBoost.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + my_boosts.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.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(0x1cb5c415); + int count = my_boosts.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + my_boosts.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = chats.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + chats.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_premium_getMyBoosts extends TLObject { + public static int constructor = 0xbe77b4a; + + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_premium_myBoosts.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_premium_boostsStatus extends TLObject { + public static int constructor = 0x4959427a; + + public int flags; + public boolean my_boost; + public int level; + public int current_level_boosts; + public int boosts; + public int gift_boosts; + public int next_level_boosts; + public TL_statsPercentValue premium_audience; + public String boost_url; + public ArrayList prepaid_giveaways = new ArrayList<>(); + public ArrayList my_boost_slots = new ArrayList<>(); + + public static TL_premium_boostsStatus TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_premium_boostsStatus.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_premium_boostsStatus", constructor)); + } else { + return null; + } + } + TL_premium_boostsStatus result = new TL_premium_boostsStatus(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + my_boost = (flags & 4) != 0; + level = stream.readInt32(exception); + current_level_boosts = stream.readInt32(exception); + boosts = stream.readInt32(exception); + if ((flags & 16) != 0) { + gift_boosts = stream.readInt32(exception); + } + if ((flags & 1) != 0) { + next_level_boosts = stream.readInt32(exception); + } + if ((flags & 2) != 0) { + premium_audience = TL_statsPercentValue.TLdeserialize(stream, stream.readInt32(exception), exception); + } + boost_url = stream.readString(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++) { + TL_prepaidGiveaway object = TL_prepaidGiveaway.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + prepaid_giveaways.add(object); + } + } + if ((flags & 4) != 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++) { + my_boost_slots.add(stream.readInt32(exception)); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = my_boost ? (flags | 4) : (flags &~ 4); + stream.writeInt32(flags); + stream.writeInt32(level); + stream.writeInt32(current_level_boosts); + stream.writeInt32(boosts); + if ((flags & 16) != 0) { + stream.writeInt32(gift_boosts); + } + if ((flags & 1) != 0) { + stream.writeInt32(next_level_boosts); + } + if ((flags & 2) != 0) { + premium_audience.serializeToStream(stream); + } + stream.writeString(boost_url); + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = prepaid_giveaways.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + prepaid_giveaways.get(a).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = my_boost_slots.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(my_boost_slots.get(a)); + } + } + } + } + + public static class TL_premium_getBoostsStatus extends TLObject { + public static int constructor = 0x42f1f61; + + public TLRPC.InputPeer peer; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_premium_boostsStatus.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + } + } + + public static class TL_premium_applyBoost extends TLObject { + public static int constructor = 0x6b7da746; + + public int flags; + public ArrayList slots = new ArrayList<>(); + public TLRPC.InputPeer peer; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_premium_myBoosts.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = slots.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt32(slots.get(a)); + } + } + peer.serializeToStream(stream); + } + } + + public static class TL_boost extends TLObject { + public static int constructor = 0x2a1c8c71; + public static final long NO_USER_ID = -1L; //custom + + public int flags; + public boolean gift; + public boolean giveaway; + public boolean unclaimed; + public String id; + public long user_id = NO_USER_ID; + public int giveaway_msg_id; + public int date; + public int expires; + public String used_gift_slug; + public int multiplier; + + public static TL_boost TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_boost.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_boost", constructor)); + } else { + return null; + } + } + TL_boost result = new TL_boost(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + gift = (flags & 2) != 0; + giveaway = (flags & 4) != 0; + unclaimed = (flags & 8) != 0; + id = stream.readString(exception); + if ((flags & 1) != 0) { + user_id = stream.readInt64(exception); + } + if ((flags & 4) != 0) { + giveaway_msg_id = stream.readInt32(exception); + } + date = stream.readInt32(exception); + expires = stream.readInt32(exception); + if ((flags & 16) != 0) { + used_gift_slug = stream.readString(exception); + } + if ((flags & 32) != 0) { + multiplier = stream.readInt32(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = gift ? (flags | 2) : (flags &~ 2); + flags = giveaway ? (flags | 4) : (flags &~ 4); + flags = unclaimed ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeString(id); + if ((flags & 1) != 0) { + stream.writeInt64(user_id); + } + if ((flags & 4) != 0) { + stream.writeInt32(giveaway_msg_id); + } + stream.writeInt32(date); + stream.writeInt32(expires); + if ((flags & 16) != 0) { + stream.writeString(used_gift_slug); + } + if ((flags & 32) != 0) { + stream.writeInt32(multiplier); + } + } + } + + public static class TL_premium_boostsList extends TLObject { + public static int constructor = 0x86f8613c; + + public int flags; + public int count; + public ArrayList boosts = new ArrayList<>(); + public String next_offset; + public ArrayList users = new ArrayList<>(); + + public static TL_premium_boostsList TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_premium_boostsList.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_premium_boostsList", constructor)); + } else { + return null; + } + } + TL_premium_boostsList result = new TL_premium_boostsList(); + result.readParams(stream, exception); + return result; + } + + 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++) { + TL_boost object = TL_boost.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + boosts.add(object); + } + 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 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.writeInt32(count); + stream.writeInt32(0x1cb5c415); + int count = boosts.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + boosts.get(a).serializeToStream(stream); + } + if ((flags & 1) != 0) { + stream.writeString(next_offset); + } + stream.writeInt32(0x1cb5c415); + count = users.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + users.get(a).serializeToStream(stream); + } + } + } + + public static class TL_premium_getBoostsList extends TLObject { + public static int constructor = 0x60f67660; + + public int flags; + public boolean gifts; + public TLRPC.InputPeer peer; + public String offset; + public int limit; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_premium_boostsList.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = gifts ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeString(offset); + stream.writeInt32(limit); + } + } + + public static abstract class StoryItem extends TLObject { + + public int flags; + public boolean pinned; + public boolean isPublic; + public boolean close_friends; + public boolean contacts; + public boolean selected_contacts; + public boolean noforwards; + public boolean min; + public boolean out; + public int id; + public int date; + public int expire_date; + public String caption; + public boolean edited; + public ArrayList entities = new ArrayList<>(); + public TLRPC.MessageMedia media; + public ArrayList media_areas = new ArrayList(); + public ArrayList privacy = new ArrayList<>(); + public StoryViews views; + public TLRPC.Reaction sent_reaction; + public long lastUpdateTime; //custom + public String attachPath; //custom + public String firstFramePath; //custom + public long dialogId;// custom + public boolean justUploaded;// custom + public int messageId;//custom + public int messageType;//custom + public int fileReference; + public String detectedLng; //custom + public String translatedLng; //custom + public boolean translated; //custom + public TLRPC.TL_textWithEntities translatedText; //custom + public StoryPrivacyBottomSheet.StoryPrivacy parsedPrivacy; //custom + + public static StoryItem TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StoryItem result = null; + switch (constructor) { + case 0x44c457ce: + result = new TL_storyItem(); + break; + case 0x562aa637: + result = new TL_storyItem_layer160(); + break; + case 0x51e6ee4f: + result = new TL_storyItemDeleted(); + break; + case 0xffadc913: + result = new TL_storyItemSkipped(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StoryItem", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static abstract class StoryViews extends TLObject { + + public int flags; + public int views_count; + public int reactions_count; + public ArrayList recent_viewers = new ArrayList<>(); + public boolean has_viewers; + public int forwards_count; + public ArrayList reactions = new ArrayList<>(); + + public static StoryViews TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + StoryViews result = null; + switch (constructor) { + case 0xd36760cf: + result = new TL_storyViews_layer160(); + break; + case 0xc64c0b97: + result = new TL_storyViews_layer161(); + break; + case 0x8d595cd6: + result = new TL_storyViews(); + break; + + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in StoryViews", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_storyViews_layer160 extends StoryViews { + public static final int constructor = 0xd36760cf; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + views_count = stream.readInt32(exception); + if ((flags & 1) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + recent_viewers.add(stream.readInt64(exception)); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(views_count); + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = recent_viewers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_viewers.get(a)); + } + } + } + } + + public static class TL_storyViews_layer161 extends StoryViews { + public static final int constructor = 0xc64c0b97; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + views_count = stream.readInt32(exception); + reactions_count = stream.readInt32(exception); + if ((flags & 1) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + recent_viewers.add(stream.readInt64(exception)); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt32(views_count); + stream.writeInt32(reactions_count); + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = recent_viewers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_viewers.get(a)); + } + } + } + } + + public static class TL_storyViews extends StoryViews { + public static final int constructor = 0x8d595cd6; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + has_viewers = (flags & 2) != 0; + views_count = stream.readInt32(exception); + if ((flags & 4) != 0) { + forwards_count = stream.readInt32(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++) { + TLRPC.ReactionCount object = TLRPC.ReactionCount.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + reactions.add(object); + } + } + if ((flags & 16) != 0) { + reactions_count = stream.readInt32(exception); + } + if ((flags & 1) != 0) { + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + recent_viewers.add(stream.readInt64(exception)); + } + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = has_viewers ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt32(views_count); + if ((flags & 4) != 0) { + stream.writeInt32(forwards_count); + } + if ((flags & 8) != 0) { + stream.writeInt32(0x1cb5c415); + int count = reactions.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + reactions.get(a).serializeToStream(stream); + } + } + if ((flags & 16) != 0) { + stream.writeInt32(reactions_count); + } + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = recent_viewers.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeInt64(recent_viewers.get(a)); + } + } + } + } + + public static class TL_storyItem extends StoryItem { + public static final int constructor = 0x44c457ce; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 32) != 0; + isPublic = (flags & 128) != 0; + close_friends = (flags & 256) != 0; + min = (flags & 512) != 0; + noforwards = (flags & 1024) != 0; + edited = (flags & 2048) != 0; + contacts = (flags & 4096) != 0; + selected_contacts = (flags & 8192) != 0; + out = (flags & 65536) != 0; + id = stream.readInt32(exception); + date = stream.readInt32(exception); + expire_date = stream.readInt32(exception); + if ((flags & 1) != 0) { + caption = stream.readString(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++) { + TLRPC.MessageEntity object = TLRPC.MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + media = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 16384) != 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++) { + MediaArea object = MediaArea.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + media_areas.add(object); + } + } + if ((flags & 4) != 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.PrivacyRule object = TLRPC.PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + privacy.add(object); + } + } + if ((flags & 8) != 0) { + views = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32768) != 0) { + sent_reaction = TLRPC.Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 32) : (flags &~ 32); + flags = isPublic ? (flags | 128) : (flags &~ 128); + flags = close_friends ? (flags | 256) : (flags &~ 256); + flags = min ? (flags | 512) : (flags &~ 512); + flags = noforwards ? (flags | 1024) : (flags &~ 1024); + flags = edited ? (flags | 2048) : (flags &~ 2048); + flags = contacts ? (flags | 4096) : (flags &~ 4096); + flags = selected_contacts ? (flags | 8192) : (flags &~ 8192); + flags = out ? (flags | 65536) : (flags &~ 65536); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeInt32(date); + stream.writeInt32(expire_date); + if ((flags & 1) != 0) { + stream.writeString(caption); + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + media.serializeToStream(stream); + if ((flags & 16384) != 0) { + stream.writeInt32(0x1cb5c415); + int count = media_areas.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + media_areas.get(a).serializeToStream(stream); + } + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = privacy.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + privacy.get(a).serializeToStream(stream); + } + } + if ((flags & 8) != 0) { + views.serializeToStream(stream); + } + if ((flags & 32768) != 0) { + sent_reaction.serializeToStream(stream); + } + } + } + + public static class TL_storyItem_layer160 extends TL_storyItem { + public static final int constructor = 0x562aa637; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pinned = (flags & 32) != 0; + isPublic = (flags & 128) != 0; + close_friends = (flags & 256) != 0; + min = (flags & 512) != 0; + noforwards = (flags & 1024) != 0; + edited = (flags & 2048) != 0; + contacts = (flags & 4096) != 0; + selected_contacts = (flags & 8192) != 0; + id = stream.readInt32(exception); + date = stream.readInt32(exception); + expire_date = stream.readInt32(exception); + if ((flags & 1) != 0) { + caption = stream.readString(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++) { + TLRPC.MessageEntity object = TLRPC.MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + entities.add(object); + } + } + media = TLRPC.MessageMedia.TLdeserialize(stream, stream.readInt32(exception), exception); + if ((flags & 4) != 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.PrivacyRule object = TLRPC.PrivacyRule.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + privacy.add(object); + } + } + if ((flags & 8) != 0) { + views = StoryViews.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pinned ? (flags | 32) : (flags &~ 32); + flags = isPublic ? (flags | 128) : (flags &~ 128); + flags = close_friends ? (flags | 256) : (flags &~ 256); + flags = min ? (flags | 512) : (flags &~ 512); + flags = noforwards ? (flags | 1024) : (flags &~ 1024); + flags = edited ? (flags | 2048) : (flags &~ 2048); + flags = contacts ? (flags | 4096) : (flags &~ 4096); + flags = selected_contacts ? (flags | 8192) : (flags &~ 8192); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeInt32(date); + stream.writeInt32(expire_date); + if ((flags & 1) != 0) { + stream.writeString(caption); + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + entities.get(a).serializeToStream(stream); + } + } + media.serializeToStream(stream); + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = privacy.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + privacy.get(a).serializeToStream(stream); + } + } + if ((flags & 8) != 0) { + views.serializeToStream(stream); + } + } + } + + public static class TL_storyItemDeleted extends StoryItem { + public static final int constructor = 0x51e6ee4f; + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(id); + } + } + + public static class TL_storyItemSkipped extends StoryItem { + public static final int constructor = 0xffadc913; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + close_friends = (flags & 256) != 0; + id = stream.readInt32(exception); + date = stream.readInt32(exception); + expire_date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = close_friends ? (flags | 256) : (flags &~ 256); + stream.writeInt32(flags); + stream.writeInt32(id); + stream.writeInt32(date); + stream.writeInt32(expire_date); + } + } + + public static class TL_mediaAreaCoordinates extends TLObject { + public static final int constructor = 0x3d1ea4e; + + public double x; + public double y; + public double w; + public double h; + public double rotation; + + public static TL_mediaAreaCoordinates TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_mediaAreaCoordinates.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_mediaAreaCoordinates", constructor)); + } else { + return null; + } + } + TL_mediaAreaCoordinates result = new TL_mediaAreaCoordinates(); + result.readParams(stream, exception); + return result; + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + x = stream.readDouble(exception); + y = stream.readDouble(exception); + w = stream.readDouble(exception); + h = stream.readDouble(exception); + rotation = stream.readDouble(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeDouble(x); + stream.writeDouble(y); + stream.writeDouble(w); + stream.writeDouble(h); + stream.writeDouble(rotation); + } + } + + public static class MediaArea extends TLObject { + public TL_mediaAreaCoordinates coordinates; + public TLRPC.Reaction reaction; + public int flags; + public boolean dark; + public boolean flipped; + + public static MediaArea TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + MediaArea result = null; + switch (constructor) { + case TL_mediaAreaVenue.constructor: + result = new TL_mediaAreaVenue(); + break; + case TL_mediaAreaGeoPoint.constructor: + result = new TL_mediaAreaGeoPoint(); + break; + case TL_inputMediaAreaVenue.constructor: + result = new TL_inputMediaAreaVenue(); + break; + case TL_mediaAreaSuggestedReaction.constructor: + result = new TL_mediaAreaSuggestedReaction(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in MediaArea", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_mediaAreaSuggestedReaction extends MediaArea { + public static final int constructor = 0x14455871; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + dark = (flags & 1) != 0; + flipped = (flags & 2) != 0; + coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); + reaction = TLRPC.Reaction.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = dark ? (flags | 1) : (flags &~ 1); + flags = flipped ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + coordinates.serializeToStream(stream); + reaction.serializeToStream(stream); + } + } + + public static class TL_mediaAreaVenue extends MediaArea { + public static final int constructor = 0xbe82db9c; + + public TLRPC.GeoPoint geo; + public String title; + public String address; + public String provider; + public String venue_id; + public String venue_type; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); + geo = TLRPC.GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + title = stream.readString(exception); + address = stream.readString(exception); + provider = stream.readString(exception); + venue_id = stream.readString(exception); + venue_type = stream.readString(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + coordinates.serializeToStream(stream); + geo.serializeToStream(stream); + stream.writeString(title); + stream.writeString(address); + stream.writeString(provider); + stream.writeString(venue_id); + stream.writeString(venue_type); + } + } + + public static class TL_inputMediaAreaVenue extends MediaArea { + public static final int constructor = 0xb282217f; + + public long query_id; + public String result_id; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); + query_id = stream.readInt64(exception); + result_id = stream.readString(exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + coordinates.serializeToStream(stream); + stream.writeInt64(query_id); + stream.writeString(result_id); + } + } + + public static class TL_mediaAreaGeoPoint extends MediaArea { + public static final int constructor = 0xdf8b3b22; + + public TLRPC.GeoPoint geo; + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + coordinates = TL_mediaAreaCoordinates.TLdeserialize(stream, stream.readInt32(exception), exception); + geo = TLRPC.GeoPoint.TLdeserialize(stream, stream.readInt32(exception), exception); + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + coordinates.serializeToStream(stream); + geo.serializeToStream(stream); + } + } + + public static class TL_prepaidGiveaway extends TLObject { + public static int constructor = 0xb2539d54; + + public long id; + public int months; + public int quantity; + public int date; + + public static TL_prepaidGiveaway TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_prepaidGiveaway.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_prepaidGiveaway", constructor)); + } else { + return null; + } + } + TL_prepaidGiveaway result = new TL_prepaidGiveaway(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + months = stream.readInt32(exception); + quantity = stream.readInt32(exception); + date = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt32(months); + stream.writeInt32(quantity); + stream.writeInt32(date); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java index e016882a4..07a92b9c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -15,6 +15,7 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.Activity; +import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; @@ -35,6 +36,7 @@ import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; import android.view.ViewOutlineProvider; +import android.view.Window; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.animation.OvershootInterpolator; @@ -56,7 +58,9 @@ import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.ui.AllowShowingActivityInterface; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.BackButtonMenu; +import org.telegram.ui.Components.BotWebViewSheet; import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.ChatAttachAlert; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FloatingDebug.FloatingDebugController; import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider; @@ -73,6 +77,7 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F public boolean highlightActionButtons = false; private boolean attached; private boolean isSheet; + private Window window; @Override public void setHighlightActionButtons(boolean highlightActionButtons) { @@ -454,6 +459,14 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F return isSheet; } + @Override + public void updateTitleOverlay() { + BaseFragment fragment = getLastFragment(); + if (fragment != null && fragment.actionBar != null) { + fragment.actionBar.setTitleOverlayText(titleOverlayText, titleOverlayTextId, overlayAction); + } + } + @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -1229,6 +1242,16 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F if (fragment instanceof AllowShowingActivityInterface && !((AllowShowingActivityInterface) fragment).allowShowing()) { return false; } + BaseFragment lastFragment = getLastFragment(); + if (lastFragment != null && lastFragment.getVisibleDialog() != null) { + if (shouldOpenFragmentOverlay(lastFragment.getVisibleDialog())) { + BaseFragment.BottomSheetParams bottomSheetParams = new BaseFragment.BottomSheetParams(); + bottomSheetParams.transitionFromLeft = true; + bottomSheetParams.allowNestedScroll = false; + lastFragment.showAsSheet(fragment, bottomSheetParams); + return true; + } + } if (BuildVars.LOGS_ENABLED) { FileLog.d("present fragment " + fragment.getClass().getSimpleName() + " args=" + fragment.getArguments()); } @@ -1526,6 +1549,10 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F return true; } + private boolean shouldOpenFragmentOverlay(Dialog visibleDialog) { + return visibleDialog instanceof ChatAttachAlert || visibleDialog instanceof BotWebViewSheet; + } + @Override public List getFragmentStack() { return fragmentsStack; @@ -2554,4 +2581,20 @@ public class ActionBarLayout extends FrameLayout implements INavigationLayout, F } return super.dispatchTouchEvent(ev); } + + @Override + public void setWindow(Window window) { + this.window = window; + } + + @Override + public Window getWindow() { + if (window != null) { + return window; + } + if (getParentActivity() != null) { + return getParentActivity().getWindow(); + } + return null; + } } \ No newline at end of file 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 dd3cb892c..e80a1529c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -15,6 +15,7 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieImageView; @@ -23,7 +24,7 @@ public class ActionBarMenuSubItem extends FrameLayout { private TextView textView; private TextView subtextView; - private RLottieImageView imageView; + public RLottieImageView imageView; private CheckBox2 checkView; private ImageView rightIcon; @@ -140,6 +141,13 @@ public class ActionBarMenuSubItem extends FrameLayout { } addView(rightIcon, LayoutHelper.createFrame(24, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT))); } + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) textView.getLayoutParams(); + if (LocaleController.isRTL) { + layoutParams.leftMargin = rightIcon != null ? AndroidUtilities.dp(32) : 0; + } else { + layoutParams.rightMargin = rightIcon != null ? AndroidUtilities.dp(32) : 0; + } + textView.setLayoutParams(layoutParams); setPadding(AndroidUtilities.dp(LocaleController.isRTL ? 8 : 18), 0, AndroidUtilities.dp(LocaleController.isRTL ? 18 : 8), 0); rightIcon.setImageResource(icon); } @@ -273,7 +281,7 @@ public class ActionBarMenuSubItem extends FrameLayout { updateBackground(); } - void updateBackground() { + public void updateBackground() { setBackground(Theme.createRadSelectorDrawable(selectorColor, top ? 6 : 0, bottom ? 6 : 0)); } 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 c7a3fc70f..7644a3a39 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -22,6 +22,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.util.Log; import android.view.Gravity; import android.view.KeyEvent; import android.view.View; @@ -472,7 +473,11 @@ public class ActionBarPopupWindow extends PopupWindow { if (start > -AndroidUtilities.dp(16)) { int h = (int) (getMeasuredHeight() * backScaleY); if (a == 0) { - AndroidUtilities.rectTmp2.set(0, -scrollView.getScrollY() + (gapStartY != -1000000 ? AndroidUtilities.dp(1) : 0), (int) (getMeasuredWidth() * backScaleX), (gapStartY != -1000000 ? Math.min(h, start + AndroidUtilities.dp(16)) : h) - subtractBackgroundHeight); + if (swipeBackLayout != null && swipeBackLayout.stickToRight) { + AndroidUtilities.rectTmp2.set(getMeasuredWidth() - (int) (getMeasuredWidth() * backScaleX), -scrollView.getScrollY() + (gapStartY != -1000000 ? AndroidUtilities.dp(1) : 0), getMeasuredWidth(), (gapStartY != -1000000 ? Math.min(h, start + AndroidUtilities.dp(16)) : h) - subtractBackgroundHeight); + } else { + AndroidUtilities.rectTmp2.set(0, -scrollView.getScrollY() + (gapStartY != -1000000 ? AndroidUtilities.dp(1) : 0), (int) (getMeasuredWidth() * backScaleX), (gapStartY != -1000000 ? Math.min(h, start + AndroidUtilities.dp(16)) : h) - subtractBackgroundHeight); + } } else { if (h < end) { if (gapStartY != -1000000) { @@ -480,10 +485,18 @@ public class ActionBarPopupWindow extends PopupWindow { } continue; } - AndroidUtilities.rectTmp2.set(0, end, (int) (getMeasuredWidth() * backScaleX), h - subtractBackgroundHeight); + if (swipeBackLayout != null && swipeBackLayout.stickToRight) { + AndroidUtilities.rectTmp2.set(getMeasuredWidth() - (int) (getMeasuredWidth() * backScaleX), end, getMeasuredWidth(), h - subtractBackgroundHeight); + } else { + AndroidUtilities.rectTmp2.set(0, end, (int) (getMeasuredWidth() * backScaleX), h - subtractBackgroundHeight); + } } } else { - AndroidUtilities.rectTmp2.set(0, (gapStartY < 0 ? 0 : -AndroidUtilities.dp(16)), (int) (getMeasuredWidth() * backScaleX), (int) (getMeasuredHeight() * backScaleY) - subtractBackgroundHeight); + if (swipeBackLayout != null && swipeBackLayout.stickToRight) { + AndroidUtilities.rectTmp2.set(getMeasuredWidth() - (int) (getMeasuredWidth() * backScaleX), (gapStartY < 0 ? 0 : -AndroidUtilities.dp(16)), getMeasuredWidth(), (int) (getMeasuredHeight() * backScaleY) - subtractBackgroundHeight); + } else { + AndroidUtilities.rectTmp2.set(0, (gapStartY < 0 ? 0 : -AndroidUtilities.dp(16)), (int) (getMeasuredWidth() * backScaleX), (int) (getMeasuredHeight() * backScaleY) - subtractBackgroundHeight); + } } } if (reactionsEnterProgress != 1f) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java index 2024b3e97..35989a915 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java @@ -23,6 +23,8 @@ import androidx.annotation.RequiresApi; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.ChatListItemAnimator; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.UserConfig; @@ -134,7 +136,6 @@ public class AdjustPanLayoutHelper { updateTransition((float) animation.getAnimatedValue()); } }); - int selectedAccount = UserConfig.selectedAccount; animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { 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 f396ab317..209577c72 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -82,6 +82,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati public static final int ALERT_TYPE_SPINNER = 3; private View customView; + private View bottomView; private int customViewHeight = LayoutHelper.WRAP_CONTENT; private TextView titleTextView; private TextView secondTitleTextView; @@ -766,6 +767,9 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati progressViewContainer.addView(progressView, LayoutHelper.createFrame(86, 86, Gravity.CENTER)); } else { scrollContainer.addView(messageTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (topAnimationIsNew ? Gravity.CENTER_HORIZONTAL : LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 24, 0, 24, customView != null || items != null ? customViewOffset : 0)); + if (bottomView != null) { + scrollContainer.addView(bottomView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, -16, 24, 0)); + } } if (!TextUtils.isEmpty(message)) { messageTextView.setText(message); @@ -1514,6 +1518,11 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati return this; } + public Builder addBottomView(View view) { + alertDialog.bottomView = view; + return this; + } + public Builder setTitle(CharSequence title) { alertDialog.title = title; return this; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java index f0badf7c4..edaa40394 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -53,6 +53,7 @@ import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.LaunchActivity; import org.telegram.ui.Stories.StoryViewer; @@ -816,16 +817,18 @@ public abstract class BaseFragment { } BottomSheet[] bottomSheet = new BottomSheet[1]; INavigationLayout[] actionBarLayout = new INavigationLayout[]{INavigationLayout.newLayout(getParentActivity(), () -> bottomSheet[0])}; + actionBarLayout[0].setIsSheet(true); LaunchActivity.instance.sheetFragmentsStack.add(actionBarLayout[0]); + fragment.onTransitionAnimationStart(true, false); bottomSheet[0] = new BottomSheet(getParentActivity(), true, fragment.getResourceProvider()) { { drawNavigationBar = true; actionBarLayout[0].setFragmentStack(new ArrayList<>()); actionBarLayout[0].addFragmentToStack(fragment); - actionBarLayout[0].setIsSheet(true); actionBarLayout[0].showLastFragment(); actionBarLayout[0].getView().setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); - containerView = actionBarLayout[0].getView(); + ViewGroup view = actionBarLayout[0].getView(); + containerView = view; setApplyBottomPadding(false); setOnDismissListener(dialog -> { fragment.onPause(); @@ -839,6 +842,7 @@ public abstract class BaseFragment { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + actionBarLayout[0].setWindow(bottomSheet[0].getWindow()); fixNavigationBar(Theme.getColor(Theme.key_dialogBackgroundGray, fragment.getResourceProvider())); AndroidUtilities.setLightStatusBar(getWindow(), fragment.isLightStatusBar()); } @@ -848,6 +852,11 @@ public abstract class BaseFragment { return false; } + @Override + protected boolean canSwipeToBack() { + return params != null && params.transitionFromLeft && actionBarLayout[0] != null && actionBarLayout[0].getFragmentStack().size() <= 1; + } + @Override public void onBackPressed() { if (actionBarLayout[0] == null || actionBarLayout[0].getFragmentStack().size() <= 1) { @@ -871,10 +880,22 @@ public abstract class BaseFragment { @Override public void onOpenAnimationEnd() { + fragment.onTransitionAnimationEnd(true, false); if (params != null && params.onOpenAnimationFinished != null) { params.onOpenAnimationFinished.run(); } } + + @Override + protected void onInsetsChanged() { + if (actionBarLayout[0] != null) { + for (BaseFragment baseFragment : actionBarLayout[0].getFragmentStack()) { + if (baseFragment.getFragmentView() != null) { + baseFragment.getFragmentView().requestLayout(); + } + } + } + } }; if (params != null) { bottomSheet[0].setAllowNestedScroll(params.allowNestedScroll); @@ -1058,7 +1079,7 @@ public abstract class BaseFragment { public StoryViewer getOrCreateStoryViewer() { if (storyViewer == null) { storyViewer = new StoryViewer(this); - if (parentLayout.isSheet()) { + if (parentLayout != null && parentLayout.isSheet()) { storyViewer.fromBottomSheet = true; } } 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 09bac8032..0711bd2a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -178,6 +178,7 @@ public class BottomSheet extends Dialog { private AnimationNotificationsLocker notificationsLocker = new AnimationNotificationsLocker(); protected int playingImagesLayerNum; protected int openedLayerNum; + private boolean skipDismissAnimation; public void setDisableScroll(boolean b) { disableScroll = b; @@ -340,6 +341,7 @@ public class BottomSheet extends Dialog { } private float y = 0f; + private float swipeBackX = 0f; public boolean processTouchEvent(MotionEvent ev, boolean intercept) { if (dismissed) { return false; @@ -347,61 +349,132 @@ public class BottomSheet extends Dialog { if (onContainerTouchEvent(ev)) { return true; } - - if (canDismissWithTouchOutside() && ev != null && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) && (!startedTracking && !maybeStartTracking && ev.getPointerCount() == 1)) { - startedTrackingX = (int) ev.getX(); - startedTrackingY = (int) ev.getY(); - if (startedTrackingY < containerView.getTop() || startedTrackingX < containerView.getLeft() || startedTrackingX > containerView.getRight()) { - onDismissWithTouchOutside(); - return true; - } - onScrollUpBegin(y); - startedTrackingPointerId = ev.getPointerId(0); - maybeStartTracking = true; - cancelCurrentAnimation(); - if (velocityTracker != null) { - velocityTracker.clear(); - } - } else if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && ev.getPointerId(0) == startedTrackingPointerId) { - if (velocityTracker == null) { - velocityTracker = VelocityTracker.obtain(); - } - float dx = Math.abs((int) (ev.getX() - startedTrackingX)); - float dy = (int) ev.getY() - startedTrackingY; - boolean canScrollUp = onScrollUp(y + dy); - velocityTracker.addMovement(ev); - if (!disableScroll && maybeStartTracking && !startedTracking && (dy > 0 && dy / 3.0f > Math.abs(dx) && Math.abs(dy) >= touchSlop)) { + if (canSwipeToBack()) { + if (ev != null && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) && (!startedTracking && !maybeStartTracking && ev.getPointerCount() == 1)) { + startedTrackingX = (int) ev.getX(); startedTrackingY = (int) ev.getY(); + startedTrackingPointerId = ev.getPointerId(0); + maybeStartTracking = true; + cancelCurrentAnimation(); + } else if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && ev.getPointerId(0) == startedTrackingPointerId) { + float dx = ev.getX() - startedTrackingX; + float dy = ev.getY() - startedTrackingY; + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + velocityTracker.addMovement(ev); + if (!disableScroll && maybeStartTracking && !startedTracking && (dx > 0 && dx / 3.0f > Math.abs(dy) && Math.abs(dx) >= touchSlop)) { + startedTrackingX = (int) ev.getX(); + maybeStartTracking = false; + startedTracking = true; + } else if (startedTracking) { + swipeBackX += dx; + containerView.setTranslationX(Math.max(swipeBackX, 0)); + startedTrackingX = (int) ev.getX(); + container.invalidate(); + } + } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { + containerView.setTranslationX(0); + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + float velX = velocityTracker.getXVelocity(); + float velY = velocityTracker.getYVelocity(); + final boolean backAnimation = swipeBackX < containerView.getMeasuredWidth() / 3.0f && (velX < 3500 || velX < velY); + if (backAnimation) { + swipeBackX = Math.max(swipeBackX, 0); + ValueAnimator animator = ValueAnimator.ofFloat(swipeBackX, 0); + animator.addUpdateListener(animation -> { + swipeBackX = (float) animation.getAnimatedValue(); + setTranslationX(swipeBackX); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + swipeBackX = 0; + setTranslationX(0); + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setDuration(220); + animator.start(); + } else { + ValueAnimator animator = ValueAnimator.ofFloat(swipeBackX, getMeasuredWidth()); + animator.addUpdateListener(animation -> { + swipeBackX = (float) animation.getAnimatedValue(); + setTranslationX(swipeBackX); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + skipDismissAnimation = true; + dismiss(); + } + }); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.setDuration(150); + animator.start(); + } maybeStartTracking = false; - startedTracking = true; - requestDisallowInterceptTouchEvent(true); - } else if (startedTracking) { - y += dy; - if (!canScrollUp) - y = Math.max(y, 0); - containerView.setTranslationY(Math.max(y, 0)); + startedTracking = false; + startedTrackingPointerId = -1; + } + } else { + if (canDismissWithTouchOutside() && ev != null && (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) && (!startedTracking && !maybeStartTracking && ev.getPointerCount() == 1)) { + startedTrackingX = (int) ev.getX(); startedTrackingY = (int) ev.getY(); - container.invalidate(); + if (startedTrackingY < containerView.getTop() || startedTrackingX < containerView.getLeft() || startedTrackingX > containerView.getRight()) { + onDismissWithTouchOutside(); + return true; + } + onScrollUpBegin(y); + startedTrackingPointerId = ev.getPointerId(0); + maybeStartTracking = true; + cancelCurrentAnimation(); + if (velocityTracker != null) { + velocityTracker.clear(); + } + } else if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && ev.getPointerId(0) == startedTrackingPointerId) { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + float dx = Math.abs((int) (ev.getX() - startedTrackingX)); + float dy = (int) ev.getY() - startedTrackingY; + boolean canScrollUp = onScrollUp(y + dy); + velocityTracker.addMovement(ev); + if (!disableScroll && maybeStartTracking && !startedTracking && (dy > 0 && dy / 3.0f > Math.abs(dx) && Math.abs(dy) >= touchSlop)) { + startedTrackingY = (int) ev.getY(); + maybeStartTracking = false; + startedTracking = true; + requestDisallowInterceptTouchEvent(true); + } else if (startedTracking) { + y += dy; + if (!canScrollUp) + y = Math.max(y, 0); + containerView.setTranslationY(Math.max(y, 0)); + startedTrackingY = (int) ev.getY(); + container.invalidate(); + } + } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { + if (velocityTracker == null) { + velocityTracker = VelocityTracker.obtain(); + } + velocityTracker.computeCurrentVelocity(1000); + onScrollUpEnd(y); + if (startedTracking || y > 0) { + checkDismiss(velocityTracker.getXVelocity(), velocityTracker.getYVelocity()); + } else { + maybeStartTracking = false; + } + startedTracking = false; + if (velocityTracker != null) { + velocityTracker.recycle(); + velocityTracker = null; + } + startedTrackingPointerId = -1; } - } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { - if (velocityTracker == null) { - velocityTracker = VelocityTracker.obtain(); - } - velocityTracker.computeCurrentVelocity(1000); - onScrollUpEnd(y); - if (startedTracking || y > 0) { - checkDismiss(velocityTracker.getXVelocity(), velocityTracker.getYVelocity()); - } else { - maybeStartTracking = false; - } - startedTracking = false; - if (velocityTracker != null) { - velocityTracker.recycle(); - velocityTracker = null; - } - startedTrackingPointerId = -1; } - return !intercept && maybeStartTracking || startedTracking || !canDismissWithSwipe(); + return (!intercept && maybeStartTracking) || startedTracking || !(canDismissWithSwipe() || canSwipeToBack()); } @Override @@ -595,7 +668,7 @@ public class BottomSheet extends Dialog { @Override public boolean onInterceptTouchEvent(MotionEvent event) { - if (canDismissWithSwipe()) { + if (canDismissWithSwipe() || canSwipeToBack()) { return processTouchEvent(event, true); } return super.onInterceptTouchEvent(event); @@ -1010,6 +1083,7 @@ public class BottomSheet extends Dialog { } lastInsets = insets; v.requestLayout(); + onInsetsChanged(); if (Build.VERSION.SDK_INT >= 30) { return WindowInsets.CONSUMED; } else { @@ -1026,6 +1100,10 @@ public class BottomSheet extends Dialog { backDrawable.setAlpha(0); } + protected void onInsetsChanged() { + + } + protected void mainContainerDispatchDraw(Canvas canvas) { } @@ -1586,6 +1664,10 @@ public class BottomSheet extends Dialog { return containerView.getMeasuredHeight(); } + protected boolean canSwipeToBack() { + return false; + } + @Override public void dismiss() { if (delegate != null && !delegate.canDismiss()) { @@ -1601,66 +1683,76 @@ public class BottomSheet extends Dialog { cancelSheetAnimation(); long duration = 0; onDismissAnimationStart(); - if (!allowCustomAnimation || !onCustomCloseAnimation()) { - currentSheetAnimationType = 2; - if (navigationBarAnimation != null) { - navigationBarAnimation.cancel(); - } - navigationBarAnimation = ValueAnimator.ofFloat(navigationBarAlpha, 0f); - navigationBarAnimation.addUpdateListener(a -> { - navigationBarAlpha = (float) a.getAnimatedValue(); - if (container != null) { - container.invalidate(); + if (skipDismissAnimation) { + AndroidUtilities.runOnUIThread(() -> { + try { + dismissInternal(); + } catch (Exception e) { + FileLog.e(e); } }); - currentSheetAnimation = new AnimatorSet(); - ArrayList animators = new ArrayList<>(); - if (containerView != null) { + } else { + if (!allowCustomAnimation || !onCustomCloseAnimation()) { + currentSheetAnimationType = 2; + if (navigationBarAnimation != null) { + navigationBarAnimation.cancel(); + } + navigationBarAnimation = ValueAnimator.ofFloat(navigationBarAlpha, 0f); + navigationBarAnimation.addUpdateListener(a -> { + navigationBarAlpha = (float) a.getAnimatedValue(); + if (container != null) { + container.invalidate(); + } + }); + currentSheetAnimation = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + if (containerView != null) { + if (transitionFromRight) { + 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() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0))); + } + } + animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0)); + animators.add(navigationBarAnimation); + currentSheetAnimation.playTogether(animators); + if (transitionFromRight) { - animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_X, AndroidUtilities.dp(48))); - animators.add(ObjectAnimator.ofFloat(containerView, View.ALPHA, 0)); + currentSheetAnimation.setDuration(200); + currentSheetAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); } else { - animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0))); + currentSheetAnimation.setDuration(duration = 250); + currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); } - } - animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0)); - animators.add(navigationBarAnimation); - currentSheetAnimation.playTogether(animators); - - if (transitionFromRight) { - currentSheetAnimation.setDuration(200); - currentSheetAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); - } else { - currentSheetAnimation.setDuration(duration = 250); - currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); - } - currentSheetAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { - currentSheetAnimation = null; - currentSheetAnimationType = 0; - AndroidUtilities.runOnUIThread(() -> { - try { - dismissInternal(); - } catch (Exception e) { - FileLog.e(e); - } - }); + currentSheetAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + AndroidUtilities.runOnUIThread(() -> { + try { + dismissInternal(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); } - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); - } - @Override - public void onAnimationCancel(Animator animation) { - if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { - currentSheetAnimation = null; - currentSheetAnimationType = 0; + @Override + public void onAnimationCancel(Animator animation) { + if (currentSheetAnimation != null && currentSheetAnimation.equals(animation)) { + currentSheetAnimation = null; + currentSheetAnimationType = 0; + } } - } - }); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); - currentSheetAnimation.start(); + }); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + currentSheetAnimation.start(); + } } Bulletin bulletin = Bulletin.getVisibleBulletin(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java index 836eb15ab..33922de82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java @@ -256,7 +256,9 @@ public class EmojiThemes { } themeInfo = new Theme.ThemeInfo(baseTheme); accent = themeInfo.createNewAccent(tlTheme, currentAccount, true, settingsIndex); - themeInfo.setCurrentAccentId(accent.id); + if (accent != null) { + themeInfo.setCurrentAccentId(accent.id); + } } else { if (themeInfo.themeAccentsMap != null) { accent = themeInfo.themeAccentsMap.get(items.get(index).accentId); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingActionMode.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingActionMode.java index c5c923804..427080a6a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingActionMode.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingActionMode.java @@ -21,6 +21,7 @@ import android.annotation.TargetApi; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; +import android.util.Log; import android.view.ActionMode; import android.view.Menu; import android.view.MenuInflater; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java index 16874c385..df3f19d93 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/FloatingToolbar.java @@ -69,6 +69,7 @@ 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.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; @@ -106,6 +107,11 @@ public final class FloatingToolbar { premiumLockClickListener = listener; } + private Utilities.Callback0Return quoteShowCallback; + public void setQuoteShowVisible(Utilities.Callback0Return callback) { + quoteShowCallback = callback; + } + private final OnLayoutChangeListener mOrientationChangeHandler = new OnLayoutChangeListener() { private final Rect mNewRect = new Rect(); private final Rect mOldRect = new Rect(); @@ -236,6 +242,8 @@ public final class FloatingToolbar { Menu subMenu = menuItem.getSubMenu(); if (subMenu != null) { menuItems.addAll(getVisibleAndEnabledMenuItems(subMenu)); + } else if (menuItem.getItemId() == R.id.menu_quote && (quoteShowCallback != null && !quoteShowCallback.run())) { + continue; } else if (menuItem.getItemId() != TRANSLATE && (menuItem.getItemId() != R.id.menu_regular || premiumLockClickListener == null)) { menuItems.add(menuItem); } @@ -253,14 +261,15 @@ public final class FloatingToolbar { mWindowView.removeOnLayoutChangeListener(mOrientationChangeHandler); } - private static final List premiumOptions = Arrays.asList( + public static final List premiumOptions = Arrays.asList( R.id.menu_bold, R.id.menu_italic, R.id.menu_strike, R.id.menu_link, R.id.menu_mono, R.id.menu_underline, - R.id.menu_spoiler + R.id.menu_spoiler, + R.id.menu_quote ); private final class FloatingToolbarPopup { @@ -447,18 +456,24 @@ public final class FloatingToolbar { mOverflowButtonIcon.setImageDrawable(mToOverflow); mToOverflow.start(); closeOverflow(); - mOverflowButton.setClickable(false); - mOverflowButton.setOnClickListener(null); - mOverflowButtonIcon.setClickable(true); - mOverflowButtonIcon.setOnClickListener(v -> onBackPressed()); } else { mOverflowButtonIcon.setImageDrawable(mToArrow); mToArrow.start(); openOverflow(); + } + } + + private void updateOverflowButtonClickListener() { + if (mIsOverflowOpen) { mOverflowButton.setClickable(true); mOverflowButton.setOnClickListener(v -> onBackPressed()); mOverflowButtonIcon.setClickable(false); mOverflowButtonIcon.setOnClickListener(null); + } else { + mOverflowButton.setClickable(false); + mOverflowButton.setOnClickListener(null); + mOverflowButtonIcon.setClickable(true); + mOverflowButtonIcon.setOnClickListener(v -> onBackPressed()); } } @@ -679,6 +694,7 @@ public final class FloatingToolbar { mOpenOverflowAnimation.addAnimation(overflowButtonAnimation); mContentContainer.startAnimation(mOpenOverflowAnimation); mIsOverflowOpen = true; + updateOverflowButtonClickListener(); mMainPanel.animate().alpha(0).withLayer().setInterpolator(mLinearOutSlowInInterpolator).setDuration(250).start(); RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) mOverflowButton.getLayoutParams(); lp.width = mOverflowPanel.getWidth(); @@ -746,6 +762,7 @@ public final class FloatingToolbar { mCloseOverflowAnimation.addAnimation(overflowButtonAnimation); mContentContainer.startAnimation(mCloseOverflowAnimation); mIsOverflowOpen = false; + updateOverflowButtonClickListener(); mMainPanel.animate() .alpha(1).withLayer() .setInterpolator(mFastOutLinearInInterpolator) @@ -993,7 +1010,15 @@ public final class FloatingToolbar { final boolean premiumLocked = MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked; for (int i = 0; i < size; i++) { final MenuItem menuItem = menuItems.get(i); - if (premiumLockClickListener == null || premiumLocked && !premiumOptions.contains(menuItem.getItemId())) { + final boolean show; + if (premiumLockClickListener == null) { + show = true; + } else if (premiumOptions.contains(menuItem.getItemId())) { + show = !premiumLocked; + } else { + show = true; + } + if (show) { overflowPanelAdapter.add(menuItem); } } @@ -1031,6 +1056,7 @@ public final class FloatingToolbar { mOverflowPanelSize = null; mMainPanelSize = null; mIsOverflowOpen = false; + updateOverflowButtonClickListener(); mMainPanel.removeAllViews(); ArrayAdapter overflowPanelAdapter = (ArrayAdapter) mOverflowPanel.getAdapter(); overflowPanelAdapter.clear(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java index 52165dfd9..497bcef10 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/INavigationLayout.java @@ -281,6 +281,10 @@ public interface INavigationLayout { boolean isSheet(); + void updateTitleOverlay(); + + void setWindow(Window window); + interface INavigationLayoutDelegate { default boolean needPresentFragment(INavigationLayout layout, NavigationParams params) { return needPresentFragment(params.fragment, params.removeLast, params.noAnimation, layout); 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 a5663eb17..73747f736 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -38,6 +38,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Shader; +import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -795,126 +796,7 @@ public class Theme { invalidatePath = true; } if (invalidatePath || overrideRoundRadius != 0) { - path.rewind(); - int heightHalf = (bounds.height() - padding) >> 1; - if (rad > heightHalf) { - rad = heightHalf; - } - if (isOut) { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { - int radToUse = botButtonsBottom ? nearRad : rad; - if (currentType == TYPE_MEDIA) { - path.moveTo(bounds.right - dp(8) - radToUse, bounds.bottom - padding); - } else { - path.moveTo(bounds.right - dp(2.6f), bounds.bottom - padding); - } - path.lineTo(bounds.left + padding + radToUse, bounds.bottom - padding); - rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); - path.arcTo(rect, 90, 90, false); - } else { - path.moveTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); - path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); - } - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullTop) { - path.lineTo(bounds.left + padding, bounds.top + padding + rad); - rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + rad * 2, bounds.top + padding + rad * 2); - path.arcTo(rect, 180, 90, false); - - int radToUse = isTopNear ? nearRad : rad; - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.right - padding - radToUse, bounds.top + padding); - rect.set(bounds.right - padding - radToUse * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + radToUse * 2); - } else { - path.lineTo(bounds.right - dp(8) - radToUse, bounds.top + padding); - rect.set(bounds.right - dp(8) - radToUse * 2, bounds.top + padding, bounds.right - dp(8), bounds.top + padding + radToUse * 2); - } - path.arcTo(rect, 270, 90, false); - } else { - path.lineTo(bounds.left + padding, top - topY - dp(2)); - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.right - padding, top - topY - dp(2)); - } else { - path.lineTo(bounds.right - dp(8), top - topY - dp(2)); - } - } - if (currentType == TYPE_MEDIA) { - if (paintToUse != null || drawFullBottom) { - int radToUse = isBottomNear ? nearRad : rad; - - path.lineTo(bounds.right - padding, bounds.bottom - padding - radToUse); - rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); - path.arcTo(rect, 0, 90, false); - } else { - path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); - } - } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { - path.lineTo(bounds.right - dp(8), bounds.bottom - padding - smallRad - dp(3)); - rect.set(bounds.right - dp(8), bounds.bottom - padding - smallRad * 2 - dp(9), bounds.right - dp(7) + smallRad * 2, bounds.bottom - padding - dp(1)); - path.arcTo(rect, 180, -83, false); - } else { - path.lineTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); - } - } - } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { - int radToUse = botButtonsBottom ? nearRad : rad; - - if (currentType == TYPE_MEDIA) { - path.moveTo(bounds.left + dp(8) + radToUse, bounds.bottom - padding); - } else { - path.moveTo(bounds.left + dp(2.6f), bounds.bottom - padding); - } - path.lineTo(bounds.right - padding - radToUse, bounds.bottom - padding); - rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); - path.arcTo(rect, 90, -90, false); - } else { - path.moveTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); - path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); - } - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullTop) { - path.lineTo(bounds.right - padding, bounds.top + padding + rad); - rect.set(bounds.right - padding - rad * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + rad * 2); - path.arcTo(rect, 0, -90, false); - - int radToUse = isTopNear ? nearRad : rad; - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.left + padding + radToUse, bounds.top + padding); - rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + radToUse * 2, bounds.top + padding + radToUse * 2); - } else { - path.lineTo(bounds.left + dp(8) + radToUse, bounds.top + padding); - rect.set(bounds.left + dp(8), bounds.top + padding, bounds.left + dp(8) + radToUse * 2, bounds.top + padding + radToUse * 2); - } - path.arcTo(rect, 270, -90, false); - } else { - path.lineTo(bounds.right - padding, top - topY - dp(2)); - if (currentType == TYPE_MEDIA) { - path.lineTo(bounds.left + padding, top - topY - dp(2)); - } else { - path.lineTo(bounds.left + dp(8), top - topY - dp(2)); - } - } - if (currentType == TYPE_MEDIA) { - if (paintToUse != null || drawFullBottom) { - int radToUse = isBottomNear ? nearRad : rad; - - path.lineTo(bounds.left + padding, bounds.bottom - padding - radToUse); - rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); - path.arcTo(rect, 180, -90, false); - } else { - path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); - } - } else { - if (drawFullBubble || currentType == TYPE_PREVIEW || paintToUse != null || drawFullBottom) { - path.lineTo(bounds.left + dp(8), bounds.bottom - padding - smallRad - dp(3)); - rect.set(bounds.left + dp(7) - smallRad * 2, bounds.bottom - padding - smallRad * 2 - dp(9), bounds.left + dp(8), bounds.bottom - padding - dp(1)); - path.arcTo(rect, 0, 83, false); - } else { - path.lineTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); - } - } - } - path.close(); + generatePath(path, bounds, padding, rad, smallRad, nearRad, top, drawFullBottom, drawFullTop, paintToUse != null); } canvas.drawPath(path, p); @@ -925,6 +807,176 @@ public class Theme { } } + public Path makePath() { + return makePath(pathDrawCacheParams); + } + + public Path makePath(MessageDrawable.PathDrawParams pathDrawCacheParams) { + Rect bounds = getBounds(); + int padding = dp(2); + int rad; + int nearRad; + if (overrideRoundRadius != 0) { + rad = overrideRoundRadius; + nearRad = overrideRoundRadius; + } else if (overrideRounding > 0) { + rad = AndroidUtilities.lerp(dp(SharedConfig.bubbleRadius), Math.min(bounds.width(), bounds.height()) / 2, overrideRounding); + nearRad = AndroidUtilities.lerp(dp(Math.min(6, SharedConfig.bubbleRadius)), Math.min(bounds.width(), bounds.height()) / 2, overrideRounding); + } else if (currentType == TYPE_PREVIEW) { + rad = dp(6); + nearRad = dp(6); + } else { + rad = dp(SharedConfig.bubbleRadius); + nearRad = dp(Math.min(6, SharedConfig.bubbleRadius)); + } + int smallRad = dp(6); + int top = Math.max(bounds.top, 0); + boolean drawFullBottom, drawFullTop; + if (pathDrawCacheParams != null && bounds.height() < currentBackgroundHeight) { + drawFullBottom = true; + drawFullTop = true; + } else { + drawFullBottom = currentType == TYPE_MEDIA ? topY + bounds.bottom - smallRad * 2 < currentBackgroundHeight : topY + bounds.bottom - rad < currentBackgroundHeight; + drawFullTop = topY + rad * 2 >= 0; + } + Path path; + boolean invalidatePath; + if (pathDrawCacheParams != null) { + path = pathDrawCacheParams.path; + invalidatePath = pathDrawCacheParams.invalidatePath(bounds, drawFullBottom, drawFullTop); + } else { + path = this.path; + invalidatePath = true; + } + if (invalidatePath || overrideRoundRadius != 0) { + generatePath(path, bounds, padding, rad, smallRad, nearRad, top, drawFullBottom, drawFullTop, true); + } + return path; + } + + private void generatePath(Path path, Rect bounds, int padding, int rad, int smallRad, int nearRad, int top, boolean drawFullBottom, boolean drawFullTop, boolean customPaint) { + path.rewind(); + int heightHalf = (bounds.height() - padding) >> 1; + if (rad > heightHalf) { + rad = heightHalf; + } + if (isOut) { + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullBottom) { + int radToUse = botButtonsBottom ? nearRad : rad; + if (currentType == TYPE_MEDIA) { + path.moveTo(bounds.right - dp(8) - radToUse, bounds.bottom - padding); + } else { + path.moveTo(bounds.right - dp(2.6f), bounds.bottom - padding); + } + path.lineTo(bounds.left + padding + radToUse, bounds.bottom - padding); + rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); + path.arcTo(rect, 90, 90, false); + } else { + path.moveTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); + path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); + } + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullTop) { + path.lineTo(bounds.left + padding, bounds.top + padding + rad); + rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + rad * 2, bounds.top + padding + rad * 2); + path.arcTo(rect, 180, 90, false); + + int radToUse = isTopNear ? nearRad : rad; + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.right - padding - radToUse, bounds.top + padding); + rect.set(bounds.right - padding - radToUse * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + radToUse * 2); + } else { + path.lineTo(bounds.right - dp(8) - radToUse, bounds.top + padding); + rect.set(bounds.right - dp(8) - radToUse * 2, bounds.top + padding, bounds.right - dp(8), bounds.top + padding + radToUse * 2); + } + path.arcTo(rect, 270, 90, false); + } else { + path.lineTo(bounds.left + padding, top - topY - dp(2)); + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.right - padding, top - topY - dp(2)); + } else { + path.lineTo(bounds.right - dp(8), top - topY - dp(2)); + } + } + if (currentType == TYPE_MEDIA) { + if (customPaint || drawFullBottom) { + int radToUse = isBottomNear ? nearRad : rad; + + path.lineTo(bounds.right - padding, bounds.bottom - padding - radToUse); + rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); + path.arcTo(rect, 0, 90, false); + } else { + path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); + } + } else { + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullBottom) { + path.lineTo(bounds.right - dp(8), bounds.bottom - padding - smallRad - dp(3)); + rect.set(bounds.right - dp(8), bounds.bottom - padding - smallRad * 2 - dp(9), bounds.right - dp(7) + smallRad * 2, bounds.bottom - padding - dp(1)); + path.arcTo(rect, 180, -83, false); + } else { + path.lineTo(bounds.right - dp(8), top - topY + currentBackgroundHeight); + } + } + } else { + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullBottom) { + int radToUse = botButtonsBottom ? nearRad : rad; + + if (currentType == TYPE_MEDIA) { + path.moveTo(bounds.left + dp(8) + radToUse, bounds.bottom - padding); + } else { + path.moveTo(bounds.left + dp(2.6f), bounds.bottom - padding); + } + path.lineTo(bounds.right - padding - radToUse, bounds.bottom - padding); + rect.set(bounds.right - padding - radToUse * 2, bounds.bottom - padding - radToUse * 2, bounds.right - padding, bounds.bottom - padding); + path.arcTo(rect, 90, -90, false); + } else { + path.moveTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); + path.lineTo(bounds.right - padding, top - topY + currentBackgroundHeight); + } + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullTop) { + path.lineTo(bounds.right - padding, bounds.top + padding + rad); + rect.set(bounds.right - padding - rad * 2, bounds.top + padding, bounds.right - padding, bounds.top + padding + rad * 2); + path.arcTo(rect, 0, -90, false); + + int radToUse = isTopNear ? nearRad : rad; + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.left + padding + radToUse, bounds.top + padding); + rect.set(bounds.left + padding, bounds.top + padding, bounds.left + padding + radToUse * 2, bounds.top + padding + radToUse * 2); + } else { + path.lineTo(bounds.left + dp(8) + radToUse, bounds.top + padding); + rect.set(bounds.left + dp(8), bounds.top + padding, bounds.left + dp(8) + radToUse * 2, bounds.top + padding + radToUse * 2); + } + path.arcTo(rect, 270, -90, false); + } else { + path.lineTo(bounds.right - padding, top - topY - dp(2)); + if (currentType == TYPE_MEDIA) { + path.lineTo(bounds.left + padding, top - topY - dp(2)); + } else { + path.lineTo(bounds.left + dp(8), top - topY - dp(2)); + } + } + if (currentType == TYPE_MEDIA) { + if (customPaint || drawFullBottom) { + int radToUse = isBottomNear ? nearRad : rad; + + path.lineTo(bounds.left + padding, bounds.bottom - padding - radToUse); + rect.set(bounds.left + padding, bounds.bottom - padding - radToUse * 2, bounds.left + padding + radToUse * 2, bounds.bottom - padding); + path.arcTo(rect, 180, -90, false); + } else { + path.lineTo(bounds.left + padding, top - topY + currentBackgroundHeight); + } + } else { + if (drawFullBubble || currentType == TYPE_PREVIEW || customPaint || drawFullBottom) { + path.lineTo(bounds.left + dp(8), bounds.bottom - padding - smallRad - dp(3)); + rect.set(bounds.left + dp(7) - smallRad * 2, bounds.bottom - padding - smallRad * 2 - dp(9), bounds.left + dp(8), bounds.bottom - padding - dp(1)); + path.arcTo(rect, 0, 83, false); + } else { + path.lineTo(bounds.left + dp(8), top - topY + currentBackgroundHeight); + } + } + } + path.close(); + } + public void setDrawFullBubble(boolean drawFullBuble) { this.drawFullBubble = drawFullBuble; } @@ -1525,6 +1577,7 @@ public class Theme { currentColors.put(key_chat_outForwardedNameText, textColor); currentColors.put(key_chat_outViaBotNameText, textColor); currentColors.put(key_chat_outReplyLine, textColor); + currentColors.put(key_chat_outReplyLine2, textColor); currentColors.put(key_chat_outReplyNameText, textColor); currentColors.put(key_chat_outPreviewLine, textColor); @@ -1694,6 +1747,17 @@ public class Theme { Math.max(0, Color.blue(submenuBackground) - 10) )); + currentColors.put(key_chat_inCodeBackground, codeBackground(inBubble, isDarkTheme)); + if (isDarkTheme && currentColors.get(key_chat_outBubbleGradient1) != 0) { + int outBubbleAverage = averageColor(currentColors, key_chat_outBubbleGradient1, key_chat_outBubbleGradient2, key_chat_outBubbleGradient3); + Color.colorToHSV(outBubbleAverage, tempHSV); + tempHSV[1] = Utilities.clamp(tempHSV[1] + .3f, 1, 0); + tempHSV[2] = Utilities.clamp(tempHSV[2] + -.4f, 1, 0); + currentColors.put(key_chat_outCodeBackground, Color.HSVToColor(0x70, tempHSV)); + } else { + currentColors.put(key_chat_outCodeBackground, codeBackground(outBubble, isDarkTheme)); + } + return !isMyMessagesGradientColorsNear; } @@ -1750,6 +1814,20 @@ public class Theme { tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + (isDarkTheme ? .1f : 0))); return Color.HSVToColor(0x33, tempHSV); } + private int codeBackground(int bubbleColor, boolean isDarkTheme) { + Color.colorToHSV(bubbleColor, tempHSV); + int alpha = 0x20; + if (tempHSV[1] <= 0 || tempHSV[2] >= 1 || tempHSV[2] <= 0) { + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + (isDarkTheme ? .3f : -.2f))); + } else { + tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + (isDarkTheme ? -.3f : .28f))); + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] + (isDarkTheme ? +.1f : -.1f))); + if (isDarkTheme) { + alpha = 0x60; + } + } + return Color.HSVToColor(alpha, tempHSV); + } private int locationPlaceholderColor(float accentHue, int bubbleColor, boolean isDarkTheme) { if (isDarkTheme) { return 0x1effffff; @@ -1933,6 +2011,8 @@ public class Theme { } public static int multAlpha(int color, float multiply) { + if (multiply == 1f) + return color; return ColorUtils.setAlphaComponent(color, MathUtils.clamp((int) (Color.alpha(color) * multiply), 0, 0xFF)); } @@ -3007,7 +3087,7 @@ public class Theme { public static Paint avatar_backgroundPaint; public static Drawable listSelector; - public static Drawable[] avatarDrawables = new Drawable[14]; + public static Drawable[] avatarDrawables = new Drawable[17]; public static Drawable moveUpDrawable; @@ -3084,6 +3164,7 @@ public class Theme { public static Paint chat_outUrlPaint; public static Paint chat_textSearchSelectionPaint; public static Paint chat_instantViewRectPaint; + public static Paint chat_instantViewButtonPaint; public static Paint chat_pollTimerPaint; public static Paint chat_replyLinePaint; public static Paint chat_msgErrorPaint; @@ -3103,6 +3184,9 @@ public class Theme { public static Paint chat_radialProgressPausedSeekbarPaint; public static TextPaint chat_msgTextPaint; + public static TextPaint chat_msgTextCodePaint; + public static TextPaint chat_msgTextCode2Paint; + public static TextPaint chat_msgTextCode3Paint; public static TextPaint chat_actionTextPaint; public static TextPaint chat_actionTextPaint2; public static TextPaint chat_unlockExtendedMediaTextPaint; @@ -3135,10 +3219,12 @@ public class Theme { public static TextPaint chat_forwardNamePaint; public static TextPaint chat_replyNamePaint; public static TextPaint chat_replyTextPaint; + public static TextPaint chat_quoteTextPaint; public static TextPaint chat_topicTextPaint; public static TextPaint chat_commentTextPaint; public static TextPaint chat_contextResult_titleTextPaint; public static TextPaint chat_contextResult_descriptionTextPaint; + public static TextPaint chat_msgCodeBgPaint; public static Drawable chat_msgNoSoundDrawable; public static Drawable chat_composeShadowDrawable; @@ -3154,6 +3240,7 @@ public class Theme { public static MessageDrawable chat_msgOutMediaSelectedDrawable; private static StatusDrawable[] chat_status_drawables = new StatusDrawable[6]; public static PorterDuffColorFilter chat_animatedEmojiTextColorFilter; + public static PorterDuffColorFilter chat_outAnimatedEmojiTextColorFilter; public static PathAnimator playPauseAnimator; public static Drawable chat_msgOutCheckDrawable; @@ -3420,6 +3507,25 @@ public class Theme { public static int[] keys_avatar_background2 = {key_avatar_background2Red, key_avatar_background2Orange, key_avatar_background2Violet, key_avatar_background2Green, key_avatar_background2Cyan, key_avatar_background2Blue, key_avatar_background2Pink}; public static int[] keys_avatar_nameInMessage = {key_avatar_nameInMessageRed, key_avatar_nameInMessageOrange, key_avatar_nameInMessageViolet, key_avatar_nameInMessageGreen, key_avatar_nameInMessageCyan, key_avatar_nameInMessageBlue, key_avatar_nameInMessagePink}; + public static final int key_avatar_composite_nameInMessageRed = colorsCount++; + public static final int key_avatar_composite_nameInMessageOrange = colorsCount++; + public static final int key_avatar_composite_nameInMessageViolet = colorsCount++; + public static final int key_avatar_composite_nameInMessageGreen = colorsCount++; + public static final int key_avatar_composite_nameInMessageCyan = colorsCount++; + public static final int key_avatar_composite_nameInMessageBlue = colorsCount++; + public static final int key_avatar_composite_nameInMessagePink = colorsCount++; + + public static final int key_avatar_composite_nameInMessageRed2 = colorsCount++; + public static final int key_avatar_composite_nameInMessageOrange2 = colorsCount++; + public static final int key_avatar_composite_nameInMessageViolet2 = colorsCount++; + public static final int key_avatar_composite_nameInMessageGreen2 = colorsCount++; + public static final int key_avatar_composite_nameInMessageCyan2 = colorsCount++; + public static final int key_avatar_composite_nameInMessageBlue2 = colorsCount++; + public static final int key_avatar_composite_nameInMessagePink2 = colorsCount++; + + public static int[] keys_avatar_composite_nameInMessage = {key_avatar_composite_nameInMessageRed, key_avatar_composite_nameInMessageOrange, key_avatar_composite_nameInMessageViolet, key_avatar_composite_nameInMessageGreen, key_avatar_composite_nameInMessageCyan, key_avatar_composite_nameInMessageBlue, key_avatar_composite_nameInMessagePink}; + public static int[] keys_avatar_composite_nameInMessage2 = {key_avatar_composite_nameInMessageRed2, key_avatar_composite_nameInMessageOrange2, key_avatar_composite_nameInMessageViolet2, key_avatar_composite_nameInMessageGreen2, key_avatar_composite_nameInMessageCyan2, key_avatar_composite_nameInMessageBlue2, key_avatar_composite_nameInMessagePink2}; + public static final int key_actionBarDefault = colorsCount++; public static final int key_actionBarDefaultSelector = colorsCount++; public static final int key_actionBarWhiteSelector = colorsCount++; @@ -3569,6 +3675,7 @@ public class Theme { public static final int key_chat_outForwardedNameText = colorsCount++; public static final int key_chat_outViaBotNameText = colorsCount++; public static final int key_chat_outReplyLine = colorsCount++; + public static final int key_chat_outReplyLine2 = colorsCount++; public static final int key_chat_outReplyNameText = colorsCount++; public static final int key_chat_outReplyMessageText = colorsCount++; public static final int key_chat_outReplyMediaMessageText = colorsCount++; @@ -3662,6 +3769,8 @@ public class Theme { public static final int key_chat_inPsaNameText = colorsCount++; public static final int key_chat_inViaBotNameText = colorsCount++; public static final int key_chat_stickerViaBotNameText = colorsCount++; + public static final int key_chat_inQuote = colorsCount++; + public static final int key_chat_outQuote = colorsCount++; public static final int key_chat_inReplyLine = colorsCount++; public static final int key_chat_stickerReplyLine = colorsCount++; public static final int key_chat_inReplyNameText = colorsCount++; @@ -4024,6 +4133,17 @@ public class Theme { public static final int key_stories_circle_closeFriends1 = colorsCount++; public static final int key_stories_circle_closeFriends2 = colorsCount++; + public static final int key_code_background = colorsCount++; + public static final int key_chat_inCodeBackground = colorsCount++; + public static final int key_chat_outCodeBackground = colorsCount++; + public static final int key_code_keyword = colorsCount++; + public static final int key_code_operator = colorsCount++; + public static final int key_code_constant = colorsCount++; + public static final int key_code_string = colorsCount++; + public static final int key_code_number = colorsCount++; + public static final int key_code_comment = colorsCount++; + public static final int key_code_function = colorsCount++; + public static final String key_drawable_botInline = "drawableBotInline"; public static final String key_drawable_botLink = "drawableBotLink"; public static final String key_drawable_botWebView = "drawableBotWebView"; @@ -4109,6 +4229,9 @@ public class Theme { static { defaultColors = ThemeColors.createDefaultColors(); + fallbackKeys.put(key_chat_inQuote, key_featuredStickers_addButtonPressed); + fallbackKeys.put(key_chat_outQuote, key_chat_outReplyLine); + fallbackKeys.put(key_chat_outReplyLine2, key_chat_outReplyLine); fallbackKeys.put(key_chat_inAdminText, key_chat_inTimeText); fallbackKeys.put(key_chat_inAdminSelectedText, key_chat_inTimeSelectedText); fallbackKeys.put(key_player_progressCachedBackground, key_player_progressBackground); @@ -4275,6 +4398,12 @@ public class Theme { for (int i = 0; i < keys_avatar_nameInMessage.length; i++) { themeAccentExclusionKeys.add(keys_avatar_nameInMessage[i]); } + for (int i = 0; i < keys_avatar_composite_nameInMessage.length; i++) { + themeAccentExclusionKeys.add(keys_avatar_composite_nameInMessage[i]); + } + for (int i = 0; i < keys_avatar_composite_nameInMessage2.length; i++) { + themeAccentExclusionKeys.add(keys_avatar_composite_nameInMessage2[i]); + } for (int i = 0; i < keys_colors.length; i++) { themeAccentExclusionKeys.add(keys_colors[i]); } @@ -6444,7 +6573,7 @@ public class Theme { return changeColorAccent(hsvTemp3, hsvTemp4, color, themeInfo.isDark()); } - private static float[] getTempHsv(int num) { + public static float[] getTempHsv(int num) { ThreadLocal local; switch (num) { case 1: @@ -7985,6 +8114,9 @@ public class Theme { avatarDrawables[11] = resources.getDrawable(R.drawable.chats_replies); avatarDrawables[12] = resources.getDrawable(R.drawable.other_chats); avatarDrawables[13] = resources.getDrawable(R.drawable.msg_stories_closefriends); + avatarDrawables[14] = resources.getDrawable(R.drawable.filled_gift_premium); + avatarDrawables[15] = resources.getDrawable(R.drawable.filled_unknown); + avatarDrawables[16] = resources.getDrawable(R.drawable.filled_unclaimed); if (dialogs_archiveAvatarDrawable != null) { dialogs_archiveAvatarDrawable.setCallback(null); @@ -8079,6 +8211,7 @@ public class Theme { dialogs_unarchiveDrawable.commitApplyLayerColors(); chat_animatedEmojiTextColorFilter = new PorterDuffColorFilter(getColor(key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN); + chat_outAnimatedEmojiTextColorFilter = new PorterDuffColorFilter(getColor(key_chat_messageTextOut), PorterDuff.Mode.SRC_IN); PremiumGradient.getInstance().checkIconColors(); } @@ -8265,17 +8398,25 @@ public class Theme { chat_msgTextPaintTwoEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG); chat_msgTextPaintThreeEmoji = new TextPaint(Paint.ANTI_ALIAS_FLAG); chat_msgBotButtonPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - chat_msgBotButtonPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + chat_msgBotButtonPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_namePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - chat_namePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + chat_namePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_replyNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + chat_replyNamePaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_replyTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + chat_quoteTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); chat_topicTextPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); - chat_topicTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + chat_topicTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); chat_forwardNamePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); chat_adminPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); chat_timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); + chat_msgTextCodePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + chat_msgTextCodePaint.setTypeface(Typeface.MONOSPACE); + chat_msgTextCode2Paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + chat_msgTextCode2Paint.setTypeface(Typeface.MONOSPACE); + chat_msgTextCode3Paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + chat_msgTextCode3Paint.setTypeface(Typeface.MONOSPACE); + chat_msgCodeBgPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG); } final float[] emojiSizePercents = new float[] {.68f, .46f, .34f, .28f, .22f, .19f}; @@ -8293,9 +8434,13 @@ public class Theme { chat_namePaint.setTextSize(AndroidUtilities.dp(smallerDp)); chat_replyNamePaint.setTextSize(AndroidUtilities.dp(smallerDp)); chat_replyTextPaint.setTextSize(AndroidUtilities.dp(smallerDp)); + chat_quoteTextPaint.setTextSize(AndroidUtilities.dp(smallerDp - 1)); chat_topicTextPaint.setTextSize(AndroidUtilities.dp(smallerDp - 1)); chat_forwardNamePaint.setTextSize(AndroidUtilities.dp(smallerDp)); chat_adminPaint.setTextSize(AndroidUtilities.dp(smallerDp - 1)); + chat_msgTextCodePaint.setTextSize(AndroidUtilities.dp(Math.max(Math.min(10, SharedConfig.fontSize - 1), SharedConfig.fontSize - 2))); + chat_msgTextCode2Paint.setTextSize(AndroidUtilities.dp(Math.max(Math.min(10, SharedConfig.fontSize - 2), SharedConfig.fontSize - 3))); + chat_msgTextCode3Paint.setTextSize(AndroidUtilities.dp(Math.max(Math.min(10, SharedConfig.fontSize - 2), SharedConfig.fontSize - 5))); } } @@ -8361,6 +8506,7 @@ public class Theme { chat_instantViewRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_instantViewRectPaint.setStyle(Paint.Style.STROKE); chat_instantViewRectPaint.setStrokeCap(Paint.Cap.ROUND); + chat_instantViewButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_pollTimerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); chat_pollTimerPaint.setStyle(Paint.Style.STROKE); chat_pollTimerPaint.setStrokeCap(Paint.Cap.ROUND); @@ -8518,8 +8664,8 @@ public class Theme { chat_attachButtonDrawables[5] = new RLottieDrawable(R.raw.attach_poll, "attach_poll", AndroidUtilities.dp(26), AndroidUtilities.dp(26)); chat_attachEmptyDrawable = resources.getDrawable(R.drawable.nophotos3); - chat_shareIconDrawable = resources.getDrawable(R.drawable.share_arrow).mutate(); - chat_replyIconDrawable = resources.getDrawable(R.drawable.fast_reply); + chat_shareIconDrawable = resources.getDrawable(R.drawable.filled_share).mutate(); + chat_replyIconDrawable = resources.getDrawable(R.drawable.filled_reply); chat_goIconDrawable = resources.getDrawable(R.drawable.message_arrow); int rad = AndroidUtilities.dp(2); 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 eda95947e..2e434b0fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ThemeColors.java @@ -164,13 +164,29 @@ public class ThemeColors { defaultColors[key_avatar_actionBarSelectorBlue] = 0xff4981ad; defaultColors[key_avatar_actionBarIconBlue] = 0xffffffff; - defaultColors[key_avatar_nameInMessageRed] = 0xffca5650; - defaultColors[key_avatar_nameInMessageOrange] = 0xffd87b29; - defaultColors[key_avatar_nameInMessageViolet] = 0xff9B66DC; - defaultColors[key_avatar_nameInMessageGreen] = 0xff50b232; - defaultColors[key_avatar_nameInMessageCyan] = 0xff379eb8; - defaultColors[key_avatar_nameInMessageBlue] = 0xff4e92cc; - defaultColors[key_avatar_nameInMessagePink] = 0xffCF5C95; + defaultColors[key_avatar_nameInMessageRed] = 0xffCC5049; + defaultColors[key_avatar_nameInMessageOrange] = 0xffD67722; + defaultColors[key_avatar_nameInMessageViolet] = 0xff955CDB; + defaultColors[key_avatar_nameInMessageGreen] = 0xff40A920; + defaultColors[key_avatar_nameInMessageCyan] = 0xff309EBA; + defaultColors[key_avatar_nameInMessageBlue] = 0xff368AD1; + defaultColors[key_avatar_nameInMessagePink] = 0xffC7508B; + + defaultColors[key_avatar_composite_nameInMessageRed] = 0xffE15052; + defaultColors[key_avatar_composite_nameInMessageOrange] = 0xffE0802B; + defaultColors[key_avatar_composite_nameInMessageViolet] = 0xffA05FF3; + defaultColors[key_avatar_composite_nameInMessageGreen] = 0xff27A910; + defaultColors[key_avatar_composite_nameInMessageCyan] = 0xff27ACCE; + defaultColors[key_avatar_composite_nameInMessageBlue] = 0xff3391D4; + defaultColors[key_avatar_composite_nameInMessagePink] = 0xffD14972; + + defaultColors[key_avatar_composite_nameInMessageRed2] = 0xffF9AE63; + defaultColors[key_avatar_composite_nameInMessageOrange2] = 0xffFAC534; + defaultColors[key_avatar_composite_nameInMessageViolet2] = 0xffF48FFF; + defaultColors[key_avatar_composite_nameInMessageGreen2] = 0xffA7DC57; + defaultColors[key_avatar_composite_nameInMessageCyan2] = 0xff82E8D6; + defaultColors[key_avatar_composite_nameInMessageBlue2] = 0xff7DD3F0; + defaultColors[key_avatar_composite_nameInMessagePink2] = 0xffFFBE9F; defaultColors[key_actionBarDefault] = 0xff527da3; defaultColors[key_actionBarDefaultIcon] = 0xffffffff; @@ -347,6 +363,7 @@ public class ThemeColors { defaultColors[key_chat_stickerViaBotNameText] = 0xffffffff; defaultColors[key_chat_inReplyLine] = 0xff599fd8; defaultColors[key_chat_outReplyLine] = 0xff6eb969; + defaultColors[key_chat_outReplyLine2] = 0xff40A920; defaultColors[key_chat_stickerReplyLine] = 0xffffffff; defaultColors[key_chat_inReplyNameText] = 0xff3a8ccf; defaultColors[key_chat_outReplyNameText] = 0xff55ab4f; @@ -512,6 +529,8 @@ public class ThemeColors { defaultColors[key_chat_mediaLoaderPhotoIcon] = 0xffffffff; defaultColors[key_chat_mediaLoaderPhotoIconSelected] = 0xffd9d9d9; defaultColors[key_chat_serviceBackgroundSelector] = 0x20ffffff; + defaultColors[key_chat_inQuote] = 0xff459BD8; + defaultColors[key_chat_outQuote] = 0xff6AB860; defaultColors[key_profile_creatorIcon] = 0xff3a95d5; defaultColors[key_profile_actionIcon] = 0xff81868a; @@ -767,6 +786,17 @@ public class ThemeColors { defaultColors[key_stories_circle_closeFriends1] = 0xFFC9EB38; defaultColors[key_stories_circle_closeFriends2] = 0xFF09C167; + defaultColors[key_code_background] = 0x20000000; + defaultColors[key_chat_inCodeBackground] = 0x08484848; + defaultColors[key_chat_outCodeBackground] = 0x123c7503; + defaultColors[key_code_keyword] = 0xFFE05356; + defaultColors[key_code_operator] = 0xFF4DBBFF; + defaultColors[key_code_constant] = 0xFF7F79F3; + defaultColors[key_code_string] = 0xFF61C752; + defaultColors[key_code_number] = 0xFF327FE5; + defaultColors[key_code_comment] = 0x80000000; + defaultColors[key_code_function] = 0xFFF28C39; + return defaultColors; } @@ -932,6 +962,20 @@ public class ThemeColors { colorKeysMap.put(key_avatar_nameInMessageCyan, "avatar_nameInMessageCyan"); colorKeysMap.put(key_avatar_nameInMessageBlue, "avatar_nameInMessageBlue"); colorKeysMap.put(key_avatar_nameInMessagePink, "avatar_nameInMessagePink"); + colorKeysMap.put(key_avatar_composite_nameInMessageRed, "avatar_composite_nameInMessageRed"); + colorKeysMap.put(key_avatar_composite_nameInMessageOrange, "avatar_composite_nameInMessageOrange"); + colorKeysMap.put(key_avatar_composite_nameInMessageViolet, "avatar_composite_nameInMessageViolet"); + colorKeysMap.put(key_avatar_composite_nameInMessageGreen, "avatar_composite_nameInMessageGreen"); + colorKeysMap.put(key_avatar_composite_nameInMessageCyan, "avatar_composite_nameInMessageCyan"); + colorKeysMap.put(key_avatar_composite_nameInMessageBlue, "avatar_composite_nameInMessageBlue"); + colorKeysMap.put(key_avatar_composite_nameInMessagePink, "avatar_composite_nameInMessagePink"); + colorKeysMap.put(key_avatar_composite_nameInMessageRed2, "avatar_composite_nameInMessageRed2"); + colorKeysMap.put(key_avatar_composite_nameInMessageOrange2, "avatar_composite_nameInMessageOrange2"); + colorKeysMap.put(key_avatar_composite_nameInMessageViolet2, "avatar_composite_nameInMessageViolet2"); + colorKeysMap.put(key_avatar_composite_nameInMessageGreen2, "avatar_composite_nameInMessageGreen2"); + colorKeysMap.put(key_avatar_composite_nameInMessageCyan2, "avatar_composite_nameInMessageCyan2"); + colorKeysMap.put(key_avatar_composite_nameInMessageBlue2, "avatar_composite_nameInMessageBlue2"); + colorKeysMap.put(key_avatar_composite_nameInMessagePink2, "avatar_composite_nameInMessagePink2"); colorKeysMap.put(key_actionBarDefault, "actionBarDefault"); colorKeysMap.put(key_actionBarDefaultSelector, "actionBarDefaultSelector"); colorKeysMap.put(key_actionBarWhiteSelector, "actionBarWhiteSelector"); @@ -1064,6 +1108,8 @@ public class ThemeColors { colorKeysMap.put(key_chat_serviceBackground, "chat_serviceBackground"); colorKeysMap.put(key_chat_serviceBackgroundSelected, "chat_serviceBackgroundSelected"); colorKeysMap.put(key_chat_serviceBackgroundSelector, "chat_serviceBackgroundSelector"); + colorKeysMap.put(key_chat_inQuote, "chat_inQuote"); + colorKeysMap.put(key_chat_outQuote, "chat_outQuote"); colorKeysMap.put(key_chat_muteIcon, "chat_muteIcon"); colorKeysMap.put(key_chat_lockIcon, "chat_lockIcon"); colorKeysMap.put(key_chat_outSentCheck, "chat_outSentCheck"); @@ -1114,6 +1160,7 @@ public class ThemeColors { colorKeysMap.put(key_chat_stickerViaBotNameText, "chat_stickerViaBotNameText"); colorKeysMap.put(key_chat_inReplyLine, "chat_inReplyLine"); colorKeysMap.put(key_chat_outReplyLine, "chat_outReplyLine"); + colorKeysMap.put(key_chat_outReplyLine2, "chat_outReplyLine2"); colorKeysMap.put(key_chat_stickerReplyLine, "chat_stickerReplyLine"); colorKeysMap.put(key_chat_inReplyNameText, "chat_inReplyNameText"); colorKeysMap.put(key_chat_outReplyNameText, "chat_outReplyNameText"); @@ -1494,6 +1541,16 @@ public class ThemeColors { colorKeysMap.put(key_stories_circle_dialog2, "stories_circle_dialog2"); colorKeysMap.put(key_stories_circle_closeFriends1, "stories_circle_closeFriends1"); colorKeysMap.put(key_stories_circle_closeFriends2, "stories_circle_closeFriends2"); + colorKeysMap.put(key_code_background, "code_background"); + colorKeysMap.put(key_chat_inCodeBackground, "chat_inCodeBackground"); + colorKeysMap.put(key_chat_outCodeBackground, "chat_outCodeBackground"); + colorKeysMap.put(key_code_keyword, "code_keyword"); + colorKeysMap.put(key_code_operator, "code_operator"); + colorKeysMap.put(key_code_constant, "code_constant"); + colorKeysMap.put(key_code_string, "code_string"); + colorKeysMap.put(key_code_number, "code_number"); + colorKeysMap.put(key_code_comment, "code_comment"); + colorKeysMap.put(key_code_function, "code_function"); 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 6949aadad..0fd62204f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -32,6 +32,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -72,7 +73,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { private boolean hasGps; private boolean isEmpty; public boolean hasStories; - public ArrayList userStories = new ArrayList<>(); + public ArrayList userStories = new ArrayList<>(); DialogStoriesCell dialogStoriesCell; BaseFragment fragment; @@ -88,7 +89,7 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { this.fragment = fragment; } - public void setStories(ArrayList stories, boolean animated) { + public void setStories(ArrayList stories, boolean animated) { // boolean hasStories = !stories.isEmpty(); // userStories.clear(); // userStories.addAll(stories); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java index c1b2bdb5f..aaacfd0ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -18,7 +18,6 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.SystemClock; import android.util.TypedValue; -import android.view.ContextMenu; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; @@ -26,31 +25,28 @@ import android.widget.FrameLayout; import android.widget.TextView; import androidx.recyclerview.widget.DiffUtil; -import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; -import com.google.android.exoplayer2.util.Log; - -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.fakepasscode.FakePasscode; import org.telegram.messenger.UserObject; -import org.telegram.messenger.fakepasscode.FakePasscodeUtils; +import org.telegram.messenger.Utilities; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ArchiveHintCell; @@ -79,7 +75,6 @@ import org.telegram.ui.DialogsActivity; import org.telegram.ui.Stories.DialogStoriesCell; import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; -import org.telegram.ui.Stories.StoriesUtilities; import java.util.ArrayList; import java.util.Collections; @@ -268,10 +263,10 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements boolean isForumCell; private boolean pinned; private boolean isFolder; - TLRPC.TL_chatlists_chatlistUpdates chatlistUpdates; + TL_chatlists.TL_chatlists_chatlistUpdates chatlistUpdates; private int emptyType; - public ItemInternal(TLRPC.TL_chatlists_chatlistUpdates updates) { + public ItemInternal(TL_chatlists.TL_chatlists_chatlistUpdates updates) { super(VIEW_TYPE_FOLDER_UPDATE_HINT, true); this.chatlistUpdates = updates; stableId = stableIdPointer++; @@ -471,42 +466,23 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements hasHints = folderId == 0 && dialogsType == DialogsActivity.DIALOGS_TYPE_DEFAULT && !isOnlySelect && !MessagesController.getInstance(currentAccount).hintDialogs.isEmpty(); } - public void updateList(RecyclerListView recyclerListView, boolean hasHiddenArchive, float tabsTranslation, boolean hasStories) { - oldItems.clear(); + boolean isCalculatingDiff; + boolean updateListPending; + private final static boolean ALLOW_UPDATE_IN_BACKGROUND = BuildVars.DEBUG_VERSION; + + public void updateList(Runnable saveScrollPosition) { + if (isCalculatingDiff) { + updateListPending = true; + return; + } + isCalculatingDiff = true; + oldItems = new ArrayList<>(); oldItems.addAll(itemInternals); updateItemList(); + ArrayList newItems = new ArrayList<>(itemInternals); + itemInternals = oldItems; - if (recyclerListView != null && recyclerListView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE && recyclerListView.getChildCount() > 0 && recyclerListView.getLayoutManager() != null) { - LinearLayoutManager layoutManager = ((LinearLayoutManager) recyclerListView.getLayoutManager()); - View view = null; - int position = -1; - int top = Integer.MAX_VALUE; - for (int i = 0; i < recyclerListView.getChildCount(); i++) { - int childPosition = recyclerListView.getChildAdapterPosition(recyclerListView.getChildAt(i)); - View child = recyclerListView.getChildAt(i); - if (childPosition != RecyclerListView.NO_POSITION && child != null && child.getTop() < top) { - view = child; - position = childPosition; - top = child.getTop(); - } - } - if (view != null) { - float offset = view.getTop() - recyclerListView.getPaddingTop(); - if (!hasStories) { - // offset += tabsTranslation; - } else { - tabsTranslation = 0; - } - if (recyclerListView.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING) { - if (hasHiddenArchive && position == 0 && recyclerListView.getPaddingTop() - view.getTop() - view.getMeasuredHeight() + tabsTranslation < 0) { - position = 1; - offset = tabsTranslation; - } - layoutManager.scrollToPositionWithOffset(position, (int) offset); - } - } - } - DiffUtil.calculateDiff(new DiffUtil.Callback() { + DiffUtil.Callback callback = new DiffUtil.Callback() { @Override public int getOldListSize() { return oldItems.size(); @@ -514,23 +490,56 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements @Override public int getNewListSize() { - return itemInternals.size(); + return newItems.size(); } @Override public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).compare(itemInternals.get(newItemPosition)); + return oldItems.get(oldItemPosition).compare(newItems.get(newItemPosition)); } @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - return oldItems.get(oldItemPosition).viewType == itemInternals.get(newItemPosition).viewType; + return oldItems.get(oldItemPosition).viewType == newItems.get(newItemPosition).viewType; } - }).dispatchUpdatesTo(this); + }; + if (itemInternals.size() < 50 || !ALLOW_UPDATE_IN_BACKGROUND) { + DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback); + isCalculatingDiff = false; + if (saveScrollPosition != null) { + saveScrollPosition.run(); + } + itemInternals = newItems; + result.dispatchUpdatesTo(this); + } else { + Utilities.searchQueue.postRunnable(() -> { + DiffUtil.DiffResult result = DiffUtil.calculateDiff(callback); + AndroidUtilities.runOnUIThread(() -> { + if (!isCalculatingDiff) { + return; + } + isCalculatingDiff = false; + if (saveScrollPosition != null) { + saveScrollPosition.run(); + } + itemInternals = newItems; + result.dispatchUpdatesTo(this); + if (updateListPending) { + updateListPending = false; + updateList(saveScrollPosition); + } + }); + }); + } + } @Override public void notifyDataSetChanged() { + if (isCalculatingDiff) { + itemInternals = new ArrayList<>(); + } + isCalculatingDiff = false; updateItemList(); super.notifyDataSetChanged(); } @@ -1004,7 +1013,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements } } - public TLRPC.TL_chatlists_chatlistUpdates getChatlistUpdate() { + public TL_chatlists.TL_chatlists_chatlistUpdates getChatlistUpdate() { ItemInternal item = itemInternals.get(0); if (item != null && item.viewType == VIEW_TYPE_FOLDER_UPDATE_HINT) { return item.chatlistUpdates; @@ -1039,7 +1048,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements toDialog.pinnedNum = oldNum; } Collections.swap(dialogs, fromIndex, toIndex); - updateList(recyclerView, false, 0, false); + updateList(null); } @Override @@ -1421,7 +1430,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter implements MessagesController.DialogFilter filter = messagesController.selectedDialogFilter[dialogsType - 7]; if (filter != null && filter.isChatlist()) { messagesController.checkChatlistFolderUpdate(filter.id, false); - TLRPC.TL_chatlists_chatlistUpdates updates = messagesController.getChatlistFolderUpdates(filter.id); + TL_chatlists.TL_chatlists_chatlistUpdates updates = messagesController.getChatlistFolderUpdates(filter.id); if (updates != null && updates.missing_peers.size() > 0) { hasChatlistHint = true; itemInternals.add(new ItemInternal(updates)); 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 7bce10d03..6f72d9341 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -145,6 +145,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement private String lastSticker; private int lastReqId; private boolean delayLocalResults; + private Runnable checkAgainRunnable; private ChatActivity parentFragment; private final Theme.ResourcesProvider resourcesProvider; @@ -205,6 +206,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoadFailed); } + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentDocumentsDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersDidLoad); } public TLRPC.User getFoundContextBot() { @@ -221,6 +224,18 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement delegate.needChangePanelVisibility(getItemCountInternal() > 0); } } + } else if (id == NotificationCenter.recentDocumentsDidLoad) { + if (checkAgainRunnable != null) { + AndroidUtilities.runOnUIThread(checkAgainRunnable); + checkAgainRunnable = null; + } + } else if (id == NotificationCenter.stickersDidLoad) { + if ((int) args[0] == MediaDataController.TYPE_IMAGE) { + if (checkAgainRunnable != null) { + AndroidUtilities.runOnUIThread(checkAgainRunnable); + checkAgainRunnable = null; + } + } } } @@ -436,6 +451,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoadFailed); } + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentDocumentsDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); } public void setParentFragment(ChatActivity fragment) { @@ -834,6 +851,10 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement AndroidUtilities.cancelRunOnUIThread(searchGlobalRunnable); searchGlobalRunnable = null; } + if (checkAgainRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(checkAgainRunnable); + checkAgainRunnable = null; + } if (TextUtils.isEmpty(text) || text.length() > MessagesController.getInstance(currentAccount).maxMessageLength) { searchForContextBot(null, null); delegate.needChangePanelVisibility(false); @@ -898,6 +919,9 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement delayLocalResults = false; if (!serverStickersOnly) { + checkAgainRunnable = () -> searchUsernameOrHashtag(charSequence, position, messageObjects, usernameOnly, forSearch); + MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_IMAGE, false, true, false); + MediaDataController.getInstance(currentAccount).loadRecents(MediaDataController.TYPE_FAVE, false, true, false); final ArrayList recentStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_IMAGE); final ArrayList favsStickers = MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_FAVE); int recentsAdded = 0; @@ -918,6 +942,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement } } + MediaDataController.getInstance(currentAccount).checkStickers(MediaDataController.TYPE_IMAGE); HashMap> allStickers = MediaDataController.getInstance(currentAccount).getAllStickers(); ArrayList newStickers = allStickers != null ? allStickers.get(lastSticker) : null; if (newStickers != null && !newStickers.isEmpty()) { @@ -1421,7 +1446,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement searchResultCommandsUsers = null; notifyDataSetChanged(); delegate.needChangePanelVisibility(searchResultSuggestions != null && !searchResultSuggestions.isEmpty()); - }, true); + }, SharedConfig.suggestAnimatedEmoji && UserConfig.getInstance(currentAccount).isPremium()); } else if (foundType == 4) { searchResultHashtags = null; searchResultUsernames = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java index 2b5988122..00e47162e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -20,6 +20,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; @@ -101,7 +102,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement notifyDataSetChanged(); delegate.needChangePanelVisibility(visible = !param.isEmpty()); } - }, true); + }, SharedConfig.suggestAnimatedEmoji && UserConfig.getInstance(currentAccount).isPremium()); if (keywordResults == null || keywordResults.isEmpty()) { AndroidUtilities.runOnUIThread(searchRunnable, 1000); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index d2a49236c..b83f7637c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -65,7 +65,6 @@ import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; -import android.view.PixelCopy; import android.view.SoundEffectConstants; import android.view.Surface; import android.view.SurfaceView; @@ -149,7 +148,6 @@ import org.telegram.ui.Cells.TextSelectionHelper; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AnchorSpan; import org.telegram.ui.Components.AnimatedArrowDrawable; -import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BulletinFactory; @@ -210,7 +208,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private boolean isVisible; private boolean collapsed; private boolean attachedToWindow; - + private int currentAccount; private int lastBlockNum = 1; @@ -1153,7 +1151,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg windowView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); } } else if (pressedLinkOwnerLayout != null && pressedLinkOwnerView != null) { - windowView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);; + windowView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); int[] location = new int[2]; pressedLinkOwnerView.getLocationInWindow(location); @@ -1777,7 +1775,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg builder.setDelegate(new BottomSheet.BottomSheetDelegate() { @Override public boolean canDismiss() { - if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isInSelectionMode()){ + if (textSelectionHelperBottomSheet != null && textSelectionHelperBottomSheet.isInSelectionMode()) { textSelectionHelperBottomSheet.clear(); return false; } @@ -2189,7 +2187,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg return ((TLRPC.TL_textEmail) richText).email; } else if (richText instanceof TLRPC.TL_textUrl) { return ((TLRPC.TL_textUrl) richText).url; - }else if (richText instanceof TLRPC.TL_textPhone) { + } else if (richText instanceof TLRPC.TL_textPhone) { return ((TLRPC.TL_textPhone) richText).phone; } return null; @@ -2801,7 +2799,16 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg openUrlReqId = 0; showProgressView(true, false); if (isVisible) { - if (response instanceof TLRPC.TL_webPage && ((TLRPC.TL_webPage) response).cached_page instanceof TLRPC.TL_page) { + if (response instanceof TLRPC.TL_messages_webPage) { + TLRPC.TL_messages_webPage res = (TLRPC.TL_messages_webPage) response; + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + if (res.webpage != null && res.webpage.cached_page instanceof TLRPC.TL_page) { + addPageToStack(res.webpage, anchor, 1); + } else { + Browser.openUrl(parentActivity, req.url); + } + } else if (response instanceof TLRPC.TL_webPage && ((TLRPC.TL_webPage) response).cached_page instanceof TLRPC.TL_page) { addPageToStack((TLRPC.TL_webPage) response, anchor, 1); } else { Browser.openUrl(parentActivity, req.url); @@ -4236,7 +4243,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } final TLRPC.WebPage webPageFinal = webpage; final int currentAccount = UserConfig.selectedAccount; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (_response, error) -> AndroidUtilities.runOnUIThread(() -> { + Object response = _response; + if (response instanceof TLRPC.TL_messages_webPage) { + TLRPC.TL_messages_webPage res = (TLRPC.TL_messages_webPage) response; + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + response = res.webpage; + } if (response instanceof TLRPC.TL_webPage) { final TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) response; if (webPage.cached_page == null) { @@ -4631,7 +4645,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg customViewCallback.onCustomViewHidden(); fullscreenVideoContainer.removeView(customView); customView = null; - } else if (fullscreenedVideo != null) { + } else if (fullscreenedVideo != null) { fullscreenedVideo.exitFullscreen(); } if (!force) { @@ -4930,7 +4944,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - public static File getMediaFile(TLRPC.WebPage page, TLRPC.PageBlock block) { + public static File getMediaFile(TLRPC.WebPage page, TLRPC.PageBlock block) { if (block instanceof TLRPC.TL_pageBlockPhoto) { TLRPC.Photo photo = getPhotoWithId(page, ((TLRPC.TL_pageBlockPhoto) block).photo_id); if (photo != null) { @@ -6036,6 +6050,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg private DrawingText captionLayout; private DrawingText creditLayout; private ImageReceiver imageView; + FrameLayout aspectRationContainer; private AspectRatioFrameLayout aspectRatioFrameLayout; private TextureView textureView; private RadialProgress2 radialProgress; @@ -6087,15 +6102,17 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); textureView = new TextureView(context); textureView.setOpaque(false); - aspectRatioFrameLayout.addView(textureView); + aspectRationContainer = new FrameLayout(getContext()); + aspectRatioFrameLayout.addView(textureView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); - addView(aspectRatioFrameLayout); + aspectRationContainer.addView(aspectRatioFrameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); + addView(aspectRationContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); addView(channelCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child == aspectRatioFrameLayout && pinchToZoomHelper.isInOverlayModeFor(this)) { + if (child == aspectRationContainer && pinchToZoomHelper.isInOverlayModeFor(this)) { return true; } return super.drawChild(canvas, child, drawingTime); @@ -6109,6 +6126,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg isFirst = first; channelCell.setVisibility(INVISIBLE); updateButtonState(false); + requestLayout(); } @@ -6126,7 +6144,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @Override public boolean onTouchEvent(MotionEvent event) { - if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, textureView, null)) { + if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, aspectRationContainer, textureView, null)) { return true; } float x = event.getX(); @@ -6238,25 +6256,20 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg imageView.setImageCoords(photoX, photoY, photoWidth, photoHeight); if (isGif) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(DownloadController.AUTODOWNLOAD_TYPE_VIDEO, currentDocument.size); - File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); - if (autoDownload || path.exists()) { + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument); + File path2 = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); + if (autoDownload || path.exists() || path2.exists()) { imageView.setStrippedLocation(null); - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(currentDocument.thumbs, 1000); - imageView.setImage(null, null, ImageLocation.getForObject(photoSize, currentDocument), "200_200", ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); + imageView.setImage(null, null, ImageLocation.getForDocument(currentDocument), "200_200_pframe", ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); } else { imageView.setStrippedLocation(ImageLocation.getForDocument(currentDocument)); imageView.setImage(null, null, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); } - FrameLayout.LayoutParams params = (LayoutParams) aspectRatioFrameLayout.getLayoutParams(); - params.leftMargin = photoX; - params.topMargin = photoY; - params.width = photoWidth; - params.height = photoHeight; } else { imageView.setStrippedLocation(null); imageView.setImage(null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", 0, null, parentAdapter.currentPage, 1); } - // imageView.setAspectFit(true); + imageView.setAspectFit(true); buttonX = (int) (imageView.getImageX() + (imageView.getImageWidth() - size) / 2.0f); buttonY = (int) (imageView.getImageY() + (imageView.getImageHeight() - size) / 2.0f); radialProgress.setProgressRect(buttonX, buttonY, buttonX + size, buttonY + size); @@ -6289,7 +6302,11 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } channelCell.measure(widthMeasureSpec, heightMeasureSpec); channelCell.setTranslationY(imageView.getImageHeight() - AndroidUtilities.dp(39)); - + FrameLayout.LayoutParams params = (LayoutParams) aspectRationContainer.getLayoutParams(); + params.leftMargin = (int) imageView.getImageX(); + params.topMargin = (int) imageView.getImageY(); + params.width = (int) imageView.getImageWidth(); + params.height = (int) imageView.getImageHeight(); super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); } @@ -6346,8 +6363,9 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public void updateButtonState(boolean animated) { String fileName = FileLoader.getAttachFileName(currentDocument); - File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); - boolean fileExists = path.exists(); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument); + File path2 = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); + boolean fileExists = path.exists() || path2.exists(); if (TextUtils.isEmpty(fileName)) { radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, false); return; @@ -6457,6 +6475,12 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg }.with(textureView); TLRPC.Document document = currentDocument; + for (int i = 0; i < document.attributes.size(); i++) { + if (document.attributes.get(i) instanceof TLRPC.TL_documentAttributeVideo) { + TLRPC.TL_documentAttributeVideo videoAttr = (TLRPC.TL_documentAttributeVideo) document.attributes.get(i); + aspectRatioFrameLayout.setAspectRatio(videoAttr.w / (float) videoAttr.h, 0); + } + } Uri uri = FileStreamLoadOperation.prepareUri(currentAccount, document, parentAdapter.currentPage); if (uri == null) { return; @@ -6984,7 +7008,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } nameLayout = createLayoutForText(this, currentBlock.author, null, width - AndroidUtilities.dp(36 + 14 + (avatarVisible ? 40 + 14 : 0)), 0, currentBlock, Layout.Alignment.ALIGN_NORMAL, 1, parentAdapter); - if (nameLayout != null){ + if (nameLayout != null) { nameLayout.x = AndroidUtilities.dp(18 + 14 + (avatarVisible ? 40 + 14 : 0)); nameLayout.y = AndroidUtilities.dp(dateLayout != null ? 10 : 19); } @@ -7903,7 +7927,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private class BlockCollageCell extends FrameLayout implements TextSelectionHelper.ArticleSelectableView{ + private class BlockCollageCell extends FrameLayout implements TextSelectionHelper.ArticleSelectableView { private RecyclerListView innerListView; private RecyclerView.Adapter innerAdapter; @@ -7935,18 +7959,18 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public float[] heights; public MessageGroupedLayoutAttempt(int i1, int i2, float f1, float f2) { - lineCounts = new int[] {i1, i2}; - heights = new float[] {f1, f2}; + lineCounts = new int[]{i1, i2}; + heights = new float[]{f1, f2}; } public MessageGroupedLayoutAttempt(int i1, int i2, int i3, float f1, float f2, float f3) { - lineCounts = new int[] {i1, i2, i3}; - heights = new float[] {f1, f2, f3}; + lineCounts = new int[]{i1, i2, i3}; + heights = new float[]{f1, f2, f3}; } public MessageGroupedLayoutAttempt(int i1, int i2, int i3, int i4, float f1, float f2, float f3, float f4) { - lineCounts = new int[] {i1, i2, i3, i4}; - heights = new float[] {f1, f2, f3, f4}; + lineCounts = new int[]{i1, i2, i3, i4}; + heights = new float[]{f1, f2, f3, f4}; } } @@ -8068,7 +8092,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg position3.set(0, 1, 1, 1, rightWidth, thirdHeight / maxSizeHeight, POSITION_FLAG_RIGHT | POSITION_FLAG_BOTTOM); position3.spanSize = maxSizeWidth; - position1.siblingHeights = new float[] {thirdHeight / maxSizeHeight, secondHeight / maxSizeHeight}; + position1.siblingHeights = new float[]{thirdHeight / maxSizeHeight, secondHeight / maxSizeHeight}; position2.spanSize = maxSizeWidth - leftWidth; position3.leftSpanOffset = leftWidth; @@ -8122,7 +8146,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg position3.leftSpanOffset = w0; position4.leftSpanOffset = w0; - position1.siblingHeights = new float[] {h0, h1, h2}; + position1.siblingHeights = new float[]{h0, h1, h2}; hasSibling = true; } } @@ -8179,7 +8203,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg MessageGroupedLayoutAttempt attempt = attempts.get(a); float height = 0; float minLineHeight = Float.MAX_VALUE; - for (int b = 0; b < attempt.heights.length; b++){ + for (int b = 0; b < attempt.heights.length; b++) { height += attempt.heights[b]; if (attempt.heights[b] < minLineHeight) { minLineHeight = attempt.heights[b]; @@ -8974,7 +8998,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas, this); canvas.restore(); } @@ -9172,8 +9196,8 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg ((TextSelectionHelper.ArticleSelectableView) blockLayout.itemView).fillTextLayoutBlocks(textSelectionHelper.arrayList); for (TextSelectionHelper.TextLayoutBlock block : textSelectionHelper.arrayList) { if (block instanceof DrawingText) { - ((DrawingText)block).x += blockX; - ((DrawingText)block).y += blockY; + ((DrawingText) block).x += blockX; + ((DrawingText) block).y += blockY; } } } @@ -9319,7 +9343,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas, this); canvas.restore(); } @@ -10058,7 +10082,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg @Override public boolean onTouchEvent(MotionEvent event) { - if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, null, null)) { + if (pinchToZoomHelper.checkPinchToZoom(event, this, imageView, null, null, null)) { return true; } float x = event.getX(); @@ -10238,14 +10262,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (captionLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this, count++); + drawTextSelection(canvas, this, count++); captionLayout.draw(canvas, this); canvas.restore(); } if (creditLayout != null) { canvas.save(); canvas.translate(textX, textY + creditOffset); - drawTextSelection(canvas,this, count); + drawTextSelection(canvas, this, count); creditLayout.draw(canvas, this); canvas.restore(); } @@ -10857,14 +10881,14 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setEnabled(true); + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); if (textLayout == null) return; - info.setText(textLayout.getText()); - } + info.setText(textLayout.getText()); + } @Override public void fillTextLayoutBlocks(ArrayList blocks) { @@ -10933,7 +10957,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (textLayout != null) { canvas.save(); canvas.translate(textX, textY); - drawTextSelection(canvas,this); + drawTextSelection(canvas, this); textLayout.draw(canvas, this); canvas.restore(); } @@ -11234,7 +11258,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg } } - private class BlockSubheaderCell extends View implements TextSelectionHelper.ArticleSelectableView{ + private class BlockSubheaderCell extends View implements TextSelectionHelper.ArticleSelectableView { private DrawingText textLayout; private int textX = AndroidUtilities.dp(18); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index bf7a211c0..b5b7477a9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -116,6 +116,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Locale; import java.util.Objects; public class CacheControlActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -675,7 +676,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe String percentString = percent <= 0 ? String.format("<%.1f%%", 1f) : String.format("%d%%", percent); SpannableString percentStr = new SpannableString(percentString); percentStr.setSpan(new RelativeSizeSpan(.834f), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - percentStr.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + percentStr.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, percentStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); SpannableStringBuilder string = new SpannableStringBuilder(header); string.append(" "); string.append(percentStr); @@ -1246,26 +1247,30 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe actionModeTitle = new AnimatedTextView(context, true, true, true); actionModeTitle.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); actionModeTitle.setTextSize(AndroidUtilities.dp(18)); - actionModeTitle.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + actionModeTitle.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); actionModeTitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - actionModeLayout.addView(actionModeTitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, -11, 0, 0)); + actionModeLayout.addView(actionModeTitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, -11, 18, 0)); actionModeSubtitle = new AnimatedTextView(context, true, true, true); actionModeSubtitle.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); actionModeSubtitle.setTextSize(AndroidUtilities.dp(14)); actionModeSubtitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); - actionModeLayout.addView(actionModeSubtitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, 10, 0, 0)); + actionModeLayout.addView(actionModeSubtitle, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 18, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, 10, 18, 0)); actionModeClearButton = new TextView(context); actionModeClearButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); actionModeClearButton.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0); actionModeClearButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); actionModeClearButton.setBackground(Theme.AdaptiveRipple.filledRectByKey(Theme.key_featuredStickers_addButton, 6)); - actionModeClearButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + actionModeClearButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); actionModeClearButton.setGravity(Gravity.CENTER); actionModeClearButton.setText(LocaleController.getString("CacheClear", R.string.CacheClear)); actionModeClearButton.setOnClickListener(e -> clearSelectedFiles()); - actionModeLayout.addView(actionModeClearButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 14, 0)); + if (LocaleController.isRTL) { + actionModeLayout.addView(actionModeClearButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.LEFT | Gravity.CENTER_VERTICAL, 0, 0, 0, 0)); + } else { + actionModeLayout.addView(actionModeClearButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 14, 0)); + } ActionBarMenuItem otherItem = actionBar.createMenu().addItem(other_id, R.drawable.ic_ab_other); clearDatabaseItem = otherItem.addSubItem(clear_database_id, R.drawable.msg_delete, LocaleController.getString("ClearLocalDatabase", R.string.ClearLocalDatabase)); @@ -1691,7 +1696,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe title = new AnimatedTextView(context); title.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); - title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); title.setTextSize(AndroidUtilities.dp(20)); title.setText(LocaleController.getString("StorageUsage", R.string.StorageUsage)); title.setGravity(Gravity.CENTER); @@ -1851,7 +1856,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe loadingDrawable.setAlpha((int) (0xFF * barAlpha * loading)); loadingDrawable.draw(canvas); - usedPercentPaint.setColor(Theme.percentSV(Theme.getColor(Theme.key_radioBackgroundChecked), Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), .922f, 1.8f)); + usedPercentPaint.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_radioBackgroundChecked), Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), .75f)); usedPercentPaint.setAlpha((int) (usedPercentPaint.getAlpha() * barAlpha)); AndroidUtilities.rectTmp.set( progressRect.left + (1f - loading) * Math.max(AndroidUtilities.dp(4), percent * progressRect.width()) + AndroidUtilities.dp(1), @@ -2144,7 +2149,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe rtlTextView.setText(LocaleController.getString("ClearCache", R.string.ClearCache)); rtlTextView.setGravity(Gravity.CENTER); rtlTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - rtlTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + rtlTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); rtlTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); button.addView(rtlTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); } @@ -2155,15 +2160,15 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe textView.setTextSize(AndroidUtilities.dp(14)); textView.setText(LocaleController.getString("ClearCache", R.string.ClearCache)); textView.setGravity(Gravity.RIGHT); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); valueTextView = new AnimatedTextView.AnimatedTextDrawable(true, true, true); valueTextView.setAnimationProperties(.25f, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); valueTextView.setCallback(button); valueTextView.setTextSize(AndroidUtilities.dp(14)); - valueTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - valueTextView.setTextColor(Theme.adaptHSV(Theme.getColor(Theme.key_featuredStickers_addButton), -.46f, +.08f)); + valueTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + valueTextView.setTextColor(Theme.blendOver(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.multAlpha(Theme.getColor(Theme.key_featuredStickers_buttonText), .7f))); valueTextView.setText(""); button.setContentDescription(TextUtils.concat(textView.getText(), "\t", valueTextView.getText())); @@ -2721,8 +2726,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe filesString = LocaleController.formatPluralString("Files", cacheModel.getSelectedFiles(), cacheModel.getSelectedFiles()); } String sizeString = AndroidUtilities.formatFileSize(cacheModel.getSelectedFilesSize()); - actionModeTitle.setText(sizeString); - actionModeSubtitle.setText(filesString); + actionModeTitle.setText(sizeString, !LocaleController.isRTL); + actionModeSubtitle.setText(filesString, !LocaleController.isRTL); cachedMediaLayout.showActionMode(true); } } else { @@ -2982,7 +2987,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe checkBox.setColor(-1, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); checkBox.setDrawBackgroundAsArc(3); - addView(checkBox, LayoutHelper.createFrame(24, 24, 0, 38, 25, 0, 0)); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 38, 25, 38, 0)); } checkBox.setChecked(checked, animated); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CachedMediaLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/CachedMediaLayout.java index 24bba1cda..c0e9dc0f2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CachedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CachedMediaLayout.java @@ -40,6 +40,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.BackDrawable; @@ -160,7 +161,7 @@ public class CachedMediaLayout extends FrameLayout implements NestedSizeNotifier if (view instanceof SharedPhotoVideoCell2) { boolean isStory = ((MediaAdapter) adapter).isStories; if (isStory) { - TLRPC.StoryItem storyItem = new TLRPC.TL_storyItem(); + TL_stories.StoryItem storyItem = new TL_stories.TL_storyItem(); storyItem.dialogId = itemInner.file.dialogId; storyItem.id = Objects.hash(itemInner.file.file.getAbsolutePath()); storyItem.attachPath = itemInner.file.file.getAbsolutePath(); 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 a332b75f6..1dcd5a6f6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -13,8 +13,11 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.ColorFilter; import android.graphics.Paint; import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; import android.os.Build; @@ -39,6 +42,7 @@ import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; +import org.telegram.messenger.DialogObject; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; @@ -59,6 +63,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -66,8 +71,10 @@ import org.telegram.ui.ChatBackgroundDrawable; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.ButtonBounce; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.ImageUpdater; +import org.telegram.ui.Components.LoadingDrawable; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.Premium.StarParticlesView; import org.telegram.ui.Components.RLottieDrawable; @@ -83,6 +90,7 @@ import org.telegram.ui.Stories.StoriesUtilities; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Stack; @@ -103,6 +111,8 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD private int backgroundRectHeight; private int backgroundButtonTop; + private ButtonBounce bounce = new ButtonBounce(this); + private LoadingDrawable loadingDrawable; @Override public void didReceivedNotification(int id, int account, Object... args) { @@ -149,6 +159,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD default void didOpenPremiumGift(ChatActionCell cell, TLRPC.TL_premiumGiftOption giftOption, boolean animateConfetti) { } + default void didOpenPremiumGiftChannel(ChatActionCell cell, String slug, boolean animateConfetti) { + } + default boolean didLongPress(ChatActionCell cell, float x, float y) { return false; } @@ -268,7 +281,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD private RadialProgress2 radialProgress = new RadialProgress2(this); private int giftPremiumAdditionalHeight; private boolean forceWasUnread; - private RectF backroundRect; + private RectF backgroundRect; private ImageReceiver.ImageReceiverDelegate giftStickerDelegate = (imageReceiver1, set, thumb, memCache) -> { if (set) { RLottieDrawable drawable = imageReceiver.getLottieAnimation(); @@ -277,7 +290,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (messageObject != null && !messageObject.playedGiftAnimation) { messageObject.playedGiftAnimation = true; drawable.setCurrentFrame(0, false); - AndroidUtilities.runOnUIThread(drawable::start); + AndroidUtilities.runOnUIThread(drawable::restart); if (messageObject != null && messageObject.wasUnread || forceWasUnread) { forceWasUnread = messageObject.wasUnread = false; @@ -327,7 +340,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD giftSubtitlePaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics())); rippleView = new View(context); - rippleView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ROUNDRECT_6DP, AndroidUtilities.dp(16))); + rippleView.setBackground(Theme.createSelectorDrawable(Theme.multAlpha(Color.WHITE, .07f), Theme.RIPPLE_MASK_ROUNDRECT_6DP, AndroidUtilities.dp(16))); rippleView.setVisibility(GONE); addView(rippleView); @@ -424,7 +437,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (messageObject.isStoryMention()) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(messageObject.messageOwner.media.user_id); avatarDrawable.setInfo(user); - TLRPC.StoryItem storyItem = messageObject.messageOwner.media.storyItem; + TL_stories.StoryItem storyItem = messageObject.messageOwner.media.storyItem; if (storyItem != null && storyItem.noforwards) { imageReceiver.setForUserOrChat(user, avatarDrawable, null, true, 0, true); } else { @@ -498,7 +511,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD } else { radialProgress.setIcon(MediaActionDrawable.ICON_CANCEL, !messageIdChanged, !messageIdChanged); } - } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { imageReceiver.setRoundRadius(0); if (USE_PREMIUM_GIFT_LOCAL_STICKER) { @@ -520,8 +533,12 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD set = MediaDataController.getInstance(currentAccount).getStickerSetByEmojiOrName(packName); } if (set != null) { - int months = messageObject.messageOwner.action.months; - + int months; + if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { + months = ((TLRPC.TL_messageActionGiftCode) messageObject.messageOwner.action).months; + } else { + months = messageObject.messageOwner.action.months; + } String monthsEmoticon; if (USE_PREMIUM_GIFT_MONTHS_AS_EMOJI_NUMBERS) { StringBuilder monthsEmoticonBuilder = new StringBuilder(); @@ -560,7 +577,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD forceWasUnread = messageObject.wasUnread; giftSticker = document; if (document != null) { - imageReceiver.setAllowStartLottieAnimation(false); + imageReceiver.setAllowStartLottieAnimation(true); imageReceiver.setDelegate(giftStickerDelegate); giftEffectAnimation = null; @@ -570,14 +587,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD break; } } - - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_emptyListPlaceholder, 0.2f); - if (svgThumb != null) { - svgThumb.overrideWidthAndHeight(512, 512); - } - + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.3f); imageReceiver.setAutoRepeat(0); - imageReceiver.setImage(ImageLocation.getForDocument(document), messageObject.getId() + "_130_130", svgThumb, "tgs", set, 1); + imageReceiver.setImage(ImageLocation.getForDocument(document), String.format(Locale.US, "%d_%d_nr_messageId=%d", 160, 160, messageObject.stableId), svgThumb, "tgs", set, 1); } else { MediaDataController.getInstance(currentAccount).loadStickersByEmojiOrName(packName, false, set == null); } @@ -733,12 +745,13 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD imagePressed = true; result = true; } - if (radialProgress.getIcon() == MediaActionDrawable.ICON_NONE && (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || messageObject.type == MessageObject.TYPE_ACTION_WALLPAPER) && backroundRect.contains(x, y)) { + if (radialProgress.getIcon() == MediaActionDrawable.ICON_NONE && (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO || messageObject.type == MessageObject.TYPE_ACTION_WALLPAPER) && backgroundRect.contains(x, y)) { imagePressed = true; result = true; } - if (isButtonLayout(messageObject) && giftButtonRect.contains(x, y)) { + if (isButtonLayout(messageObject) && (giftButtonRect.contains(x, y) || backgroundRect.contains(x, y))) { rippleView.setPressed(giftButtonPressed = true); + bounce.setPressed(true); result = true; } if (result) { @@ -749,11 +762,45 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (event.getAction() != MotionEvent.ACTION_MOVE) { cancelCheckLongPress(); } - if (imagePressed) { + if (giftButtonPressed) { switch (event.getAction()) { case MotionEvent.ACTION_UP: imagePressed = false; - if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + rippleView.setPressed(giftButtonPressed = false); + bounce.setPressed(false); + if (delegate != null) { + if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { + openPremiumGiftChannel(); + } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + playSoundEffect(SoundEffectConstants.CLICK); + openPremiumGiftPreview(); + } else { + ImageUpdater imageUpdater = MessagesController.getInstance(currentAccount).photoSuggestion.get(messageObject.messageOwner.local_id); + if (imageUpdater == null) { + delegate.didClickImage(this); + } + } + } + break; + case MotionEvent.ACTION_CANCEL: + imagePressed = false; + rippleView.setPressed(giftButtonPressed = false); + bounce.setPressed(false); + break; + case MotionEvent.ACTION_MOVE: + if (!(isButtonLayout(messageObject) && (giftButtonRect.contains(x, y) || backgroundRect.contains(x, y)))) { + rippleView.setPressed(giftButtonPressed = false); + bounce.setPressed(false); + } + break; + } + } else if (imagePressed) { + switch (event.getAction()) { + case MotionEvent.ACTION_UP: + imagePressed = false; + if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { + openPremiumGiftChannel(); + } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { openPremiumGiftPreview(); } else if (delegate != null) { boolean consumed = false; @@ -775,7 +822,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD break; case MotionEvent.ACTION_MOVE: if (isNewStyleButtonLayout()) { - if (!backroundRect.contains(x, y)) { + if (!backgroundRect.contains(x, y)) { imagePressed = false; } } else { @@ -785,31 +832,6 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD } break; } - } else if (giftButtonPressed) { - switch (event.getAction()) { - case MotionEvent.ACTION_UP: - rippleView.setPressed(giftButtonPressed = false); - if (delegate != null) { - if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { - playSoundEffect(SoundEffectConstants.CLICK); - openPremiumGiftPreview(); - } else { - ImageUpdater imageUpdater = MessagesController.getInstance(currentAccount).photoSuggestion.get(messageObject.messageOwner.local_id); - if (imageUpdater == null) { - delegate.didClickImage(this); - } - } - } - break; - case MotionEvent.ACTION_CANCEL: - rippleView.setPressed(giftButtonPressed = false); - break; - case MotionEvent.ACTION_MOVE: - if (!giftButtonRect.contains(x, y)) { - rippleView.setPressed(giftButtonPressed = false); - } - break; - } } } if (!result) { @@ -854,6 +876,13 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD return result; } + private void openPremiumGiftChannel() { + if (delegate != null) { + TLRPC.TL_messageActionGiftCode gifCodeAction = (TLRPC.TL_messageActionGiftCode) currentMessageObject.messageOwner.action; + AndroidUtilities.runOnUIThread(() -> delegate.didOpenPremiumGiftChannel(ChatActionCell.this, gifCodeAction.slug, false)); + } + } + private void openPremiumGiftPreview() { TLRPC.TL_premiumGiftOption giftOption = new TLRPC.TL_premiumGiftOption(); TLRPC.MessageAction action = currentMessageObject.messageOwner.action; @@ -958,7 +987,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD spoilersPool.addAll(spoilers); spoilers.clear(); if (text instanceof Spannable) { - SpoilerEffect.addSpoilers(this, textLayout, textX, textX + textWidth, (Spannable) text, spoilersPool, spoilers); + SpoilerEffect.addSpoilers(this, textLayout, textX, textX + textWidth, (Spannable) text, spoilersPool, spoilers, null); } } @@ -971,7 +1000,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD return; } if (isButtonLayout(messageObject)) { - giftRectSize = Math.min((int) (AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() * 0.6f : AndroidUtilities.displaySize.x * 0.6f - AndroidUtilities.dp(34)), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(64)); + giftRectSize = Math.min((int) (AndroidUtilities.isTablet() ? AndroidUtilities.getMinTabletSide() * 0.6f : AndroidUtilities.displaySize.x * 0.62f - AndroidUtilities.dp(34)), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(64)); + if (!AndroidUtilities.isTablet() && messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { + giftRectSize = (int) (giftRectSize * 1.2f); + } stickerSize = giftRectSize - AndroidUtilities.dp(106); if (isNewStyleButtonLayout()) { imageReceiver.setRoundRadius(stickerSize / 2); @@ -996,6 +1028,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD int exactlyHeight = 0; if (isButtonLayout(messageObject)) { + boolean isGiftChannel = isGiftChannel(messageObject); int imageSize = getImageSize(messageObject); float y; if (isNewStyleButtonLayout()) { @@ -1006,6 +1039,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD giftPremiumAdditionalHeight = 0; if (giftPremiumTitleLayout != null) { y += giftPremiumTitleLayout.getHeight(); + y += AndroidUtilities.dp(isGiftChannel ? 6 : 0); } else { y -= AndroidUtilities.dp(12); giftPremiumAdditionalHeight -= AndroidUtilities.dp(30); @@ -1014,6 +1048,9 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (giftPremiumSubtitleLayout.getLineCount() > 2) { giftPremiumAdditionalHeight += (giftPremiumSubtitleLayout.getLineBottom(0) - giftPremiumSubtitleLayout.getLineTop(0)) * giftPremiumSubtitleLayout.getLineCount() - 2; } + + giftPremiumAdditionalHeight -= AndroidUtilities.dp(isGiftChannel ? 14 : 0); + additionalHeight += giftPremiumAdditionalHeight; int h = textHeight + additionalHeight + AndroidUtilities.dp(14); @@ -1104,6 +1141,8 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (messageObject != null) { if (messageObject.type == MessageObject.TYPE_ACTION_PHOTO) { imageReceiver.setImageCoords((previousWidth - AndroidUtilities.roundMessageSize) / 2f, textHeight + AndroidUtilities.dp(19), AndroidUtilities.roundMessageSize, AndroidUtilities.roundMessageSize); + } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL) { + createGiftPremiumChannelLayouts(); } else if (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM) { createGiftPremiumLayouts(LocaleController.getString(R.string.ActionGiftPremiumTitle), LocaleController.formatString(R.string.ActionGiftPremiumSubtitle, LocaleController.formatPluralString("Months", messageObject.messageOwner.action.months)), LocaleController.getString(R.string.ActionGiftPremiumView), giftRectSize); } else if (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO) { @@ -1170,9 +1209,55 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD } } + private void createGiftPremiumChannelLayouts() { + int width = giftRectSize; + width -= AndroidUtilities.dp(16); + giftTitlePaint.setTextSize(AndroidUtilities.dp(14)); + giftSubtitlePaint.setTextSize(AndroidUtilities.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)); + String from = chat == null ? null : chat.title; + boolean isPrize = gifCodeAction.via_giveaway; + CharSequence title = gifCodeAction.unclaimed ? + LocaleController.getString("BoostingUnclaimedPrize", R.string.BoostingUnclaimedPrize) + : LocaleController.getString("BoostingCongratulations", R.string.BoostingCongratulations); + SpannableStringBuilder subtitle; + CharSequence monthsStr = months == 12 ? LocaleController.formatPluralString("BoldYears", 1) : LocaleController.formatPluralString("BoldMonths", months); + if (isPrize) { + if (gifCodeAction.unclaimed) { + subtitle = new SpannableStringBuilder(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingYouHaveUnclaimedPrize", R.string.BoostingYouHaveUnclaimedPrize, from))); + subtitle.append("\n\n"); + subtitle.append(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingUnclaimedPrizeDuration", R.string.BoostingUnclaimedPrizeDuration, monthsStr))); + } else { + subtitle = new SpannableStringBuilder(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingReceivedPrizeFrom", R.string.BoostingReceivedPrizeFrom, from))); + subtitle.append("\n\n"); + subtitle.append(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingReceivedPrizeDuration", R.string.BoostingReceivedPrizeDuration, monthsStr))); + } + } else { + subtitle = new SpannableStringBuilder(AndroidUtilities.replaceTags(from == null ? LocaleController.getString("BoostingReceivedGiftNoName", R.string.BoostingReceivedGiftNoName) : LocaleController.formatString("BoostingReceivedGiftFrom", R.string.BoostingReceivedGiftFrom, from))); + subtitle.append("\n\n"); + subtitle.append(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingReceivedGiftDuration", R.string.BoostingReceivedGiftDuration, monthsStr))); + } + + String btnText = LocaleController.getString("BoostingReceivedGiftOpenBtn", R.string.BoostingReceivedGiftOpenBtn); + + SpannableStringBuilder titleBuilder = SpannableStringBuilder.valueOf(title); + titleBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, titleBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + giftPremiumTitleLayout = new StaticLayout(titleBuilder, giftTitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.1f, 0.0f, false); + + giftPremiumSubtitleLayout = new StaticLayout(subtitle, giftSubtitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.1f, 0.0f, false); + SpannableStringBuilder buttonBuilder = SpannableStringBuilder.valueOf(btnText); + buttonBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 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); + giftPremiumButtonWidth = measureLayoutWidth(giftPremiumButtonLayout); + } + private void createGiftPremiumLayouts(CharSequence title, CharSequence subtitle, CharSequence button, int width) { width -= AndroidUtilities.dp(16); if (title != null) { + giftTitlePaint.setTextSize(AndroidUtilities.dp(16)); SpannableStringBuilder titleBuilder = SpannableStringBuilder.valueOf(title); titleBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)), 0, titleBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); giftPremiumTitleLayout = new StaticLayout(titleBuilder, giftTitlePaint, width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); @@ -1229,9 +1314,12 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD imageReceiver.setImageCoords(x, y, imageSize, imageSize); } else if (messageObject.type == MessageObject.TYPE_ACTION_PHOTO) { imageReceiver.setImageCoords((previousWidth - stickerSize) / 2f, textY + textHeight + giftRectSize * 0.075f, stickerSize, stickerSize); + } 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 - AndroidUtilities.dp(22), imageSize, imageSize); } else { - imageSize = (int) (stickerSize * 0.7f); - imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f + AndroidUtilities.dp(8), imageSize, imageSize); + imageSize = (int) (stickerSize * 1f); + imageReceiver.setImageCoords((previousWidth - imageSize) / 2f, textY + textHeight + giftRectSize * 0.075f - AndroidUtilities.dp(4), imageSize, imageSize); } textPaint = (TextPaint) getThemedPaint(Theme.key_paint_chatActionText); if (textPaint != null) { @@ -1300,7 +1388,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD SpoilerEffect.clipOutCanvas(canvas, spoilers); textLayout.draw(canvas); if (delegate == null || delegate.canDrawOutboundsContent()) { - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f, textLayout == null ? null : getAdaptiveEmojiColorFilter(textLayout.getPaint().getColor())); } canvas.restore(); @@ -1317,7 +1405,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD float x = (previousWidth - giftRectSize) / 2f + AndroidUtilities.dp(8); float y; if (isNewStyleButtonLayout()) { - float top = backroundRect != null ? backroundRect.top : (textY + textHeight + AndroidUtilities.dp(4)); + float top = backgroundRect != null ? backgroundRect.top : (textY + textHeight + AndroidUtilities.dp(4)); y = top + AndroidUtilities.dp(16) * 2 + imageSize; } else { y = textY + textHeight + giftRectSize * 0.075f + (messageObject.type == MessageObject.TYPE_SUGGEST_PHOTO ? imageSize : stickerSize) + AndroidUtilities.dp(4); @@ -1333,6 +1421,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (giftPremiumTitleLayout != null) { giftPremiumTitleLayout.draw(canvas); y += giftPremiumTitleLayout.getHeight(); + y += AndroidUtilities.dp(messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL ? 6 : 0); } else { y -= AndroidUtilities.dp(4); } @@ -1411,6 +1500,10 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD Theme.applyServiceShaderMatrix(getMeasuredWidth(), backgroundHeight, 0, viewTop + AndroidUtilities.dp(4)); } + final float S = bounce.getScale(0.02f); + canvas.save(); + canvas.scale(S, S, giftButtonRect.centerX(), giftButtonRect.centerY()); + if (giftPremiumButtonLayout != null) { Paint backgroundPaint = getThemedPaint(Theme.key_paint_chatActionBackground); canvas.drawRoundRect(giftButtonRect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), backgroundPaint); @@ -1462,6 +1555,35 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD giftPremiumButtonLayout.draw(canvas); canvas.restore(); } + + if (messageObject.flickerLoading) { + if (loadingDrawable == null) { + loadingDrawable = new LoadingDrawable(themeDelegate); + loadingDrawable.setGradientScale(2f); + loadingDrawable.setAppearByGradient(true); + loadingDrawable.setColors( + Theme.multAlpha(Color.WHITE, .08f), + Theme.multAlpha(Color.WHITE, .2f), + Theme.multAlpha(Color.WHITE, .2f), + Theme.multAlpha(Color.WHITE, .7f) + ); + loadingDrawable.strokePaint.setStrokeWidth(AndroidUtilities.dp(1)); + } + loadingDrawable.resetDisappear(); + loadingDrawable.setBounds(giftButtonRect); + loadingDrawable.setRadiiDp(16); + loadingDrawable.draw(canvas); + } else if (loadingDrawable != null) { + loadingDrawable.setBounds(giftButtonRect); + loadingDrawable.setRadiiDp(16); + loadingDrawable.disappear(); + loadingDrawable.draw(canvas); + if (loadingDrawable.isDisappeared()) { + loadingDrawable.reset(); + } + } + + canvas.restore(); } } @@ -1651,14 +1773,14 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD y += AndroidUtilities.dp(12); AndroidUtilities.rectTmp.set(x, y, x + giftRectSize, y + giftRectSize + giftPremiumAdditionalHeight); } - if (backroundRect == null) { - backroundRect = new RectF(); + if (backgroundRect == null) { + backgroundRect = new RectF(); } - backroundRect.set(AndroidUtilities.rectTmp); - canvas.drawRoundRect(backroundRect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), backgroundPaint); + backgroundRect.set(AndroidUtilities.rectTmp); + canvas.drawRoundRect(backgroundRect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), backgroundPaint); if (hasGradientService()) { - canvas.drawRoundRect(backroundRect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); + canvas.drawRoundRect(backgroundRect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), Theme.chat_actionBackgroundGradientDarkenPaint); } } @@ -1767,12 +1889,16 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD public void drawOutboundsContent(Canvas canvas) { canvas.save(); canvas.translate(textXLeft, textY); - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, textLayout, animatedEmojiStack, 0, spoilers, 0, 0, 0, 1f, textLayout != null ? getAdaptiveEmojiColorFilter(textLayout.getPaint().getColor()) : null); canvas.restore(); } private boolean isButtonLayout(MessageObject messageObject) { - return messageObject != null && (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM || isNewStyleButtonLayout()); + return messageObject != null && (messageObject.type == MessageObject.TYPE_GIFT_PREMIUM || messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL || isNewStyleButtonLayout()); + } + + private boolean isGiftChannel(MessageObject messageObject) { + return messageObject != null && messageObject.type == MessageObject.TYPE_GIFT_PREMIUM_CHANNEL; } @Override @@ -1798,4 +1924,13 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD invalidateWithParent.invalidate(); } } + + private ColorFilter adaptiveEmojiColorFilter; + private int adaptiveEmojiColor; + private ColorFilter getAdaptiveEmojiColorFilter(int color) { + if (color != adaptiveEmojiColor || adaptiveEmojiColorFilter == null) { + adaptiveEmojiColorFilter = new PorterDuffColorFilter(adaptiveEmojiColor = color, PorterDuff.Mode.SRC_IN); + } + return adaptiveEmojiColorFilter; + } } 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 26a07b98d..e9a7fa9d7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -8,6 +8,8 @@ package org.telegram.ui.Cells; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -32,15 +34,18 @@ import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; import android.graphics.Shader; import android.graphics.Typeface; +import android.graphics.Xfermode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; +import android.graphics.text.LineBreaker; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -55,6 +60,8 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; +import android.text.style.LeadingMarginSpan; +import android.text.style.LineHeightSpan; import android.text.style.URLSpan; import android.util.Log; import android.util.Property; @@ -120,6 +127,8 @@ import org.telegram.messenger.video.VideoPlayerRewinder; 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.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedEmojiDrawable; @@ -131,6 +140,7 @@ import org.telegram.ui.Components.AnimationProperties; import org.telegram.ui.Components.AudioVisualizerDrawable; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackgroundGradientDrawable; +import org.telegram.ui.Components.ButtonBounce; import org.telegram.ui.Components.CheckBoxBase; import org.telegram.ui.Components.ClipRoundedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -146,10 +156,13 @@ import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.MsgClockDrawable; import org.telegram.ui.Components.Point; +import org.telegram.ui.Components.Premium.boosts.cells.msg.GiveawayMessageCell; +import org.telegram.ui.Components.QuoteHighlight; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ReplyMessageLine; import org.telegram.ui.Components.RoundVideoPlayingDrawable; import org.telegram.ui.Components.SeekBar; import org.telegram.ui.Components.SeekBarAccessibilityDelegate; @@ -243,10 +256,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (id == NotificationCenter.emojiLoaded) { invalidate(); + } else if (id == NotificationCenter.didUpdatePremiumGiftStickers) { + MessageObject messageObject = currentMessageObject; + if (messageObject != null && messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { + setMessageObject(messageObject, currentMessagesGroup, pinnedBottom, pinnedTop); + } } } - private void setAvatar(MessageObject messageObject) { + public void setAvatar(MessageObject messageObject) { if (messageObject == null) { return; } @@ -299,14 +317,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public void setSpoilersSuppressed(boolean s) { - for (int i = 0; i < captionSpoilers.size(); i++) { - SpoilerEffect eff = captionSpoilers.get(i); - eff.setSuppressUpdates(s); - } for (int i = 0; i < replySpoilers.size(); i++) { SpoilerEffect eff = replySpoilers.get(i); eff.setSuppressUpdates(s); } + if (captionLayout != null && captionLayout.textLayoutBlocks != null) { + for (int k = 0; k < captionLayout.textLayoutBlocks.size(); k++) { + MessageObject.TextLayoutBlock bl = captionLayout.textLayoutBlocks.get(k); + for (int i = 0; i < bl.spoilers.size(); i++) { + SpoilerEffect eff = bl.spoilers.get(i); + eff.setSuppressUpdates(s); + } + } + } if (getMessageObject() != null && getMessageObject().textLayoutBlocks != null) { for (int k = 0; k < getMessageObject().textLayoutBlocks.size(); k++) { MessageObject.TextLayoutBlock bl = getMessageObject().textLayoutBlocks.get(k); @@ -319,8 +342,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public boolean hasSpoilers() { - if (hasCaptionLayout() && !captionSpoilers.isEmpty() || replyTextLayout != null && !replySpoilers.isEmpty()) { - return true; + if (captionLayout != null && captionLayout.textLayoutBlocks != null) { + for (MessageObject.TextLayoutBlock bl : captionLayout.textLayoutBlocks) { + if (!bl.spoilers.isEmpty()) { + return true; + } + } } if (getMessageObject() != null && getMessageObject().textLayoutBlocks != null) { for (MessageObject.TextLayoutBlock bl : getMessageObject().textLayoutBlocks) { @@ -333,10 +360,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void updateSpoilersVisiblePart(int top, int bottom) { - if (hasCaptionLayout()) { - float off = -captionY; - for (SpoilerEffect eff : captionSpoilers) { - eff.setVisibleBounds(0, top + off, getWidth(), bottom + off); + if (captionLayout != null && captionLayout.textLayoutBlocks != null) { + for (MessageObject.TextLayoutBlock bl : captionLayout.textLayoutBlocks) { + for (SpoilerEffect eff : bl.spoilers) { + eff.setVisibleBounds(0, top - bl.textYOffset - captionX, getWidth(), bottom - bl.textYOffset - captionY); + } } } if (replyTextLayout != null) { @@ -470,9 +498,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressUrl(ChatMessageCell cell, CharacterStyle url, boolean longPress) { } + default void didPressCode(ChatMessageCell cell, CharacterStyle span, boolean longPress) { + + } + default void needOpenWebView(MessageObject message, String url, String title, String description, String originalUrl, int w, int h) { } + default void didPressWebPage(ChatMessageCell cell, TLRPC.WebPage webpage, String url, boolean safe) { + Browser.openUrl(cell.getContext(), url); + } + default void didPressImage(ChatMessageCell cell, float x, float y) { } @@ -482,6 +518,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressOther(ChatMessageCell cell, float otherX, float otherY) { } + default void didPressSponsoredClose() { + } + default void didPressTime(ChatMessageCell cell) { } @@ -500,6 +539,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressInstantButton(ChatMessageCell cell, int type) { } + default void didPressGiveawayChatButton(ChatMessageCell cell, int pressedPos) { + } + default void didPressCommentButton(ChatMessageCell cell) { } @@ -593,6 +635,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default boolean shouldShowTopicButton() { return false; } + + default void didPressEmojiStatus() { + + } } private final static int DOCUMENT_ATTACH_TYPE_NONE = 0; @@ -690,23 +736,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean pinnedTop; public boolean pinnedBottom; - private boolean drawPinnedTop; + public boolean drawPinnedTop; public boolean drawPinnedBottom; private MessageObject.GroupedMessages currentMessagesGroup; private MessageObject.GroupedMessagePosition currentPosition; private boolean groupPhotoInvisible; public final ReactionsLayoutInBubble reactionsLayoutInBubble = new ReactionsLayoutInBubble(this); + public final GiveawayMessageCell giveawayMessageCell = new GiveawayMessageCell(this); private boolean invalidateSpoilersParent; - private int textX; + public int textX; private int unmovedTextX; - private int textY; + private int linkPreviewY; + public int textY; private int totalHeight; private int additionalTimeOffsetY; private int keyboardHeight; private int linkBlockNum; private int linkSelectionBlockNum; + private boolean highlightedQuote; private boolean inLayout; @@ -725,6 +774,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public float parentViewTopOffset; private boolean attachedToWindow; + public boolean isCellAttachedToWindow() { + return attachedToWindow; + } private boolean isUpdating; @@ -753,6 +805,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private long lastCheckBoxAnimationTime; private int checkBoxTranslation; + public boolean linkPreviewAbove; private boolean isSmallImage; private boolean drawImageButton; private boolean drawVideoImageButton; @@ -775,14 +828,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean hasOldCaptionPreview; private boolean hasGamePreview; private boolean hasInvoicePreview; - private int linkPreviewHeight; + public int linkPreviewHeight; private int mediaOffsetY; private int descriptionY; private int durationWidth; private int photosCountWidth; private int descriptionX; + private int descriptionLayoutWidth, descriptionLayoutLeft; private int titleX; - private int authorX; + private int authorLayoutWidth, authorLayoutLeft; + private int titleLayoutWidth, titleLayoutLeft; private float siteNameLeft, siteNameLayoutWidth; private int siteNameWidth; private StaticLayout siteNameLayout; @@ -792,6 +847,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private StaticLayout photosCountLayout; private StaticLayout authorLayout; private StaticLayout instantViewLayout; + private float instantViewLayoutWidth; + private float instantViewLayoutLeft; private boolean drawInstantView; private boolean pollInstantViewTouchesBottom; public int drawInstantViewType; @@ -813,12 +870,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean instantTextNewLine; private boolean instantPressed; private boolean instantButtonPressed; - private float instantButtonPressProgress; - private Drawable[] selectorDrawable = new Drawable[2]; + private ButtonBounce instantButtonBounce; + private final Drawable[] selectorDrawable = new Drawable[2]; private int[] selectorDrawableMaskType = new int[2]; private RectF instantButtonRect = new RectF(); private LoadingDrawable instantButtonLoading; - private ValueAnimator instantButtonPressAnimator; private int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; private float animatingLoadingProgressProgress; CharSequence accessibilityText; @@ -835,11 +891,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int docTitleOffsetX; private boolean locationExpired; - private StaticLayout captionLayout; + private int highlightCaptionToSetStart = -1, highlightCaptionToSetEnd = -1; + private int captionFullWidth; + public MessageObject.TextLayoutBlocks captionLayout; + public QuoteHighlight quoteHighlight; + public float quoteHighlightOffsetX, quoteHighlightOffsetY; private CharSequence currentCaption; private int captionOffsetX; private float captionX; - private float captionY; + public float captionY; private int captionHeight; private int captionWidth; private int addedCaptionHeight; @@ -997,9 +1057,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int pressedBotButton; private SpoilerEffect spoilerPressed; - private boolean isCaptionSpoilerPressed; private boolean isSpoilerRevealing; + private boolean checkFileLoad; private MessageObject currentMessageObject; private MessageObject messageObjectToSet; private MessageObject.GroupedMessages groupedMessagesToSet; @@ -1042,7 +1102,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean drawBackground = true; private int substractBackgroundHeight; private boolean allowAssistant; - private Theme.MessageDrawable currentBackgroundDrawable; + public Theme.MessageDrawable currentBackgroundDrawable; private Theme.MessageDrawable currentBackgroundSelectedDrawable; private int backgroundDrawableLeft; private int backgroundDrawableRight; @@ -1087,13 +1147,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean commentButtonPressed; private ImageReceiver avatarImage; - private AvatarDrawable avatarDrawable; + protected AvatarDrawable avatarDrawable; private boolean avatarPressed; private boolean forwardNamePressed; private boolean forwardBotPressed; private ImageReceiver locationImageReceiver; + public int replyQuoteDrawableColor; + public Drawable replyQuoteDrawable; + public boolean isReplyQuote; public StaticLayout replyNameLayout; public StaticLayout replyTextLayout; private AtomicReference spoilersPatchedReplyTextLayout = new AtomicReference<>(); @@ -1104,13 +1167,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int replyNameWidth; private int replyNameOffset; private int replyTextWidth; - private int replyTextOffset; + private int replyTextHeight; + public int replyTextOffset; + public boolean replyTextRTL; public boolean needReplyImage; private boolean replyPressed; private boolean replySelectorPressed, replySelectorCanBePressed; private AnimatedFloat replyPressedFloat; private float replyTouchX, replyTouchY; private TLRPC.PhotoSize currentReplyPhoto; + public int instantDrawableColor; + public Drawable instantDrawable; + public ReplyMessageLine quoteLine, linkLine, replyLine; private AnimatedFloat translationLoadingFloat; private LinkPath translationLoadingPath; @@ -1136,6 +1204,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean drawName; private boolean drawNameLayout; + private Paint closeSponsoredPaint; + private Path closeSponsoredPath; + private ButtonBounce closeSponsoredBounce; + private RectF closeSponsoredBounds; + private final StaticLayout[] forwardedNameLayout = new StaticLayout[2]; private int forwardedNameWidth; private boolean drawForwardedName; @@ -1192,7 +1265,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private TLRPC.User currentForwardUser; private TLRPC.User currentViaBotUser; - private long currentReplyUserId; private TLRPC.Chat currentForwardChannel; private String currentForwardName; private String currentForwardNameString; @@ -1202,15 +1274,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiReplyStack; public AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiDescriptionStack; + public ButtonBounce replyBounce; + public float replyBounceX, replyBounceY; public Drawable replySelector; public LoadingDrawable replyLoadingDrawable; - private float replyLoadingT; - private float[] replyLoadingSegment; - private float[] replyRoundRectRadii; private Path replyRoundRectPath; - public Rect replySelectorRect = new Rect(); + public float[] replyBackgroundRadii; + public RectF replySelectorRect = new RectF(); public int replySelectorColor; public float replySelectorRadLeft, replySelectorRadRight; + private ButtonBounce linkPreviewBounce; + private Drawable linkPreviewSelector; + public int linkPreviewSelectorColor; private ChatMessageCellDelegate delegate; @@ -1235,7 +1310,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private final boolean ALPHA_PROPERTY_WORKAROUND = Build.VERSION.SDK_INT == 28; private float alphaInternal = 1f; - private final TransitionParams transitionParams = new TransitionParams(); + public final TransitionParams transitionParams = new TransitionParams(); private boolean edited; private boolean imageDrawn; private boolean photoImageOutOfBounds; @@ -1311,9 +1386,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate // Public for enter transition public List replySpoilers = new ArrayList<>(); private final Stack replySpoilersPool = new Stack<>(); - private final List captionSpoilers = new ArrayList<>(); - private final Stack captionSpoilersPool = new Stack<>(); - private final AtomicReference captionPatchedSpoilersLayout = new AtomicReference<>(); private final Path sPath = new Path(); public boolean isBlurred; @@ -1358,7 +1430,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate seekBar = new SeekBar(this) { @Override protected void onTimestampUpdate(URLSpanNoUnderline link) { - highlightCaptionLink(link); + setHighlightedSpan(link); } }; seekBar.setDelegate(this); @@ -1480,6 +1552,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void resetUrlPaths() { + if (quoteHighlight != null) { + quoteHighlight = null; + } if (urlPathSelection.isEmpty()) { return; } @@ -1524,7 +1599,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!(currentMessageObject.type == MessageObject.TYPE_TEXT || currentMessageObject.type == MessageObject.TYPE_EMOJIS || currentMessageObject.type == MessageObject.TYPE_STORY_MENTION) || currentMessageObject.textLayoutBlocks == null || currentMessageObject.textLayoutBlocks.isEmpty() || !(currentMessageObject.messageText instanceof Spannable)) { return false; } - if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && pressedLinkType == 1) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1)) { int x = (int) event.getX(); int y = (int) event.getY(); if (x >= textX && y >= textY && x <= textX + currentMessageObject.textWidth && y <= textY + currentMessageObject.textHeight) { @@ -1572,6 +1647,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); pressedLink.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outLinkSelectBackground : Theme.key_chat_linkSelectBackground)); + if (block.quote && quoteLine != null) { + pressedLink.setColor(Theme.multAlpha(quoteLine.getColor(), Theme.isCurrentThemeDark() ? .13f : .10f)); + } linkBlockNum = blockNum; pressedLinkType = 1; try { @@ -1664,76 +1742,141 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!(currentCaption instanceof Spannable) || captionLayout == null) { return false; } - if (event.getAction() == MotionEvent.ACTION_DOWN || (linkPreviewPressed || pressedLink != null || pressedEmoji != null) && event.getAction() == MotionEvent.ACTION_UP) { + if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && (pressedLinkType == 1)) { int x = (int) event.getX(); int y = (int) event.getY(); - if (x >= captionX && x <= captionX + captionWidth && y >= captionY && y <= captionY + captionHeight) { - if (event.getAction() == MotionEvent.ACTION_DOWN) { - try { - x -= captionX; - y -= captionY; - final int line = captionLayout.getLineForVertical(y); - final int off = captionLayout.getOffsetForHorizontal(line, x); + if (x >= captionX && y >= captionY && x <= captionX + captionLayout.textWidth && y <= captionY + captionLayout.textHeight) { + x -= captionX; + y -= captionY; + int blockNum = 0; + for (int a = 0; a < captionLayout.textLayoutBlocks.size(); a++) { + if (captionLayout.textLayoutBlocks.get(a).textYOffset > y) { + break; + } + blockNum = a; + } + try { + MessageObject.TextLayoutBlock block = captionLayout.textLayoutBlocks.get(blockNum); + x -= (block.isRtl() ? captionLayout.textXOffset : 0); + y -= block.textYOffset; + final int line = block.textLayout.getLineForVertical(y); + final int off = block.charactersOffset + block.textLayout.getOffsetForHorizontal(line, x); - final float left = captionLayout.getLineLeft(line); - if (left <= x && left + captionLayout.getLineWidth(line) >= x) { - Spannable buffer = (Spannable) currentCaption; - CharacterStyle[] link = buffer.getSpans(off, off, ClickableSpan.class); - if (link == null || link.length == 0) { - link = buffer.getSpans(off, off, URLSpanMono.class); - } - if (link == null || link.length == 0) { - link = buffer.getSpans(off, off, AnimatedEmojiSpan.class); - } - boolean ignore = false; - if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { - ignore = true; - } - if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { + final float left = block.textLayout.getLineLeft(line); + if (left <= x && left + block.textLayout.getLineWidth(line) >= x) { + Spannable buffer = (Spannable) currentCaption; + CharacterStyle[] link = buffer.getSpans(off, off, ClickableSpan.class); + boolean isMono = false; + if (link == null || link.length == 0) { + link = buffer.getSpans(off, off, URLSpanMono.class); + isMono = true; + } + if (link == null || link.length == 0) { + link = buffer.getSpans(off, off, AnimatedEmojiSpan.class); + isMono = false; + } + boolean ignore = false; + if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { + ignore = true; + } + if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { if (link[0] instanceof AnimatedEmojiSpan) { - resetPressedLink(3); - pressedLinkType = 3; - pressedEmoji = (AnimatedEmojiSpan) link[0]; + if (pressedEmoji == null || pressedEmoji != link[0]) { + resetPressedLink(1); + pressedEmoji = (AnimatedEmojiSpan) link[0]; + pressedLinkType = 1; + } } else if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); pressedLink.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outLinkSelectBackground : Theme.key_chat_linkSelectBackground)); - pressedLinkType = 3; + if (block.quote && quoteLine != null) { + pressedLink.setColor(Theme.multAlpha(quoteLine.getColor(), Theme.isCurrentThemeDark() ? .13f : .10f)); + } + linkBlockNum = blockNum; + pressedLinkType = 1; try { LinkPath path = pressedLink.obtainNewPath(); int[] pos = getRealSpanStartAndEnd(buffer, pressedLink.getSpan()); - path.setCurrentLayout(captionLayout, pos[0], 0); - captionLayout.getSelectionPath(pos[0], pos[1], path); + pos[0] -= block.charactersOffset; + pos[1] -= block.charactersOffset; + path.setCurrentLayout(block.textLayout, pos[0], 0); + block.textLayout.getSelectionPath(pos[0], pos[1], path); + if (pos[1] >= block.charactersEnd) { + for (int a = blockNum + 1; a < captionLayout.textLayoutBlocks.size(); a++) { + MessageObject.TextLayoutBlock nextBlock = captionLayout.textLayoutBlocks.get(a); + CharacterStyle[] nextLink; + if (isMono) { + nextLink = buffer.getSpans(nextBlock.charactersOffset, nextBlock.charactersOffset, URLSpanMono.class); + } else { + nextLink = buffer.getSpans(nextBlock.charactersOffset, nextBlock.charactersOffset, ClickableSpan.class); + } + if (nextLink == null || nextLink.length == 0 || nextLink[0] != pressedLink.getSpan()) { + break; + } + path = pressedLink.obtainNewPath(); + path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.textYOffset - block.textYOffset); + int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; + nextBlock.textLayout.getSelectionPath(0, p1, path); + if (p1 < nextBlock.charactersEnd - 1) { + break; + } + } + } + if (pos[0] <= block.charactersOffset) { + int offsetY = 0; + for (int a = blockNum - 1; a >= 0; a--) { + MessageObject.TextLayoutBlock nextBlock = captionLayout.textLayoutBlocks.get(a); + CharacterStyle[] nextLink; + if (isMono) { + nextLink = buffer.getSpans(nextBlock.charactersEnd - 1, nextBlock.charactersEnd - 1, URLSpanMono.class); + } else { + nextLink = buffer.getSpans(nextBlock.charactersEnd - 1, nextBlock.charactersEnd - 1, ClickableSpan.class); + } + if (nextLink == null || nextLink.length == 0 || nextLink[0] != pressedLink.getSpan()) { + break; + } + path = pressedLink.obtainNewPath(); + offsetY -= nextBlock.height; + int p0 = pos[0] + block.charactersOffset - nextBlock.charactersOffset; + int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset; + path.setCurrentLayout(nextBlock.textLayout, p0, offsetY); + nextBlock.textLayout.getSelectionPath(p0, p1, path); + if (p0 > nextBlock.charactersOffset) { + break; + } + } + } } catch (Exception e) { FileLog.e(e); } - links.addLink(pressedLink, 3); + links.addLink(pressedLink, 1); } - invalidateWithParent(); + invalidate(); return true; + } else { + if (link[0] instanceof AnimatedEmojiSpan && pressedEmoji == link[0]) { + if (delegate.didPressAnimatedEmoji(this, pressedEmoji)) { + resetPressedLink(1); + pressedEmoji = null; + return true; + } + resetPressedLink(1); + pressedEmoji = null; + } else if (pressedLink != null && link[0] == pressedLink.getSpan()) { + delegate.didPressUrl(this, pressedLink.getSpan(), false); + resetPressedLink(1); + return true; + } } } - } catch (Exception e) { - FileLog.e(e); - } - } else if (pressedLinkType == 3) { - if (pressedEmoji != null) { - if (delegate.didPressAnimatedEmoji(this, pressedEmoji)) { - resetPressedLink(3); - pressedEmoji = null; - return true; - } - resetPressedLink(3); - pressedEmoji = null; - return false; - } else { - delegate.didPressUrl(this, pressedLink.getSpan(), false); - resetPressedLink(3); - return true; } + } catch (Exception e) { + FileLog.e(e); } } else { - resetPressedLink(3); + resetPressedLink(1); } } return false; @@ -1840,9 +1983,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int x = (int) event.getX(); int y = (int) event.getY(); - if (x >= unmovedTextX && x <= unmovedTextX + backgroundWidth && y >= textY + currentMessageObject.textHeight && y <= textY + currentMessageObject.textHeight + linkPreviewHeight + AndroidUtilities.dp(8 + (drawInstantView ? 46 : 0))) { + if (x >= unmovedTextX && x <= unmovedTextX + backgroundWidth && y >= linkPreviewY && y <= linkPreviewY + linkPreviewHeight + AndroidUtilities.dp(8 + (drawInstantView ? 46 : 0))) { if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (descriptionLayout != null && y >= descriptionY) { + if (descriptionLayout != null && y >= descriptionY && !currentMessageObject.preview) { try { int checkX = x - (unmovedTextX + AndroidUtilities.dp(10) + descriptionX); int checkY = y - descriptionY; @@ -1862,7 +2005,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); - pressedLink.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outLinkSelectBackground : Theme.key_chat_linkSelectBackground)); + pressedLink.setColor(hasLinkPreview && linkLine != null && currentMessageObject != null && !currentMessageObject.isOutOwner() ? Theme.multAlpha(linkLine.getColor(), .10f) : getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outLinkSelectBackground : Theme.key_chat_linkSelectBackground)); linkBlockNum = -10; pressedLinkType = 2; startCheckLongPress(); @@ -1904,36 +2047,71 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonPressed = 1; invalidate(); return true; - } else if (drawInstantView) { + } else { instantPressed = true; selectorDrawableMaskType[0] = 0; - if (Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) { - if (selectorDrawable[0].getBounds().contains(x, y)) { + 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); - setInstantButtonPressed(true); } + if (linkPreviewSelector != null && linkPreviewSelector.getBounds().contains(x, y)) { + linkPreviewSelector.setHotspot(x, y); + linkPreviewSelector.setState(pressedState); + } + setInstantButtonPressed(true); + } + if (linkPreviewBounce != null) { + linkPreviewBounce.setPressed(true); } invalidate(); return true; - } else if (documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && drawPhotoImage && photoImage.isInsideImage(x, y)) { - linkPreviewPressed = true; - TLRPC.WebPage webPage = MessageObject.getMedia(currentMessageObject.messageOwner).webpage; - if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && buttonState == -1 && SharedConfig.isAutoplayGifs() && (photoImage.getAnimation() == null || !TextUtils.isEmpty(webPage.embed_url))) { - linkPreviewPressed = false; - return false; - } - return true; } +// else if (documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && drawPhotoImage && photoImage.isInsideImage(x, y)) { +// linkPreviewPressed = true; +// TLRPC.WebPage webPage = MessageObject.getMedia(currentMessageObject.messageOwner).webpage; +// if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && buttonState == -1 && SharedConfig.isAutoplayGifs() && (photoImage.getAnimation() == null || !TextUtils.isEmpty(webPage.embed_url))) { +// linkPreviewPressed = false; +// return false; +// } +// return true; +// } } } else if (event.getAction() == MotionEvent.ACTION_UP) { if (instantPressed) { - if (delegate != null) { - delegate.didPressInstantButton(this, drawInstantViewType); + if (drawInstantView) { + if (delegate != null) { + delegate.didPressInstantButton(this, drawInstantViewType); + } + } else if (drawPhotoImage && authorLayout == null && titleLayout == null && descriptionLayout == null && siteNameLayout == null) { + if (delegate != null) { + delegate.didPressImage(this, lastTouchX, lastTouchY); + } + } else if (!currentMessageObject.preview) { + TLRPC.WebPage webPage = MessageObject.getMedia(currentMessageObject.messageOwner).webpage; + if (webPage != null && !TextUtils.isEmpty(webPage.embed_url)) { + if (delegate != null) { + delegate.needOpenWebView(currentMessageObject, webPage.embed_url, webPage.site_name, webPage.title, webPage.url, webPage.embed_width, webPage.embed_height); + } + } else if (webPage != null) { + if (delegate != null) { + delegate.didPressWebPage(this, webPage, webPage.url, MessageObject.getMedia(currentMessageObject.messageOwner).safe); + } else { + Browser.openUrl(getContext(), webPage.url); + } + } } playSoundEffect(SoundEffectConstants.CLICK); - if (Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) { - selectorDrawable[0].setState(StateSet.NOTHING); + if (Build.VERSION.SDK_INT >= 21) { + if (selectorDrawable[0] != null) { + selectorDrawable[0].setState(StateSet.NOTHING); + } + if (linkPreviewSelector != null) { + linkPreviewSelector.setState(StateSet.NOTHING); + } + } + if (linkPreviewBounce != null) { + linkPreviewBounce.setPressed(false); } setInstantButtonPressed(instantPressed = false); invalidate(); @@ -1991,7 +2169,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate didPressButton(true, false); playSoundEffect(SoundEffectConstants.CLICK); } - } else { + } else if (!currentMessageObject.preview) { TLRPC.WebPage webPage = MessageObject.getMedia(currentMessageObject.messageOwner).webpage; if (webPage != null && !TextUtils.isEmpty(webPage.embed_url)) { delegate.needOpenWebView(currentMessageObject, webPage.embed_url, webPage.site_name, webPage.title, webPage.url, webPage.embed_width, webPage.embed_height); @@ -1999,7 +2177,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate delegate.didPressImage(this, lastTouchX, lastTouchY); playSoundEffect(SoundEffectConstants.CLICK); } else if (webPage != null) { - Browser.openUrl(getContext(), webPage.url); + if (delegate != null) { + delegate.didPressWebPage(this, webPage, webPage.url, MessageObject.getMedia(currentMessageObject.messageOwner).safe); + } else { + Browser.openUrl(getContext(), webPage.url); + } } } resetPressedLink(2); @@ -2010,8 +2192,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate resetPressedLink(2); } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (instantButtonPressed && Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) { - selectorDrawable[0].setHotspot(x, y); + if (instantButtonPressed && Build.VERSION.SDK_INT >= 21) { + if (selectorDrawable[0] != null) { + selectorDrawable[0].setHotspot(x, y); + } + if (linkPreviewSelector != null) { + linkPreviewSelector.setHotspot(x, y); + } } } } @@ -2245,6 +2432,27 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return false; } + private boolean checkSponsoredCloseMotionEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && closeSponsoredBounds != null && closeSponsoredBounce != null && closeSponsoredBounds.contains(event.getX(), event.getY())) { + closeSponsoredBounce.setPressed(true); + return true; + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (closeSponsoredBounce != null && closeSponsoredBounce.isPressed()) { + if (delegate != null) { + delegate.didPressSponsoredClose(); + } + } + if (closeSponsoredBounce != null) { + closeSponsoredBounce.setPressed(false); + } + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + if (closeSponsoredBounce != null) { + closeSponsoredBounce.setPressed(false); + } + } + return closeSponsoredBounce != null && closeSponsoredBounce.isPressed(); + } + private boolean checkOtherButtonMotionEvent(MotionEvent event) { if ((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) && currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { return false; @@ -2314,33 +2522,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void setInstantButtonPressed(boolean pressed) { - if (instantButtonPressed != pressed) { - invalidate(); - if (pressed) { - if (instantButtonPressAnimator != null) { - instantButtonPressAnimator.removeAllListeners(); - instantButtonPressAnimator.cancel(); - } - } - if (!pressed && instantButtonPressProgress != 0) { - instantButtonPressAnimator = ValueAnimator.ofFloat(instantButtonPressProgress, 0); - instantButtonPressAnimator.addUpdateListener(animation -> { - instantButtonPressProgress = (float) animation.getAnimatedValue(); - invalidate(); - }); - instantButtonPressAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - super.onAnimationEnd(animation); - instantButtonPressAnimator = null; - } - }); - instantButtonPressAnimator.setInterpolator(new OvershootInterpolator(5.0f)); - instantButtonPressAnimator.setDuration(350); - instantButtonPressAnimator.start(); - } - instantButtonPressed = pressed; + if (instantButtonBounce == null) { + instantButtonBounce = new ButtonBounce(this); } + instantButtonBounce.setPressed(instantButtonPressed = pressed); } private boolean checkDateMotionEvent(MotionEvent event) { @@ -2680,19 +2865,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate for (SpoilerEffect eff : block.spoilers) { if (eff.getBounds().contains(x - textX + offX, (int) (y - textY - block.textYOffset))) { spoilerPressed = eff; - isCaptionSpoilerPressed = false; return true; } } } } - - if (hasCaptionLayout() && x >= captionX && y >= captionY && x <= captionX + captionLayout.getWidth() && y <= captionY + captionLayout.getHeight()) { - for (SpoilerEffect eff : captionSpoilers) { - if (eff.getBounds().contains((int) (x - captionX), (int) (y - captionY))) { - spoilerPressed = eff; - isCaptionSpoilerPressed = true; - return true; + if (captionLayout != null && x >= captionX && y >= captionY && x <= captionX + captionLayout.textWidth && y <= captionY + captionLayout.textHeight) { + List blocks = captionLayout.textLayoutBlocks; + for (int i = 0; i < blocks.size(); i++) { + if (blocks.get(i).textYOffset > y) { + break; + } + MessageObject.TextLayoutBlock block = blocks.get(i); + int offX = block.isRtl() ? (int) captionLayout.textXOffset : 0; + for (SpoilerEffect eff : block.spoilers) { + if (eff.getBounds().contains((int) (x - captionX + offX), (int) (y - captionY - block.textYOffset))) { + spoilerPressed = eff; + return true; + } } } } @@ -2700,10 +2890,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate playSoundEffect(SoundEffectConstants.CLICK); sPath.rewind(); - if (isCaptionSpoilerPressed) { - for (SpoilerEffect eff : captionSpoilers) { - Rect b = eff.getBounds(); - sPath.addRect(b.left, b.top, b.right, b.bottom, Path.Direction.CW); + if (captionLayout != null) { + for (MessageObject.TextLayoutBlock block : captionLayout.textLayoutBlocks) { + for (SpoilerEffect eff : block.spoilers) { + Rect b = eff.getBounds(); + sPath.addRect(b.left, b.top + block.textYOffset, b.right, b.bottom + block.textYOffset, Path.Direction.CW); + } } } else { for (MessageObject.TextLayoutBlock block : currentMessageObject.textLayoutBlocks) { @@ -2721,8 +2913,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate spoilerPressed.setOnRippleEndCallback(() -> post(() -> { isSpoilerRevealing = false; getMessageObject().isSpoilersRevealed = true; - if (isCaptionSpoilerPressed) { - captionSpoilers.clear(); + if (captionLayout != null) { + for (MessageObject.TextLayoutBlock block : captionLayout.textLayoutBlocks) { + block.spoilers.clear(); + } } else if (currentMessageObject.textLayoutBlocks != null) { for (MessageObject.TextLayoutBlock block : currentMessageObject.textLayoutBlocks) { block.spoilers.clear(); @@ -2730,9 +2924,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } invalidate(); })); - if (isCaptionSpoilerPressed) { - for (SpoilerEffect eff : captionSpoilers) { - eff.startRipple(x - captionX, y - captionY, rad); + if (captionLayout != null) { + for (MessageObject.TextLayoutBlock block : captionLayout.textLayoutBlocks) { + int offX = block.isRtl() ? (int) captionLayout.textXOffset : 0; + for (SpoilerEffect eff : block.spoilers) { + eff.startRipple(x - captionX + offX, y - block.textYOffset - captionY, rad); + } } } else if (currentMessageObject.textLayoutBlocks != null) { for (MessageObject.TextLayoutBlock block : currentMessageObject.textLayoutBlocks) { @@ -2861,8 +3058,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override public boolean onTouchEvent(MotionEvent event) { if (currentMessageObject == null || !delegate.canPerformActions() || animationRunning) { - checkTextSelection(event); - return super.onTouchEvent(event); + if (currentMessageObject != null && currentMessageObject.preview) { + return checkTextSelection(event); + } else { + checkTextSelection(event); + return super.onTouchEvent(event); + } } if (checkTextSelection(event)) { @@ -2911,6 +3112,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!result) { result = checkOtherButtonMotionEvent(event); } + if (!result) { + result = checkSponsoredCloseMotionEvent(event); + } if (!result) { result = checkCaptionMotionEvent(event); } @@ -2941,10 +3145,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!result) { result = checkPollButtonMotionEvent(event); } + if (!result) { + result = giveawayMessageCell.checkMotionEvent(event); + } if (event.getAction() == MotionEvent.ACTION_CANCEL) { spoilerPressed = null; - isCaptionSpoilerPressed = false; buttonPressed = 0; miniButtonPressed = 0; pressedBotButton = -1; @@ -2965,6 +3171,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate selectorDrawable[a].setState(StateSet.NOTHING); } } + if (linkPreviewSelector != null) { + linkPreviewSelector.setState(StateSet.NOTHING); + } + } + if (linkPreviewBounce != null) { + linkPreviewBounce.setPressed(false); } result = false; if (hadLongPress) { @@ -3047,6 +3259,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate }, ViewConfiguration.getTapTimeout() / 6); invalidate(); } + if (replyBounce != null) { + replyBounce.setPressed(true); + replyBounceX = x; + replyBounceY = y; + } result = true; } } @@ -3169,6 +3386,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replySelectorCanBePressed = false; invalidate(); } + if (replyBounce != null) { + replyBounce.setPressed(false); + } playSoundEffect(SoundEffectConstants.CLICK); if (replyPanelIsForward) { if (delegate != null) { @@ -3181,7 +3401,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } else { - if (delegate != null && (currentMessageObject.hasValidReplyMessageObject() || currentMessageObject.isReplyToStory())) { + if (delegate != null && (currentMessageObject.hasValidReplyMessageObject() || currentMessageObject.isReplyToStory() || isReplyQuote || currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.reply_to != null && currentMessageObject.messageOwner.reply_to.reply_from != null)) { delegate.didPressReplyMessage(this, currentMessageObject.getReplyMsgId()); } } @@ -3192,6 +3412,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replySelector.setState(new int[]{}); } invalidate(); + if (replyBounce != null) { + replyBounce.setPressed(false); + } } else if (event.getAction() == MotionEvent.ACTION_MOVE) { int replyEnd; if (currentMessageObject.shouldDrawWithoutBackground()) { @@ -3207,6 +3430,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replySelector.setState(new int[]{}); } invalidate(); + if (replyBounce != null) { + replyBounce.setPressed(false); + } } else if (replySelector != null && replySelectorCanBePressed && Math.sqrt(Math.pow(x - replyTouchX, 2) + Math.pow((y + getY()) - replyTouchY, 2)) > 0.75f) { replySelectorCanBePressed = false; } @@ -3275,7 +3501,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate isRoundVideo || currentMessageObject.isAnimatedSticker() || (currentMessageObject.isDocument() && !currentMessageObject.isGif()) || currentMessageObject.needDrawBluredPreview()) { return false; } - return pinchToZoomHelper.checkPinchToZoom(ev, this, photoImage, null, currentMessageObject, mediaSpoilerEffect2 == null ? 0 : mediaSpoilerEffect2.getAttachIndex(this)); + return pinchToZoomHelper.checkPinchToZoom(ev, this, photoImage, null, null, currentMessageObject, mediaSpoilerEffect2 == null ? 0 : mediaSpoilerEffect2.getAttachIndex(this)); } private boolean checkTextSelection(MotionEvent event) { @@ -3324,22 +3550,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasCaptionLayout()) { textSelectionHelper.setIsDescription(false); textSelectionHelper.setMaybeTextCord((int) captionX, (int) captionY); - } else { - if (descriptionLayout != null && event.getY() > descriptionY) { - textSelectionHelper.setIsDescription(true); - int linkX; - if (hasGamePreview) { - linkX = unmovedTextX - AndroidUtilities.dp(10); - } else if (hasInvoicePreview) { - linkX = unmovedTextX + AndroidUtilities.dp(1); - } else { - linkX = unmovedTextX + AndroidUtilities.dp(1); - } - textSelectionHelper.setMaybeTextCord(linkX + AndroidUtilities.dp(10) + descriptionX, descriptionY); + } else if ((currentMessageObject != null && !currentMessageObject.preview) && descriptionLayout != null && (linkPreviewAbove ? event.getY() < textY : event.getY() > descriptionY)) { + textSelectionHelper.setIsDescription(true); + int linkX; + if (hasGamePreview) { + linkX = unmovedTextX - AndroidUtilities.dp(10); + } else if (hasInvoicePreview) { + linkX = unmovedTextX + AndroidUtilities.dp(1); } else { - textSelectionHelper.setIsDescription(false); - textSelectionHelper.setMaybeTextCord(textX, textY); + linkX = unmovedTextX + AndroidUtilities.dp(1); } + textSelectionHelper.setMaybeTextCord(linkX + AndroidUtilities.dp(10) + descriptionX, descriptionY); + } else { + textSelectionHelper.setIsDescription(false); + textSelectionHelper.setMaybeTextCord(textX, textY); } textSelectionHelper.setMessageObject(this); } @@ -3361,6 +3585,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } getDelegate().getTextSelectionHelper().updateTextPosition(linkX + AndroidUtilities.dp(10) + descriptionX, descriptionY); } else if (textSelectionType == TextSelectionHelper.ChatListTextSelectionHelper.TYPE_CAPTION) { + updateCaptionLayout(); getDelegate().getTextSelectionHelper().updateTextPosition((int) captionX, (int) captionY); } else { getDelegate().getTextSelectionHelper().updateTextPosition(textX, textY); @@ -3428,11 +3653,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate double duration = 0; TLRPC.Document document = currentMessageObject.getDocument(); - for (int a = 0; a < document.attributes.size(); a++) { - TLRPC.DocumentAttribute attribute = document.attributes.get(a); - if (attribute instanceof TLRPC.TL_documentAttributeVideo) { - duration = attribute.duration; - break; + if (document != null) { + for (int a = 0; a < document.attributes.size(); a++) { + TLRPC.DocumentAttribute attribute = document.attributes.get(a); + if (attribute instanceof TLRPC.TL_documentAttributeVideo) { + duration = attribute.duration; + break; + } } } if (MediaController.getInstance().isPlayingMessage(currentMessageObject)) { @@ -3813,26 +4040,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public void updateAnimatedEmojis() { - if (!imageReceiversAttachState) { + if (!imageReceiversAttachState || currentMessageObject == null) { return; } int cache = currentMessageObject.wasJustSent ? AnimatedEmojiDrawable.getCacheTypeForEnterView() : AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES; - if (captionLayout != null) { - animatedEmojiStack = AnimatedEmojiSpan.update(cache, this, false, animatedEmojiStack, captionLayout); + if (captionLayout != null && captionLayout.textLayoutBlocks != null) { + animatedEmojiStack = AnimatedEmojiSpan.update(cache, this, false, animatedEmojiStack, captionLayout.textLayoutBlocks); } else { animatedEmojiStack = AnimatedEmojiSpan.update(cache, this, delegate == null || !delegate.canDrawOutboundsContent(), animatedEmojiStack, currentMessageObject.textLayoutBlocks); } } - private void updateCaptionSpoilers() { - captionSpoilersPool.addAll(captionSpoilers); - captionSpoilers.clear(); - - if (captionLayout != null && !getMessageObject().isSpoilersRevealed) { - SpoilerEffect.addSpoilers(this, captionLayout, -1, captionOffsetX + captionWidth, captionSpoilersPool, captionSpoilers); - } - } - private boolean isUserDataChanged() { if (currentMessageObject != null && (!hasLinkPreview && MessageObject.getMedia(currentMessageObject.messageOwner) != null && MessageObject.getMedia(currentMessageObject.messageOwner).webpage instanceof TLRPC.TL_webPage)) { return true; @@ -3937,6 +4155,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return currentUser; } + public TLRPC.Chat getCurrentChat() { + return currentChat; + } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -3944,6 +4166,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.startSpoilers); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.stopSpoilers); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didUpdatePremiumGiftStickers); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad); cancelShakeAnimation(); @@ -4005,6 +4228,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.startSpoilers); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.stopSpoilers); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didUpdatePremiumGiftStickers); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad); if (currentMessageObject != null) { @@ -4088,7 +4312,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private void checkImageReceiversAttachState() { boolean newAttachState = attachedToWindow; - boolean newVisibleState = (visibleOnScreen || !shouldCheckVisibleOnScreen); if (newAttachState != imageReceiversAttachState) { imageReceiversAttachState = newAttachState; if (newAttachState) { @@ -4104,6 +4327,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate commentAvatarImages[a].onAttachedToWindow(); } } + giveawayMessageCell.onAttachedToWindow(); replyImageReceiver.onAttachedToWindow(); locationImageReceiver.onAttachedToWindow(); blurredPhotoImage.onAttachedToWindow(); @@ -4134,46 +4358,63 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate locationImageReceiver.onDetachedFromWindow(); photoImage.onDetachedFromWindow(); blurredPhotoImage.onDetachedFromWindow(); + giveawayMessageCell.onDetachedFromWindow(); AnimatedEmojiSpan.release(this, animatedEmojiDescriptionStack); AnimatedEmojiSpan.release(this, animatedEmojiReplyStack); AnimatedEmojiSpan.release(this, animatedEmojiStack); } } + + boolean newVisibleState = attachedToWindow && (visibleOnScreen || !shouldCheckVisibleOnScreen); if (newVisibleState != imageReceiversVisibleState) { imageReceiversVisibleState = newVisibleState; if (newVisibleState) { - photoImage.setFileLoadingPriority(FileLoader.PRIORITY_NORMAL); - if (currentMessageObject != null && (isRoundVideo || currentMessageObject.isVideo())) { - checkVideoPlayback(true, null); - } - if (currentMessageObject != null && !currentMessageObject.mediaExists) { - int canDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject.messageOwner); - TLRPC.Document document = currentMessageObject.getDocument(); - boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document); - if (!loadDocumentFromImageReceiver) { - TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()) : null; - if (canDownload == 2 || canDownload == 1 && currentMessageObject.isVideo()) { - if (canDownload != 2 && document != null && !currentMessageObject.shouldEncryptPhotoOrVideo() && currentMessageObject.canStreamVideo()) { - FileLoader.getInstance(currentAccount).loadFile(document, currentMessageObject, FileLoader.PRIORITY_NORMAL, 0); - } - } else if (canDownload != 0) { - if (document != null) { - FileLoader.getInstance(currentAccount).loadFile(document, currentMessageObject, FileLoader.PRIORITY_NORMAL, MessageObject.isVideoDocument(document) && currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); - } else if (photo != null) { - FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForObject(photo, currentMessageObject.photoThumbsObject), currentMessageObject, null, FileLoader.PRIORITY_NORMAL, currentMessageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); - } - } - updateButtonState(false, false, false); - } - } + fileAttach(true, currentMessageObject); } else { - photoImage.setFileLoadingPriority(FileLoader.PRIORITY_LOW); - cancelLoading(currentMessageObject); + fileDetach(currentMessageObject); } } } + private void fileAttach(boolean checkUI, final MessageObject messageObject) { + if (photoImage != null) { + photoImage.setFileLoadingPriority(FileLoader.PRIORITY_NORMAL); + } + if (checkUI && messageObject != null && (isRoundVideo || messageObject.isVideo())) { + checkVideoPlayback(true, null); + } + if (messageObject != null && !messageObject.mediaExists) { + int canDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(messageObject.messageOwner); + TLRPC.Document document = messageObject.getDocument(); + boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document); + if (!loadDocumentFromImageReceiver) { + TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()) : null; + if (canDownload == 2 || canDownload == 1 && messageObject.isVideo()) { + if (canDownload != 2 && document != null && !messageObject.shouldEncryptPhotoOrVideo() && messageObject.canStreamVideo()) { + FileLoader.getInstance(currentAccount).loadFile(document, messageObject, FileLoader.PRIORITY_NORMAL, 0); + } + } else if (canDownload != 0) { + if (document != null) { + FileLoader.getInstance(currentAccount).loadFile(document, messageObject, FileLoader.PRIORITY_NORMAL, MessageObject.isVideoDocument(document) && messageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + } else if (photo != null) { + FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForObject(photo, messageObject.photoThumbsObject), messageObject, null, FileLoader.PRIORITY_NORMAL, messageObject.shouldEncryptPhotoOrVideo() ? 2 : 0); + } + } + if (checkUI) { + updateButtonState(false, false, false); + } + } + } + } + + private void fileDetach(MessageObject messageObject) { + if (photoImage != null) { + photoImage.setFileLoadingPriority(FileLoader.PRIORITY_LOW); + } + cancelLoading(messageObject); + } + private void cancelLoading(MessageObject messageObject) { if (messageObject != null && !messageObject.mediaExists && !messageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(messageObject.messageOwner.id) && !PhotoViewer.getInstance().isVisible()) { TLRPC.Document document = messageObject.getDocument(); @@ -4293,6 +4534,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (messageIdChanged || groupChanged) { isHighlightedAnimated = false; wasTranscriptionOpen = false; + if (highlightedQuote) { + resetUrlPaths(); + } + highlightedQuote = false; } widthBeforeNewTimeLine = -1; if (currentMessagesGroup != null && (currentMessagesGroup.posArray.size() > 1)) { @@ -4335,7 +4580,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate isThreadPost = isThreadChat && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.channel_post != 0 && messageObject.messageOwner.reply_to == null; isAvatarVisible = !isThreadPost && isChat && !messageObject.isOutOwner() && messageObject.needDrawAvatar() && (currentPosition == null || currentPosition.edge); boolean drawAvatar = isChat && !isThreadPost && !messageObject.isOutOwner() && messageObject.needDrawAvatar(); - if (messageObject.customAvatarDrawable != null) { + if (messageObject.customAvatarDrawable != null || messageObject.forceAvatar) { isAvatarVisible = true; drawAvatar = true; } @@ -4353,6 +4598,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawSideButton = 2; } } + isReplyQuote = false; replyNameLayout = null; adminLayout = null; checkOnlyButtonPressed = false; @@ -4363,16 +4609,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate autoPlayingMedia = false; replyNameWidth = 0; replyTextWidth = 0; + replyTextHeight = 0; viaWidth = 0; viaNameWidth = 0; addedCaptionHeight = 0; currentReplyPhoto = null; currentUser = null; currentChat = null; - currentReplyUserId = 0; currentViaBotUser = null; instantViewLayout = null; drawNameLayout = false; + linkPreviewAbove = false; lastLoadingSizeTotal = 0; if (scheduledInvalidate) { AndroidUtilities.cancelRunOnUIThread(invalidateRunnable); @@ -4401,7 +4648,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } spoilerPressed = null; - isCaptionSpoilerPressed = false; isSpoilerRevealing = false; linkPreviewPressed = false; buttonPressed = 0; @@ -4421,11 +4667,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photosCountLayout = null; siteNameLayout = null; authorLayout = null; + captionFullWidth = 0; captionLayout = null; captionWidth = 0; captionHeight = 0; captionOffsetX = 0; currentCaption = null; + captionLayout = null; docTitleLayout = null; drawImageButton = false; drawVideoImageButton = false; @@ -4637,12 +4885,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate measureTime(currentMessageObject); backgroundWidth += timeWidth + AndroidUtilities.dp(12); drawForwardedName = false; + isReplyQuote = false; replyNameLayout = null; replyTextLayout = null; forwardedNameLayout[0] = null; forwardedNameLayout[1] = null; drawName = false; - } else if (messageObject.type == MessageObject.TYPE_TEXT || messageObject.type == MessageObject.TYPE_STORY_MENTION) { + } else if (messageObject.type == MessageObject.TYPE_TEXT || messageObject.type == MessageObject.TYPE_STORY_MENTION || messageObject.isGiveaway()) { drawForwardedName = !isRepliesChat; int maxWidth; @@ -4681,18 +4930,29 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate hasLinkPreview = true; webpage = messageObject.getStoryMentionWebpage(); } + drawInstantView = hasLinkPreview && webpage.cached_page != null; String siteName = hasLinkPreview ? webpage.site_name : null; hasEmbed = hasLinkPreview && !TextUtils.isEmpty(webpage.embed_url) && !messageObject.isGif() && !"instagram".equalsIgnoreCase(siteName); boolean slideshow = false; String webpageType = webpage != null ? webpage.type : null; TLRPC.Document androidThemeDocument = null; - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; TLRPC.ThemeSettings androidThemeSettings = null; + if (messageObject.isGiveaway()) { + hasLinkPreview = true; + } + if (!drawInstantView) { - if ("telegram_channel_boost".equals(webpageType)) { + if (messageObject.isGiveaway()) { + drawInstantView = true; + drawInstantViewType = 19; + } else if ("telegram_channel_boost".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 18; + } else if ("telegram_giftcode".equals(webpageType)) { + drawInstantView = true; + drawInstantViewType = 20; } else if ("telegram_livestream".equals(webpageType)) { drawInstantView = true; drawInstantViewType = 11; @@ -4757,7 +5017,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (storyItem != null) { storyItem.messageId = messageObject.getId(); storyItem.dialogId = DialogObject.getPeerDialogId(attribute.peer); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { drawInstantView = false; hasLinkPreview = false; drawInstantViewType = 0; @@ -4857,7 +5117,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } backgroundWidth = maxWidth; - if (hasLinkPreview || hasGamePreview || hasInvoicePreview || maxWidth - messageObject.lastLineWidth < timeMore) { + if (hasLinkPreview && !linkPreviewAbove || hasGamePreview || hasInvoicePreview || maxWidth - messageObject.lastLineWidth < timeMore) { backgroundWidth = Math.max(backgroundWidth, messageObject.lastLineWidth) + AndroidUtilities.dp(31); backgroundWidth = Math.max(backgroundWidth, timeWidth + AndroidUtilities.dp(31)); } else { @@ -4892,6 +5152,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawPinnedTop) { namesOffset -= AndroidUtilities.dp(1); } + if (currentMessageObject != null && currentMessageObject.hasCodeAtTop && namesOffset > 0) { + totalHeight += AndroidUtilities.dp(5); + } int maxChildWidth = Math.max(backgroundWidth, nameWidth); maxChildWidth = Math.max(maxChildWidth, forwardedNameWidth); @@ -4908,17 +5171,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasLinkPreview || hasGamePreview || hasInvoicePreview) { int linkPreviewMaxWidth; if (AndroidUtilities.isTablet()) { - if (drawAvatar) { - linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80 + 52); - } else { - linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80); - } + linkPreviewMaxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80 + (drawAvatar ? 52 : 0)); } else { - if (drawAvatar) { - linkPreviewMaxWidth = getParentWidth() - AndroidUtilities.dp(80 + 52); - } else { - linkPreviewMaxWidth = getParentWidth() - AndroidUtilities.dp(80); - } + linkPreviewMaxWidth = getParentWidth() - AndroidUtilities.dp(80 + (drawAvatar ? 52 : 0)); } if (drawSideButton != 0) { linkPreviewMaxWidth -= AndroidUtilities.dp(20); @@ -4935,10 +5190,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean smallImage; String type; final int smallImageSide = AndroidUtilities.dp(48), smallSideMargin = AndroidUtilities.dp(10); - if (drawInstantViewType == 17) { + if (drawInstantViewType == 19) { + site_name = null; + title = null; + webDocument = null; + description = null; + photo = null; + author = null; + document = null; + duration = 0; + type = null; + isSmallImage = false; + linkPreviewAbove = false; + smallImage = false; + } else if (drawInstantViewType == 17) { site_name = null; TLRPC.User user = storyItem == null ? null : MessagesController.getInstance(currentAccount).getUser(storyItem.dialogId); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { site_name_additionalWidth += AndroidUtilities.dp(14); site_name = StoriesUtilities.createExpiredStoryString(); } else if (user != null) { @@ -4956,6 +5224,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate duration = storyItem != null && storyItem.media != null && storyItem.media.document != null ? (int) MessageObject.getDocumentDuration(storyItem.media.document) : 0; smallImage = false; isSmallImage = false; + linkPreviewAbove = currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.invert_media; } else if (hasLinkPreview) { TLRPC.TL_webPage webPage = (TLRPC.TL_webPage) webpage; site_name = webPage.site_name; @@ -4983,7 +5252,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate "telegram_user".equals(type) || "telegram_channel".equals(type) || "telegram_megagroup".equals(type) || "telegram_voicechat".equals(type) || "telegram_livestream".equals(type) || "telegram_channel_boost".equals(type); - smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18) && document == null && isSmallImageType; + smallImage = !slideshow && (!drawInstantView || drawInstantViewType == 1 || drawInstantViewType == 2 || drawInstantViewType == 9 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 18 || drawInstantViewType == 20) && document == null && isSmallImageType; + TLRPC.MessageMedia media = MessageObject.getMedia(messageObject.messageOwner); + if (media != null) { + if (media.force_large_media) { + smallImage = false; + } + if (media.force_small_media) { + smallImage = true; + } + } + linkPreviewAbove = currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.invert_media; isSmallImage = smallImage && type != null && currentMessageObject.photoThumbs != null; } else if (hasInvoicePreview) { TLRPC.TL_messageMediaInvoice invoice = (TLRPC.TL_messageMediaInvoice) MessageObject.getMedia(messageObject.messageOwner); @@ -5001,6 +5280,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate duration = 0; type = "invoice"; isSmallImage = false; + linkPreviewAbove = false; smallImage = false; } else { TLRPC.TL_game game = MessageObject.getMedia(messageObject.messageOwner).game; @@ -5014,6 +5294,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate duration = 0; type = "game"; isSmallImage = false; + linkPreviewAbove = false; smallImage = false; } if (drawInstantViewType == 18) { @@ -5028,7 +5309,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate site_name = LocaleController.getString("ColorTheme", R.string.ColorTheme); } - int additinalWidth = hasInvoicePreview ? 0 : AndroidUtilities.dp(10); + int additinalWidth = AndroidUtilities.dp(20); + if (hasInvoicePreview) { + additinalWidth = 0; + } + if (drawInstantViewType == 17) { + additinalWidth += AndroidUtilities.dp(20); + } int restLinesCount = 3; linkPreviewMaxWidth -= additinalWidth; @@ -5036,6 +5323,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentMessageObject.generateThumbs(true); } + giveawayMessageCell.setMessageContent(messageObject, getParentWidth(), forwardedNameWidth); + totalHeight += giveawayMessageCell.getMeasuredHeight(); + linkPreviewHeight += giveawayMessageCell.getMeasuredHeight(); + maxChildWidth = Math.max(maxChildWidth, giveawayMessageCell.getMeasuredWidth()); + if (site_name != null) { try { int width = (int) Math.ceil(Theme.chat_replyNamePaint.measureText(site_name.toString()) + 1 + site_name_additionalWidth); @@ -5047,10 +5339,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate siteNameLayout = generateStaticLayout(site_name, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 1); restLinesCount -= siteNameLayout.getLineCount(); } - siteNameLeft = siteNameLayoutWidth = 0; + siteNameLeft = siteNameLayout.getWidth(); + siteNameLayoutWidth = 0; for (int i = 0; i < siteNameLayout.getLineCount(); ++i) { - siteNameLeft = siteNameLayout.getLineLeft(i); - siteNameLayoutWidth = siteNameLayout.getLineWidth(i); + siteNameLeft = Math.min(siteNameLeft, siteNameLayout.getLineLeft(i)); + siteNameLayoutWidth = Math.max(siteNameLayoutWidth, siteNameLayout.getLineWidth(i)); } int height = siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); linkPreviewHeight += height; @@ -5082,12 +5375,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } boolean titleIsRTL = false; - if (!titleIsRTL && author != null) { - titleIsRTL = AndroidUtilities.isRTL(author); - } - if (!titleIsRTL && messageObject.linkDescription != null) { - titleIsRTL = AndroidUtilities.isRTL(messageObject.linkDescription); - } if (title != null) { try { titleX = Integer.MAX_VALUE; @@ -5096,42 +5383,36 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate totalHeight += AndroidUtilities.dp(2); } int restLines = 0; + CharSequence titleCs = title; + try { + titleCs = Emoji.replaceEmoji(title, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + } catch (Exception ignore) { + } if (!isSmallImage) { - titleLayout = StaticLayoutEx.createStaticLayout(title, Theme.chat_replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, 4); + titleLayout = StaticLayoutEx.createStaticLayout(titleCs, Theme.chat_replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, AndroidUtilities.dp(1), false, TextUtils.TruncateAt.END, linkPreviewMaxWidth, 4); } else { restLines = restLinesCount; - titleLayout = generateStaticLayout(title, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 4); + titleLayout = generateStaticLayout(titleCs, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 4); restLinesCount -= titleLayout.getLineCount(); } + + titleLayoutWidth = 0; + titleLayoutLeft = titleLayout.getWidth(); + for (int a = 0; a < titleLayout.getLineCount(); a++) { + titleLayoutLeft = (int) Math.min(titleLayoutLeft, titleLayout.getLineLeft(a)); + float width = titleLayout.getLineWidth(a); + if (a < restLines || titleLayoutLeft != 0 && isSmallImage) { + width += smallImageSide + smallSideMargin; + } + titleLayoutWidth = (int) Math.max(titleLayoutWidth, width); + } + maxChildWidth = Math.max(maxChildWidth, titleLayoutWidth + additinalWidth); + maxWebWidth = Math.max(maxWebWidth, titleLayoutWidth + additinalWidth); + titleIsRTL = titleLayoutLeft != 0; + int height = titleLayout.getLineBottom(titleLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; - for (int a = 0; a < titleLayout.getLineCount(); a++) { - int lineLeft = (int) Math.max(0, titleLayout.getLineLeft(a)); - if (lineLeft != 0) { - titleIsRTL = true; - } - if (titleX == Integer.MAX_VALUE) { - titleX = -lineLeft; - } else { - titleX = Math.max(titleX, -lineLeft); - } - int width; - if (lineLeft != 0) { - width = titleLayout.getWidth() - lineLeft; - } else { - int max = linkPreviewMaxWidth; - if (a < restLines || lineLeft != 0 && isSmallImage) { - max -= smallImageSide + smallSideMargin; - } - width = (int) Math.min(max, Math.ceil(titleLayout.getLineWidth(a))); - } - if (a < restLines || lineLeft != 0 && isSmallImage) { - width += smallImageSide + smallSideMargin; - } - maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); - maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); - } } catch (Exception e) { FileLog.e(e); } @@ -5140,7 +5421,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewMaxWidth -= AndroidUtilities.dp(48); } - boolean authorIsRTL = false; if (author != null && title == null) { try { if (linkPreviewHeight != 0) { @@ -5157,20 +5437,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate authorLayout = generateStaticLayout(author, Theme.chat_replyNamePaint, linkPreviewMaxWidth, linkPreviewMaxWidth - smallImageSide - smallSideMargin, restLinesCount, 1); restLinesCount -= authorLayout.getLineCount(); } + authorLayoutLeft = authorLayout.getWidth(); + authorLayoutWidth = 0; + for (int i = 0; i < authorLayout.getLineCount(); ++i) { + authorLayoutLeft = (int) Math.min(authorLayoutLeft, authorLayout.getLineLeft(i)); + authorLayoutWidth = (int) Math.max(authorLayoutWidth, authorLayout.getLineWidth(i)); + } int height = authorLayout.getLineBottom(authorLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; - int lineLeft = (int) Math.max(authorLayout.getLineLeft(0), 0); - authorX = -lineLeft; - int width; - if (lineLeft != 0) { - width = authorLayout.getWidth() - lineLeft; - authorIsRTL = true; - } else { - width = (int) Math.ceil(authorLayout.getLineWidth(0)); - } - maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); - maxWebWidth = Math.max(maxWebWidth, width + additinalWidth); + maxChildWidth = Math.max(maxChildWidth, authorLayoutWidth + additinalWidth); + maxWebWidth = Math.max(maxWebWidth, authorLayoutWidth + additinalWidth); } catch (Exception e) { FileLog.e(e); } @@ -5194,54 +5471,25 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate descriptionLayout = generateStaticLayout(messageObject.linkDescription, Theme.chat_replyTextPaint, linkPreviewMaxWidth - (isRTL ? smallImageSide : 0), linkPreviewMaxWidth - smallImageSide - (isRTL ? 0 : smallSideMargin), restLinesCount, allowAllLines ? 100 : 6); } animatedEmojiDescriptionStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, animatedEmojiDescriptionStack, descriptionLayout); + int height = descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1); linkPreviewHeight += height; totalHeight += height; - boolean hasRTL = false; + descriptionLayoutWidth = 0; + descriptionLayoutLeft = descriptionLayout.getWidth(); for (int a = 0; a < descriptionLayout.getLineCount(); a++) { - int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a)); - if (lineLeft > 0) { - hasRTL = true; - if (descriptionX == 0) { - descriptionX = -lineLeft; - } else { - descriptionX = Math.max(descriptionX, -lineLeft); - } - } - } - - int textWidth = descriptionLayout.getWidth(); - for (int a = 0; a < descriptionLayout.getLineCount(); a++) { - int lineLeft = (int) Math.ceil(descriptionLayout.getLineLeft(a)); - if (lineLeft == 0 && descriptionX != 0) { - descriptionX = 0; - } - - int width; - if (lineLeft > 0) { - width = textWidth - lineLeft; - } else { - if (hasRTL) { - width = textWidth; - } else { - width = Math.min((int) Math.ceil(descriptionLayout.getLineWidth(a)), textWidth); - } - } - if (a < restLines || restLines != 0 && lineLeft != 0 && isSmallImage) { + descriptionLayoutLeft = (int) Math.min(descriptionLayoutLeft, descriptionLayout.getLineLeft(a)); + float width = descriptionLayout.getLineWidth(a); + if (a < restLines || restLines != 0 && descriptionLayoutLeft != 0 && isSmallImage) { width += smallImageSide + smallSideMargin; } - if (maxWebWidth < width + additinalWidth) { - if (titleIsRTL) { - titleX += (width + additinalWidth - maxWebWidth); - } - if (authorIsRTL) { - authorX += (width + additinalWidth - maxWebWidth); - } - maxWebWidth = width + additinalWidth; - } - maxChildWidth = Math.max(maxChildWidth, width + additinalWidth); + descriptionLayoutWidth = (int) Math.max(descriptionLayoutWidth, width); } + if (maxWebWidth < descriptionLayoutWidth + additinalWidth) { + maxWebWidth = descriptionLayoutWidth + additinalWidth; + } + maxChildWidth = Math.max(maxChildWidth, descriptionLayoutWidth + additinalWidth); } catch (Exception e) { FileLog.e(e); } @@ -5436,9 +5684,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (MessageObject.isVoiceDocument(document)) { createDocumentLayout(backgroundWidth - AndroidUtilities.dp(10), messageObject); - mediaOffsetY = currentMessageObject.textHeight + AndroidUtilities.dp(8) + linkPreviewHeight; - totalHeight += AndroidUtilities.dp(30 + 14); - linkPreviewHeight += AndroidUtilities.dp(44); + mediaOffsetY = (linkPreviewAbove ? 0 : currentMessageObject.textHeight) + AndroidUtilities.dp(8) + linkPreviewHeight; + totalHeight += AndroidUtilities.dp(44 + (hasLinkPreview ? 4 : (linkPreviewAbove ? -4 : 0))); + linkPreviewHeight += AndroidUtilities.dp(44 + (hasLinkPreview ? 4 : 0)); maxWidth = maxWidth - AndroidUtilities.dp(86); if (AndroidUtilities.isTablet()) { @@ -5449,9 +5697,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate calcBackgroundWidth(maxWidth, timeMore, maxChildWidth); } else if (MessageObject.isMusicDocument(document)) { int durationWidth = createDocumentLayout(backgroundWidth - AndroidUtilities.dp(10), messageObject); - mediaOffsetY = currentMessageObject.textHeight + AndroidUtilities.dp(8) + linkPreviewHeight; - totalHeight += AndroidUtilities.dp(42 + 14); - linkPreviewHeight += AndroidUtilities.dp(56); + mediaOffsetY = (linkPreviewAbove ? 0 : currentMessageObject.textHeight) + AndroidUtilities.dp(8) + linkPreviewHeight; + totalHeight += AndroidUtilities.dp(56 + (linkPreviewAbove ? -4 : 0)); + linkPreviewHeight += AndroidUtilities.dp(60); maxWidth = maxWidth - AndroidUtilities.dp(86); maxChildWidth = Math.max(maxChildWidth, durationWidth + additinalWidth + AndroidUtilities.dp(86 + 8)); @@ -5471,9 +5719,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewHeight += AndroidUtilities.dp(86); photoImage.setImageCoords(0, totalHeight + namesOffset, AndroidUtilities.dp(86), AndroidUtilities.dp(86)); } else { - mediaOffsetY = currentMessageObject.textHeight + AndroidUtilities.dp(8) + linkPreviewHeight; + mediaOffsetY = (linkPreviewAbove ? 0 : currentMessageObject.textHeight) + AndroidUtilities.dp(8) + linkPreviewHeight; photoImage.setImageCoords(0, totalHeight + namesOffset - AndroidUtilities.dp(14), AndroidUtilities.dp(56), AndroidUtilities.dp(56)); - totalHeight += AndroidUtilities.dp(50 + 14); + totalHeight += AndroidUtilities.dp(50 + 14 + (linkPreviewAbove ? -4 : 0)); linkPreviewHeight += AndroidUtilities.dp(50); if (docTitleLayout != null && docTitleLayout.getLineCount() > 1) { int h = (docTitleLayout.getLineCount() - 1) * AndroidUtilities.dp(16); @@ -5506,6 +5754,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC && documentAttachType != DOCUMENT_ATTACH_TYPE_AUDIO && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (currentPhotoObject != null || webDocument != null || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { drawImageButton = photo != null && !smallImage || type != null && (type.equals("photo") || type.equals("document") && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER || type.equals("gif") || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER); + if (isSmallImage) { + drawImageButton = false; + } if (linkPreviewHeight != 0) { linkPreviewHeight += AndroidUtilities.dp(2); totalHeight += AndroidUtilities.dp(2); @@ -5626,101 +5877,99 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (webDocument != null) { /*TODO*/ photoImage.setImage(ImageLocation.getForWebFile(webDocument), currentPhotoFilter, null, null, webDocument.size, null, messageObject, 1); - } else { - if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { - if (messageObject.mediaExists) { - photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); - } else { - photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); - } - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { - if (document instanceof DocumentObject.ThemeDocument) { - photoImage.setImage(ImageLocation.getForDocument(document), currentPhotoFilter, null, "b1", 0, "jpg", messageObject, 1); - } else { - photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, document), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); - } - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STORY) { - if (document != null) { - photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, document), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); - } else if (photo != null) { - photoImage.setImage(ImageLocation.getForPhoto(currentPhotoObject, photo), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photo), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); - } - if (currentPhotoObject != null && (currentPhotoObject.gradientTopColor != 0 && currentPhotoObject.gradientBottomColor != 0)) { - gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] { currentPhotoObject.gradientTopColor, currentPhotoObject.gradientBottomColor }); - } else if (currentPhotoObjectThumbStripped != null && currentPhotoObjectThumbStripped.getBitmap() != null) { - final int[] colors = DominantColors.getColorsSync(false, currentPhotoObjectThumbStripped.getBitmap(), Theme.isCurrentThemeDark()); - gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors); - if (currentPhotoObject != null) { - currentPhotoObject.gradientTopColor = colors[0]; - currentPhotoObject.gradientBottomColor = colors[1]; - } - } - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { - boolean isWebpSticker = messageObject.isSticker(); - if (!SharedConfig.loopStickers() && messageObject.isVideoSticker()) { - photoImage.animatedFileDrawableRepeatMaxCount = 1; - } - if (SharedConfig.loopStickers() || (isWebpSticker && !messageObject.isVideoSticker())) { - photoImage.setAutoRepeat(1); - } else { - currentPhotoFilter = String.format(Locale.US, "%d_%d_nr_messageId=%d", w, h, messageObject.stableId); - photoImage.setAutoRepeat(delegate != null && delegate.shouldRepeatSticker(messageObject) ? 2 : 3); - } - photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", documentAttach.size, "webp", messageObject, 1); - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - photoImage.setNeedsQualityThumb(true); - photoImage.setShouldGenerateQualityThumb(true); - if (SharedConfig.isAutoplayVideo() && (!currentMessageObject.hasMediaSpoilers() || currentMessageObject.isMediaSpoilersRevealed || currentMessageObject.revealingMediaSpoilers) && ( - (currentMessageObject.mediaExists || currentMessageObject.attachPathExists) || - messageObject.canStreamVideo() && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) - )) { - photoImage.setAllowDecodeSingleFrame(true); - photoImage.setAllowStartAnimation(true); - photoImage.startAnimation(); - photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, documentAttach.size, null, messageObject, 0); - autoPlayingMedia = true; - } else { - if (currentPhotoObjectThumb != null || currentPhotoObjectThumbStripped != null) { - photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, 0, null, messageObject, 0); - } else { - photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, currentPhotoObjectThumbStripped, 0, null, messageObject, 0); - } - } - } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { - photoImage.setAllowDecodeSingleFrame(true); - boolean autoDownload = false; - if (MessageObject.isRoundVideoDocument(document)) { - photoImage.setRoundRadius(AndroidUtilities.roundMessageSize / 2); - canChangeRadius = false; - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } else if (MessageObject.isGifDocument(document, messageObject.hasValidGroupId())) { - autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); - } - String filter = currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter; - if (messageObject.mediaExists || autoDownload) { - autoPlayingMedia = true; - TLRPC.VideoSize videoSize = MessageObject.getDocumentVideoThumb(document); - if (!messageObject.mediaExists && videoSize != null && (currentPhotoObject == null || currentPhotoObjectThumb == null)) { - photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? filter : currentPhotoFilterThumb, currentPhotoObjectThumbStripped, document.size, null, messageObject, 0); - } else { - photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, document.size, null, messageObject, 0); - } - } else { - photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, 0, null, currentMessageObject, 0); - } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER) { + if (messageObject.mediaExists) { + photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); } else { - boolean photoExist = messageObject.mediaExists; - String fileName = FileLoader.getAttachFileName(currentPhotoObject); - if (hasGamePreview || photoExist || DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { - photoNotSet = false; + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, document), "b1", 0, "jpg", messageObject, 1); + } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_THEME) { + if (document instanceof DocumentObject.ThemeDocument) { + photoImage.setImage(ImageLocation.getForDocument(document), currentPhotoFilter, null, "b1", 0, "jpg", messageObject, 1); + } else { + photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, document), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); + } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STORY) { + if (document != null) { + photoImage.setImage(ImageLocation.getForDocument(currentPhotoObject, document), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); + } else if (photo != null) { + photoImage.setImage(ImageLocation.getForPhoto(currentPhotoObject, photo), currentPhotoFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, photo), "b1", currentPhotoObjectThumbStripped, 0, "jpg", messageObject, 1); + } + if (currentPhotoObject != null && (currentPhotoObject.gradientTopColor != 0 && currentPhotoObject.gradientBottomColor != 0)) { + gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] { currentPhotoObject.gradientTopColor, currentPhotoObject.gradientBottomColor }); + } else if (currentPhotoObjectThumbStripped != null && currentPhotoObjectThumbStripped.getBitmap() != null) { + final int[] colors = DominantColors.getColorsSync(false, currentPhotoObjectThumbStripped.getBitmap(), Theme.isCurrentThemeDark()); + gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors); + if (currentPhotoObject != null) { + currentPhotoObject.gradientTopColor = colors[0]; + currentPhotoObject.gradientBottomColor = colors[1]; + } + } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER) { + boolean isWebpSticker = messageObject.isSticker(); + if (!SharedConfig.loopStickers() && messageObject.isVideoSticker()) { + photoImage.animatedFileDrawableRepeatMaxCount = 1; + } + if (SharedConfig.loopStickers() || (isWebpSticker && !messageObject.isVideoSticker())) { + photoImage.setAutoRepeat(1); + } else { + currentPhotoFilter = String.format(Locale.US, "%d_%d_nr_messageId=%d", w, h, messageObject.stableId); + photoImage.setAutoRepeat(delegate != null && delegate.shouldRepeatSticker(messageObject) ? 2 : 3); + } + photoImage.setImage(ImageLocation.getForDocument(documentAttach), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObject, documentAttach), "b1", documentAttach.size, "webp", messageObject, 1); + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { + photoImage.setNeedsQualityThumb(true); + photoImage.setShouldGenerateQualityThumb(true); + if (!isSmallImage && SharedConfig.isAutoplayVideo() && (!currentMessageObject.hasMediaSpoilers() || currentMessageObject.isMediaSpoilersRevealed || currentMessageObject.revealingMediaSpoilers) && ( + (currentMessageObject.mediaExists || currentMessageObject.attachPathExists) || + messageObject.canStreamVideo() && DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) + )) { + photoImage.setAllowDecodeSingleFrame(true); + photoImage.setAllowStartAnimation(true); + photoImage.startAnimation(); + photoImage.setImage(ImageLocation.getForDocument(documentAttach), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, documentAttach.size, null, messageObject, 0); + autoPlayingMedia = true; + } else { + if (currentPhotoObjectThumb != null || currentPhotoObjectThumbStripped != null) { photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, 0, null, messageObject, 0); } else { - photoNotSet = true; - if (currentPhotoObjectThumb != null || currentPhotoObjectThumbStripped != null) { - photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), String.format(Locale.US, "%d_%d_b", w, h), currentPhotoObjectThumbStripped, 0, null, messageObject, 0); - } else { - photoImage.setImageBitmap((Drawable) null); - } + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter, currentPhotoObjectThumbStripped, 0, null, messageObject, 0); + } + } + } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { + photoImage.setAllowDecodeSingleFrame(true); + boolean autoDownload = false; + if (MessageObject.isRoundVideoDocument(document)) { + photoImage.setRoundRadius(AndroidUtilities.roundMessageSize / 2); + canChangeRadius = false; + autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); + } else if (MessageObject.isGifDocument(document, messageObject.hasValidGroupId())) { + autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject); + } + String filter = currentPhotoObject instanceof TLRPC.TL_photoStrippedSize || "s".equals(currentPhotoObject.type) ? currentPhotoFilterThumb : currentPhotoFilter; + if (messageObject.mediaExists || autoDownload) { + autoPlayingMedia = true; + TLRPC.VideoSize videoSize = MessageObject.getDocumentVideoThumb(document); + if (!messageObject.mediaExists && videoSize != null && (currentPhotoObject == null || currentPhotoObjectThumb == null)) { + photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(videoSize, documentAttach), null, ImageLocation.getForDocument(currentPhotoObject != null ? currentPhotoObject : currentPhotoObjectThumb, documentAttach), currentPhotoObject != null ? filter : currentPhotoFilterThumb, currentPhotoObjectThumbStripped, document.size, null, messageObject, 0); + } else { + photoImage.setImage(ImageLocation.getForDocument(document), document.size < 1024 * 32 ? null : ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, ImageLocation.getForDocument(currentPhotoObjectThumb, documentAttach), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, document.size, null, messageObject, 0); + } + } else { + photoImage.setImage(null, null, ImageLocation.getForDocument(currentPhotoObject, documentAttach), filter, 0, null, currentMessageObject, 0); + } + } else { + boolean photoExist = messageObject.mediaExists; + String fileName = FileLoader.getAttachFileName(currentPhotoObject); + if (hasGamePreview || photoExist || DownloadController.getInstance(currentAccount).canDownloadMedia(currentMessageObject) || FileLoader.getInstance(currentAccount).isLoadingFile(fileName)) { + photoNotSet = false; + photoImage.setImage(ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, 0, null, messageObject, 0); + } else { + photoNotSet = true; + if (currentPhotoObjectThumb != null || currentPhotoObjectThumbStripped != null) { + photoImage.setImage(null, null, ImageLocation.getForObject(currentPhotoObjectThumb, photoParentObject), String.format(Locale.US, "%d_%d_b", w, h), currentPhotoObjectThumbStripped, 0, null, messageObject, 0); + } else { + photoImage.setImageBitmap((Drawable) null); } } } @@ -5762,7 +6011,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate blurredPhotoImage.getBitmap().recycle(); blurredPhotoImage.setImageBitmap((Bitmap) null); } - linkPreviewHeight -= AndroidUtilities.dp(6); + linkPreviewHeight -= AndroidUtilities.dp(4); totalHeight += AndroidUtilities.dp(4); } if (hasInvoicePreview) { @@ -5798,6 +6047,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } calcBackgroundWidth(maxWidth, timeMore, maxChildWidth); } + + if (!hasInvoicePreview && !currentMessageObject.isSponsored() && !currentMessageObject.isGiveaway()) { + linkPreviewHeight += AndroidUtilities.dp(6); + totalHeight += AndroidUtilities.dp(6); + } + if (!hasInvoicePreview && !currentMessageObject.isSponsored() && !currentMessageObject.isGiveaway() && ( + currentPhotoObject != null || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO + ) && (authorLayout != null || descriptionLayout != null || titleLayout != null || siteNameLayout != null)) { + linkPreviewHeight += AndroidUtilities.dp(2.66f); + } + + totalHeight += AndroidUtilities.dp(2 + (!drawInstantView ? 4 : 0)); + createInstantViewButton(); } else { photoImage.setImageBitmap((Drawable) null); @@ -6403,25 +6665,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int widthForCaption = 0; createDocumentLayout(maxWidth, messageObject); int width = backgroundWidth - AndroidUtilities.dp(31); - widthForCaption = width - AndroidUtilities.dp(10) - getExtraTextX() * 2; + captionFullWidth = width - AndroidUtilities.dp(10); + widthForCaption = captionFullWidth - getExtraTextX() * 2; - if (!messageObject.isRestrictedMessage && !TextUtils.isEmpty(messageObject.caption)) { - try { - currentCaption = messageObject.caption; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - captionLayout = StaticLayout.Builder.obtain(messageObject.caption, 0, messageObject.caption.length(), Theme.chat_msgTextPaint, widthForCaption) - .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) - .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .build(); - } else { - captionLayout = new StaticLayout(messageObject.caption, Theme.chat_msgTextPaint, widthForCaption, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - } - updateCaptionSpoilers(); - } catch (Exception e) { - FileLog.e(e); - } - } + int captionLayoutAddWidth = 0; if (docTitleLayout != null) { for (int a = 0, N = docTitleLayout.getLineCount(); a < N; a++) { @@ -6434,12 +6681,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (captionLayout != null) { - for (int a = 0, N = captionLayout.getLineCount(); a < N; a++) { - int w = (int) Math.ceil(Math.min(widthForCaption, captionLayout.getLineWidth(a) + captionLayout.getLineLeft(a))) + AndroidUtilities.dp(31); - if (w > maxTextWidth) { - maxTextWidth = w; - } - } + maxTextWidth = Math.max(captionLayout.textWidth, maxTextWidth); } if (!reactionsLayoutInBubble.isSmall) { reactionsLayoutInBubble.measure(widthForCaption, Gravity.LEFT); @@ -7129,7 +7371,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoWidth += AndroidUtilities.dp(10); } photoHeight = h; - widthForCaption += photoWidth - AndroidUtilities.dp(10); + widthForCaption += photoWidth - AndroidUtilities.dp(15); boolean checkCaption = true; if ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 || currentMessagesGroup.hasSibling && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0) { widthForCaption += getAdditionalWidthForPosition(currentPosition); @@ -7164,7 +7406,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { w -= AndroidUtilities.dp(9); } - if (isChat && !isThreadPost && !m.isOutOwner() && m.needDrawAvatar() && (rowPosition == null || rowPosition.edge)) { + if ((isChat && !isThreadPost && !m.isOutOwner() || m.forceAvatar) && m.needDrawAvatar() && (rowPosition == null || rowPosition.edge)) { w -= AndroidUtilities.dp(48); } w += getAdditionalWidthForPosition(rowPosition); @@ -7214,60 +7456,46 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentCaption != null) { try { + captionFullWidth = widthForCaption; widthForCaption -= getExtraTextX() * 2; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - captionLayout = StaticLayout.Builder.obtain(currentCaption, 0, currentCaption.length(), Theme.chat_msgTextPaint, widthForCaption) - .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) - .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .build(); - } else { - captionLayout = new StaticLayout(currentCaption, Theme.chat_msgTextPaint, widthForCaption, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - } - int lineCount = captionLayout.getLineCount(); - if (lineCount > 0) { - if (fixPhotoWidth) { - captionWidth = 0; - for (int a = 0; a < lineCount; a++) { - captionWidth = (int) Math.max(captionWidth, Math.ceil(captionLayout.getLineWidth(a))); - if (captionLayout.getLineLeft(a) != 0) { - captionWidth = widthForCaption; - break; - } - } - if (captionWidth > widthForCaption) { - captionWidth = widthForCaption; - } - } else { + captionLayout = new MessageObject.TextLayoutBlocks(currentMessageObject, currentCaption, Theme.chat_msgTextPaint, widthForCaption); + if (fixPhotoWidth) { + captionWidth = captionLayout.textWidth; + if (captionWidth > widthForCaption) { captionWidth = widthForCaption; } - updateCaptionSpoilers(); - if (widthCaptionMin > 0 && captionWidth > widthCaptionMin) { - photoWidth += captionWidth - widthCaptionMin; - backgroundWidth += captionWidth - widthCaptionMin; - } - captionHeight = captionLayout.getHeight(); - addedCaptionHeight = captionHeight + AndroidUtilities.dp(9); - if (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { - additionHeight += addedCaptionHeight; - int widthToCheck = Math.max(captionWidth, photoWidth - AndroidUtilities.dp(10)); - float lastLineWidth = captionLayout.getLineWidth(captionLayout.getLineCount() - 1) + captionLayout.getLineLeft(captionLayout.getLineCount() - 1); - if ((reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) && !shouldDrawTimeOnMedia() && widthToCheck + AndroidUtilities.dp(2) - lastLineWidth < timeWidthTotal + getExtraTimeX()) { - additionHeight += AndroidUtilities.dp(14); - addedCaptionHeight += AndroidUtilities.dp(14); - captionNewLine = 1; - } - } else { - captionLayout = null; - updateCaptionSpoilers(); + } else { + captionWidth = widthForCaption; + } + if (widthCaptionMin > 0 && captionWidth > widthCaptionMin) { + photoWidth += captionWidth - widthCaptionMin; + backgroundWidth += captionWidth - widthCaptionMin; + } + captionHeight = captionLayout.textHeight; + addedCaptionHeight = captionHeight + AndroidUtilities.dp(9); + if (captionLayout.hasCodeAtBottom || captionLayout.hasQuoteAtBottom) { + captionHeight += AndroidUtilities.dp(14); + addedCaptionHeight += AndroidUtilities.dp(14); + } + if (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0) { + additionHeight += addedCaptionHeight; + int widthToCheck = Math.max(captionWidth, photoWidth - AndroidUtilities.dp(10)); + if ((reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) && !shouldDrawTimeOnMedia() && widthToCheck + AndroidUtilities.dp(2) - captionLayout.lastLineWidth < timeWidthTotal + getExtraTimeX()) { + additionHeight += AndroidUtilities.dp(14); + addedCaptionHeight += AndroidUtilities.dp(14); + captionNewLine = 1; } } else { - updateCaptionSpoilers(); + captionLayout = null; } } catch (Exception e) { FileLog.e(e); } } + if (highlightCaptionToSetStart >= 0 && captionLayout != null) { + highlight(highlightCaptionToSetStart, highlightCaptionToSetEnd, captionLayout.textLayoutBlocks); + } + highlightCaptionToSetStart = highlightCaptionToSetEnd = -1; if (!reactionsLayoutInBubble.isSmall) { boolean useBackgroundWidth = backgroundWidth - AndroidUtilities.dp(24) > widthForCaption; int maxWidth = Math.max(backgroundWidth - AndroidUtilities.dp(36), widthForCaption); @@ -7402,9 +7630,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setImage(ImageLocation.getForDocument(document), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForObject(currentPhotoObject, photoParentObject), currentPhotoFilter, ImageLocation.getForDocument(currentPhotoObjectThumb, document), currentPhotoFilterThumb, currentPhotoObjectThumbStripped, messageObject.getDocument().size, null, messageObject, 0); } } else if (messageObject.type == MessageObject.TYPE_STORY || messageObject.type == MessageObject.TYPE_STORY_MENTION) { - TLRPC.StoryItem storyItem = messageObject.messageOwner.media.storyItem; + TL_stories.StoryItem storyItem = messageObject.messageOwner.media.storyItem; if (storyItem != null) { - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { photoImage.setImageBitmap(StoriesUtilities.getExpiredStoryDrawable()); } else { StoriesUtilities.setImage(photoImage, storyItem); @@ -7598,6 +7826,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0 && !messageObject.isExpiredStory()) { + int addCaptionLayoutWidth = 0; if (!messageObject.isRestrictedMessage && captionLayout == null && (messageObject.caption != null || messageObject.isVoiceTranscriptionOpen())) { currentCaption = messageObject.isVoiceTranscriptionOpen() ? messageObject.getVoiceTranscription() : messageObject.caption; if (currentCaption != null && !TextUtils.isEmpty(messageObject.messageOwner.voiceTranscription) && currentMessageObject.isVoiceTranscriptionOpen() && !currentMessageObject.messageOwner.voiceTranscriptionFinal) { @@ -7619,47 +7848,41 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawSideButton != 0 && isRoundVideo) { width -= AndroidUtilities.dp(24); } - int widthForCaption = width - AndroidUtilities.dp(31 + (currentMessageObject.type != MessageObject.TYPE_ROUND_VIDEO ? 10 : 0)) - getExtraTextX() * 2; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - captionLayout = StaticLayout.Builder.obtain(currentCaption, 0, currentCaption.length(), Theme.chat_msgTextPaint, widthForCaption) - .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) - .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) - .setAlignment(Layout.Alignment.ALIGN_NORMAL) - .build(); - } else { - captionLayout = new StaticLayout(currentCaption, Theme.chat_msgTextPaint, widthForCaption, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - } + int widthForCaption = captionFullWidth = width - AndroidUtilities.dp(31 + (currentMessageObject.type != MessageObject.TYPE_ROUND_VIDEO ? 14 : 0)) - getExtraTextX() * 2; + captionLayout = new MessageObject.TextLayoutBlocks(currentMessageObject, currentCaption, Theme.chat_msgTextPaint, widthForCaption); updateSeekBarWaveformWidth(null); - updateCaptionSpoilers(); } catch (Exception e) { FileLog.e(e); } } + if (highlightCaptionToSetStart >= 0 && captionLayout != null) { + highlight(highlightCaptionToSetStart, highlightCaptionToSetEnd, captionLayout.textLayoutBlocks); + } + highlightCaptionToSetStart = highlightCaptionToSetEnd = -1; if (captionLayout != null || currentMessageObject.type == MessageObject.TYPE_VOICE || currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { try { if (messageObject.isVoiceTranscriptionOpen() && captionLayout != null) { float startMaxWidth = backgroundWidth - AndroidUtilities.dp(31) - AndroidUtilities.dp(10) - getExtraTextX() * 2, maxWidth = startMaxWidth; - for (int i = 0; i < captionLayout.getLineCount(); ++i) { - float captionLineWidth = captionLayout.getLineWidth(i); - if (captionLineWidth > maxWidth) { - maxWidth = captionLineWidth; - } - } + maxWidth = Math.max(maxWidth, captionLayout.textWidth); backgroundWidth += maxWidth - startMaxWidth; } int width = backgroundWidth - AndroidUtilities.dp(31); Float lastCaptionLineWidth = null; - if (captionLayout != null && captionLayout.getLineCount() > 0) { - lastCaptionLineWidth = captionLayout.getLineWidth(captionLayout.getLineCount() - 1) + captionLayout.getLineLeft(captionLayout.getLineCount() - 1); + if (captionLayout != null) { + lastCaptionLineWidth = (float) captionLayout.lastLineWidth; } else if (currentMessageObject.type == MessageObject.TYPE_VOICE) { lastCaptionLineWidth = (float) AndroidUtilities.dp(64); } if (lastCaptionLineWidth != null) { if (captionLayout != null) { captionWidth = width; - captionHeight = captionLayout.getHeight(); + captionHeight = captionLayout.textHeight; } totalHeight += captionHeight + AndroidUtilities.dp(9); + if (captionLayout != null && (captionLayout.hasCodeAtBottom || captionLayout.hasQuoteAtBottom)) { + captionHeight += AndroidUtilities.dp(10); + totalHeight += AndroidUtilities.dp(10); + } if ((reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) && (currentPosition == null || (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0)) { int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX(); if (width - AndroidUtilities.dp(8) - lastCaptionLineWidth < timeWidthTotal) { @@ -7818,20 +8041,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int buttonWidth = (widthForButtons - AndroidUtilities.dp(5) * (buttonsCount - 1) - AndroidUtilities.dp(2)) / buttonsCount; for (int column = 0; column < buttonRow.buttons.size(); column++) { BotButton botButton = new BotButton(); - TLRPC.TL_keyboardButtonRequestPeer button = new TLRPC.TL_keyboardButtonRequestPeer(); - button.button_id = 0; - button.text = "Request peer"; - button.peer_type = new TLRPC.TL_requestPeerTypeChat(); - ((TLRPC.TL_requestPeerTypeChat) button.peer_type).forum = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights = new TLRPC.TL_chatAdminRights(); -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights.change_info = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights.delete_messages = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights.pin_messages = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights.anonymous = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).user_admin_rights.post_messages = true; -// ((TLRPC.TL_requestPeerTypeChat) button.peer_type).premium = false; -// botButton.button = button; - botButton.button = buttonRow.buttons.get(column); + botButton.button = buttonRow.buttons.get(column); String key = Utilities.bytesToHex(botButton.button.data); String position = buttonRow + "" + column; BotButton oldButton; @@ -8067,6 +8277,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentNameStatusDrawable != null) { currentNameStatusDrawable.play(); } + if (replyLine != null) { + replyLine.resetAnimation(); + } + quoteHighlight = null; } if (transcribeButton != null) { transcribeButton.setOpen(currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.voiceTranscriptionOpen && currentMessageObject.messageOwner.voiceTranscriptionFinal && TranscribeButton.isVideoTranscriptionOpen(currentMessageObject), !messageIdChanged); @@ -8081,12 +8295,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.setIcon(getIconForCurrentState(), false, false); } - if (delegate != null && delegate.getTextSelectionHelper() != null && !messageIdChanged && messageChanged && messageObject != null) { + if (delegate != null && delegate.getTextSelectionHelper() != null && !messageIdChanged && messageChanged && messageObject != null && !messageObject.preview) { delegate.getTextSelectionHelper().checkDataChanged(messageObject); } accessibilityVirtualViewBounds.clear(); transitionParams.updatePhotoImageX = true; + highlightCaptionToSetStart = highlightCaptionToSetEnd = -1; + updateFlagSecure(); } @@ -8094,31 +8310,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_CHAT); } - private void highlightCaptionLink(URLSpan link) { - try { - if (link != null && captionLayout != null && captionLayout.getText() instanceof Spanned) { - if (link == highlightPathSpan) { - return; - } - highlightPathSpan = link; - Spanned caption = (Spanned) captionLayout.getText(); - int start = caption.getSpanStart(highlightPathSpan); - int end = caption.getSpanEnd(highlightPathSpan); - if (highlightPath != null) { - highlightPath.rewind(); - } else { - highlightPath = new LinkPath(true); - } - highlightPath.setCurrentLayout(captionLayout, start, 0); - captionLayout.getSelectionPath(start, end, highlightPath); - highlightPathStart = System.currentTimeMillis(); - invalidate(); - } - } catch (Exception e) { - FileLog.e(e); - } - } - private void calculateUnlockXY() { if (currentMessageObject.type == MessageObject.TYPE_EXTENDED_MEDIA_PREVIEW && unlockLayout != null) { unlockX = backgroundDrawableLeft + (photoImage.getImageWidth() - unlockLayout.getWidth()) / 2f; @@ -8231,6 +8422,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replySelector.setState(new int[]{}); invalidate(); } + if (replyBounce != null) { + replyBounce.setPressed(false); + } if (topicButton != null) { topicButton.resetClick(); } @@ -8275,6 +8469,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate imagePressed = false; timePressed = false; gamePreviewPressed = false; + giveawayMessageCell.setButtonPressed(false); if (pressedVoteButton != -1 || pollHintPressed || psaHintPressed || instantPressed || otherPressed || commentButtonPressed) { instantPressed = commentButtonPressed = false; @@ -8289,6 +8484,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate selectorDrawable[a].setState(StateSet.NOTHING); } } + if (linkPreviewSelector != null) { + linkPreviewSelector.setState(StateSet.NOTHING); + } + } + if (linkPreviewBounce != null) { + linkPreviewBounce.setPressed(false); } invalidate(); } @@ -8371,7 +8572,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean invalidateParentForce() { return ( !links.isEmpty() || - !reactionsLayoutInBubble.isEmpty + !reactionsLayoutInBubble.isEmpty || + currentMessageObject != null && currentMessageObject.preview ); } @@ -8445,6 +8647,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return; } isHighlighted = value; + if (value) { + quoteHighlight = null; + } if (!isHighlighted) { lastHighlightProgressTime = System.currentTimeMillis(); isHighlightedAnimated = true; @@ -8571,14 +8776,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (seekBarWaveform != null) { if (transitionParams.animateUseTranscribeButton) { seekBarWaveform.setSize( - backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()), + backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()) - AndroidUtilities.dp(hasLinkPreview ? 10 : 0), AndroidUtilities.dp(30), fromBackgroundWidth + offset + (!useTranscribeButton ? -AndroidUtilities.dp(34) : 0), toBackgroundWidth + offset + (useTranscribeButton ? -AndroidUtilities.dp(34) : 0) ); } else { seekBarWaveform.setSize( - backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()), + backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()) - AndroidUtilities.dp(hasLinkPreview ? 10 : 0), AndroidUtilities.dp(30), fromBackgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()), toBackgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()) @@ -8586,26 +8791,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (seekBar != null) { - seekBar.setSize(backgroundWidth - (int) (getUseTranscribeButtonProgress() * AndroidUtilities.dp(34)) - AndroidUtilities.dp((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? 65 : 72) + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); + seekBar.setSize(backgroundWidth - (int) (getUseTranscribeButtonProgress() * AndroidUtilities.dp(34)) - AndroidUtilities.dp((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? 65 : 72) + (hasLinkPreview ? 20 : 0)), AndroidUtilities.dp(30)); } } else { if (seekBarWaveform != null) { if (transitionParams.animateUseTranscribeButton) { seekBarWaveform.setSize( - backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()), + backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()) - AndroidUtilities.dp(hasLinkPreview ? 10 : 0), AndroidUtilities.dp(30), - backgroundWidth + offset + (!useTranscribeButton ? -AndroidUtilities.dp(34) : 0), + backgroundWidth + offset + (!useTranscribeButton ? -AndroidUtilities.dp(34) : 0) - AndroidUtilities.dp(hasLinkPreview ? 10 : 0), backgroundWidth + offset + (useTranscribeButton ? -AndroidUtilities.dp(34) : 0) ); } else { seekBarWaveform.setSize( - backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()), + backgroundWidth + offset - (int) (AndroidUtilities.dp(34) * getUseTranscribeButtonProgress()) - AndroidUtilities.dp(hasLinkPreview ? 10 : 0), AndroidUtilities.dp(30) ); } } if (seekBar != null) { - seekBar.setSize(backgroundWidth - (int) (getUseTranscribeButtonProgress() * AndroidUtilities.dp(34)) - AndroidUtilities.dp((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? 65 : 72) + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); + seekBar.setSize(backgroundWidth - (int) (getUseTranscribeButtonProgress() * AndroidUtilities.dp(34)) - AndroidUtilities.dp((documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? 65 : 72) + (hasLinkPreview ? 20 : 0)), AndroidUtilities.dp(30)); } } } @@ -8763,11 +8968,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate totalHeight += AndroidUtilities.dp(14); } } else { - newLineForTime = hasLinkPreview || hasOldCaptionPreview || hasGamePreview || hasInvoicePreview || maxWidth - lastLineWidth < timeMore || currentMessageObject.hasRtl; + newLineForTime = !linkPreviewAbove && (hasLinkPreview || hasOldCaptionPreview || hasGamePreview || hasInvoicePreview) || maxWidth - lastLineWidth < timeMore || currentMessageObject.hasRtl; + } + + int newLineForTimeDp = 14; + if ( + currentMessageObject.hasCodeAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) || + currentMessageObject.hasQuoteAtBottom && (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) + ) { + newLineForTime = true; + newLineForTimeDp = 18; } if (newLineForTime) { - totalHeight += AndroidUtilities.dp(14); + totalHeight += AndroidUtilities.dp(newLineForTimeDp); hasNewLineForTime = true; backgroundWidth = Math.max(maxChildWidth, lastLineWidth) + AndroidUtilities.dp(31); backgroundWidth = Math.max(backgroundWidth, (currentMessageObject.isOutOwner() ? timeWidth + AndroidUtilities.dp(17) : timeWidth) + AndroidUtilities.dp(31)); @@ -8781,102 +8995,275 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - public void setHighlightedText(String text) { + public boolean setHighlightedText(String text) { + return setHighlightedText(text, false); + } + public boolean setHighlightedText(String text, boolean quote) { + if (highlightedQuote && !quote && TextUtils.isEmpty(text)) { + return false; + } MessageObject messageObject = messageObjectToSet != null ? messageObjectToSet : currentMessageObject; - if (messageObject == null || messageObject.messageOwner.message == null || TextUtils.isEmpty(text)) { + highlightedQuote = quote; + if (messageObject == null || TextUtils.isEmpty(text)) { if (!urlPathSelection.isEmpty()) { linkSelectionBlockNum = -1; + highlightedQuote = false; resetUrlPaths(); invalidate(); } - return; + return false; } - text = text.toLowerCase(); - String message = messageObject.messageOwner.message.toLowerCase(); - int start = -1; - int length = -1; + if (!quote) { + quoteHighlight = null; + } + String message; + if (currentCaption != null) { + message = currentCaption.toString(); + } else { + message = messageObject.messageOwner.message; + } + if (message == null || TextUtils.isEmpty(message)) { + if (!urlPathSelection.isEmpty()) { + linkSelectionBlockNum = -1; + highlightedQuote = false; + resetUrlPaths(); + invalidate(); + } + return false; + } + if (!quote) { + text = text.toLowerCase(); + message = message.toLowerCase(); + } + int start = -1, length = -1; String punctuationsChars = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n"; - for (int a = 0, N1 = message.length(); a < N1; a++) { - int currentLen = 0; - for (int b = 0, N2 = Math.min(text.length(), N1 - a); b < N2; b++) { - boolean match = message.charAt(a + b) == text.charAt(b); - if (match) { - if (currentLen != 0 || a == 0 || punctuationsChars.indexOf(message.charAt(a - 1)) >= 0) { - currentLen++; - } else { - match = false; + if (quote) { + start = message.indexOf(text); + length = text.length(); + } else { + for (int a = 0, N1 = message.length(); a < N1; a++) { + int currentLen = 0; + for (int b = 0, N2 = Math.min(text.length(), N1 - a); b < N2; b++) { + boolean match = message.charAt(a + b) == text.charAt(b); + if (match) { + if (currentLen != 0 || a == 0 || punctuationsChars.indexOf(message.charAt(a - 1)) >= 0) { + currentLen++; + } else { + match = false; + } } - } - if (!match || b == N2 - 1) { - if (currentLen > 0 && currentLen > length) { - length = currentLen; - start = a; + if (!match || b == N2 - 1) { + if (currentLen > 0 && currentLen > length) { + length = currentLen; + start = a; + } + break; } - break; } } } if (start == -1) { if (!urlPathSelection.isEmpty()) { linkSelectionBlockNum = -1; + highlightedQuote = false; resetUrlPaths(); invalidate(); } - return; + return false; } - for (int a = start + length, N = message.length(); a < N; a++) { - if (punctuationsChars.indexOf(message.charAt(a)) < 0) { - length++; - } else { - break; - } - } - int end = start + length; - if (captionLayout != null && !TextUtils.isEmpty(messageObject.caption)) { - resetUrlPaths(); - try { - LinkPath path = obtainNewUrlPath(); - path.setCurrentLayout(captionLayout, start, 0); - captionLayout.getSelectionPath(start, end, path); - } catch (Exception e) { - FileLog.e(e); - } - invalidate(); - } else if (messageObject.textLayoutBlocks != null) { - for (int c = 0; c < messageObject.textLayoutBlocks.size(); c++) { - MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(c); - if (start >= block.charactersOffset && start < block.charactersEnd) { - linkSelectionBlockNum = c; - resetUrlPaths(); - try { - LinkPath path = obtainNewUrlPath(); - path.setCurrentLayout(block.textLayout, start, 0); - block.textLayout.getSelectionPath(start, end, path); - if (end >= block.charactersOffset + length) { - for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) { - MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a); - length = nextBlock.charactersEnd - nextBlock.charactersOffset; - path = obtainNewUrlPath(); - path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); - nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); - if (end < block.charactersOffset + length - 1) { - break; - } - } - } - } catch (Exception e) { - FileLog.e(e); - } - invalidate(); + if (!quote) { + for (int a = start + length, N = message.length(); a < N; a++) { + if (punctuationsChars.indexOf(message.charAt(a)) < 0) { + length++; + } else { break; } } } + highlightedQuote = quote; + int end = start + length; + if (quote && currentMessagesGroup == null && groupedMessagesToSet == null) { + if (quoteHighlight == null || quoteHighlight.id != messageObject.getId() || quoteHighlight.start != start || quoteHighlight.end != end) { + if (captionLayout != null) { + quoteHighlight = new QuoteHighlight(this, getParent(), messageObject.getId(), captionLayout.textLayoutBlocks, start, end, captionLayout.textXOffset); + } else { + quoteHighlight = new QuoteHighlight(this, getParent(), messageObject.getId(), messageObject.textLayoutBlocks, start, end, messageObject.textXOffset); + } + } + } else if (!TextUtils.isEmpty(currentCaption)) { + if (captionLayout == null) { + highlightCaptionToSetStart = start; + highlightCaptionToSetEnd = end; + } else { + highlight(start, end, captionLayout.textLayoutBlocks); + } + } else if (messageObject.textLayoutBlocks != null) { + highlight(start, end, messageObject.textLayoutBlocks); + } + return true; + } + + private void highlight(int start, int end, ArrayList textLayoutBlocks) { + if (textLayoutBlocks == null) { + return; + } + int length = end - start; + for (int c = 0; c < textLayoutBlocks.size(); c++) { + MessageObject.TextLayoutBlock block = textLayoutBlocks.get(c); + if (start >= block.charactersOffset && start < block.charactersEnd) { + linkSelectionBlockNum = c; + resetUrlPaths(); + try { + LinkPath path = obtainNewUrlPath(); + path.setCurrentLayout(block.textLayout, start, 0); + block.textLayout.getSelectionPath(start, end, path); + float y = block.height + block.padBottom; + if (end >= block.charactersOffset + length) { + for (int a = c + 1; a < textLayoutBlocks.size(); a++) { + MessageObject.TextLayoutBlock nextBlock = textLayoutBlocks.get(a); + length = nextBlock.charactersEnd - nextBlock.charactersOffset; + path = obtainNewUrlPath(); + y += nextBlock.padTop; + path.setCurrentLayout(nextBlock.textLayout, 0, y); + y += nextBlock.height + nextBlock.padBottom; + nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); + if (end < block.charactersOffset + length - 1) { + break; + } + } + } + if (highlightedQuote) { + isHighlightedAnimated = true; + highlightProgress = 2500; + } + } catch (Exception e) { + FileLog.e(e); + } + invalidate(); + break; + } + } + highlightCaptionToSetStart = -1; + highlightCaptionToSetEnd = -1; + } + + + public boolean setHighlightedSpan(CharacterStyle span) { + MessageObject messageObject = messageObjectToSet != null ? messageObjectToSet : currentMessageObject; + highlightedQuote = false; + if (messageObject == null || messageObject.messageOwner.message == null || span == null) { + if (!urlPathSelection.isEmpty()) { + linkSelectionBlockNum = -1; + highlightedQuote = false; + resetUrlPaths(); + invalidate(); + } + return false; + } + if (captionLayout != null && !TextUtils.isEmpty(messageObject.caption) && messageObject.caption instanceof Spannable) { + Spanned spanned = (Spanned) messageObject.caption; + int start = -1, end = -1; + CharacterStyle[] spans = spanned.getSpans(0, spanned.length(), CharacterStyle.class); + if (spans != null && spans.length > 0) { + for (int i = 0; i < spans.length; ++i) { + if (spans[i] == span) { + start = spanned.getSpanStart(span); + end = spanned.getSpanEnd(span); + break; + } + } + } + if (start >= 0 && end >= 0) { + int length = (end - start); + for (int c = 0; c < captionLayout.textLayoutBlocks.size(); c++) { + MessageObject.TextLayoutBlock block = captionLayout.textLayoutBlocks.get(c); + if (start >= block.charactersOffset && start < block.charactersEnd) { + linkSelectionBlockNum = c; + highlightedQuote = false; + resetUrlPaths(); + try { + LinkPath path = obtainNewUrlPath(); + path.setCurrentLayout(block.textLayout, start, 0); + block.textLayout.getSelectionPath(start, end, path); + if (end >= block.charactersOffset + length) { + for (int a = c + 1; a < captionLayout.textLayoutBlocks.size(); a++) { + MessageObject.TextLayoutBlock nextBlock = captionLayout.textLayoutBlocks.get(a); + length = nextBlock.charactersEnd - nextBlock.charactersOffset; + path = obtainNewUrlPath(); + path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); + nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); + if (end < block.charactersOffset + length - 1) { + break; + } + } + } + } catch (Exception e) { + FileLog.e(e); + } + invalidate(); + return true; + } + } + } + } + if (messageObject.messageText instanceof Spanned && messageObject.textLayoutBlocks != null) { + Spanned spanned = (Spanned) messageObject.messageText; + int start = -1, end = -1; + CharacterStyle[] spans = spanned.getSpans(0, spanned.length(), CharacterStyle.class); + if (spans != null && spans.length > 0) { + for (int i = 0; i < spans.length; ++i) { + if (spans[i] == span) { + start = spanned.getSpanStart(span); + end = spanned.getSpanEnd(span); + break; + } + } + } + if (start >= 0 && end >= 0) { + int length = (end - start); + for (int c = 0; c < messageObject.textLayoutBlocks.size(); c++) { + MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(c); + if (start >= block.charactersOffset && start < block.charactersEnd) { + linkSelectionBlockNum = c; + highlightedQuote = false; + resetUrlPaths(); + try { + LinkPath path = obtainNewUrlPath(); + path.setCurrentLayout(block.textLayout, start, 0); + block.textLayout.getSelectionPath(start, end, path); + if (end >= block.charactersOffset + length) { + for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) { + MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a); + length = nextBlock.charactersEnd - nextBlock.charactersOffset; + path = obtainNewUrlPath(); + path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height); + nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path); + if (end < block.charactersOffset + length - 1) { + break; + } + } + } + } catch (Exception e) { + FileLog.e(e); + } + invalidate(); + return true; + } + } + } + } + if (!urlPathSelection.isEmpty()) { + linkSelectionBlockNum = -1; + highlightedQuote = false; + resetUrlPaths(); + invalidate(); + } + return false; } @Override protected boolean verifyDrawable(Drawable who) { - return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1]; + return super.verifyDrawable(who) || who == selectorDrawable[0] || who == selectorDrawable[1] || who == linkPreviewSelector; } @Override @@ -8950,6 +9337,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int color; if (psaHintPressed) { color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outViews : Theme.key_chat_inViews); + } else if (linkLine != null) { + color = linkLine.getColor(); } else { color = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewInstantText : Theme.key_chat_inPreviewInstantText); } @@ -9085,8 +9474,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate str = LocaleController.getString("ViewStory").toUpperCase(); } else if (drawInstantViewType == 18) { str = LocaleController.getString("BoostLinkButton", R.string.BoostLinkButton); + } else if (drawInstantViewType == 19) { + str = LocaleController.getString("BoostingHowItWork", R.string.BoostingHowItWork); + } else if (drawInstantViewType == 20) { + str = LocaleController.getString(R.string.OpenGift); } else { - str = LocaleController.getString("InstantView", R.string.InstantView); + str = LocaleController.getString(R.string.InstantView); } if (currentMessageObject.isSponsored()) { int buttonWidth = (int) (Theme.chat_instantViewPaint.measureText(str) + AndroidUtilities.dp(10 + 24 + 10 + 31)); @@ -9096,17 +9489,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } int mWidth = backgroundWidth - AndroidUtilities.dp(10 + 24 + 10 + 31); instantViewLayout = new StaticLayout(TextUtils.ellipsize(str, Theme.chat_instantViewPaint, mWidth, TextUtils.TruncateAt.END), Theme.chat_instantViewPaint, mWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - if (drawInstantViewType == 8) { - instantWidth = backgroundWidth - AndroidUtilities.dp(13); - } else { - instantWidth = backgroundWidth - AndroidUtilities.dp(34); - } + instantViewLayoutWidth = instantViewLayout.getLineCount() > 0 ? instantViewLayout.getLineWidth(0) : 0; + instantViewLayoutLeft = instantViewLayout.getLineCount() > 0 ? instantViewLayout.getLineLeft(0) : 0; + instantWidth = backgroundWidth - AndroidUtilities.dp(drawInstantViewType == 8 ? 13 : 34); totalHeight += AndroidUtilities.dp(46); if (currentMessageObject.type == MessageObject.TYPE_CONTACT) { totalHeight += AndroidUtilities.dp(14); } - if (currentMessageObject.isSponsored() && hasNewLineForTime) { - totalHeight += AndroidUtilities.dp(16); + if (currentMessageObject.isSponsored()) { + totalHeight += AndroidUtilities.dp(2); } if (instantViewLayout != null && instantViewLayout.getLineCount() > 0) { instantTextX = (int) (instantWidth - Math.ceil(instantViewLayout.getLineWidth(0))) / 2 + (drawInstantViewType == 0 ? AndroidUtilities.dp(8) : 0); @@ -9278,6 +9669,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.type == MessageObject.TYPE_TEXT) { textY = AndroidUtilities.dp(10) + namesOffset; + if (linkPreviewAbove) { + linkPreviewY = textY + AndroidUtilities.dp(10); + textY += linkPreviewHeight + AndroidUtilities.dp(13); + if (drawInstantView && !hasInvoicePreview && !currentMessageObject.isSponsored() && !currentMessageObject.isGiveaway()) { + textY += AndroidUtilities.dp(44); + } + } else { + linkPreviewY = textY + currentMessageObject.textHeight + AndroidUtilities.dp(!currentMessageObject.isSponsored() ? 10 : 0); + } } if (isRoundVideo) { updatePlayingMessageProgress(); @@ -9288,7 +9688,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(14); timeAudioX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67); } else { - if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { seekBarX = AndroidUtilities.dp(114); buttonX = AndroidUtilities.dp(71); timeAudioX = AndroidUtilities.dp(124); @@ -9334,7 +9734,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate x = layoutWidth - backgroundWidth + AndroidUtilities.dp(6); } } else { - if (isChat && isAvatarVisible && (!isPlayingRound || currentMessageObject.isVoiceTranscriptionOpen())) { + if ((isChat || currentMessageObject != null && currentMessageObject.forceAvatar) && isAvatarVisible && (!isPlayingRound || currentMessageObject.isVoiceTranscriptionOpen())) { x = AndroidUtilities.dp(63); } else { x = AndroidUtilities.dp(15); @@ -9369,7 +9769,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(14); timeAudioX = layoutWidth - backgroundWidth + AndroidUtilities.dp(67); } else { - if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { seekBarX = AndroidUtilities.dp(113); buttonX = AndroidUtilities.dp(71); timeAudioX = AndroidUtilities.dp(124); @@ -9394,7 +9794,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isOutOwner()) { buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(14); } else { - if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { buttonX = AndroidUtilities.dp(71); } else { buttonX = AndroidUtilities.dp(23); @@ -9410,7 +9810,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int x; if (currentMessageObject.isOutOwner()) { x = layoutWidth - backgroundWidth + AndroidUtilities.dp(14); - } else if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + } else if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { x = AndroidUtilities.dp(72); } else { x = AndroidUtilities.dp(23); @@ -9654,7 +10054,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - private void drawContent(Canvas canvas) { + public void drawContent(Canvas canvas, boolean preview) { + if (preview != (currentMessageObject != null && currentMessageObject.preview)) { + return; + } boolean newPart = needNewVisiblePart && currentMessageObject.type == MessageObject.TYPE_TEXT, hasSpoilers = hasSpoilers(); if (newPart || hasSpoilers) { getLocalVisibleRect(scrollRect); @@ -9670,8 +10073,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate float buttonX = this.buttonX; float buttonY = this.buttonY; if (transitionParams.animateButton) { - buttonX = transitionParams.animateFromButtonX * (1f - transitionParams.animateChangeProgress) + this.buttonX * (transitionParams.animateChangeProgress); - buttonY = (transitionParams.animateFromButtonY * (1f - transitionParams.animateChangeProgress) + this.buttonY * (transitionParams.animateChangeProgress)); + buttonX = AndroidUtilities.lerp(transitionParams.animateFromButtonX, this.buttonX, transitionParams.animateChangeProgress); + buttonY = AndroidUtilities.lerp(transitionParams.animateFromButtonY, this.buttonY, transitionParams.animateChangeProgress); radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + AndroidUtilities.dp(44), (int) buttonY + AndroidUtilities.dp(44)); } updateSeekBarWaveformWidth(canvas); @@ -9708,73 +10111,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate imageDrawn = false; radialProgress.setCircleCrossfadeColor(-1, 0.0f, 1.0f); - if (currentMessageObject.type == MessageObject.TYPE_TEXT || currentMessageObject.type == MessageObject.TYPE_STORY_MENTION || currentMessageObject.type == MessageObject.TYPE_EMOJIS) { - if (currentMessageObject.isOutOwner()) { - textX = getCurrentBackgroundLeft() + AndroidUtilities.dp(11) + getExtraTextX(); - } else { - textX = getCurrentBackgroundLeft() + (currentMessageObject.type == MessageObject.TYPE_EMOJIS ? 0 : AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17)) + getExtraTextX(); - } - if (hasGamePreview) { - textX += AndroidUtilities.dp(11); - textY = AndroidUtilities.dp(14) + namesOffset; - if (siteNameLayout != null) { - textY += siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); - } - } else if (hasInvoicePreview) { - textY = AndroidUtilities.dp(14) + namesOffset; - if (siteNameLayout != null) { - textY += siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); - } - } else if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) { - textY = AndroidUtilities.dp(6) + namesOffset; - if (!currentMessageObject.isOut()) { - textX = getCurrentBackgroundLeft(); - } else { - textX -= AndroidUtilities.dp(4); - } - } else { - textY = AndroidUtilities.dp(8) + namesOffset; - } - unmovedTextX = textX; - if (currentMessageObject.textXOffset != 0 && replyNameLayout != null) { - int diff = backgroundWidth - AndroidUtilities.dp(31) - currentMessageObject.textWidth; - if (!hasNewLineForTime) { - diff -= timeWidth + AndroidUtilities.dp(4 + (currentMessageObject.isOutOwner() ? 20 : 0)); - } - if (diff > 0) { - textX += diff - getExtraTimeX(); - } - } + if (currentMessageObject.type == MessageObject.TYPE_TEXT || currentMessageObject.type == MessageObject.TYPE_STORY_MENTION || currentMessageObject.type == MessageObject.TYPE_EMOJIS || currentMessageObject.isGiveaway()) { + layoutTextXY(false); if (!enterTransitionInProgress && currentMessageObject != null && !currentMessageObject.preview) { if (!drawForBlur && animatedEmojiStack != null && ((currentMessageObject.textLayoutBlocks != null && !currentMessageObject.textLayoutBlocks.isEmpty()) || (transitionParams.animateOutTextBlocks != null && !transitionParams.animateOutTextBlocks.isEmpty()))) { animatedEmojiStack.clearPositions(); } - if (transitionParams.animateChangeProgress != 1.0f && transitionParams.animateMessageText) { - canvas.save(); - if (currentBackgroundDrawable != null) { - Rect r = currentBackgroundDrawable.getBounds(); - if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { - canvas.clipRect( - r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), - r.right - AndroidUtilities.dp(10), r.bottom - AndroidUtilities.dp(4) - ); - } else { - canvas.clipRect( - r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), - r.right - AndroidUtilities.dp(4), r.bottom - AndroidUtilities.dp(4) - ); - } - } - drawMessageText(canvas, transitionParams.animateOutTextBlocks, transitionParams.animateOutTextXOffset, false, (1.0f - transitionParams.animateChangeProgress), false); - drawMessageText(canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, true, transitionParams.animateChangeProgress, false); - canvas.restore(); - } else { - drawMessageText(canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, true, 1.0f, false); - } + drawMessageText(canvas); } if (!(enterTransitionInProgress && !currentMessageObject.isVoice())) { drawLinkPreview(canvas, 1f); + getIconForCurrentState(); // sets colors } drawTime = true; } else if (drawPhotoImage) { @@ -9931,7 +10279,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { - if (drawPhotoImage && photoImage.getVisible() && !hasGamePreview && !currentMessageObject.needDrawBluredPreview()) { + if (drawPhotoImage && photoImage.getVisible() && !hasGamePreview && !currentMessageObject.needDrawBluredPreview() && !currentMessageObject.preview && !isSmallImage) { int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); Theme.chat_msgMediaMenuDrawable.setAlpha((int) (oldAlpha * controlsAlpha)); setDrawableBounds(Theme.chat_msgMediaMenuDrawable, otherX = (int) (photoImage.getImageX() + photoImage.getImageWidth() - AndroidUtilities.dp(14)), otherY = (int) (photoImage.getImageY() + AndroidUtilities.dp(8.1f))); @@ -9944,6 +10292,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_audioPerformerPaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioPerformerSelectedText : Theme.key_chat_outAudioPerformerText)); Theme.chat_audioTimePaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); radialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + } else if (linkLine != null && hasLinkPreview) { + Theme.chat_audioTitlePaint.setColor(linkLine.getColor()); + Theme.chat_audioPerformerPaint.setColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioPerformerSelectedText : Theme.key_chat_inAudioPerformerText), linkLine.getColor())); + Theme.chat_audioTimePaint.setColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText), linkLine.getColor())); + radialProgress.setProgressColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress), linkLine.getColor())); + + seekBar.setColors(Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioCacheSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarSelected), linkLine.getColor())); } else { Theme.chat_audioTitlePaint.setColor(getThemedColor(Theme.key_chat_inAudioTitleText)); Theme.chat_audioPerformerPaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioPerformerSelectedText : Theme.key_chat_inAudioPerformerText)); @@ -9955,7 +10310,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.draw(canvas); canvas.save(); - canvas.translate(timeAudioX + songX, AndroidUtilities.dp(13) + namesOffset + mediaOffsetY); + canvas.translate(timeAudioX + songX, AndroidUtilities.dp(13) + namesOffset + getMediaOffsetY()); songLayout.draw(canvas); canvas.restore(); @@ -9985,7 +10340,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (toSeekBarProgress < 1f) { float x = timeAudioX + performerX; - float y = AndroidUtilities.dp(35) + namesOffset + mediaOffsetY; + float y = AndroidUtilities.dp(35) + namesOffset + getMediaOffsetY(); if (toSeekBarProgress != 0) { canvas.saveLayerAlpha(x, y, x + performerLayout.getWidth(), y + performerLayout.getHeight(), (int) (255 * (1f - toSeekBarProgress)), Canvas.ALL_SAVE_FLAG); } else { @@ -10001,7 +10356,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } canvas.save(); - canvas.translate(timeAudioX, AndroidUtilities.dp(57) + namesOffset + mediaOffsetY); + canvas.translate(timeAudioX, AndroidUtilities.dp(57) + namesOffset + getMediaOffsetY()); durationLayout.draw(canvas); canvas.restore(); @@ -10012,7 +10367,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } - setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == MessageObject.TYPE_TEXT ? 58 : 48), otherY = (int) buttonY - AndroidUtilities.dp(2)); + setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == MessageObject.TYPE_TEXT ? 58 : 48) - AndroidUtilities.dp(hasLinkPreview ? 18 : 0), otherY = (int) buttonY - AndroidUtilities.dp(2)); if (transitionParams.animateChangeProgress != 1f && transitionParams.animateShouldDrawMenuDrawable) { menuDrawable.setAlpha((int) (255 * transitionParams.animateChangeProgress)); } @@ -10025,6 +10380,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isOutOwner()) { Theme.chat_audioTimePaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outAudioDurationSelectedText : Theme.key_chat_outAudioDurationText)); radialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_outAudioSelectedProgress : Theme.key_chat_outAudioProgress)); + } else if (hasLinkPreview && linkLine != null) { + Theme.chat_audioTimePaint.setColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText), linkLine.getColor())); + radialProgress.setProgressColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress), linkLine.getColor())); + + seekBar.setColors(Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioCacheSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarSelected), linkLine.getColor())); } else { Theme.chat_audioTimePaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inAudioDurationSelectedText : Theme.key_chat_inAudioDurationText)); radialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() || buttonPressed != 0 ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); @@ -10038,7 +10398,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (audioVisualizerDrawable != null && !(documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND && hasLinkPreview)) { audioVisualizerDrawable.setParentView(this); - audioVisualizerDrawable.draw(canvas, buttonX + AndroidUtilities.dp(22), buttonY + AndroidUtilities.dp(22), currentMessageObject.isOutOwner(), documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND ? getVideoTranscriptionProgress() : 1, resourcesProvider); + if (linkLine != null) { + audioVisualizerDrawable.draw(canvas, buttonX + AndroidUtilities.dp(22), buttonY + AndroidUtilities.dp(22), linkLine.getColor(), documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND ? getVideoTranscriptionProgress() : 1, resourcesProvider); + } else { + audioVisualizerDrawable.draw(canvas, buttonX + AndroidUtilities.dp(22), buttonY + AndroidUtilities.dp(22), currentMessageObject.isOutOwner(), documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND ? getVideoTranscriptionProgress() : 1, resourcesProvider); + } } if (!enterTransitionInProgress && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { @@ -10148,7 +10512,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!reactionsLayoutInBubble.isEmpty) { y -= reactionsLayoutInBubble.getCurrentTotalHeight(transitionParams.animateChangeProgress); } - y = AndroidUtilities.lerp(y, AndroidUtilities.dp(44) + namesOffset + mediaOffsetY - AndroidUtilities.dp(1.7f), getVideoTranscriptionProgress()); + y = AndroidUtilities.lerp(y, AndroidUtilities.dp(44) + namesOffset + getMediaOffsetY() - AndroidUtilities.dp(1.7f), getVideoTranscriptionProgress()); y += AndroidUtilities.dp(1.7f); transcribeY = AndroidUtilities.lerp( seekBarY + AndroidUtilities.dp(3), @@ -10179,13 +10543,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { canvas.save(); - canvas.translate(timeAudioX, AndroidUtilities.dp(44) + namesOffset + mediaOffsetY + yoffset); + canvas.translate(timeAudioX, AndroidUtilities.dp(44) + namesOffset + getMediaOffsetY() + yoffset); durationLayout.draw(canvas); canvas.restore(); if (currentMessageObject.type != MessageObject.TYPE_TEXT && currentMessageObject.isContentUnread()) { Theme.chat_docBackPaint.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outVoiceSeekbarFill : Theme.key_chat_inVoiceSeekbarFill)); - canvas.drawCircle(timeAudioX + timeWidthAudio + AndroidUtilities.dp(6), AndroidUtilities.dp(51) + namesOffset + mediaOffsetY, AndroidUtilities.dp(3), Theme.chat_docBackPaint); + canvas.drawCircle(timeAudioX + timeWidthAudio + AndroidUtilities.dp(6), AndroidUtilities.dp(51) + namesOffset + getMediaOffsetY(), AndroidUtilities.dp(3), Theme.chat_docBackPaint); } } @@ -10213,7 +10577,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate updateCaptionLayout(); } updateReactionLayoutPosition(); - if (shouldDrawCaptionLayout()) { + if (shouldDrawCaptionLayout() && !currentMessageObject.preview) { drawCaptionLayout(canvas, false, 1f); } @@ -10229,23 +10593,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { linkX = backgroundDrawableLeft + AndroidUtilities.dp(currentMessageObject.isOutOwner() ? 11 : 17); } - float startY = totalHeight - AndroidUtilities.dp(drawPinnedTop ? 9 : 10) - linkPreviewHeight - AndroidUtilities.dp(8); + float startY = totalHeight - AndroidUtilities.dp(drawPinnedTop ? 9 : 10) - linkPreviewHeight - AndroidUtilities.dp(8 + 3); float linkPreviewY = startY; Theme.chat_replyLinePaint.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewLine : Theme.key_chat_inPreviewLine)); - AndroidUtilities.rectTmp.set(linkX, linkPreviewY - AndroidUtilities.dp(3), linkX + AndroidUtilities.dp(3), linkPreviewY + linkPreviewHeight); + AndroidUtilities.rectTmp.set(linkX, linkPreviewY - AndroidUtilities.dp(3), linkX + AndroidUtilities.dp(6), linkPreviewY + linkPreviewHeight); if (replyRoundRectPath == null) { replyRoundRectPath = new Path(); } else { replyRoundRectPath.rewind(); } - if (replyRoundRectRadii == null) { - replyRoundRectRadii = new float[8]; - replyRoundRectRadii[0] = replyRoundRectRadii[1] = replyRoundRectRadii[6] = replyRoundRectRadii[7] = AndroidUtilities.dp(2); // left - replyRoundRectRadii[2] = replyRoundRectRadii[3] = replyRoundRectRadii[4] = replyRoundRectRadii[5] = AndroidUtilities.dp(1); // right - } - replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyRoundRectRadii, Path.Direction.CW); + canvas.save(); + canvas.clipRect(AndroidUtilities.rectTmp.left, AndroidUtilities.rectTmp.top, AndroidUtilities.rectTmp.left + AndroidUtilities.dp(3), AndroidUtilities.rectTmp.bottom); + replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Path.Direction.CW); canvas.drawPath(replyRoundRectPath, Theme.chat_replyLinePaint); + canvas.restore(); if (siteNameLayout != null) { Theme.chat_replyNamePaint.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outSiteNameText : Theme.key_chat_inSiteNameText)); @@ -10270,8 +10632,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate descriptionY = (int) linkPreviewY - AndroidUtilities.dp(3); canvas.save(); canvas.translate(linkX + AndroidUtilities.dp(10) + descriptionX, descriptionY); - descriptionLayout.draw(canvas); - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, descriptionLayout, animatedEmojiDescriptionStack, 0, null, 0, 0, 0, 1f, Theme.chat_animatedEmojiTextColorFilter); + SpoilerEffect.layoutDrawMaybe(descriptionLayout, canvas); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, descriptionLayout, animatedEmojiDescriptionStack, 0, null, 0, 0, 0, 1f, currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); canvas.restore(); } drawTime = true; @@ -10284,6 +10646,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_infoPaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outFileInfoSelectedText : Theme.key_chat_outFileInfoText)); Theme.chat_docBackPaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outFileBackgroundSelected : Theme.key_chat_outFileBackground)); menuDrawable = getThemedDrawable(isDrawSelectionBackground() ? Theme.key_drawable_msgOutMenuSelected : Theme.key_drawable_msgOutMenu); + } else if (linkLine != null && hasLinkPreview) { + Theme.chat_docNamePaint.setColor(Theme.adaptHue(getThemedColor(Theme.key_chat_inFileNameText), linkLine.getColor())); + Theme.chat_infoPaint.setColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inFileInfoSelectedText : Theme.key_chat_inFileInfoText), linkLine.getColor())); + Theme.chat_docBackPaint.setColor(Theme.adaptHue(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inFileBackgroundSelected : Theme.key_chat_inFileBackground), linkLine.getColor())); + menuDrawable = isDrawSelectionBackground() ? Theme.chat_msgInMenuSelectedDrawable : Theme.chat_msgInMenuDrawable; } else { Theme.chat_docNamePaint.setColor(getThemedColor(Theme.key_chat_inFileNameText)); Theme.chat_infoPaint.setColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inFileInfoSelectedText : Theme.key_chat_inFileInfoText)); @@ -10296,9 +10663,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int subtitleY; if (drawPhotoImage) { if (currentMessageObject.type == MessageObject.TYPE_TEXT) { - setDrawableBounds(menuDrawable, otherX = (int) (photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(56)), otherY = (int) (photoImage.getImageY() + AndroidUtilities.dp(4))); + setDrawableBounds(menuDrawable, otherX = (int) (photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(56 + (hasLinkPreview ? 12 : 0))), otherY = (int) (photoImage.getImageY() + AndroidUtilities.dp(4))); } else { - setDrawableBounds(menuDrawable, otherX = (int) (photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(40)), otherY = (int) (photoImage.getImageY() + AndroidUtilities.dp(4))); + setDrawableBounds(menuDrawable, otherX = (int) (photoImage.getImageX() + backgroundWidth - AndroidUtilities.dp(40 + (hasLinkPreview ? 12 : 0))), otherY = (int) (photoImage.getImageY() + AndroidUtilities.dp(4))); } x = (int) (photoImage.getImageX() + photoImage.getImageWidth() + AndroidUtilities.dp(10)); @@ -10310,6 +10677,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); videoRadialProgress.setColorKeys(Theme.key_chat_outLoader, Theme.key_chat_outLoaderSelected, Theme.key_chat_outMediaIcon, Theme.key_chat_outMediaIconSelected); videoRadialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outFileProgressSelected : Theme.key_chat_outFileProgress)); + } else if (linkLine != null && hasLinkPreview) { + radialProgress.setColors(linkLine.getColor(), linkLine.getColor(), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f)), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .05f))); + radialProgress.setProgressColor(Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f))); + videoRadialProgress.setColors(linkLine.getColor(), linkLine.getColor(), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f)), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .05f))); + videoRadialProgress.setProgressColor(Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f))); } else { radialProgress.setColorKeys(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); radialProgress.setProgressColor(getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inFileProgressSelected : Theme.key_chat_inFileProgress)); @@ -10339,7 +10711,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } } else { - setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == MessageObject.TYPE_TEXT ? 58 : 48), otherY = (int) buttonY - AndroidUtilities.dp(2)); + setDrawableBounds(menuDrawable, otherX = (int) buttonX + backgroundWidth - AndroidUtilities.dp(currentMessageObject.type == MessageObject.TYPE_TEXT ? 58 : 48) - AndroidUtilities.dp(hasLinkPreview ? 18 + 6 : 0), otherY = (int) buttonY - AndroidUtilities.dp(2)); x = buttonX + AndroidUtilities.dp(53); titleY = (int) buttonY + AndroidUtilities.dp(4); subtitleY = (int) buttonY + AndroidUtilities.dp(27); @@ -10380,7 +10752,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); canvas.translate(x, subtitleY); if (buttonState == 1 && loadingProgressLayout != null) { -// loadingProgressLayout.copyStylesFrom(Theme.chat_infoPaint); loadingProgressLayout.draw(canvas); } else { infoLayout.draw(canvas); @@ -10563,7 +10934,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!currentMessageObject.isSponsored() && !hasLinkPreview && !hasGamePreview && !hasInvoicePreview) { return; } + int restoreCount = canvas.getSaveCount(); + + final int backgroundWidth = (int) (this.backgroundWidth + (transitionParams != null ? - transitionParams.deltaLeft + transitionParams.deltaRight : 0)); + final float right = getBackgroundDrawableRight() + (transitionParams != null ? transitionParams.deltaRight : 0) - AndroidUtilities.dp(10 + (currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) - getExtraTextX(); + int startY; + int linkPreviewYDiff = 0; int linkX; if (hasGamePreview) { startY = AndroidUtilities.dp(14) + namesOffset; @@ -10572,175 +10949,250 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate startY = AndroidUtilities.dp(14) + namesOffset; linkX = unmovedTextX + AndroidUtilities.dp(1); } else if (currentMessageObject.isSponsored()) { - startY = textY + currentMessageObject.textHeight - AndroidUtilities.dp(2); + startY = this.linkPreviewY - AndroidUtilities.dp(2); if (hasNewLineForTime) { - startY += AndroidUtilities.dp(16); + startY += AndroidUtilities.dp(12); } linkX = unmovedTextX + AndroidUtilities.dp(1); } else { - startY = textY + currentMessageObject.textHeight + AndroidUtilities.dp(8); - linkX = unmovedTextX + AndroidUtilities.dp(1); + if (currentMessageObject.isOutOwner()) { + linkX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); + if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) { + linkX -= Math.max(0, linkX + Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(14) - AndroidUtilities.displaySize.x); + } + } else { + if (mediaBackground) { + linkX = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); + } else { + linkX = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); + } + } + linkX += transitionParams.deltaLeft; + linkX -= AndroidUtilities.dp(1.33f); + + startY = this.linkPreviewY; + if (transitionParams.animateLinkPreviewY) { + final int animatedStartY = AndroidUtilities.lerp(transitionParams.animateFromLinkPreviewY, startY, transitionParams.animateChangeProgress); + linkPreviewYDiff = animatedStartY - startY; + startY = animatedStartY; + } } + + final int width = (int) (right - linkX); int linkPreviewY = startY; int smallImageStartY = 0; - if (!hasInvoicePreview && !currentMessageObject.isSponsored()) { - Theme.chat_replyLinePaint.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outPreviewLine : Theme.key_chat_inPreviewLine)); - if (alpha != 1f) { - Theme.chat_replyLinePaint.setAlpha((int) (alpha * Theme.chat_replyLinePaint.getAlpha())); + int linkPreviewHeight = this.linkPreviewHeight; + if (transitionParams != null && transitionParams.animateLinkPreviewHeight) { + linkPreviewHeight = AndroidUtilities.lerp(transitionParams.animateFromLinkPreviewHeight, linkPreviewHeight, transitionParams.animateChangeProgress); + } + + if (linkLine == null) { + linkLine = new ReplyMessageLine(this); + } + Theme.chat_replyNamePaint.setColor(linkLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, false)); + + boolean restore = false; + boolean drawInstantButtonInside = false; + boolean loading = delegate != null && delegate.isProgressLoading(this, ChatActivity.PROGRESS_INSTANT); + if (!hasInvoicePreview && !currentMessageObject.isSponsored() && !currentMessageObject.isGiveaway()) { + drawInstantButtonInside = true; + + if (linkPreviewBounce == null) { + linkPreviewBounce = new ButtonBounce(this, 2.0f, 2.0f); } - AndroidUtilities.rectTmp.set(linkX, linkPreviewY - AndroidUtilities.dp(3), linkX + AndroidUtilities.dp(3), linkPreviewY + linkPreviewHeight + AndroidUtilities.dp(3)); - if (replyRoundRectPath == null) { - replyRoundRectPath = new Path(); - } else { - replyRoundRectPath.rewind(); + canvas.save(); + final float s = linkPreviewBounce.getScale(0.01f); + canvas.scale(s, s, linkX + width / 2f, linkPreviewY + (linkPreviewHeight + (drawInstantButtonInside && drawInstantView ? AndroidUtilities.dp(42) : 0)) / 2f); + restore = true; + + AndroidUtilities.rectTmp.set(linkX, linkPreviewY - AndroidUtilities.dp(6), linkX + width, linkPreviewY + linkPreviewHeight + (drawInstantButtonInside && drawInstantView ? AndroidUtilities.dp(42) : 0)); + linkLine.setLoading(loading); + float rad = (float) Math.floor(SharedConfig.bubbleRadius / 3); + linkLine.drawBackground(canvas, AndroidUtilities.rectTmp, rad, rad, rad, alpha); + + int rippleColor = linkLine.getBackgroundColor(); + if (linkPreviewSelector == null) { + linkPreviewSelector = Theme.createRadSelectorDrawable(linkPreviewSelectorColor = rippleColor, 0, 0); + Theme.setMaskDrawableRad(linkPreviewSelector, 3, 6, 6, 3); + linkPreviewSelector.setCallback(this); + } else if (linkPreviewSelectorColor != rippleColor) { + Theme.setSelectorDrawableColor(linkPreviewSelector, linkPreviewSelectorColor = rippleColor, true); } - if (replyRoundRectRadii == null) { - replyRoundRectRadii = new float[8]; - replyRoundRectRadii[0] = replyRoundRectRadii[1] = replyRoundRectRadii[6] = replyRoundRectRadii[7] = AndroidUtilities.dp(2); // left - replyRoundRectRadii[2] = replyRoundRectRadii[3] = replyRoundRectRadii[4] = replyRoundRectRadii[5] = AndroidUtilities.dp(1); // right - } - replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyRoundRectRadii, Path.Direction.CW); - canvas.drawPath(replyRoundRectPath, Theme.chat_replyLinePaint); + linkPreviewSelector.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + linkPreviewSelector.draw(canvas); + + linkLine.drawLine(canvas, AndroidUtilities.rectTmp, alpha); + linkLine.drawLoadingBackground(canvas, AndroidUtilities.rectTmp, rad, rad, rad, alpha); } if (siteNameLayout != null) { smallImageStartY = linkPreviewY - AndroidUtilities.dp(1); - Theme.chat_replyNamePaint.setColor(getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outSiteNameText : Theme.key_chat_inSiteNameText)); + int wasAlpha = Theme.chat_replyNamePaint.getAlpha(); if (alpha != 1f) { - Theme.chat_replyNamePaint.setAlpha((int) (alpha * Theme.chat_replyLinePaint.getAlpha())); + Theme.chat_replyNamePaint.setAlpha((int) (alpha * wasAlpha)); } canvas.save(); - float x = -siteNameLeft + (hasInvoicePreview ? 0 : AndroidUtilities.dp(10)); - canvas.translate(linkX + x, linkPreviewY - AndroidUtilities.dp(3)); + float x = (Math.abs(siteNameLeft) > 1 ? width - AndroidUtilities.dp(hasInvoicePreview ? 0 : 20) - siteNameWidth - siteNameLeft : 0) + (hasInvoicePreview ? 0 : AndroidUtilities.dp(10)); + canvas.translate(linkX + x, linkPreviewY - AndroidUtilities.dp(1)); siteNameLayout.draw(canvas); canvas.restore(); linkPreviewY += siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); + Theme.chat_replyNamePaint.setAlpha(wasAlpha); } if ((hasGamePreview || hasInvoicePreview) && currentMessageObject.textHeight != 0) { startY += currentMessageObject.textHeight + AndroidUtilities.dp(4); linkPreviewY += currentMessageObject.textHeight + AndroidUtilities.dp(4); } - if (drawPhotoImage && drawInstantView && drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18 || drawInstantViewType == 6 && imageBackgroundColor != 0) { - if (linkPreviewY != startY) { - linkPreviewY += AndroidUtilities.dp(2); - } - float tx = 0; - if (!isSmallImage && drawInstantViewType == 17) { - AndroidUtilities.rectTmp2.set(linkX + AndroidUtilities.dp(10), linkPreviewY, linkX + instantWidth, linkPreviewY + (int) photoImage.getImageHeight()); - AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); - if (gradientDrawable == null) { - if (currentPhotoObject != null && currentPhotoObject.gradientTopColor != 0 && currentPhotoObject.gradientBottomColor != 0) { - gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {currentPhotoObject.gradientTopColor, currentPhotoObject.gradientBottomColor}); - } else if (photoImage.getBitmap() != null) { - int[] colors = DominantColors.getColorsSync(false, photoImage.getBitmap(), Theme.isCurrentThemeDark()); - gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors); - if (currentPhotoObject != null) { - currentPhotoObject.gradientTopColor = colors[0]; - currentPhotoObject.gradientBottomColor = colors[1]; - } - } + if (drawPhotoImage && drawInstantView && (drawInstantViewType != 9 && drawInstantViewType != 2 && drawInstantViewType != 13 && drawInstantViewType != 11 && drawInstantViewType != 1 && drawInstantViewType != 18) || drawInstantViewType == 6 && imageBackgroundColor != 0) { + if (isSmallImage) { + if (transitionParams != null && transitionParams.animateSmallImage) { + float diff = (linkPreviewY != startY ? AndroidUtilities.dp(2) : 0) + transitionParams.photoImageFromHeight + AndroidUtilities.dp(6); + linkPreviewY += diff * (1f - transitionParams.animateChangeProgress); } - if (gradientDrawable != null) { - canvas.save(); - if (drillHolePath != null) { - drillHolePath.rewind(); - } else { - drillHolePath = new Path(); - } - drillHolePath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Path.Direction.CW); - canvas.clipPath(drillHolePath); - gradientDrawable.setBounds(AndroidUtilities.rectTmp2); - gradientDrawable.draw(canvas); - canvas.restore(); - } - tx = (instantWidth - photoImage.getImageWidth() - AndroidUtilities.dp(10)) / 2f; - } - if (imageBackgroundSideColor != 0) { - int x = linkX + AndroidUtilities.dp(10); - photoImage.setImageCoords(tx + x + (imageBackgroundSideWidth - photoImage.getImageWidth()) / 2, linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); - rect.set(x, photoImage.getImageY(), x + imageBackgroundSideWidth, photoImage.getImageY2()); - Theme.chat_instantViewPaint.setColor(ColorUtils.setAlphaComponent(imageBackgroundSideColor, (int) (255 * alpha))); - canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); } else { - photoImage.setImageCoords(tx + linkX + AndroidUtilities.dp(10), linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); - } - if (imageBackgroundColor != 0) { - rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); - if (imageBackgroundGradientColor1 != 0) { - if (imageBackgroundGradientColor2 != 0) { - if (motionBackgroundDrawable == null) { - motionBackgroundDrawable = new MotionBackgroundDrawable(imageBackgroundColor, imageBackgroundGradientColor1, imageBackgroundGradientColor2, imageBackgroundGradientColor3, true); - if (imageBackgroundIntensity < 0) { - photoImage.setGradientBitmap(motionBackgroundDrawable.getBitmap()); + float yProgress = 1f; + if (transitionParams != null && transitionParams.animateSmallImage) { + yProgress = transitionParams.animateChangeProgress; + } + if (linkPreviewY != startY) { + linkPreviewY += yProgress * AndroidUtilities.dp(2); + } + int photoWidth = width - AndroidUtilities.dp(17); + float tx = 0; + if (!isSmallImage && drawInstantViewType == 17) { + AndroidUtilities.rectTmp2.set(linkX + AndroidUtilities.dp(10), linkPreviewY, linkX + AndroidUtilities.dp(10) + photoWidth, linkPreviewY + (int) photoImage.getImageHeight()); + AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); + if (gradientDrawable == null) { + if (currentPhotoObject != null && currentPhotoObject.gradientTopColor != 0 && currentPhotoObject.gradientBottomColor != 0) { + gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[]{currentPhotoObject.gradientTopColor, currentPhotoObject.gradientBottomColor}); + } else if (photoImage.getBitmap() != null) { + int[] colors = DominantColors.getColorsSync(false, photoImage.getBitmap(), Theme.isCurrentThemeDark()); + gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors); + if (currentPhotoObject != null) { + currentPhotoObject.gradientTopColor = colors[0]; + currentPhotoObject.gradientBottomColor = colors[1]; } - if (!photoImage.hasImageSet()) { - motionBackgroundDrawable.setRoundRadius(AndroidUtilities.dp(4)); + } + } + if (gradientDrawable != null) { + canvas.save(); + if (drillHolePath != null) { + drillHolePath.rewind(); + } else { + drillHolePath = new Path(); + } + drillHolePath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Path.Direction.CW); + canvas.clipPath(drillHolePath); + gradientDrawable.setBounds(AndroidUtilities.rectTmp2); + gradientDrawable.draw(canvas); + canvas.restore(); + } + tx = (instantWidth - photoImage.getImageWidth() - AndroidUtilities.dp(10) - (transitionParams == null ? 0 : (currentMessageObject.isOutOwner() ? transitionParams.deltaLeft : -transitionParams.deltaRight))) / 2f; + } + if (imageBackgroundSideColor != 0) { + int x = linkX + AndroidUtilities.dp(10); + photoImage.setImageX(tx + x + (imageBackgroundSideWidth - photoImage.getImageWidth()) / 2); + photoImage.setImageY(linkPreviewY); + rect.set(x, photoImage.getImageY(), x + imageBackgroundSideWidth, photoImage.getImageY2()); + Theme.chat_instantViewPaint.setColor(ColorUtils.setAlphaComponent(imageBackgroundSideColor, (int) (255 * alpha))); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); + } else { + photoImage.setImageX(tx + linkX + AndroidUtilities.dp(10)); + photoImage.setImageY(linkPreviewY); + } + if (drawInstantViewType != 17) { + if (transitionParams != null && transitionParams.animateSmallImage) { + if (!isSmallImage && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { + photoImage.setImageWidth((int) AndroidUtilities.lerp(transitionParams.photoImageFromWidth, photoWidth, transitionParams.animateChangeProgress)); + } + photoImage.setImageX(AndroidUtilities.lerp(transitionParams.photoImageFromCenterX, photoImage.getCenterX(), transitionParams.animateChangeProgress) - photoImage.getImageWidth() / 2f); + photoImage.setImageY(AndroidUtilities.lerp(transitionParams.photoImageFromCenterY, photoImage.getCenterY(), transitionParams.animateChangeProgress) - photoImage.getImageHeight() / 2f); + } else if (!isSmallImage && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { + photoImage.setImageWidth(photoWidth); + } + } + if (imageBackgroundColor != 0) { + rect.set(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2()); + if (imageBackgroundGradientColor1 != 0) { + if (imageBackgroundGradientColor2 != 0) { + if (motionBackgroundDrawable == null) { + motionBackgroundDrawable = new MotionBackgroundDrawable(imageBackgroundColor, imageBackgroundGradientColor1, imageBackgroundGradientColor2, imageBackgroundGradientColor3, true); + if (imageBackgroundIntensity < 0) { + photoImage.setGradientBitmap(motionBackgroundDrawable.getBitmap()); + } + if (!photoImage.hasImageSet()) { + motionBackgroundDrawable.setRoundRadius(AndroidUtilities.dp(4)); + } + } + } else { + if (gradientShader == null) { + Rect r = BackgroundGradientDrawable.getGradientPoints(AndroidUtilities.getWallpaperRotation(imageBackgroundGradientRotation, false), (int) rect.width(), (int) rect.height()); + gradientShader = new LinearGradient(r.left, r.top, r.right, r.bottom, new int[]{imageBackgroundColor, imageBackgroundGradientColor1}, null, Shader.TileMode.CLAMP); + } + Theme.chat_instantViewPaint.setShader(gradientShader); + if (alpha != 1f) { + Theme.chat_instantViewPaint.setAlpha((int) (255 * alpha)); } } } else { - if (gradientShader == null) { - Rect r = BackgroundGradientDrawable.getGradientPoints(AndroidUtilities.getWallpaperRotation(imageBackgroundGradientRotation, false), (int) rect.width(), (int) rect.height()); - gradientShader = new LinearGradient(r.left, r.top, r.right, r.bottom, new int[]{imageBackgroundColor, imageBackgroundGradientColor1}, null, Shader.TileMode.CLAMP); - } - Theme.chat_instantViewPaint.setShader(gradientShader); + Theme.chat_instantViewPaint.setShader(null); + Theme.chat_instantViewPaint.setColor(imageBackgroundColor); if (alpha != 1f) { Theme.chat_instantViewPaint.setAlpha((int) (255 * alpha)); } } - } else { - Theme.chat_instantViewPaint.setShader(null); - Theme.chat_instantViewPaint.setColor(imageBackgroundColor); - if (alpha != 1f) { - Theme.chat_instantViewPaint.setAlpha((int) (255 * alpha)); - } - } - if (motionBackgroundDrawable != null) { - motionBackgroundDrawable.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); - motionBackgroundDrawable.draw(canvas); - } else if (imageBackgroundSideColor != 0) { - canvas.drawRect(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2(), Theme.chat_instantViewPaint); - } else { - canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); - } - Theme.chat_instantViewPaint.setShader(null); - Theme.chat_instantViewPaint.setAlpha(255); - } - if (drawPhotoImage && drawInstantView && drawInstantViewType != 9) { - if (drawImageButton) { - int size = AndroidUtilities.dp(48); - buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); - buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); - } - if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this)) { - if (alpha != 1f) { - photoImage.setAlpha(alpha); - if (allowDrawPhotoImage()) { - imageDrawn = photoImage.draw(canvas); - } else { - imageDrawn = true; - } - if (currentMessageObject.hasMediaSpoilers()) { - blurredPhotoImage.setAlpha(alpha); - drawBlurredPhoto(canvas); - blurredPhotoImage.setAlpha(1f); - } - photoImage.setAlpha(1f); + if (motionBackgroundDrawable != null) { + motionBackgroundDrawable.setBounds((int) rect.left, (int) rect.top, (int) rect.right, (int) rect.bottom); + motionBackgroundDrawable.draw(canvas); + } else if (imageBackgroundSideColor != 0) { + canvas.drawRect(photoImage.getImageX(), photoImage.getImageY(), photoImage.getImageX2(), photoImage.getImageY2(), Theme.chat_instantViewPaint); } else { - if (allowDrawPhotoImage()) { - imageDrawn = photoImage.draw(canvas); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_instantViewPaint); + } + Theme.chat_instantViewPaint.setShader(null); + Theme.chat_instantViewPaint.setAlpha(255); + } + if (drawPhotoImage && drawInstantView && drawInstantViewType != 9) { + if (drawImageButton) { + int size = AndroidUtilities.dp(48); + buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); + buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); + radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); + } + if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this)) { + if (alpha != 1f) { + photoImage.setAlpha(alpha); + if (allowDrawPhotoImage()) { + imageDrawn = photoImage.draw(canvas); + } else { + imageDrawn = true; + } + if (currentMessageObject.hasMediaSpoilers()) { + blurredPhotoImage.setAlpha(alpha); + drawBlurredPhoto(canvas); + blurredPhotoImage.setAlpha(1f); + } + photoImage.setAlpha(1f); } else { - imageDrawn = true; - } - if (currentMessageObject.hasMediaSpoilers()) { - drawBlurredPhoto(canvas); + if (allowDrawPhotoImage()) { + imageDrawn = photoImage.draw(canvas); + } else { + imageDrawn = true; + } + if (currentMessageObject.hasMediaSpoilers()) { + drawBlurredPhoto(canvas); + } } } } + if (transitionParams != null && transitionParams.animateChange) { + linkPreviewY += yProgress * (transitionParams.animateToImageH + AndroidUtilities.dp(6)); + } else { + linkPreviewY += yProgress * (photoImage.getImageHeight() + AndroidUtilities.dp(6)); + } } - linkPreviewY += photoImage.getImageHeight() + AndroidUtilities.dp(6); } if (currentMessageObject.isOutOwner()) { @@ -10751,15 +11203,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_replyTextPaint.setColor(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_chat_messageTextIn), (int) (255 * alpha))); } if (titleLayout != null) { + float oy = 0; if (linkPreviewY != startY) { - linkPreviewY += AndroidUtilities.dp(2); + linkPreviewY += AndroidUtilities.dp(4); + oy = AndroidUtilities.dp(1); } if (smallImageStartY == 0) { smallImageStartY = linkPreviewY - AndroidUtilities.dp(1); } canvas.save(); - canvas.translate(linkX + AndroidUtilities.dp(10) + titleX, linkPreviewY - AndroidUtilities.dp(3)); + canvas.translate(linkX + AndroidUtilities.dp(10) + (Math.abs(titleLayoutLeft) > 1 ? width - AndroidUtilities.dp(20) - titleLayoutWidth - titleLayoutLeft : 0), linkPreviewY - AndroidUtilities.dp(3) + (!transitionParams.animateLinkPreviewY ? -transitionParams.deltaTop + transitionParams.deltaBottom : 0)); + TextPaint paint = titleLayout.getPaint(); + int wasAlpha = paint.getAlpha(); + paint.setAlpha((int) (wasAlpha * alpha)); titleLayout.draw(canvas); + paint.setAlpha(wasAlpha); canvas.restore(); linkPreviewY += titleLayout.getLineBottom(titleLayout.getLineCount() - 1); } @@ -10772,8 +11230,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate smallImageStartY = linkPreviewY - AndroidUtilities.dp(1); } canvas.save(); - canvas.translate(linkX + AndroidUtilities.dp(10) + authorX, linkPreviewY - AndroidUtilities.dp(3)); + canvas.translate(linkX + AndroidUtilities.dp(10) + (Math.abs(authorLayoutLeft) > 1 ? width - AndroidUtilities.dp(20) - authorLayoutWidth - authorLayoutLeft : 0), linkPreviewY - AndroidUtilities.dp(3) + (!transitionParams.animateLinkPreviewY ? -transitionParams.deltaTop + transitionParams.deltaBottom : 0)); + TextPaint paint = authorLayout.getPaint(); + int wasAlpha = paint.getAlpha(); + paint.setAlpha((int) (wasAlpha * alpha)); authorLayout.draw(canvas); + paint.setAlpha(wasAlpha); canvas.restore(); linkPreviewY += authorLayout.getLineBottom(authorLayout.getLineCount() - 1); } @@ -10787,7 +11249,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } descriptionY = linkPreviewY - AndroidUtilities.dp(3); canvas.save(); - canvas.translate(linkX + (hasInvoicePreview ? 0 : AndroidUtilities.dp(10)) + descriptionX, descriptionY); + canvas.translate(linkX + AndroidUtilities.dp(10) + (Math.abs(descriptionLayoutLeft) > 1 ? width - AndroidUtilities.dp(20) - descriptionLayoutWidth - descriptionLayoutLeft : 0), descriptionY + (!transitionParams.animateLinkPreviewY ? -transitionParams.deltaTop + transitionParams.deltaBottom : 0)); if (linkBlockNum == -10) { if (links.draw(canvas)) { invalidate(); @@ -10797,27 +11259,47 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (delegate != null && delegate.getTextSelectionHelper() != null && getDelegate().getTextSelectionHelper().isSelected(currentMessageObject)) { delegate.getTextSelectionHelper().drawDescription(currentMessageObject.isOutOwner(), descriptionLayout, canvas); } + TextPaint paint = descriptionLayout.getPaint(); + if (drawInstantButtonInside && currentMessageObject != null && !currentMessageObject.isOutOwner() && linkLine != null) { + paint.linkColor = linkLine.getColor(); + } + int wasAlpha = paint.getAlpha(); + paint.setAlpha((int) (wasAlpha * alpha)); descriptionLayout.draw(canvas); - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, descriptionLayout, animatedEmojiDescriptionStack, 0, null, 0, 0, 0, 1f, Theme.chat_animatedEmojiTextColorFilter); + paint.setAlpha(wasAlpha); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, descriptionLayout, animatedEmojiDescriptionStack, 0, null, 0, 0, 0, 1f, currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); canvas.restore(); + paint.linkColor = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_messageLinkOut : Theme.key_chat_messageLinkIn); linkPreviewY += descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1); } - if (drawPhotoImage && (!drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18)) { + if (drawPhotoImage && (!drawInstantView || drawInstantViewType == 9 || drawInstantViewType == 2 || drawInstantViewType == 11 || drawInstantViewType == 13 || drawInstantViewType == 1 || drawInstantViewType == 18 || isSmallImage)) { if (linkPreviewY != startY) { linkPreviewY += AndroidUtilities.dp(2); } + final int photoWidth = width - AndroidUtilities.dp(17); if (isSmallImage) { - photoImage.setImageCoords(linkX + backgroundWidth - AndroidUtilities.dp(81), smallImageStartY, photoImage.getImageWidth(), photoImage.getImageHeight()); + photoImage.setImageX(linkX + width - photoImage.getImageWidth() - AndroidUtilities.dp(6)); + photoImage.setImageY(smallImageStartY); } else { - photoImage.setImageCoords(linkX + (hasInvoicePreview ? -AndroidUtilities.dp(6.3f) : AndroidUtilities.dp(10)), linkPreviewY, photoImage.getImageWidth(), photoImage.getImageHeight()); - if (drawImageButton) { - int size = AndroidUtilities.dp(48); - buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); - buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); - radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); + photoImage.setImageX(linkX + (hasInvoicePreview ? -AndroidUtilities.dp(6.3f) : AndroidUtilities.dp(10))); + photoImage.setImageY(linkPreviewY); + } + if (transitionParams != null && transitionParams.animateSmallImage) { + if (!isSmallImage && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { + photoImage.setImageWidth((int) AndroidUtilities.lerp(transitionParams.photoImageFromWidth, photoWidth, transitionParams.animateChangeProgress)); } + photoImage.setImageX(AndroidUtilities.lerp(transitionParams.photoImageFromCenterX, photoImage.getCenterX(), transitionParams.animateChangeProgress) - photoImage.getImageWidth() / 2f); + photoImage.setImageY(AndroidUtilities.lerp(transitionParams.photoImageFromCenterY, photoImage.getCenterY(), transitionParams.animateChangeProgress) - photoImage.getImageHeight() / 2f); + } else if (!isSmallImage && documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT) { + photoImage.setImageWidth(photoWidth); + } + if (!isSmallImage && drawImageButton) { + int size = AndroidUtilities.dp(48); + buttonX = this.buttonX = (int) (photoImage.getImageX() + (photoImage.getImageWidth() - size) / 2.0f); + buttonY = this.buttonY = (int) (photoImage.getImageY() + (photoImage.getImageHeight() - size) / 2.0f); + radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + size, (int) buttonY + size); } if (isRoundVideo && MediaController.getInstance().isPlayingMessage(currentMessageObject) && MediaController.getInstance().isVideoDrawingReady() && canvas.isHardwareAccelerated()) { imageDrawn = true; @@ -10908,27 +11390,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate videoInfoLayout.draw(canvas); canvas.restore(); } + giveawayMessageCell.draw(canvas, namesOffset, linkX, resourcesProvider); if (drawInstantView) { Drawable instantDrawable; - int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(10); - Paint backPaint = Theme.chat_instantViewRectPaint; - boolean loading = delegate != null && delegate.isProgressLoading(this, ChatActivity.PROGRESS_INSTANT); - if (instantButtonLoading != null && !loading && !instantButtonLoading.isDisappeared() && !instantButtonLoading.isDisappearing()) { - instantButtonLoading.disappear(); - } - if (instantButtonLoading == null && loading) { - instantButtonLoading = new LoadingDrawable(); - instantButtonLoading.strokePaint.setStrokeWidth(AndroidUtilities.dp(1.25f)); - instantButtonLoading.setAppearByGradient(true); - } else if (instantButtonLoading != null && loading && (instantButtonLoading.isDisappeared() || instantButtonLoading.isDisappearing())) { - instantButtonLoading.reset(); - instantButtonLoading.resetDisappear(); - } if (currentMessageObject.isOutOwner()) { instantDrawable = getThemedDrawable(Theme.key_drawable_msgOutInstant); Theme.chat_instantViewPaint.setColor(getThemedColor(Theme.key_chat_outPreviewInstantText)); - backPaint.setColor(getThemedColor(Theme.key_chat_outPreviewInstantText)); + Theme.chat_instantViewButtonPaint.setColor(Theme.multAlpha(getThemedColor(Theme.key_chat_outPreviewInstantText), .10f)); if (instantButtonLoading != null) { instantButtonLoading.setColors( Theme.multAlpha(getThemedColor(Theme.key_chat_outPreviewInstantText), .1f), @@ -10938,81 +11407,130 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ); } } else { - instantDrawable = getThemedDrawable(Theme.key_drawable_msgInInstant); - Theme.chat_instantViewPaint.setColor(getThemedColor(Theme.key_chat_inPreviewInstantText)); - backPaint.setColor(getThemedColor(Theme.key_chat_inPreviewInstantText)); + int color = getThemedColor(Theme.key_chat_inPreviewInstantText); + if (linkLine != null) { + color = linkLine.getColor(); + } + if (this.instantDrawable == null) { + this.instantDrawable = getContext().getResources().getDrawable(R.drawable.msg_instant).mutate(); + } + if (this.instantDrawableColor != color) { + this.instantDrawable.setColorFilter(new PorterDuffColorFilter(this.instantDrawableColor = color, PorterDuff.Mode.SRC_IN)); + } + instantDrawable = this.instantDrawable; + Theme.chat_instantViewPaint.setColor(color); + Theme.chat_instantViewButtonPaint.setColor(Theme.multAlpha(color, .10f)); if (instantButtonLoading != null) { instantButtonLoading.setColors( - Theme.multAlpha(getThemedColor(Theme.key_chat_inPreviewInstantText), .1f), - Theme.multAlpha(getThemedColor(Theme.key_chat_inPreviewInstantText), .3f), - Theme.multAlpha(getThemedColor(Theme.key_chat_inPreviewInstantText), .3f), - Theme.multAlpha(getThemedColor(Theme.key_chat_inPreviewInstantText), 1.2f) + Theme.multAlpha(color, .1f), + Theme.multAlpha(color, .3f), + Theme.multAlpha(color, .3f), + Theme.multAlpha(color, 1.2f) ); } } - - instantButtonRect.set(linkX, instantY, linkX + instantWidth, instantY + AndroidUtilities.dp(36)); - if (instantButtonPressed && instantButtonPressProgress != 1f) { - instantButtonPressProgress += (float) Math.min(40, 1000f / AndroidUtilities.screenRefreshRate) / 100f; - instantButtonPressProgress = Utilities.clamp(instantButtonPressProgress, 1f, 0); - invalidate(); - } - float scale = 0.98f + 0.02f * (1f - instantButtonPressProgress); - boolean scaleRestore = scale != 1; - if (scaleRestore) { - canvas.save(); - canvas.scale(scale, scale, instantButtonRect.centerX(), instantButtonRect.centerY()); - } - if (Build.VERSION.SDK_INT >= 21) { - selectorDrawableMaskType[0] = 0; - selectorDrawable[0].setBounds(linkX, instantY, linkX + instantWidth, instantY + AndroidUtilities.dp(36)); - selectorDrawable[0].draw(canvas); - } - if (instantButtonLoading != null && !instantButtonLoading.isDisappeared()) { - instantButtonLoading.setBounds(instantButtonRect); - instantButtonLoading.setRadiiDp(6); - instantButtonLoading.draw(canvas); - invalidate(); - } - canvas.drawRoundRect(instantButtonRect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), backPaint); - if (drawInstantViewType == 0) { - setDrawableBounds(instantDrawable, instantTextLeftX + instantTextX + linkX - AndroidUtilities.dp(15), instantY + AndroidUtilities.dp(11.5f), AndroidUtilities.dp(9), AndroidUtilities.dp(13)); - instantDrawable.draw(canvas); - } else if (drawInstantViewType == 16) { - if (instantLinkArrowPaint == null) { - instantLinkArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - instantLinkArrowPaint.setStyle(Paint.Style.STROKE); - instantLinkArrowPaint.setStrokeCap(Paint.Cap.ROUND); - instantLinkArrowPaint.setStrokeJoin(Paint.Join.ROUND); + if (drawInstantButtonInside) { + int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(14); + int wasAlpha = Theme.chat_instantViewPaint.getAlpha(); + Theme.chat_instantViewPaint.setAlpha((int) (wasAlpha * .18f)); + canvas.drawRect(linkX + AndroidUtilities.dp(3 + 7), startY + linkPreviewHeight + AndroidUtilities.dp(2), linkX + width - AndroidUtilities.dp(7), startY + linkPreviewHeight + AndroidUtilities.dp(2) + Math.max(1, AndroidUtilities.dp(0.66f)), Theme.chat_instantViewPaint); + Theme.chat_instantViewPaint.setAlpha(wasAlpha); + final float textWidth = AndroidUtilities.dp(drawInstantViewType == 0 ? 15 : 0) + instantViewLayoutWidth; + float l = linkX + (width - textWidth) / 2f; + if (drawInstantViewType == 0) { + setDrawableBounds(instantDrawable, l, instantY + AndroidUtilities.dp(1), AndroidUtilities.dp(9), AndroidUtilities.dp(13)); + instantDrawable.setAlpha((int) (0xFF * alpha)); + instantDrawable.draw(canvas); + l += AndroidUtilities.dp(15); } - instantLinkArrowPaint.setColor(Theme.chat_instantViewPaint.getColor()); - instantLinkArrowPaint.setStrokeWidth(AndroidUtilities.dpf2(1.333f)); - if (instantLinkArrowPath == null) { - instantLinkArrowPath = new Path(); - } else { - instantLinkArrowPath.rewind(); + if (instantViewLayout != null) { + canvas.save(); + canvas.translate(l - instantViewLayoutLeft, instantY); + instantViewLayout.draw(canvas); + canvas.restore(); + } + } else { + int instantY = startY + linkPreviewHeight + AndroidUtilities.dp(10); + if (instantButtonLoading != null && !loading && !instantButtonLoading.isDisappeared() && !instantButtonLoading.isDisappearing()) { + instantButtonLoading.disappear(); + } + if (instantButtonLoading == null && loading) { + instantButtonLoading = new LoadingDrawable(); + instantButtonLoading.strokePaint.setStrokeWidth(AndroidUtilities.dp(1.25f)); + instantButtonLoading.setAppearByGradient(true); + } else if (instantButtonLoading != null && loading && (instantButtonLoading.isDisappeared() || instantButtonLoading.isDisappearing())) { + instantButtonLoading.reset(); + instantButtonLoading.resetDisappear(); + } + instantButtonRect.set(linkX, instantY, linkX + instantWidth, instantY + AndroidUtilities.dp(36)); + float scale = instantButtonBounce.getScale(.02f); + boolean scaleRestore = scale != 1; + if (scaleRestore) { + canvas.save(); + canvas.scale(scale, scale, instantButtonRect.centerX(), instantButtonRect.centerY()); + } + if (Build.VERSION.SDK_INT >= 21) { + selectorDrawableMaskType[0] = 0; + createSelectorDrawable(0); + selectorDrawable[0].setBounds(linkX, instantY, linkX + instantWidth, instantY + AndroidUtilities.dp(36)); + selectorDrawable[0].draw(canvas); + } + if (instantButtonLoading != null && !instantButtonLoading.isDisappeared()) { + instantButtonLoading.setBounds(instantButtonRect); + instantButtonLoading.setRadiiDp(6); + instantButtonLoading.draw(canvas); + invalidate(); + } + canvas.drawRoundRect(instantButtonRect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewButtonPaint); + if (drawInstantViewType == 0) { + setDrawableBounds(instantDrawable, instantTextLeftX + instantTextX + linkX - AndroidUtilities.dp(15), instantY + AndroidUtilities.dp(11.5f), AndroidUtilities.dp(9), AndroidUtilities.dp(13)); + instantDrawable.setAlpha((int) (0xFF * alpha)); + instantDrawable.draw(canvas); + } else if (drawInstantViewType == 16) { + if (instantLinkArrowPaint == null) { + instantLinkArrowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + instantLinkArrowPaint.setStyle(Paint.Style.STROKE); + instantLinkArrowPaint.setStrokeCap(Paint.Cap.ROUND); + instantLinkArrowPaint.setStrokeJoin(Paint.Join.ROUND); + } + instantLinkArrowPaint.setColor(Theme.chat_instantViewPaint.getColor()); + instantLinkArrowPaint.setStrokeWidth(AndroidUtilities.dpf2(1.333f)); + if (instantLinkArrowPath == null) { + instantLinkArrowPath = new Path(); + } else { + instantLinkArrowPath.rewind(); + } + instantLinkArrowPath.moveTo(instantButtonRect.right - AndroidUtilities.dp(6 + 5), instantButtonRect.top + AndroidUtilities.dp(6)); + instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6)); + instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6 + 5)); + instantLinkArrowPath.moveTo(instantButtonRect.right - AndroidUtilities.dpf2(6 + 5.66f), instantButtonRect.top + AndroidUtilities.dp(6 + 5.66f)); + instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6)); + canvas.drawPath(instantLinkArrowPath, instantLinkArrowPaint); + } + if (instantViewLayout != null) { + canvas.save(); + canvas.translate(linkX + instantTextX, instantY + AndroidUtilities.dp(10.5f)); + instantViewLayout.draw(canvas); + canvas.restore(); + } + if (scaleRestore) { + canvas.restore(); } - instantLinkArrowPath.moveTo(instantButtonRect.right - AndroidUtilities.dp(6+5), instantButtonRect.top + AndroidUtilities.dp(6)); - instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6)); - instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6+5)); - instantLinkArrowPath.moveTo(instantButtonRect.right - AndroidUtilities.dpf2(6+5.66f), instantButtonRect.top + AndroidUtilities.dp(6+5.66f)); - instantLinkArrowPath.lineTo(instantButtonRect.right - AndroidUtilities.dp(6), instantButtonRect.top + AndroidUtilities.dp(6)); - canvas.drawPath(instantLinkArrowPath, instantLinkArrowPaint); - } - if (instantViewLayout != null) { - canvas.save(); - canvas.translate(linkX + instantTextX, instantY + AndroidUtilities.dp(10.5f)); - instantViewLayout.draw(canvas); - canvas.restore(); - } - if (scaleRestore) { - canvas.restore(); } } + + canvas.restoreToCount(restoreCount); + } + + private float isSmallImage() { + if (transitionParams.animateSmallImage) { + return isSmallImage ? transitionParams.animateChangeProgress : 1f - transitionParams.animateChangeProgress; + } + return isSmallImage ? 1f : 0f; } private boolean shouldDrawMenuDrawable() { - return currentMessagesGroup == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0; + return (currentMessagesGroup == null || (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) != 0) && !hasLinkPreview; } private void drawBotButtons(Canvas canvas, ArrayList botButtons, int alpha) { @@ -11146,18 +11664,140 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return !currentMessageObject.hasMediaSpoilers() || currentMessageObject.isMediaSpoilersRevealed || mediaSpoilerRevealProgress != 0f || blurredPhotoImage.getBitmap() == null; } + public void layoutTextXY(boolean parent) { + if (currentMessageObject.isOutOwner()) { + textX = (parent ? (int) (backgroundDrawableLeft + transitionParams.deltaLeft) : getCurrentBackgroundLeft()) + AndroidUtilities.dp(11) + getExtraTextX(); + } else { + textX = (parent ? (int) (backgroundDrawableLeft + transitionParams.deltaLeft) : getCurrentBackgroundLeft()) + (currentMessageObject.type == MessageObject.TYPE_EMOJIS ? 0 : AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17)) + getExtraTextX(); + } + if (hasGamePreview) { + textX += AndroidUtilities.dp(11); + textY = AndroidUtilities.dp(14) + namesOffset; + if (siteNameLayout != null) { + textY += siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); + } + } else if (hasInvoicePreview) { + textY = AndroidUtilities.dp(14) + namesOffset; + if (siteNameLayout != null) { + textY += siteNameLayout.getLineBottom(siteNameLayout.getLineCount() - 1); + } + } else if (currentMessageObject.type == MessageObject.TYPE_EMOJIS) { + textY = AndroidUtilities.dp(6) + namesOffset; + if (!currentMessageObject.isOut()) { + textX = getCurrentBackgroundLeft(); + } else { + textX -= AndroidUtilities.dp(4); + } + } else { + textY = AndroidUtilities.dp(8) + namesOffset; + if (currentMessageObject.hasCodeAtTop && SharedConfig.bubbleRadius > 10) { + textY += AndroidUtilities.dp(SharedConfig.bubbleRadius < 15 ? 1 : 2); + } + if (currentMessageObject.hasCodeAtTop && namesOffset > 0) { + textY += AndroidUtilities.dp(5); + } + } + if (linkPreviewAbove) { + linkPreviewY = textY + AndroidUtilities.dp(10); + textY += linkPreviewHeight + AndroidUtilities.dp(13); + if (drawInstantView && !hasInvoicePreview && !currentMessageObject.isSponsored() && !currentMessageObject.isGiveaway()) { + textY += AndroidUtilities.dp(44); + } + } else { + linkPreviewY = textY + currentMessageObject.textHeight + AndroidUtilities.dp(!currentMessageObject.isSponsored() ? 10 : 0); + } + unmovedTextX = textX; + if (currentMessageObject.textXOffset != 0 && replyNameLayout != null) { + int diff = backgroundWidth - AndroidUtilities.dp(31) - currentMessageObject.textWidth; + if (!hasNewLineForTime) { + diff -= timeWidth + AndroidUtilities.dp(4 + (currentMessageObject.isOutOwner() ? 20 : 0)); + } + if (diff > 0) { + textX += diff - getExtraTimeX(); + } + } + } + + public void drawMessageText(Canvas canvas) { + if (currentMessageObject == null) { + return; + } + float textY = this.textY; + if (transitionParams.animateText) { + textY = transitionParams.animateFromTextY * (1f - transitionParams.animateChangeProgress) + this.textY * transitionParams.animateChangeProgress; + } + if (transitionParams.animateChangeProgress != 1.0f && transitionParams.animateMessageText) { + canvas.save(); + if (currentBackgroundDrawable != null) { + Rect r = currentBackgroundDrawable.getBounds(); + if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { + canvas.clipRect( + r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), + r.right - AndroidUtilities.dp(10), r.bottom - AndroidUtilities.dp(4) + ); + } else { + canvas.clipRect( + r.left + AndroidUtilities.dp(4), r.top + AndroidUtilities.dp(4), + r.right - AndroidUtilities.dp(4), r.bottom - AndroidUtilities.dp(4) + ); + } + } + drawMessageText(textX, textY, canvas, transitionParams.animateOutTextBlocks, transitionParams.animateOutTextXOffset, false, (1.0f - transitionParams.animateChangeProgress), true, false, false); + drawMessageText(textX, textY, canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, true, transitionParams.animateChangeProgress, true, false, false); + canvas.restore(); + } else if (transitionParams.animateLinkAbove && currentBackgroundDrawable != null) { + float oldTextY = textY; + if (transitionParams.animateLinkAbove) { + textY = this.textY + (linkPreviewAbove ? 1 : -1) * currentMessageObject.textHeight * (1f - transitionParams.animateChangeProgress); + oldTextY = transitionParams.animateFromTextY - (linkPreviewAbove ? 1 : -1) * currentMessageObject.textHeight * transitionParams.animateChangeProgress; + } + + canvas.save(); + AndroidUtilities.rectTmp.set(currentBackgroundDrawable.getBounds()); + if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { + AndroidUtilities.rectTmp.left += AndroidUtilities.dp(4); + AndroidUtilities.rectTmp.right -= AndroidUtilities.dp(10); + } else { + AndroidUtilities.rectTmp.left += AndroidUtilities.dp(4); + AndroidUtilities.rectTmp.right -= AndroidUtilities.dp(4); + } + canvas.clipRect(AndroidUtilities.rectTmp.left, transitionParams.animateFromTextY, AndroidUtilities.rectTmp.right, transitionParams.animateFromTextY + currentMessageObject.textHeight + AndroidUtilities.dp(4)); + drawMessageText(textX, oldTextY, canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, false, (1.0f - transitionParams.animateChangeProgress), true, false, false); + canvas.restore(); + + canvas.save(); + AndroidUtilities.rectTmp.set(currentBackgroundDrawable.getBounds()); + if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { + AndroidUtilities.rectTmp.left += AndroidUtilities.dp(4); + AndroidUtilities.rectTmp.right -= AndroidUtilities.dp(10); + } else { + AndroidUtilities.rectTmp.left += AndroidUtilities.dp(4); + AndroidUtilities.rectTmp.right -= AndroidUtilities.dp(4); + } + canvas.clipRect(AndroidUtilities.rectTmp.left, this.textY, AndroidUtilities.rectTmp.right, this.textY + currentMessageObject.textHeight + AndroidUtilities.dp(4)); + drawMessageText(textX, textY, canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, true, 1.0f, true, false, false); + canvas.restore(); + } else { + drawMessageText(textX, textY, canvas, currentMessageObject.textLayoutBlocks, currentMessageObject.textXOffset, true, 1.0f, true, false, false); + } + } + public void drawMessageText(Canvas canvas, ArrayList textLayoutBlocks, boolean origin, float alpha, boolean drawOnlyText) { - drawMessageText(canvas, textLayoutBlocks, currentMessageObject == null ? 0 : currentMessageObject.textXOffset, origin, alpha, drawOnlyText); + float textY = this.textY; + if (transitionParams.animateText) { + textY = transitionParams.animateFromTextY * (1f - transitionParams.animateChangeProgress) + this.textY * transitionParams.animateChangeProgress; + } + drawMessageText(textX, textY, canvas, textLayoutBlocks, currentMessageObject == null ? 0 : currentMessageObject.textXOffset, origin, alpha, false, drawOnlyText, false); } @SuppressLint("Range") - public void drawMessageText(Canvas canvas, ArrayList textLayoutBlocks, float rtlOffset, boolean origin, float alpha, boolean drawOnlyText) { + public void drawMessageText(float textX, float textY, Canvas canvas, ArrayList textLayoutBlocks, float rtlOffset, boolean origin, float alpha, boolean drawAllBlocks, boolean drawOnlyText, boolean caption) { if (textLayoutBlocks == null || textLayoutBlocks.isEmpty() || alpha == 0) { return; } int firstVisibleBlockNum; int lastVisibleBlockNum; - if (origin) { + if (origin && !drawAllBlocks) { if (fullyDraw) { this.firstVisibleBlockNum = 0; this.lastVisibleBlockNum = textLayoutBlocks.size(); @@ -11169,13 +11809,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastVisibleBlockNum = textLayoutBlocks.size(); } - float textY = this.textY; - if (transitionParams.animateText) { - textY = transitionParams.animateFromTextY * (1f - transitionParams.animateChangeProgress) + this.textY * transitionParams.animateChangeProgress; - } - boolean translating = MessagesController.getInstance(currentAccount).getTranslateController().isTranslating(getMessageObject()); - if ((textLayoutBlocks == transitionParams.animateOutTextBlocks) == (currentMessageObject != null && currentMessageObject.translated)) { + if (!origin == (currentMessageObject != null && currentMessageObject.translated)) { if (translationLoadingFloat == null) { translationLoadingFloat = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT_QUINT); } @@ -11230,12 +11865,45 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (firstVisibleBlockNum >= 0) { + final float maxWidth; + if (caption) { + if (currentMessagesGroup != null) { + float endX = textX - getExtraTextX(); + if (currentMessagesGroup != null && !currentMessageObject.isMusic() && !currentMessageObject.isDocument()) { + int dWidth = getGroupPhotosWidth(); + if ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0) { + endX += Math.ceil(currentPosition.pw / 1000.0f * dWidth); + } else { + int firstLineWidth = 0; + for (int i = 0; i < currentMessagesGroup.posArray.size(); i++) { + MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(i); + if (position.minY == 0) { + firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); + } else { + break; + } + } + endX += firstLineWidth - AndroidUtilities.dp(9); + } + } else { + endX += backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(9)); + } + if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 && !currentMessagesGroup.hasSibling) { + endX += AndroidUtilities.dp(14); + } + maxWidth = endX - textX - AndroidUtilities.dp(6 + 4 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)); + } else { + maxWidth = captionFullWidth - AndroidUtilities.dp(3 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)) - 2 * getExtraTextX(); + } + } else { + maxWidth = getCurrentBackgroundRight() - AndroidUtilities.dp(11 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)) - getExtraTextX() - textX; + } int restore = Integer.MIN_VALUE; int oldAlpha = 0; int oldLinkAlpha = 0; boolean needRestoreColor = false; if (alpha != 1.0f) { - if (drawOnlyText) { + if (drawOnlyText || caption) { needRestoreColor = true; oldAlpha = Theme.chat_msgTextPaint.getAlpha(); oldLinkAlpha = Color.alpha(Theme.chat_msgTextPaint.linkColor); @@ -11245,17 +11913,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentBackgroundDrawable != null) { int top = currentBackgroundDrawable.getBounds().top; int bottom = currentBackgroundDrawable.getBounds().bottom; - - if (getY() < 0) { - top = (int) -getY(); + if (caption) { + rect.set(getCurrentBackgroundLeft() - AndroidUtilities.dp(10), top, currentBackgroundDrawable.getBounds().right + AndroidUtilities.dp(10), bottom); + } else { + if (getY() < 0) { + top = (int) -getY(); + } + if (getY() + getMeasuredHeight() > parentHeight) { + bottom = (int) (parentHeight - getY()); + } + rect.set(getCurrentBackgroundLeft(), top, currentBackgroundDrawable.getBounds().right, bottom); } - if (getY() + getMeasuredHeight() > parentHeight) { - bottom = (int) (parentHeight - getY()); - } - rect.set( - getCurrentBackgroundLeft(), top, - currentBackgroundDrawable.getBounds().right, bottom - ); } else { rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); } @@ -11263,30 +11931,111 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } int spoilersColor = currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : Theme.chat_msgTextPaint.getColor(); + if (quoteHighlight != null && currentMessagesGroup == null) { + Theme.MessageDrawable backgroundDrawable = currentBackgroundDrawable; + if (backgroundDrawable != null) { + canvas.save(); + canvas.clipPath(backgroundDrawable.makePath()); + quoteHighlight.paint.setColor(Theme.multAlpha(getThemedColor(currentMessageObject != null && currentMessageObject.isOutOwner() && !currentMessageObject.preview ? Theme.key_chat_outReplyLine : Theme.key_chat_inReplyLine), Theme.isCurrentThemeDark() ? .2f : .2f)); + quoteHighlight.draw(canvas, textX, textY, backgroundDrawable.getBounds(), getHighlightAlpha(true)); + canvas.restore(); + } + } for (int a = firstVisibleBlockNum; a <= lastVisibleBlockNum; a++) { if (a >= textLayoutBlocks.size()) { break; } MessageObject.TextLayoutBlock block = textLayoutBlocks.get(a); canvas.save(); - canvas.translate(textX - (block.isRtl() ? rtlOffset : 0), textY + block.textYOffset + transitionYOffsetForDrawables); + canvas.translate(textX - (block.isRtl() ? rtlOffset - (block.quote ? AndroidUtilities.dp(10) : 0) : 0), textY + block.textYOffset + transitionYOffsetForDrawables + block.padTop); if (a == linkBlockNum) { if (!drawOnlyText && links.draw(canvas)) { invalidate(); } drawProgressLoadingLink(canvas, a); } - if (a == linkSelectionBlockNum && !urlPathSelection.isEmpty() && !drawOnlyText) { - for (int b = 0; b < urlPathSelection.size(); b++) { - canvas.drawPath(urlPathSelection.get(b), Theme.chat_textSearchSelectionPaint); + int blockSpoilersColor = spoilersColor; + if (block.quote) { + if (quoteLine == null) { + quoteLine = new ReplyMessageLine(this); + } + quoteLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, false); + + final int width = (int) (block.maxRight + AndroidUtilities.dp(24) > maxWidth * .7f ? maxWidth : block.maxRight + AndroidUtilities.dp(24)); + AndroidUtilities.rectTmp.set((block.isRtl() ? rtlOffset - AndroidUtilities.dp(10) : 0), -block.padTop + AndroidUtilities.dp(block.first ? 3 + 1.66f : 3), (block.isRtl() ? rtlOffset - AndroidUtilities.dp(10) : 0) + width, block.height + AndroidUtilities.dp(4)); + quoteLine.drawBackground(canvas, AndroidUtilities.rectTmp, 5, 5, 5, alpha); + quoteLine.drawLine(canvas, AndroidUtilities.rectTmp, alpha); + + if (replyQuoteDrawable == null) { + replyQuoteDrawable = getContext().getResources().getDrawable(R.drawable.mini_quote).mutate(); + } + if (quoteLine.getColor() != replyQuoteDrawableColor) { + replyQuoteDrawable.setColorFilter(new PorterDuffColorFilter(replyQuoteDrawableColor = quoteLine.getColor(), PorterDuff.Mode.SRC_IN)); + } + replyQuoteDrawable.setBounds( + (int) (AndroidUtilities.rectTmp.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) - replyQuoteDrawable.getIntrinsicWidth()), + (int) (AndroidUtilities.rectTmp.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))), + (int) (AndroidUtilities.rectTmp.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))), + (int) (AndroidUtilities.rectTmp.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) + replyQuoteDrawable.getIntrinsicHeight()) + ); + replyQuoteDrawable.setAlpha((int) (0xFF * alpha)); + replyQuoteDrawable.draw(canvas); + + blockSpoilersColor = quoteLine.getColor(); + + Theme.chat_msgGameTextPaint.linkColor = + Theme.chat_replyTextPaint.linkColor = + Theme.chat_quoteTextPaint.linkColor = + Theme.chat_msgTextPaint.linkColor = quoteLine.getColor(); + } else { + Theme.chat_msgGameTextPaint.linkColor = + Theme.chat_replyTextPaint.linkColor = + Theme.chat_quoteTextPaint.linkColor = + Theme.chat_msgTextPaint.linkColor = getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_messageLinkOut : Theme.key_chat_messageLinkIn); + + if (block.code) { + Theme.chat_msgCodeBgPaint.setColor(Theme.getColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outCodeBackground : Theme.key_chat_inCodeBackground, resourcesProvider)); + Theme.chat_msgCodeBgPaint.setAlpha((int) (Theme.chat_msgCodeBgPaint.getAlpha() * alpha)); + + AndroidUtilities.rectTmp.set(-AndroidUtilities.dp(4), -AndroidUtilities.dp(2), maxWidth + AndroidUtilities.dp(4), block.height + AndroidUtilities.dp(2)); + if (replyRoundRectPath == null) { + replyRoundRectPath = new Path(); + } else { + replyRoundRectPath.rewind(); + } + if (replyBackgroundRadii == null) { + replyBackgroundRadii = new float[8]; + } + final int rad = dp(SharedConfig.bubbleRadius); + final int nearRad = dp(Math.min(6, SharedConfig.bubbleRadius)); + final int defrad = dp(Math.min(5, SharedConfig.bubbleRadius)); + replyBackgroundRadii[0] = replyBackgroundRadii[1] = block.first && namesOffset <= 0 && !caption ? ((currentMessageObject.isOutOwner() || !pinnedTop) ? rad / 3f * 2f : nearRad) : defrad; + replyBackgroundRadii[2] = replyBackgroundRadii[3] = block.first && namesOffset <= 0 && !caption ? ((!currentMessageObject.isOutOwner() || !pinnedTop) ? rad / 3f * 2f : nearRad) : defrad; + replyBackgroundRadii[4] = replyBackgroundRadii[5] = replyBackgroundRadii[6] = replyBackgroundRadii[7] = defrad; + replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyBackgroundRadii, Path.Direction.CW); + canvas.drawPath(replyRoundRectPath, Theme.chat_msgCodeBgPaint); } } + if (a == linkSelectionBlockNum && quoteHighlight == null && !urlPathSelection.isEmpty() && !drawOnlyText) { + final Paint paint = currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.chat_outUrlPaint : Theme.chat_urlPaint; + paint.setColor(getThemedColor(currentMessageObject != null && currentMessageObject.isOutOwner() && !currentMessageObject.preview ? Theme.key_chat_outReplyLine : Theme.key_chat_inReplyLine)); + int wasAlpha = (int) (paint.getAlpha() * (Theme.isCurrentThemeDark() ? .2f : .3f)); + paint.setAlpha((int) (wasAlpha * (highlightedQuote ? getHighlightAlpha() : 1))); + for (int b = 0; b < urlPathSelection.size(); b++) { + canvas.drawPath(urlPathSelection.get(b), paint); + } + paint.setAlpha(wasAlpha); + } if (delegate.getTextSelectionHelper() != null && transitionParams.animateChangeProgress == 1f && !drawOnlyText) { - delegate.getTextSelectionHelper().draw(currentMessageObject, block, canvas); + if (caption) { + delegate.getTextSelectionHelper().drawCaption(currentMessageObject, block, canvas); + } else { + delegate.getTextSelectionHelper().draw(currentMessageObject, block, canvas); + } } try { Emoji.emojiDrawingYOffset = -transitionYOffsetForDrawables; - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, 0, block.spoilersPatchedTextLayout, block.textLayout, block.spoilers, canvas, false); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, blockSpoilersColor, 0, block.spoilersPatchedTextLayout, block.textLayout, block.spoilers, canvas, false); Emoji.emojiDrawingYOffset = 0; } catch (Exception e) { FileLog.e(e); @@ -11406,6 +12155,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.isOutOwner()) { radialProgress.setColorKeys(Theme.key_chat_outLoader, Theme.key_chat_outLoaderSelected, Theme.key_chat_outMediaIcon, Theme.key_chat_outMediaIconSelected); + } else if (linkLine != null && hasLinkPreview) { + radialProgress.setColors(linkLine.getColor(), linkLine.getColor(), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f)), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .05f))); } else { radialProgress.setColorKeys(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); } @@ -11421,6 +12172,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT && !drawPhotoImage) { if (currentMessageObject.isOutOwner()) { radialProgress.setColorKeys(Theme.key_chat_outLoader, Theme.key_chat_outLoaderSelected, Theme.key_chat_outMediaIcon, Theme.key_chat_outMediaIconSelected); + } else if (linkLine != null && hasLinkPreview) { + radialProgress.setColors(linkLine.getColor(), linkLine.getColor(), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .01f)), Theme.blendOver(0xffffffff, Theme.multAlpha(linkLine.getColor(), .05f))); } else { radialProgress.setColorKeys(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); } @@ -11465,13 +12218,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType == DOCUMENT_ATTACH_TYPE_STICKER || documentAttachType == DOCUMENT_ATTACH_TYPE_WALLPAPER || currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO) { int maxWidth; if (AndroidUtilities.isTablet()) { - if (isChat && !isThreadPost && !currentMessageObject.isOutOwner() && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost && !currentMessageObject.isOutOwner() || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(42); } else { maxWidth = AndroidUtilities.getMinTabletSide(); } } else { - if (isChat && !isThreadPost && !currentMessageObject.isOutOwner() && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost && !currentMessageObject.isOutOwner() || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y) - AndroidUtilities.dp(42); } else { maxWidth = Math.min(getParentWidth(), AndroidUtilities.displaySize.y); @@ -12662,7 +13415,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean isDrawSelectionBackground() { - return (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) && !textIsSelectionMode() && !hasSelectionOverlay(); + return (isPressed() && isCheckPressed || !isCheckPressed && isPressed || isHighlighted) && !textIsSelectionMode() && !hasSelectionOverlay() && (currentMessageObject == null || !currentMessageObject.preview); } private boolean isOpenChatByShare(MessageObject messageObject) { @@ -12692,7 +13445,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate MessagesController messagesController = MessagesController.getInstance(currentAccount); TLRPC.MessageFwdHeader fwd_from = currentMessageObject.messageOwner.fwd_from; long currentUserId = UserConfig.getInstance(currentAccount).getClientUserId(); - if (fwd_from != null && fwd_from.from_id instanceof TLRPC.TL_peerChannel && currentMessageObject.getDialogId() == currentUserId) { + if (fwd_from != null && fwd_from.from_id instanceof TLRPC.TL_peerChannel && (currentMessageObject.getDialogId() == currentUserId || currentMessageObject.getDialogId() == UserObject.REPLY_BOT)) { currentChat = MessagesController.getInstance(currentAccount).getChat(fwd_from.from_id.channel_id); } else if (fwd_from != null && fwd_from.saved_from_peer != null) { if (fwd_from.saved_from_peer.user_id != 0) { @@ -12729,11 +13482,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentChat = messagesController.getChat(currentMessageObject.messageOwner.peer_id.channel_id); } } - if (currentMessageObject != null && currentMessageObject.getChatId() != 0 && currentMessageObject.messageOwner != null && currentMessageObject.replyMessageObject != null && currentMessageObject.replyMessageObject.isFromUser()) { - currentReplyUserId = currentMessageObject.replyMessageObject.messageOwner.from_id.user_id; - } else { - currentReplyUserId = 0; - } } private void setMessageObjectInternal(MessageObject messageObject) { @@ -12807,11 +13555,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { currentNameString = ""; } + int additionalWidth = AndroidUtilities.dp(currentMessageObject.isSponsored() ? -24 : 0); CharSequence nameStringFinal = currentNameString.replace('\n', ' ').replace('\u200F', ' '); try { nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.chat_namePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); } catch (Exception ignore) {} - nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.chat_namePaint, nameWidth - (viaBot ? viaWidth : 0), TextUtils.TruncateAt.END); + nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.chat_namePaint, nameWidth + additionalWidth - (viaBot ? viaWidth : 0), TextUtils.TruncateAt.END); if (viaBot) { viaNameWidth = (int) Math.ceil(Theme.chat_namePaint.measureText(nameStringFinal, 0, nameStringFinal.length())); if (viaNameWidth != 0) { @@ -12835,10 +13584,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate stringBuilder.setSpan(viaSpan2 = new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, color), 1 + viaBotString.length(), stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); nameStringFinal = stringBuilder; } - nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.chat_namePaint, nameWidth, TextUtils.TruncateAt.END); + nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.chat_namePaint, nameWidth + additionalWidth, TextUtils.TruncateAt.END); } try { - nameLayout = new StaticLayout(nameStringFinal, Theme.chat_namePaint, nameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + nameLayout = new StaticLayout(nameStringFinal, Theme.chat_namePaint, nameWidth + additionalWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout.getLineCount() > 0) { nameWidth = nameLayoutWidth = (int) Math.ceil(nameLayout.getLineWidth(0)); if (!messageObject.isAnyKindOfSticker()) { @@ -12851,6 +13600,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentNameStatus != null) { nameWidth += AndroidUtilities.dp(4 + 12 + 4); } + nameWidth -= additionalWidth; if (adminString != null) { adminLayout = new StaticLayout(adminString, Theme.chat_adminPaint, adminWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); nameWidth += adminLayout.getLineWidth(0) + AndroidUtilities.dp(8); @@ -13031,10 +13781,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate topicButton = null; } - if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.story_id != 0)) { + if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || messageObject.messageOwner.fwd_from != null && messageObject.isDice() || (messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.story_id != 0 || !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) || messageObject.messageOwner.reply_to.reply_from != null))) { if (currentPosition == null || currentPosition.minY == 0) { if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO || messageObject.type == MessageObject.TYPE_EMOJIS) { - namesOffset += AndroidUtilities.dp(14) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); + namesOffset += AndroidUtilities.dp(20) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); if (messageObject.type == MessageObject.TYPE_EMOJIS && !drawForwardedName) { namesOffset += AndroidUtilities.dp(12); } else if (messageObject.type != MessageObject.TYPE_TEXT) { @@ -13047,17 +13797,27 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int maxWidth = getMaxNameWidth(); if (!messageObject.shouldDrawWithoutBackground()) { - maxWidth -= AndroidUtilities.dp(10); + maxWidth -= AndroidUtilities.dp(messageObject.isOutOwner() ? 20 : 10); + if (messageObject.type != MessageObject.TYPE_TEXT) { + maxWidth -= AndroidUtilities.dp(10); + } } else if (messageObject.type == MessageObject.TYPE_ROUND_VIDEO) { maxWidth += AndroidUtilities.dp(13); } CharSequence stringFinalText = null; - String name = null; + CharSequence name = null; + isReplyQuote = messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.flags & 64) != 0 && messageObject.messageOwner.reply_to.quote_text != null; + final boolean showQuote = isReplyQuote && messageObject.messageOwner.reply_to.quote; + if (isReplyQuote && showQuote && replyQuoteDrawable == null) { + replyQuoteDrawable = getContext().getResources().getDrawable(R.drawable.mini_quote).mutate(); + replyQuoteDrawableColor = Color.WHITE; + } + final TextPaint textPaint = isReplyQuote && messageObject.shouldDrawWithoutBackground() ? Theme.chat_quoteTextPaint : Theme.chat_replyTextPaint; if (messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.story_id != 0) { name = getNameFromDialogId(messageObject.messageOwner.reply_to.user_id); - if (messageObject.messageOwner.replyStory == null || messageObject.messageOwner.replyStory instanceof TLRPC.TL_storyItemDeleted) { + if (messageObject.messageOwner.replyStory == null || messageObject.messageOwner.replyStory instanceof TL_stories.TL_storyItemDeleted) { if (messageObject.messageOwner.replyStory == null) { stringFinalText = LocaleController.getString("Loading", R.string.Loading); } else { @@ -13068,34 +13828,59 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate needReplyImage = true; StoriesUtilities.setStoryMiniImage(replyImageReceiver, messageObject.messageOwner.replyStory); stringFinalText = StoriesUtilities.createReplyStoryString(); - maxWidth -= AndroidUtilities.dp(16) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); + maxWidth -= AndroidUtilities.dp(16) + (textPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); } - } else if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject()) { - lastReplyMessage = messageObject.replyMessageObject.messageOwner; + } else if ((!isThreadChat || messageObject.getReplyTopMsgId(isForum) != 0 || isForumGeneral) && messageObject.hasValidReplyMessageObject() || isReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) { + lastReplyMessage = messageObject.replyMessageObject == null ? null : messageObject.replyMessageObject.messageOwner; int cacheType = 1; int size = 0; - boolean hasReplySpoiler = messageObject.replyMessageObject.hasMediaSpoilers(); - TLObject photoObject; - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 320); - TLRPC.PhotoSize thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 40); - photoObject = messageObject.replyMessageObject.photoThumbsObject2; - if (photoSize == null) { - if (messageObject.replyMessageObject.mediaExists) { - photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - if (photoSize != null) { - size = photoSize.size; + boolean hasReplySpoiler = false; + TLObject photoObject = null; + TLRPC.PhotoSize photoSize = null; + TLRPC.PhotoSize thumbPhotoSize = null; + if (messageObject.replyMessageObject != null) { + hasReplySpoiler = messageObject.replyMessageObject.hasMediaSpoilers(); + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 320); + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs2, 40); + photoObject = messageObject.replyMessageObject.photoThumbsObject2; + if (photoSize == null) { + if (messageObject.replyMessageObject.mediaExists) { + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (photoSize != null) { + size = photoSize.size; + } + cacheType = 0; + } else { + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 320); } - cacheType = 0; - } else { - photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 320); + thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 40); + photoObject = messageObject.replyMessageObject.photoThumbsObject; + } + if (thumbPhotoSize == photoSize) { + thumbPhotoSize = null; } - thumbPhotoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.replyMessageObject.photoThumbs, 40); - photoObject = messageObject.replyMessageObject.photoThumbsObject; } - if (thumbPhotoSize == photoSize) { - thumbPhotoSize = null; - } - if (photoSize == null || messageObject.replyMessageObject.isAnyKindOfSticker() || messageObject.isAnyKindOfSticker() && !AndroidUtilities.isTablet() || messageObject.replyMessageObject.isSecretMedia() || messageObject.replyMessageObject.isWebpageDocument()) { + if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_media != null) { + if (messageObject.messageOwner.reply_to.reply_media.document != null) { + photoObject = messageObject.messageOwner.reply_to.reply_media.document; + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.messageOwner.reply_to.reply_media.document.thumbs, 320); + needReplyImage = true; + } else if (messageObject.messageOwner.reply_to.reply_media.photo != null) { + photoObject = messageObject.messageOwner.reply_to.reply_media.photo; + photoSize = FileLoader.getClosestPhotoSizeWithSize(messageObject.messageOwner.reply_to.reply_media.photo.sizes, 320); + needReplyImage = true; + } + + if (photoSize == null) { + replyImageReceiver.setImageBitmap((Drawable) null); + needReplyImage = false; + } else { + currentReplyPhoto = photoSize; + replyImageReceiver.setImage(ImageLocation.getForObject(photoSize, photoObject), hasReplySpoiler ? "5_5_b" : "50_50", ImageLocation.getForObject(thumbPhotoSize, photoObject), hasReplySpoiler ? "50_50_b4" : "50_50_b", size, null, messageObject, cacheType); + needReplyImage = true; + maxWidth -= AndroidUtilities.dp(35); + } + } else if (photoSize == null || messageObject.replyMessageObject == null || messageObject.replyMessageObject.isAnyKindOfSticker() || messageObject.isAnyKindOfSticker() && !AndroidUtilities.isTablet() || messageObject.replyMessageObject.isSecretMedia() || messageObject.replyMessageObject.isWebpageDocument()) { replyImageReceiver.setImageBitmap((Drawable) null); needReplyImage = false; } else { @@ -13107,10 +13892,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentReplyPhoto = photoSize; replyImageReceiver.setImage(ImageLocation.getForObject(photoSize, photoObject), hasReplySpoiler ? "5_5_b" : "50_50", ImageLocation.getForObject(thumbPhotoSize, photoObject), hasReplySpoiler ? "50_50_b4" : "50_50_b", size, null, messageObject.replyMessageObject, cacheType); needReplyImage = true; - maxWidth -= AndroidUtilities.dp(16) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); + maxWidth -= AndroidUtilities.dp(35); } - if (messageObject.hideSendersName) { + if (isReplyQuote) { + name = messageObject.getReplyQuoteNameWithIcon(); + } else if (messageObject.hideSendersName) { if (messageObject.sendAsPeer != null) { if (messageObject.sendAsPeer.channel_id != 0) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(messageObject.sendAsPeer.channel_id); @@ -13126,7 +13913,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } else if (messageObject.customReplyName != null) { name = messageObject.customReplyName; - } else { + } else if (messageObject.replyMessageObject == null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null) { + name = messageObject.getReplyQuoteNameWithIcon(); + } else if (messageObject.replyMessageObject != null) { if (drawForwardedName) { if (messageObject.replyMessageObject.messageOwner.fwd_from != null) { name = UserConfig.getChatTitleOverride(currentAccount, @@ -13140,8 +13929,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (name == null) { long fromId = messageObject.replyMessageObject.getFromChatId(); - if (fromId != 0) { - name = getNameFromDialogId(fromId); + if (fromId > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(fromId); + if (user != null) { + name = UserObject.getUserName(user); + } + } else if (fromId < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-fromId); + if (chat != null) { + name = chat.title; + } } else { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(messageObject.replyMessageObject.messageOwner.peer_id.channel_id); if (chat != null) { @@ -13154,25 +13951,34 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (name == null) { name = LocaleController.getString("Loading", R.string.Loading); } - if (messageObject.replyMessageObject.messageTextForReply != null) { + if (isReplyQuote || messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote_text != null && messageObject.messageOwner.reply_to.reply_from != null) { + stringFinalText = new SpannableStringBuilder(messageObject.messageOwner.reply_to.quote_text); + stringFinalText = Emoji.replaceEmoji(stringFinalText, textPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + if (messageObject.messageOwner.reply_to.quote_entities != null) { + stringFinalText = MessageObject.replaceAnimatedEmoji(stringFinalText, messageObject.messageOwner.reply_to.quote_entities, textPaint.getFontMetricsInt(), true); + MessageObject.addEntitiesToText(stringFinalText, messageObject.messageOwner.reply_to.quote_entities, currentMessageObject.isOutOwner(), false, false, false); + } + } else if (messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.reply_from != null && messageObject.messageOwner.reply_to.reply_media != null) { + stringFinalText = messageObject.getMediaTitle(messageObject.messageOwner.reply_to.reply_media); + } else if (messageObject.replyMessageObject != null && messageObject.replyMessageObject.messageTextForReply != null) { stringFinalText = messageObject.replyMessageObject.messageTextForReply; } else if (MessageObject.getMedia(messageObject.replyMessageObject) instanceof TLRPC.TL_messageMediaGame) { - stringFinalText = Emoji.replaceEmoji(MessageObject.getMedia(messageObject.replyMessageObject).game.title, Theme.chat_replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); - stringFinalText = TextUtils.ellipsize(stringFinalText, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); + stringFinalText = Emoji.replaceEmoji(MessageObject.getMedia(messageObject.replyMessageObject).game.title, textPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + stringFinalText = TextUtils.ellipsize(stringFinalText, textPaint, maxWidth, TextUtils.TruncateAt.END); } else if (MessageObject.getMedia(messageObject.replyMessageObject) instanceof TLRPC.TL_messageMediaInvoice) { - stringFinalText = Emoji.replaceEmoji(MessageObject.getMedia(messageObject.replyMessageObject).title, Theme.chat_replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); - stringFinalText = TextUtils.ellipsize(stringFinalText, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); - } else if (!TextUtils.isEmpty(messageObject.replyMessageObject.caption)) { + stringFinalText = Emoji.replaceEmoji(MessageObject.getMedia(messageObject.replyMessageObject).title, textPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + stringFinalText = TextUtils.ellipsize(stringFinalText, textPaint, maxWidth, TextUtils.TruncateAt.END); + } else if (messageObject.replyMessageObject != null && !TextUtils.isEmpty(messageObject.replyMessageObject.caption)) { String mess = messageObject.replyMessageObject.caption.toString(); if (mess.length() > 150) { mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); - stringFinalText = Emoji.replaceEmoji(mess, Theme.chat_replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + stringFinalText = Emoji.replaceEmoji(mess, textPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); if (messageObject.replyMessageObject.messageOwner != null) { - stringFinalText = MessageObject.replaceAnimatedEmoji(stringFinalText, messageObject.replyMessageObject.messageOwner.entities, Theme.chat_replyTextPaint.getFontMetricsInt(), true); + stringFinalText = MessageObject.replaceAnimatedEmoji(stringFinalText, messageObject.replyMessageObject.messageOwner.entities, textPaint.getFontMetricsInt(), true); } - stringFinalText = TextUtils.ellipsize(stringFinalText, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); + stringFinalText = TextUtils.ellipsize(stringFinalText, textPaint, maxWidth, TextUtils.TruncateAt.END); if (stringFinalText instanceof Spannable && messageObject.replyMessageObject.messageOwner != null) { MediaDataController.addTextStyleRuns(messageObject.replyMessageObject.messageOwner.entities, messageObject.replyMessageObject.caption, (Spannable) stringFinalText); } @@ -13182,11 +13988,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate mess = mess.substring(0, 150); } mess = mess.replace('\n', ' '); - stringFinalText = Emoji.replaceEmoji(mess, Theme.chat_replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + stringFinalText = Emoji.replaceEmoji(mess, textPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); if (messageObject.replyMessageObject.messageOwner != null) { - stringFinalText = MessageObject.replaceAnimatedEmoji(stringFinalText, messageObject.replyMessageObject.messageOwner.entities, Theme.chat_replyTextPaint.getFontMetricsInt(), true); + stringFinalText = MessageObject.replaceAnimatedEmoji(stringFinalText, messageObject.replyMessageObject.messageOwner.entities, textPaint.getFontMetricsInt(), true); } - stringFinalText = TextUtils.ellipsize(stringFinalText, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); + stringFinalText = TextUtils.ellipsize(stringFinalText, textPaint, maxWidth, TextUtils.TruncateAt.END); if (stringFinalText instanceof Spannable) { MediaDataController.addTextStyleRuns(messageObject.replyMessageObject, (Spannable) stringFinalText); } @@ -13231,7 +14037,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (idx >= 0 && (currentForwardName == null || messageObject.messageOwner.fwd_from.from_id != null)) { stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), idx, idx + ellipsizedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } - stringFinalText = TextUtils.ellipsize(stringBuilder, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); + stringFinalText = TextUtils.ellipsize(stringBuilder, textPaint, maxWidth, TextUtils.TruncateAt.END); forwardNameCenterX = fromWidth + (int) Math.ceil(Theme.chat_replyNamePaint.measureText(ellipsizedText, 0, ellipsizedText.length())) / 2; } } @@ -13239,9 +14045,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate try { stringFinalName = Emoji.replaceEmoji(stringFinalName, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); } catch (Exception ignore) {} + if (isReplyQuote) { + maxWidth -= AndroidUtilities.dp(24); + } stringFinalName = stringFinalName == null ? "" : TextUtils.ellipsize(AndroidUtilities.replaceCharSequence("\n", stringFinalName, " "), Theme.chat_replyNamePaint, maxWidth, TextUtils.TruncateAt.END); try { - replyNameWidth = AndroidUtilities.dp(4) + (needReplyImage ? AndroidUtilities.dp(16) + (int) (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()) : 0); + replyNameWidth = AndroidUtilities.dp(4) + (needReplyImage ? AndroidUtilities.dp(16) + (int) (textPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()) : 0); if (stringFinalName != null) { replyNameLayout = new StaticLayout(stringFinalName, Theme.chat_replyNamePaint, maxWidth + AndroidUtilities.dp(6), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (replyNameLayout.getLineCount() > 0) { @@ -13249,11 +14058,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyNameOffset = (int) replyNameLayout.getLineLeft(0); } } + if (isReplyQuote && showQuote && replyQuoteDrawable != null) { + replyNameWidth += AndroidUtilities.dp(2 + 4 + (!drawPinnedTop ? 2 : 0)) + replyQuoteDrawable.getIntrinsicWidth(); + } else { + replyNameWidth += AndroidUtilities.dp(3); + } } catch (Exception e) { FileLog.e(e); } try { - replyTextWidth = AndroidUtilities.dp(4) + (needReplyImage ? AndroidUtilities.dp(16) + (int) (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()) : 0); + replyTextWidth = AndroidUtilities.dp(4) + (needReplyImage ? AndroidUtilities.dp(33) : 0); if (stringFinalText != null) { SpannableStringBuilder sb = new SpannableStringBuilder(stringFinalText); boolean changed = false; @@ -13263,15 +14077,53 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate sb.removeSpan(span); } } - stringFinalText = TextUtils.ellipsize(sb, Theme.chat_replyTextPaint, maxWidth, TextUtils.TruncateAt.END); + replyTextRTL = AndroidUtilities.isRTL(sb); + if (isReplyQuote) { + maxWidth += AndroidUtilities.dp(24); + } + if (isReplyQuote && needReplyImage && !replyTextRTL) { + sb.setSpan(new LeadingMarginSpan.Standard(AndroidUtilities.dp(35 + 3), 0), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + maxWidth += AndroidUtilities.dp(35); + replyTextWidth -= AndroidUtilities.dp(33); + } + if (!isReplyQuote || currentMessageObject.shouldDrawWithoutBackground() || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + stringFinalText = TextUtils.ellipsize(sb, textPaint, maxWidth, TextUtils.TruncateAt.END); + } else { + stringFinalText = sb; + } replyTextOffset = 0; - replyTextLayout = new StaticLayout(stringFinalText, Theme.chat_replyTextPaint, maxWidth + AndroidUtilities.dp(10), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + StaticLayout.Builder slb = StaticLayout.Builder.obtain(stringFinalText, 0, stringFinalText.length(), textPaint, maxWidth) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setIncludePad(false); + slb.setBreakStrategy(LineBreaker.BREAK_STRATEGY_SIMPLE); + if (isReplyQuote && !currentMessageObject.replyTextRevealed) { + slb + .setMaxLines(5) + .setEllipsize(TextUtils.TruncateAt.END); + } + replyTextLayout = slb.build(); + if (!currentMessageObject.replyTextRevealed) { + currentMessageObject.replyTextEllipsized = replyTextLayout.getLineCount() > 0 && replyTextLayout.getEllipsisCount(replyTextLayout.getLineCount() - 1) > 0; + } + } else { + replyTextLayout = new StaticLayout(stringFinalText, 0, stringFinalText.length(), textPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false, TextUtils.TruncateAt.END, maxWidth); + } + replyTextHeight = replyTextLayout.getHeight(); + if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO || messageObject.type == MessageObject.TYPE_EMOJIS) { + namesOffset += Math.max(0, replyTextHeight - AndroidUtilities.dp(3.66f) - Theme.chat_replyTextPaint.getTextSize()); + } if (replyTextLayout.getLineCount() > 0) { - replyTextWidth += (int) Math.ceil(replyTextLayout.getLineWidth(0)) + AndroidUtilities.dp(8); - replyTextOffset = (int) replyTextLayout.getLineLeft(0); + int width = 0; + replyTextOffset = replyTextLayout.getWidth(); + for (int i = 0; i < replyTextLayout.getLineCount(); ++i) { + width = Math.max(width, (int) Math.ceil(replyTextLayout.getLineWidth(i))); + replyTextOffset = Math.min(replyTextOffset, (int) Math.ceil(replyTextLayout.getLineLeft(i))); + } + replyTextWidth += width + AndroidUtilities.dp(18); } replySpoilers.clear(); - if (getMessageObject().replyMessageObject != null && !getMessageObject().replyMessageObject.isSpoilersRevealed) { + if (isReplyQuote || getMessageObject().replyMessageObject != null && !getMessageObject().replyMessageObject.isSpoilersRevealed) { SpoilerEffect.addSpoilers(this, replyTextLayout, replyTextOffset, replyTextOffset + replyTextWidth, replySpoilersPool, replySpoilers); } animatedEmojiReplyStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, false, animatedEmojiReplyStack, replyTextLayout); @@ -13286,7 +14138,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (!isThreadChat && messageObject.getReplyMsgId() != 0) { if (!(messageObject.replyMessageObject != null && (messageObject.replyMessageObject.messageOwner instanceof TLRPC.TL_messageEmpty || messageObject.replyMessageObject.messageOwner != null && messageObject.replyMessageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate))) { if (!messageObject.isAnyKindOfSticker() && messageObject.type != MessageObject.TYPE_ROUND_VIDEO) { - namesOffset += AndroidUtilities.dp(14) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); + namesOffset += AndroidUtilities.dp(14 + 4) + (Theme.chat_replyTextPaint.getTextSize() + Theme.chat_replyNamePaint.getTextSize()); if (messageObject.type != MessageObject.TYPE_TEXT) { namesOffset += AndroidUtilities.dp(5); } @@ -13328,6 +14180,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private boolean isNeedAuthorName() { + if (currentMessageObject.forceAvatar) { + return true; + } + if (currentMessageObject.isGiveaway()) { + return false; + } return ( isPinnedChat && currentMessageObject.type == MessageObject.TYPE_TEXT || !pinnedTop && drawName && isChat && (!currentMessageObject.isOutOwner() || currentMessageObject.isSupergroup() && currentMessageObject.isFromGroup()) || @@ -13479,6 +14337,52 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private Paint selectionOverlayPaint; + private void setupTextColors() { + if (currentMessageObject.isOutOwner()) { + Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgTextCodePaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgTextCode2Paint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgTextCode3Paint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); + Theme.chat_msgGameTextPaint.linkColor = + Theme.chat_replyTextPaint.linkColor = + Theme.chat_quoteTextPaint.linkColor = + Theme.chat_msgTextPaint.linkColor = + Theme.chat_msgTextCodePaint.linkColor = + Theme.chat_msgTextCode2Paint.linkColor = + Theme.chat_msgTextCode3Paint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); +// } else if (currentMessageObject.overrideLinkColor >= 0 || currentMessageObject.isFromUser() && currentUser != null || currentMessageObject.isFromChannel() && currentChat != null) { +// int color; +// if (currentMessageObject.overrideLinkColor >= 0) { +// color = currentMessageObject.overrideLinkColor; +// } else if (currentMessageObject.isFromUser() && currentUser != null) { +// color = currentUser.color; +// } else { +// color = currentChat.color; +// } +// int hueColor = Theme.isCurrentThemeDark() ? AvatarDrawable.getNameColorKey2For(color) : AvatarDrawable.getNameColorKey1For(color); +// Theme.chat_msgTextPaint.setColor(Theme.adaptHue(getThemedColor(Theme.key_chat_messageTextIn), hueColor)); +// Theme.chat_msgGameTextPaint.setColor(Theme.adaptHue(getThemedColor(Theme.key_chat_messageTextIn), hueColor)); +// Theme.chat_msgGameTextPaint.linkColor = +// Theme.chat_replyTextPaint.linkColor = +// Theme.chat_quoteTextPaint.linkColor = +// Theme.chat_msgTextPaint.linkColor = Theme.adaptHue(getThemedColor(Theme.key_chat_messageLinkIn), hueColor); + } else { + Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgTextCodePaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgTextCode2Paint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgTextCode3Paint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); + Theme.chat_msgGameTextPaint.linkColor = + Theme.chat_replyTextPaint.linkColor = + Theme.chat_quoteTextPaint.linkColor = + Theme.chat_msgTextPaint.linkColor = + Theme.chat_msgTextCodePaint.linkColor = + Theme.chat_msgTextCode2Paint.linkColor = + Theme.chat_msgTextCode3Paint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); + } + } + @SuppressLint("WrongCall") @Override protected void onDraw(Canvas canvas) { @@ -13492,25 +14396,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return; } - if (currentMessageObject.isOutOwner()) { - Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); - Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); - Theme.chat_msgGameTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); - Theme.chat_replyTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); - Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); - } else { - Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); - Theme.chat_msgGameTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); - Theme.chat_msgGameTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); - Theme.chat_replyTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); - Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); - } + setupTextColors(); if (documentAttach != null) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) { if (currentMessageObject.isOutOwner()) { seekBarWaveform.setColors(getThemedColor(Theme.key_chat_outVoiceSeekbar), getThemedColor(Theme.key_chat_outVoiceSeekbarFill), getThemedColor(Theme.key_chat_outVoiceSeekbarSelected)); seekBar.setColors(getThemedColor(Theme.key_chat_outAudioSeekbar), getThemedColor(Theme.key_chat_outAudioCacheSeekbar), getThemedColor(Theme.key_chat_outAudioSeekbarFill), getThemedColor(Theme.key_chat_outAudioSeekbarFill), getThemedColor(Theme.key_chat_outAudioSeekbarSelected)); + } else if (hasLinkPreview && linkLine != null) { + seekBarWaveform.setColors(Theme.adaptHue(getThemedColor(Theme.key_chat_inVoiceSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inVoiceSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inVoiceSeekbarSelected), linkLine.getColor())); + seekBar.setColors(Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioCacheSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarSelected), linkLine.getColor())); } else { seekBarWaveform.setColors(getThemedColor(Theme.key_chat_inVoiceSeekbar), getThemedColor(Theme.key_chat_inVoiceSeekbarFill), getThemedColor(Theme.key_chat_inVoiceSeekbarSelected)); seekBar.setColors(getThemedColor(Theme.key_chat_inAudioSeekbar), getThemedColor(Theme.key_chat_inAudioCacheSeekbar), getThemedColor(Theme.key_chat_inAudioSeekbarFill), getThemedColor(Theme.key_chat_inAudioSeekbarFill), getThemedColor(Theme.key_chat_inAudioSeekbarSelected)); @@ -13518,6 +14413,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { if (currentMessageObject.isOutOwner()) { seekBar.setColors(getThemedColor(Theme.key_chat_outAudioSeekbar), getThemedColor(Theme.key_chat_outAudioCacheSeekbar), getThemedColor(Theme.key_chat_outAudioSeekbarFill), getThemedColor(Theme.key_chat_outAudioSeekbarFill), getThemedColor(Theme.key_chat_outAudioSeekbarSelected)); + } else if (hasLinkPreview && linkLine != null) { + seekBar.setColors(Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioCacheSeekbar), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarFill), linkLine.getColor()), Theme.adaptHue(getThemedColor(Theme.key_chat_inAudioSeekbarSelected), linkLine.getColor())); } else { seekBar.setColors(getThemedColor(Theme.key_chat_inAudioSeekbar), getThemedColor(Theme.key_chat_inAudioCacheSeekbar), getThemedColor(Theme.key_chat_inAudioSeekbarFill), getThemedColor(Theme.key_chat_inAudioSeekbarFill), getThemedColor(Theme.key_chat_inAudioSeekbarSelected)); } @@ -13562,6 +14459,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (highlightProgress <= 0) { highlightProgress = 0; isHighlightedAnimated = false; + if (highlightedQuote) { + resetUrlPaths(); + } + highlightedQuote = false; } invalidate(); if (getParent() != null) { @@ -13609,7 +14510,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ); clipContent = true; } - drawContent(canvas); + drawContent(canvas, false); if (expiredStoryView != null && expiredStoryView.visible) { expiredStoryView.draw(canvas, this); @@ -13624,7 +14525,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (replyNameLayout != null) { - replyHeight = AndroidUtilities.dp(7) + Theme.chat_replyNamePaint.getTextSize() + Theme.chat_replyTextPaint.getTextSize(); + float replyTextHeight = this.replyTextHeight; + if (transitionParams != null && transitionParams.animateReplyTextLayout != null) { + replyTextHeight = AndroidUtilities.lerp(transitionParams.animateFromReplyTextHeight, replyTextHeight, transitionParams.animateChangeProgress); + } + replyHeight = AndroidUtilities.dp(9) + Theme.chat_replyNamePaint.getTextSize() + Math.max(replyTextHeight - AndroidUtilities.dp(3.66f), Theme.chat_replyTextPaint.getTextSize()); if (currentMessageObject.shouldDrawWithoutBackground() && currentMessageObject.type != MessageObject.TYPE_EMOJIS) { if (currentMessageObject.isOutOwner()) { replyStartX = AndroidUtilities.dp(23); @@ -13667,12 +14572,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate replyStartY += topicButton.height() + AndroidUtilities.dp(5); } } + replyStartY += AndroidUtilities.dp(.66f); } if (currentPosition == null && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInProgress && !currentMessageObject.isVoice())) { drawNamesLayout(canvas, 1f); } - if ((!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject) || isRoundVideo) && !transitionParams.animateBackgroundBoundsInner) { + if ((!autoPlayingMedia || !MediaController.getInstance().isPlayingMessageAndReadyToDraw(currentMessageObject) || isRoundVideo) && !transitionParams.animateBackgroundBoundsInner && !(currentMessageObject != null && currentMessageObject.preview)) { drawOverlays(canvas); } if ((drawTime || !mediaBackground) && !forceNotDrawTime && !transitionParams.animateBackgroundBoundsInner && !(enterTransitionInProgress && !currentMessageObject.isVoice())) { @@ -13837,7 +14743,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundShadowDrawable = currentBackgroundDrawable.getShadowDrawable(); } - backgroundDrawableLeft = AndroidUtilities.dp((isChat && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); + backgroundDrawableLeft = AndroidUtilities.dp(((isChat || currentMessageObject != null && currentMessageObject.forceAvatar) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); backgroundDrawableRight = backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(3)); if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (!currentPosition.edge) { @@ -13999,7 +14905,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundSelectedDrawable.setAlpha((int) (alphaInternal * currentSelectedBackgroundAlpha * 255)); currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams); } - } else if (selectedBackgroundProgress != 0 && !(currentMessagesGroup != null && currentMessagesGroup.isDocuments)) { + } else if (selectedBackgroundProgress != 0 && (currentMessageObject == null || !currentMessageObject.preview) && !(currentMessagesGroup != null && currentMessagesGroup.isDocuments)) { currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); currentSelectedBackgroundAlpha = selectedBackgroundProgress; @@ -14009,7 +14915,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundShadowDrawable = null; } } else { - if (isDrawSelectionBackground() && (currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument() || getBackground() != null)) { + if (isDrawSelectionBackground() && quoteHighlight == null && (currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument() || getBackground() != null)) { if (currentPosition != null) { canvas.save(); canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); @@ -14092,7 +14998,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } Interpolator interpolator = checkBoxVisible ? CubicBezierInterpolator.EASE_OUT : CubicBezierInterpolator.EASE_IN; checkBoxTranslation = (int) Math.ceil(interpolator.getInterpolation(checkBoxAnimationProgress) * AndroidUtilities.dp(35)); - if (!currentMessageObject.isOutOwner()) { + if (!currentMessageObject.isOutOwner() || currentMessageObject.hasWideCode) { updateTranslation(); } @@ -14238,28 +15144,46 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { nameX = backgroundDrawableLeft + transitionParams.deltaLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17) + getExtraTextX(); } - if (currentUser != null) { + if (currentMessageObject.isOutOwner() && ChatObject.isChannel(currentChat)) { if (currentBackgroundDrawable != null && currentBackgroundDrawable.hasGradient()) { color = getThemedColor(Theme.key_chat_messageTextOut); } else { - color = getThemedColor(AvatarDrawable.getNameColorNameForId(currentUser.id)); - } - } else if (currentChat != null) { - if (currentMessageObject.isOutOwner() && ChatObject.isChannel(currentChat)) { - if (currentBackgroundDrawable != null && currentBackgroundDrawable.hasGradient()) { - color = getThemedColor(Theme.key_chat_messageTextOut); - } else { - color = getThemedColor(Theme.key_chat_outForwardedNameText); - } - } else if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - color = Theme.changeColorAccent(getThemedColor(AvatarDrawable.getNameColorNameForId(5))); - } else if (currentMessageObject.isOutOwner()) { color = getThemedColor(Theme.key_chat_outForwardedNameText); + } + } else if (currentMessageObject.isOutOwner()) { + color = getThemedColor(Theme.key_chat_outForwardedNameText); + } else if ( + currentMessageObject.overrideLinkColor >= 0 || + currentMessageObject.isFromUser() && currentUser != null || + currentMessageObject.isFromChannel() && currentChat != null || + currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || + currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + ) { + int colorId; + if (currentMessageObject.overrideLinkColor >= 0) { + colorId = currentMessageObject.overrideLinkColor; + } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { + colorId = currentMessageObject.sponsoredChatInvite.color; + } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { + colorId = (currentMessageObject.sponsoredChatInvite.chat.flags2 & 64) != 0 ? currentMessageObject.sponsoredChatInvite.chat.color : (int) (currentMessageObject.sponsoredChatInvite.chat.id % 7); + } else if (currentMessageObject.isFromUser() && currentUser != null) { + colorId = (currentUser.flags2 & 128) != 0 ? currentUser.color : (int) (currentUser.id % 7); } else { - color = getThemedColor(AvatarDrawable.getNameColorNameForId(currentChat.id)); + colorId = (currentChat.flags2 & 64) != 0 ? currentChat.color : (int) (currentChat.id % 7); + } + if (colorId < 7) { + color = getThemedColor(Theme.keys_avatar_nameInMessage[colorId]); + } else { + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null; + if (peerColor != null) { + color = peerColor.getColor1(); + } else { + color = getThemedColor(Theme.key_chat_inForwardedNameText); + } } } else { - color = getThemedColor(AvatarDrawable.getNameColorNameForId(0)); + color = getThemedColor(Theme.key_chat_inForwardedNameText); } nameY = AndroidUtilities.dp(drawPinnedTop ? 9 : 10); } @@ -14323,12 +15247,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public void drawAnimatedEmojis(Canvas canvas, float alpha) { drawAnimatedEmojiMessageText(canvas, alpha); -// if (shouldDrawCaptionLayout()) { -// drawAnimatedEmojiCaption(canvas, 1f); -// } + if (shouldDrawCaptionLayout()) { + drawAnimatedEmojiCaption(canvas, alpha); + } } private void drawAnimatedEmojiMessageText(Canvas canvas, float alpha) { + float textY = this.textY; + if (transitionParams.animateText) { + textY = transitionParams.animateFromTextY * (1f - transitionParams.animateChangeProgress) + this.textY * transitionParams.animateChangeProgress; + } if (transitionParams.animateChangeProgress != 1.0f && transitionParams.animateMessageText) { canvas.save(); if (currentBackgroundDrawable != null) { @@ -14345,21 +15273,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ); } } - drawAnimatedEmojiMessageText(canvas, transitionParams.animateOutTextBlocks, transitionParams.animateOutAnimateEmoji, false, alpha * (1.0f - transitionParams.animateChangeProgress)); - drawAnimatedEmojiMessageText(canvas, currentMessageObject.textLayoutBlocks, animatedEmojiStack, true, alpha * transitionParams.animateChangeProgress); + drawAnimatedEmojiMessageText(textX, textY, canvas, transitionParams.animateOutTextBlocks, transitionParams.animateOutAnimateEmoji, false, alpha * (1.0f - transitionParams.animateChangeProgress), currentMessageObject.textXOffset, false); + drawAnimatedEmojiMessageText(textX, textY, canvas, currentMessageObject.textLayoutBlocks, animatedEmojiStack, true, alpha * transitionParams.animateChangeProgress, currentMessageObject.textXOffset, false); canvas.restore(); } else { - drawAnimatedEmojiMessageText(canvas, currentMessageObject.textLayoutBlocks, animatedEmojiStack, true, alpha); + drawAnimatedEmojiMessageText(textX, textY, canvas, currentMessageObject.textLayoutBlocks, animatedEmojiStack, true, alpha, currentMessageObject.textXOffset, false); } } - private void drawAnimatedEmojiMessageText(Canvas canvas, ArrayList textLayoutBlocks, AnimatedEmojiSpan.EmojiGroupedSpans stack, boolean origin, float alpha) { + private void drawAnimatedEmojiMessageText(float textX, float textY, Canvas canvas, ArrayList textLayoutBlocks, AnimatedEmojiSpan.EmojiGroupedSpans stack, boolean origin, float alpha, float rtlOffset, boolean drawAllBlocks) { if (textLayoutBlocks == null || textLayoutBlocks.isEmpty() || alpha == 0) { return; } int firstVisibleBlockNum; int lastVisibleBlockNum; - if (origin) { + if (origin && !drawAllBlocks) { if (fullyDraw) { this.firstVisibleBlockNum = 0; this.lastVisibleBlockNum = textLayoutBlocks.size(); @@ -14371,10 +15299,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastVisibleBlockNum = textLayoutBlocks.size(); } - float textY = this.textY; - if (transitionParams.animateText) { - textY = transitionParams.animateFromTextY * (1f - transitionParams.animateChangeProgress) + this.textY * transitionParams.animateChangeProgress; - } for (int a = firstVisibleBlockNum; a <= lastVisibleBlockNum; a++) { if (a >= textLayoutBlocks.size()) { break; @@ -14384,37 +15308,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } MessageObject.TextLayoutBlock block = textLayoutBlocks.get(a); canvas.save(); - canvas.translate(textX - (block.isRtl() ? (int) Math.ceil(currentMessageObject.textXOffset) : 0), textY + block.textYOffset + transitionYOffsetForDrawables); + canvas.translate(textX - (block.isRtl() ? (int) Math.ceil(rtlOffset) : 0), textY + block.padTop + block.textYOffset + transitionYOffsetForDrawables); float drawingYOffset = textY + block.textYOffset + transitionYOffsetForDrawables; float top = 0; // parentBoundsTop - getY() - drawingYOffset + AndroidUtilities.dp(20); float bottom = 0; // parentBoundsBottom - getY() - drawingYOffset - AndroidUtilities.dp(20); if (transitionParams.messageEntering) { top = bottom = 0; } - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, block.textLayout, stack, 0, block.spoilers, top, bottom, drawingYOffset, alpha, Theme.chat_animatedEmojiTextColorFilter); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, block.textLayout, stack, 0, block.spoilers, top, bottom, drawingYOffset, alpha, currentMessageObject.isOutOwner() ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); canvas.restore(); } } public void drawAnimatedEmojiCaption(Canvas canvas, float alpha) { - if (transitionParams.animateReplaceCaptionLayout && transitionParams.animateChangeProgress != 1f) { - drawAnimatedEmojiCaption(canvas, transitionParams.animateOutCaptionLayout, transitionParams.animateOutAnimateEmoji, alpha * (1f - transitionParams.animateChangeProgress)); - drawAnimatedEmojiCaption(canvas, captionLayout, animatedEmojiStack, alpha * transitionParams.animateChangeProgress); - } else { - drawAnimatedEmojiCaption(canvas, captionLayout, animatedEmojiStack, alpha); - } - } - - private void drawAnimatedEmojiCaption(Canvas canvas, Layout layout, AnimatedEmojiSpan.EmojiGroupedSpans stack, float alpha) { - if (layout == null || currentMessageObject.deleted && currentPosition != null || alpha <= 0) { - return; - } - canvas.save(); - float renderingAlpha = alpha; - if (currentMessagesGroup != null) { - renderingAlpha = currentMessagesGroup.transitionParams.captionEnterProgress * alpha; - } - if (renderingAlpha == 0) { + if (captionLayout == null) { return; } @@ -14432,14 +15339,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate captionX += transitionParams.deltaLeft; } } - - canvas.translate(captionX, captionY); - try { - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, layout, stack, 0, captionSpoilers, 0, 0, captionY, renderingAlpha, Theme.chat_animatedEmojiTextColorFilter); - } catch (Exception e) { - FileLog.e(e); + if (transitionParams.animateReplaceCaptionLayout && transitionParams.animateChangeProgress != 1f) { + drawAnimatedEmojiMessageText(captionX, captionY, canvas, transitionParams.animateOutCaptionLayout != null ? transitionParams.animateOutCaptionLayout.textLayoutBlocks : null, transitionParams.animateOutAnimateEmoji, false, alpha * (1f - transitionParams.animateChangeProgress), transitionParams.animateOutCaptionLayout != null ? transitionParams.animateOutCaptionLayout.textXOffset : 0, true); + drawAnimatedEmojiMessageText(captionX, captionY, canvas, captionLayout != null ? captionLayout.textLayoutBlocks : null, animatedEmojiStack, true, alpha * transitionParams.animateChangeProgress, captionLayout != null ? captionLayout.textXOffset : 0, true); + } else { + drawAnimatedEmojiMessageText(captionX, captionY, canvas, captionLayout != null ? captionLayout.textLayoutBlocks : null, animatedEmojiStack, true, alpha, captionLayout != null ? captionLayout.textXOffset : 0, true); } - canvas.restore(); } private void drawSideButton(Canvas canvas) { @@ -14509,9 +15414,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.restore(); } } else { - + final int scx = (int) (sideStartX + AndroidUtilities.dp(16)), scy = (int) (sideStartY + AndroidUtilities.dp(16)); Drawable drawable = getThemedDrawable(Theme.key_drawable_shareIcon); - setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(8), sideStartY + AndroidUtilities.dp(9)); + final int shw = (int) (drawable.getIntrinsicWidth() / 2 * .95f), shh = (int) (drawable.getIntrinsicHeight() / 2 * .95f); + drawable.setBounds(scx - shw, scy - shh, scx + shw, scy + shh); + setDrawableBounds(drawable, sideStartX + AndroidUtilities.dp(4), sideStartY + AndroidUtilities.dp(4)); drawable.draw(canvas); } } @@ -14535,10 +15442,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { int r; if (isRoundVideo) { - r = AndroidUtilities.dp((isChat && isAvatarVisible ? 48 : 0) + 3); + r = AndroidUtilities.dp(((isChat || currentMessageObject != null && currentMessageObject.forceAvatar) && isAvatarVisible ? 48 : 0) + 3); r += (int) (AndroidUtilities.dp(6) * (1f - getVideoTranscriptionProgress())); } else { - r = AndroidUtilities.dp((isChat && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); + r = AndroidUtilities.dp(((isChat || currentMessageObject != null && currentMessageObject.forceAvatar) && isAvatarVisible ? 48 : 0) + (!mediaBackground ? 3 : 9)); } if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { if (currentPosition.leftSpanOffset != 0) { @@ -14767,28 +15674,46 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { nameX = backgroundDrawableLeft + transitionParams.deltaLeft + AndroidUtilities.dp(!mediaBackground && drawPinnedBottom ? 11 : 17) - nameOffsetX + getExtraTextX(); } - if (currentUser != null) { + if (currentMessageObject.isOutOwner() && ChatObject.isChannel(currentChat)) { if (currentBackgroundDrawable != null && currentBackgroundDrawable.hasGradient()) { Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); } else { - Theme.chat_namePaint.setColor(getThemedColor(AvatarDrawable.getNameColorNameForId(currentUser.id))); - } - } else if (currentChat != null) { - if (currentMessageObject.isOutOwner() && ChatObject.isChannel(currentChat)) { - if (currentBackgroundDrawable != null && currentBackgroundDrawable.hasGradient()) { - Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); - } else { - Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_outForwardedNameText)); - } - } else if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - Theme.chat_namePaint.setColor(Theme.changeColorAccent(getThemedColor(AvatarDrawable.getNameColorNameForId(5)))); - } else if (currentMessageObject.isOutOwner()) { Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_outForwardedNameText)); + } + } else if (currentMessageObject.isOutOwner()) { + Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_outForwardedNameText)); + } else if ( + currentMessageObject.overrideLinkColor >= 0 || + currentMessageObject.isFromUser() && currentUser != null || + currentMessageObject.isFromChannel() && currentChat != null || + currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || + currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null + ) { + int colorId; + if (currentMessageObject.overrideLinkColor >= 0) { + colorId = currentMessageObject.overrideLinkColor; + } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { + colorId = currentMessageObject.sponsoredChatInvite.color; + } else if (currentMessageObject.isSponsored() && currentMessageObject.sponsoredChatInvite != null && currentMessageObject.sponsoredChatInvite.chat != null) { + colorId = (currentMessageObject.sponsoredChatInvite.chat.flags2 & 64) != 0 ? currentMessageObject.sponsoredChatInvite.chat.color : (int) (currentMessageObject.sponsoredChatInvite.chat.id % 7); + } else if (currentMessageObject.isFromUser() && currentUser != null) { + colorId = (currentUser.flags2 & 128) != 0 ? currentUser.color : (int) (currentUser.id % 7); } else { - Theme.chat_namePaint.setColor(getThemedColor(AvatarDrawable.getNameColorNameForId(currentChat.id))); + colorId = (currentChat.flags2 & 64) != 0 ? currentChat.color : (int) (currentChat.id % 7); + } + if (colorId < 7) { + Theme.chat_namePaint.setColor(getThemedColor(Theme.keys_avatar_nameInMessage[colorId])); + } else { + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null; + if (peerColor != null) { + Theme.chat_namePaint.setColor(peerColor.getColor1()); + } else { + Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_inForwardedNameText)); + } } } else { - Theme.chat_namePaint.setColor(getThemedColor(AvatarDrawable.getNameColorNameForId(0))); + Theme.chat_namePaint.setColor(getThemedColor(Theme.key_chat_inForwardedNameText)); } nameY = AndroidUtilities.dp(drawPinnedTop ? 9 : 10); if (viaSpan1 != null || viaSpan2 != null) { @@ -14816,6 +15741,41 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.translate(nx, nameY); nameLayout.draw(canvas); canvas.restore(); + float end; + if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { + int dWidth = getGroupPhotosWidth(); + int firstLineWidth = 0; + for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { + MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a); + if (position.minY == 0) { + firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); + } else { + break; + } + } + if (!mediaBackground && currentMessageObject.isOutOwner()) { + end = backgroundDrawableLeft + firstLineWidth - AndroidUtilities.dp(6); + } else { + end = backgroundDrawableLeft + firstLineWidth; + } + end -= getExtraTextX() + AndroidUtilities.dp(8); + if (!currentMessageObject.isOutOwner()) { + end -= AndroidUtilities.dp(48); + } + } else { + if (currentMessageObject.shouldDrawWithoutBackground()) { + if (currentMessageObject.isOutOwner()) { + end = AndroidUtilities.dp(28 + 11) + nameWidth; + } else { + end = backgroundDrawableLeft + transitionParams.deltaLeft + backgroundDrawableRight + AndroidUtilities.dp(33) + nameWidth; + } + } else if (!mediaBackground && currentMessageObject.isOutOwner()) { + end = backgroundDrawableLeft + backgroundDrawableRight - AndroidUtilities.dp(6); + } else { + end = backgroundDrawableLeft + backgroundDrawableRight; + } + } + end += transitionParams.deltaRight; if (adminLayout != null) { int color; if (currentMessageObject.shouldDrawWithoutBackground()) { @@ -14827,47 +15787,45 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } Theme.chat_adminPaint.setColor(color); canvas.save(); - float ax; - if (currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { - int dWidth = getGroupPhotosWidth(); - int firstLineWidth = 0; - for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { - MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a); - if (position.minY == 0) { - firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); - } else { - break; - } - } - if (!mediaBackground && currentMessageObject.isOutOwner()) { - ax = backgroundDrawableLeft + firstLineWidth - AndroidUtilities.dp(17) - adminLayout.getLineWidth(0); - } else { - ax = backgroundDrawableLeft + firstLineWidth - AndroidUtilities.dp(11) - adminLayout.getLineWidth(0); - } - ax -= getExtraTextX() + AndroidUtilities.dp(8); - if (!currentMessageObject.isOutOwner()) { - ax -= AndroidUtilities.dp(48); - } - } else { - if (currentMessageObject.shouldDrawWithoutBackground()) { - if (currentMessageObject.isOutOwner()) { - ax = AndroidUtilities.dp(28) + nameWidth - adminLayout.getLineWidth(0); - } else { - ax = backgroundDrawableLeft + transitionParams.deltaLeft + backgroundDrawableRight + AndroidUtilities.dp(22) + nameWidth - adminLayout.getLineWidth(0); - } - } else if (!mediaBackground && currentMessageObject.isOutOwner()) { - ax = backgroundDrawableLeft + backgroundDrawableRight - AndroidUtilities.dp(17) - adminLayout.getLineWidth(0); - } else { - ax = backgroundDrawableLeft + backgroundDrawableRight - AndroidUtilities.dp(11) - adminLayout.getLineWidth(0); - } - } - ax += transitionParams.deltaRight; + final float ax = end - AndroidUtilities.dp(11) - adminLayout.getLineWidth(0); canvas.translate(ax, nameY + AndroidUtilities.dp(0.5f)); if (transitionParams.animateSign) { Theme.chat_adminPaint.setAlpha((int) (Color.alpha(color) * transitionParams.animateChangeProgress)); } adminLayout.draw(canvas); canvas.restore(); + } else if (currentMessageObject.isSponsored()) { + if (closeSponsoredBounce == null) { + closeSponsoredBounce = new ButtonBounce(this); + } + if (closeSponsoredPaint == null) { + closeSponsoredPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + if (closeSponsoredPath == null) { + closeSponsoredPath = new Path(); + closeSponsoredPaint.setStrokeCap(Paint.Cap.ROUND); + closeSponsoredPaint.setStyle(Paint.Style.STROKE); + } else { + closeSponsoredPath.rewind(); + } + if (closeSponsoredBounds == null) { + closeSponsoredBounds = new RectF(); + } + closeSponsoredPath.moveTo(0, 0); + closeSponsoredPath.lineTo(dp(8), dp(8)); + closeSponsoredPath.moveTo(0, dp(8)); + closeSponsoredPath.lineTo(dp(8), 0); + closeSponsoredPaint.setStrokeWidth(AndroidUtilities.dpf2(1.33f)); + closeSponsoredPaint.setColor(Theme.multAlpha(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), .28f)); + canvas.save(); + closeSponsoredBounds.set(0, 0, dp(8), dp(8)); + closeSponsoredBounds.inset(-dp(16), -dp(16)); + closeSponsoredBounds.offset(end - AndroidUtilities.dp(22), nameY + AndroidUtilities.dp(5)); + canvas.translate(end - AndroidUtilities.dp(22), nameY + AndroidUtilities.dp(5)); + final float s = closeSponsoredBounce.getScale(.09f); + canvas.scale(s, s, dp(4), dp(4)); + canvas.drawPath(closeSponsoredPath, closeSponsoredPaint); + canvas.restore(); } } @@ -14888,6 +15846,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } float forwardNameXLocal; + int forwardNameRight = -1; boolean needDrawReplyBackground = true; if (drawForwardedNameLocal && forwardedNameLayoutLocal[0] != null && forwardedNameLayoutLocal[1] != null && (currentPosition == null || currentPosition.minY == 0 && currentPosition.minX == 0)) { if (currentMessageObject.type == MessageObject.TYPE_ROUND_VIDEO || currentMessageObject.isAnyKindOfSticker()) { @@ -14929,7 +15888,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (hasReply) { needDrawReplyBackground = false; int replyBackWidth = Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(14); - rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameXLocal - AndroidUtilities.dp(7) + Math.max(backWidth, replyBackWidth), forwardNameY + forwardHeight + AndroidUtilities.dp(6) + AndroidUtilities.dp(41)); + 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)); } else { rect.set((int) forwardNameXLocal - AndroidUtilities.dp(7), forwardNameY - AndroidUtilities.dp(6), (int) forwardNameXLocal - AndroidUtilities.dp(7) + backWidth, forwardNameY + forwardHeight + AndroidUtilities.dp(6)); } @@ -15092,7 +16051,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { replyStartX += transitionParams.deltaLeft; } - replyStartY = this.replyStartY * transitionParams.animateChangeProgress + transitionParams.animateFromReplyY * (1f - transitionParams.animateChangeProgress); + replyStartY = AndroidUtilities.lerp(transitionParams.animateFromReplyY, this.replyStartY, transitionParams.animateChangeProgress); } final boolean loading = currentMessageObject != null && delegate != null && delegate.isProgressLoading(this, ChatActivity.PROGRESS_REPLY); if (replyPressedFloat == null) { @@ -15100,7 +16059,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } float replyPressedT = replyPressedFloat.set(replySelectorPressed || loading ? 1f : 0f); - int rippleColor = getThemedColor(Theme.key_listSelector); + if (replyLine == null) { + replyLine = new ReplyMessageLine(this); + } + Theme.chat_replyNamePaint.setColor(replyLine.check(currentMessageObject, currentUser, currentChat, resourcesProvider, true)); + + int rippleColor = ColorUtils.setAlphaComponent(replyLine.getColor(), 0x1e); if (currentMessageObject.shouldDrawWithoutBackground()) { Theme.chat_replyLinePaint.setColor(getThemedColor(Theme.key_chat_stickerReplyLine)); int oldAlpha = Theme.chat_replyLinePaint.getAlpha(); @@ -15113,56 +16077,57 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate oldAlpha = Theme.chat_replyTextPaint.getAlpha(); Theme.chat_replyTextPaint.setAlpha((int) (oldAlpha * timeAlpha * replyForwardAlpha)); if (needDrawReplyBackground) { - int backWidth = Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(14); - rect.set((int) replyStartX - AndroidUtilities.dp(7), replyStartY - AndroidUtilities.dp(6), (int) replyStartX - AndroidUtilities.dp(7) + backWidth, replyStartY + AndroidUtilities.dp(6) + replyHeight); + if (replyBounce == null) { + replyBounce = new ButtonBounce(this, 2.0f, 2.0f); + } + canvas.save(); + final float s = replyBounce.getScale(0.0125f); + int backWidth = Math.max(replyNameWidth, replyTextWidth); + rect.set((int) replyStartX - AndroidUtilities.dp(7), replyStartY - AndroidUtilities.dp(3), (int) replyStartX - AndroidUtilities.dp(4) + backWidth, replyStartY + AndroidUtilities.dp(3) + replyHeight); + canvas.scale(s, s, Utilities.clamp(replyBounceX, rect.right, rect.left), Utilities.clamp(replyBounceY, rect.bottom, rect.top)); applyServiceShaderMatrix(); oldAlpha = getThemedPaint(Theme.key_paint_chatActionBackground).getAlpha(); getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha((int) (oldAlpha * timeAlpha * replyForwardAlpha)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), getThemedPaint(Theme.key_paint_chatActionBackground)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), getThemedPaint(Theme.key_paint_chatActionBackground)); getThemedPaint(Theme.key_paint_chatActionBackground).setAlpha(oldAlpha); if (hasGradientService()) { oldAlpha = Theme.chat_actionBackgroundGradientDarkenPaint.getAlpha(); Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha((int) (oldAlpha * timeAlpha * replyForwardAlpha)); - canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_actionBackgroundGradientDarkenPaint); + canvas.drawRoundRect(rect, AndroidUtilities.dp(4), AndroidUtilities.dp(4), Theme.chat_actionBackgroundGradientDarkenPaint); Theme.chat_actionBackgroundGradientDarkenPaint.setAlpha(oldAlpha); } + canvas.restore(); } } else { if (currentMessageObject.isOutOwner()) { - Theme.chat_replyLinePaint.setColor(getThemedColor(Theme.key_chat_outReplyLine)); - Theme.chat_replyNamePaint.setColor(getThemedColor(Theme.key_chat_outReplyNameText)); - rippleColor = ColorUtils.setAlphaComponent(getThemedColor(Theme.key_chat_outReplyLine), 0x1e); if (currentMessageObject.isReplyToStory()) { Theme.chat_replyTextPaint.setColor(Theme.chat_replyNamePaint.getColor()); - } else if (currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice)) { - Theme.chat_replyTextPaint.setColor(getThemedColor(Theme.key_chat_outReplyMessageText)); } else { - int color = getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outReplyMediaMessageSelectedText : Theme.key_chat_outReplyMediaMessageText); - Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(color, Theme.adaptHue(color, Theme.chat_replyNamePaint.getColor()), replyPressedT)); + float blendPressed = replyPressedT; + int color = getThemedColor(Theme.key_chat_outReplyMessageText); + if (!currentMessageObject.forceAvatar && !(currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) || isReplyQuote)) { + color = getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_outReplyMediaMessageSelectedText : Theme.key_chat_outReplyMediaMessageText); + blendPressed = .6f + (blendPressed * .4f); + } + Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(color, Theme.adaptHue(color, Theme.chat_replyNamePaint.getColor()), blendPressed)); } } else { - if (currentReplyUserId == 0) { - Theme.chat_replyLinePaint.setColor(getThemedColor(Theme.key_chat_inReplyLine)); - Theme.chat_replyNamePaint.setColor(getThemedColor(Theme.key_chat_inReplyNameText)); - rippleColor = ColorUtils.setAlphaComponent(getThemedColor(Theme.key_chat_inReplyLine), 0x1e); - } else { - Theme.chat_replyLinePaint.setColor(getThemedColor(AvatarDrawable.getNameColorNameForId(currentReplyUserId))); - Theme.chat_replyLinePaint.setAlpha((int) (Theme.chat_replyLinePaint.getAlpha() * .9f)); - Theme.chat_replyNamePaint.setColor(getThemedColor(AvatarDrawable.getNameColorNameForId(currentReplyUserId))); - rippleColor = ColorUtils.setAlphaComponent(getThemedColor(AvatarDrawable.getNameColorNameForId(currentReplyUserId)), 0x1e); - } if (currentMessageObject.isReplyToStory()) { Theme.chat_replyTextPaint.setColor(Theme.chat_replyNamePaint.getColor()); - } else if (currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice)) { - Theme.chat_replyTextPaint.setColor(getThemedColor(Theme.key_chat_inReplyMessageText)); } else { - int color = getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inReplyMediaMessageSelectedText : Theme.key_chat_inReplyMediaMessageText); - Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(color, Theme.adaptHue(color, Theme.chat_replyNamePaint.getColor()), replyPressedT)); + float blendPressed = replyPressedT; + int color = getThemedColor(Theme.key_chat_inReplyMessageText); + if (!currentMessageObject.forceAvatar && !(currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) || isReplyQuote)) { + color = getThemedColor(isDrawSelectionBackground() ? Theme.key_chat_inReplyMediaMessageSelectedText : Theme.key_chat_inReplyMediaMessageText); + blendPressed = .6f + (blendPressed * .4f); + } + Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(color, Theme.adaptHue(color, Theme.chat_replyNamePaint.getColor()), blendPressed)); } } } - int offset = (int) Math.min(AndroidUtilities.dp(10), (replyHeight - AndroidUtilities.dp(35)) / 1.5f + AndroidUtilities.dp(10)); - forwardNameX = replyStartX - replyTextOffset + offset + (needReplyImage ? offset - AndroidUtilities.dp(1) + replyHeight : 0); + Theme.chat_quoteTextPaint.setColor(Theme.chat_replyTextPaint.getColor()); + int offset = AndroidUtilities.dp(10); + forwardNameX = replyStartX - replyTextOffset + offset + (needReplyImage ? offset + AndroidUtilities.dp(25) : 0); if ((currentPosition == null || currentPosition.minY == 0 && currentPosition.minX == 0) && !(enterTransitionInProgress && !currentMessageObject.isVoice())) { int restoreToCount = -1; if (getAlpha() * replyForwardAlpha != 1f) { @@ -15170,120 +16135,105 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate restoreToCount = canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (0xFF * getAlpha() * replyForwardAlpha), Canvas.ALL_SAVE_FLAG); } - float leftRad, rightRad, bottomRad = Math.min(6.75f, SharedConfig.bubbleRadius); + float leftRad, rightRad, bottomRad = Math.min(4f, SharedConfig.bubbleRadius); if (currentMessageObject.shouldDrawWithoutBackground()) { - leftRad = rightRad = bottomRad = 9; + rightRad = bottomRad = needDrawReplyBackground ? 6 : 4; replySelectorRect.set( - (int) (replyStartX - AndroidUtilities.dp(7)), - (int) (replyStartY - AndroidUtilities.dp(7)), - (int) (replyStartX + Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(7)), - (int) (replyStartY + replyHeight + AndroidUtilities.dp(7)) + (replyStartX - AndroidUtilities.dp(7)), + (replyStartY - AndroidUtilities.dp(3)), + (replyStartX + Math.max(replyNameWidth, replyTextWidth) - AndroidUtilities.dp(4)), + (replyStartY + replyHeight + AndroidUtilities.dp(3)) ); - } else { - if (drawTopic || drawNameLayout || (drawForwardedName && forwardedNameLayout[0] != null)) { - leftRad = bottomRad; - } else if (currentMessageObject.isOutOwner() || !drawPinnedTop) { - leftRad = SharedConfig.bubbleRadius * .75f; - } else { - leftRad = Math.min(6, SharedConfig.bubbleRadius); + if (forwardNameRight > 0) { + replySelectorRect.right = Math.max(replySelectorRect.right, forwardNameRight); } + } else { if (drawTopic || drawNameLayout || (drawForwardedName && forwardedNameLayout[0] != null)) { rightRad = bottomRad; } else if (!currentMessageObject.isOutOwner() || !drawPinnedTop) { - rightRad = SharedConfig.bubbleRadius * .75f; + rightRad = SharedConfig.bubbleRadius * .6f; } else { - rightRad = Math.min(6, SharedConfig.bubbleRadius) / 3f; + rightRad = SharedConfig.bubbleRadius / 3f; } + float right; + if (currentMessagesGroup != null) { + int end = 0; + int dWidth = getGroupPhotosWidth(); + int firstLineWidth = 0; + for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { + MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a); + if (position.minY == 0) { + firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); + } else { + break; + } + } + if (!mediaBackground && currentMessageObject.isOutOwner()) { + end = backgroundDrawableLeft + firstLineWidth - AndroidUtilities.dp(6); + } else { + end = backgroundDrawableLeft + firstLineWidth; + } + end -= getExtraTextX() + AndroidUtilities.dp(8); + if (!currentMessageObject.isOutOwner()) { + end -= AndroidUtilities.dp(48); + } +// endX -= AndroidUtilities.dp(6 + 4 + (currentMessageObject.isOutOwner() && !drawPinnedBottom ? 6 : 0)); + right = end;//replyStartX + Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(10); + } else { + right = getBackgroundDrawableRight() + transitionParams.deltaRight; + } + right -= AndroidUtilities.dp(10 + (currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) + getExtraTextX(); replySelectorRect.set( - (int) (getCurrentBackgroundLeft() + AndroidUtilities.dp(5 + (!currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) + getExtraTextX()), - (int) (replyStartY - AndroidUtilities.dp(drawNameLayout ? 4 : (4 + (!mediaBackground && drawPinnedTop ? 2 : 0)) - (drawForwardedName && forwardedNameLayout[0] != null ? 2 : 0))), - (int) ((currentMessagesGroup != null ? replyStartX + Math.max(replyNameWidth, replyTextWidth) + AndroidUtilities.dp(10) : getBackgroundDrawableRight()) - AndroidUtilities.dp(5 + (currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) - getExtraTextX()), - (int) (replyStartY + replyHeight + AndroidUtilities.dp(4)) + (backgroundDrawableLeft + transitionParams.deltaLeft + AndroidUtilities.dp(10 + (!currentMessageObject.isOutOwner() && !mediaBackground && !drawPinnedBottom ? 6 : 0)) + getExtraTextX()), + (replyStartY - AndroidUtilities.dp((!mediaBackground && drawPinnedTop && !drawNameLayout ? 2 : 0)) - (drawForwardedName && forwardedNameLayout[0] != null && !drawNameLayout ? 2 : 0)), + right, + (replyStartY + replyHeight + AndroidUtilities.dp(4)) ); } + + if (needDrawReplyBackground) { + if (replyBounce == null) { + replyBounce = new ButtonBounce(this, 2.0f, 2.0f); + } + if (restoreToCount == -1) { + restoreToCount = canvas.getSaveCount(); + } + canvas.save(); + final float s = replyBounce.getScale(0.0125f); + canvas.scale(s, s, Utilities.clamp(replyBounceX, replySelectorRect.right, replySelectorRect.left), Utilities.clamp(replyBounceY, replySelectorRect.bottom, replySelectorRect.top)); + } + + // draw reply background + leftRad = bottomRad; // line redesign + replyLine.setLoading(loading); + replyLine.drawBackground(canvas, replySelectorRect, leftRad, rightRad, bottomRad, alpha, isReplyQuote, currentMessageObject.shouldDrawWithoutBackground()); + if (replySelector == null) { replySelector = Theme.createRadSelectorDrawable(replySelectorColor = rippleColor, 0, 0); replySelector.setCallback(this); } - replySelector.setBounds(replySelectorRect); + replySelector.setBounds((int) replySelectorRect.left, (int) replySelectorRect.top, (int) replySelectorRect.right, (int) replySelectorRect.bottom); if (leftRad != replySelectorRadLeft || rightRad != replySelectorRadRight) { Theme.setMaskDrawableRad(replySelector, replySelectorRadLeft = leftRad, replySelectorRadRight = rightRad, bottomRad, bottomRad); } if (rippleColor != replySelectorColor) { Theme.setSelectorDrawableColor(replySelector, replySelectorColor = rippleColor, true); } - if (loading) { - if (replyLoadingDrawable == null) { - replyLoadingDrawable = new LoadingDrawable(); - replyLoadingDrawable.setAppearByGradient(true); - replyLoadingDrawable.setGradientScale(3.5f); - replyLoadingDrawable.setSpeed(.5f); - } - - int a = Color.alpha(rippleColor); - replyLoadingDrawable.setColors( - ColorUtils.setAlphaComponent(rippleColor, MathUtils.clamp(a / 2, 0, 0xFF)), - ColorUtils.setAlphaComponent(rippleColor, MathUtils.clamp(a * 2, 0, 0xFF)), - ColorUtils.setAlphaComponent(rippleColor, MathUtils.clamp(a / 2, 0, 0xFF)), - ColorUtils.setAlphaComponent(rippleColor, 0xFF) - ); - - replyLoadingDrawable.setBounds(replySelectorRect); - replyLoadingDrawable.setRadiiDp(leftRad, rightRad, bottomRad, bottomRad); - replyLoadingDrawable.strokePaint.setStrokeWidth(AndroidUtilities.dp(1)); - - replyLoadingDrawable.draw(canvas); - } else if (replyLoadingDrawable != null) { - replyLoadingDrawable.reset(); - } replySelector.draw(canvas); - AndroidUtilities.rectTmp.set(replyStartX, replyStartY, replyStartX + AndroidUtilities.dp(3), replyStartY + replyHeight); if (replyRoundRectPath == null) { replyRoundRectPath = new Path(); } else { replyRoundRectPath.rewind(); } - if (replyRoundRectRadii == null) { - replyRoundRectRadii = new float[8]; - replyRoundRectRadii[0] = replyRoundRectRadii[1] = replyRoundRectRadii[6] = replyRoundRectRadii[7] = AndroidUtilities.dp(2); // left - replyRoundRectRadii[2] = replyRoundRectRadii[3] = replyRoundRectRadii[4] = replyRoundRectRadii[5] = AndroidUtilities.dp(1); // right - } - replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyRoundRectRadii, Path.Direction.CW); - int wasAlpha = Theme.chat_replyLinePaint.getAlpha(); - if (loading) { - Theme.chat_replyLinePaint.setAlpha((int) (wasAlpha * .3f)); - canvas.drawPath(replyRoundRectPath, Theme.chat_replyLinePaint); - Theme.chat_replyLinePaint.setAlpha(wasAlpha); + replyLine.drawLine(canvas, replySelectorRect); + replyLine.drawLoadingBackground(canvas, replySelectorRect, leftRad, rightRad, bottomRad, alpha); - replyRoundRectPath.rewind(); - replyLoadingT += 1000f / AndroidUtilities.screenRefreshRate; - if (replyLoadingSegment == null) { - replyLoadingSegment = new float[2]; - } - - float x = (float) Math.pow(replyLoadingT / 120f / 4f, .85f) * 4f; - final float from = MathUtils.clamp(.5f * ((Math.max(x, .5f) + 1.5f) % 3.5f), 0, 1); - final float to = MathUtils.clamp(.5f * (((x + 1.5f) % 3.5f) - 1.5f), 0, 1); - - AndroidUtilities.rectTmp.set( - replyStartX, - replyStartY + replyHeight * (1f - CubicBezierInterpolator.EASE_IN.getInterpolation(from)), - replyStartX + AndroidUtilities.dp(3), - replyStartY + replyHeight * (1f - CubicBezierInterpolator.EASE_OUT.getInterpolation(to)) - ); - replyRoundRectPath.addRoundRect(AndroidUtilities.rectTmp, replyRoundRectRadii, Path.Direction.CW); - canvas.drawPath(replyRoundRectPath, Theme.chat_replyLinePaint); - - invalidate(); - } else { - replyLoadingT = 0; - canvas.drawPath(replyRoundRectPath, Theme.chat_replyLinePaint); - } - Theme.chat_replyLinePaint.setAlpha(wasAlpha); + float replyImageSz = 0; if (needReplyImage) { replyImageReceiver.setAlpha(replyForwardAlpha); - replyImageReceiver.setImageCoords(replyStartX + offset, replyStartY, replyHeight, replyHeight); + replyImageSz = Math.min(replySelectorRect.height() - AndroidUtilities.dp(10), AndroidUtilities.dp(33)); + replyImageReceiver.setImageCoords(replySelectorRect.left + AndroidUtilities.dp(8), replySelectorRect.top + AndroidUtilities.dp(5), replyImageSz, replyImageSz); replyImageReceiver.draw(canvas); if (currentMessageObject != null && currentMessageObject.hasValidReplyMessageObject() && currentMessageObject.replyMessageObject.hasMediaSpoilers()) { @@ -15310,9 +16260,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } + final float offsetX = currentMessageObject != null && currentMessageObject.shouldDrawWithoutBackground() ? -AndroidUtilities.dp(6) : -AndroidUtilities.dp(1); + final float offsetY = currentMessageObject != null && currentMessageObject.shouldDrawWithoutBackground() ? AndroidUtilities.dp(1) : AndroidUtilities.dp(3); + + final boolean showQuote = isReplyQuote && currentMessageObject != null && currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.reply_to.quote; + if (isReplyQuote && showQuote && replyQuoteDrawable != null) { + if (replyLine.getColor() != replyQuoteDrawableColor) { + replyQuoteDrawable.setColorFilter(new PorterDuffColorFilter(replyQuoteDrawableColor = replyLine.getColor(), PorterDuff.Mode.SRC_IN)); + } + replyQuoteDrawable.setBounds( + (int) (replySelectorRect.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) - replyQuoteDrawable.getIntrinsicWidth()), + (int) (replySelectorRect.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))), + (int) (replySelectorRect.right - AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0))), + (int) (replySelectorRect.top + AndroidUtilities.dp(2 + (!drawPinnedTop ? 1 : 0)) + replyQuoteDrawable.getIntrinsicHeight()) + ); + replyQuoteDrawable.draw(canvas); + } + if (replyNameLayout != null) { canvas.save(); - canvas.translate(replyStartX - replyNameOffset + offset + (needReplyImage ? offset - AndroidUtilities.dp(1) + replyHeight : 0), replyStartY); + canvas.translate(replyStartX + offsetX - replyNameOffset + offset + (needReplyImage ? replyImageSz + AndroidUtilities.dp(3) : 0), replyStartY + offsetY); replyNameLayout.draw(canvas); canvas.restore(); } @@ -15327,22 +16294,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.clipRect(replySelectorRect); canvas.save(); - canvas.translate(forwardNameX + replyTextOffset - transitionParams.animateReplyTextOffset, replyStartY + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5)); - int wasAlpha2 = Theme.chat_replyTextPaint.getAlpha(); - Theme.chat_replyTextPaint.setAlpha((int) (wasAlpha2 * (1f - transitionParams.animateChangeProgress))); + canvas.translate(replyStartX - replyTextOffset + offset + offsetX + (needReplyImage && (!isReplyQuote || replyTextRTL) ? replyImageSz + AndroidUtilities.dp(3) : 0) + (isReplyQuote && needReplyImage ? -AndroidUtilities.dp(2) : 0) + replyTextOffset - transitionParams.animateReplyTextOffset, replyStartY + offsetY - AndroidUtilities.dp(1) + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5)); + 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); - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, transitionParams.animateReplyTextLayout, transitionParams.animateOutAnimateEmojiReply, 0, replySpoilers, 0, 0, 0, alpha, Theme.chat_animatedEmojiTextColorFilter); - Theme.chat_replyTextPaint.setAlpha(wasAlpha2); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, transitionParams.animateReplyTextLayout, transitionParams.animateOutAnimateEmojiReply, 0, replySpoilers, 0, 0, 0, alpha, currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); + paint.setAlpha(wasAlpha2); canvas.restore(); } if (replyTextLayout != null) { canvas.save(); - canvas.translate(forwardNameX, replyStartY + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5)); - int wasAlpha2 = Theme.chat_replyTextPaint.getAlpha(); - Theme.chat_replyTextPaint.setAlpha((int) (wasAlpha2 * (transitionParams.animateReplyTextLayout != null ? transitionParams.animateChangeProgress : 1))); + canvas.translate(replyStartX - replyTextOffset + offset + offsetX + (needReplyImage && (!isReplyQuote || replyTextRTL) ? replyImageSz + AndroidUtilities.dp(3) : 0) + (isReplyQuote && needReplyImage ? -AndroidUtilities.dp(2) : 0), replyStartY + offsetY - AndroidUtilities.dp(1) + Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5)); + 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); - AnimatedEmojiSpan.drawAnimatedEmojis(canvas, replyTextLayout, animatedEmojiReplyStack, 0, replySpoilers, 0, 0, 0, alpha, Theme.chat_animatedEmojiTextColorFilter); - Theme.chat_replyTextPaint.setAlpha(wasAlpha2); + AnimatedEmojiSpan.drawAnimatedEmojis(canvas, replyTextLayout, animatedEmojiReplyStack, 0, replySpoilers, 0, 0, 0, alpha, currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.chat_outAnimatedEmojiTextColorFilter : Theme.chat_animatedEmojiTextColorFilter); + paint.setAlpha(wasAlpha2); canvas.restore(); } if (transitionParams.animateReplyTextLayout != null && transitionParams.animateChangeProgress < 1) { @@ -15368,7 +16337,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } - public StaticLayout getCaptionLayout() { + public MessageObject.TextLayoutBlocks getCaptionLayout() { return captionLayout; } @@ -15384,14 +16353,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } public float getHighlightAlpha() { + return getHighlightAlpha(false); + } + + public float getHighlightAlpha(boolean quote) { + float t = 1.0f; if (!drawSelectionBackground && isHighlightedAnimated) { - return highlightProgress >= 300 ? 1.0f : highlightProgress / 300.0f; + t *= highlightProgress >= 300 ? 1.0f : highlightProgress / 300.0f; } - return 1.0f; + if (!quote && quoteHighlight != null) { + t *= (1f - quoteHighlight.getT()); + } + return t; } public void setCheckBoxVisible(boolean visible, boolean animated) { if (visible) { + quoteHighlight = null; if (checkBox == null) { checkBox = new CheckBoxBase(this, 21, resourcesProvider); if (attachedToWindow) { @@ -15483,10 +16461,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animatedEmojiStack.clearPositions(); } if (transitionParams.animateReplaceCaptionLayout && transitionParams.animateChangeProgress != 1f) { - drawCaptionLayout(canvas, transitionParams.animateOutCaptionLayout, selectionOnly, alpha * (1f - transitionParams.animateChangeProgress)); - drawCaptionLayout(canvas, captionLayout, selectionOnly, alpha * transitionParams.animateChangeProgress); + drawCaptionLayout(canvas, transitionParams.animateOutCaptionLayout, false, selectionOnly, alpha * (1f - transitionParams.animateChangeProgress)); + drawCaptionLayout(canvas, captionLayout, true, selectionOnly, alpha * transitionParams.animateChangeProgress); } else { - drawCaptionLayout(canvas, captionLayout, selectionOnly, alpha); + drawCaptionLayout(canvas, captionLayout, true, selectionOnly, alpha); } if (!selectionOnly) { @@ -15523,9 +16501,37 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - private void drawCaptionLayout(Canvas canvas, StaticLayout captionLayout, boolean selectionOnly, float alpha) { + private void drawCaptionLayout(Canvas canvas, MessageObject.TextLayoutBlocks captionLayout, boolean origin, boolean selectionOnly, float alpha) { + int x; + if (mediaBackground) { + x = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); + } else { + x = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); + } + int endX = x - getExtraTextX(); + if (currentMessagesGroup != null && !currentMessageObject.isMusic() && !currentMessageObject.isDocument()) { + int dWidth = getGroupPhotosWidth(); + if ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0) { + endX += Math.ceil(currentPosition.pw / 1000.0f * dWidth); + } else { + int firstLineWidth = 0; + for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { + MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a); + if (position.minY == 0) { + firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); + } else { + break; + } + } + endX += firstLineWidth - AndroidUtilities.dp(9); + } + } else { + endX += backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(9)); + } + if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 && !currentMessagesGroup.hasSibling) { + endX += AndroidUtilities.dp(14); + } if (currentBackgroundDrawable != null && drawCommentButton && timeLayout != null) { - int x; float y = layoutHeight + transitionParams.deltaBottom - AndroidUtilities.dp(18) - timeLayout.getHeight(); if (currentMessagesGroup != null) { y += currentMessagesGroup.transitionParams.offsetBottom; @@ -15533,32 +16539,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate y -= getTranslationY(); } } - if (mediaBackground) { - x = backgroundDrawableLeft + AndroidUtilities.dp(12) + getExtraTextX(); - } else { - x = backgroundDrawableLeft + AndroidUtilities.dp(drawPinnedBottom ? 12 : 18) + getExtraTextX(); - } - int endX = x - getExtraTextX(); - if (currentMessagesGroup != null && !currentMessageObject.isMusic() && !currentMessageObject.isDocument()) { - int dWidth = getGroupPhotosWidth(); - if ((currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0) { - endX += Math.ceil(currentPosition.pw / 1000.0f * dWidth); - } else { - int firstLineWidth = 0; - for (int a = 0; a < currentMessagesGroup.posArray.size(); a++) { - MessageObject.GroupedMessagePosition position = currentMessagesGroup.posArray.get(a); - if (position.minY == 0) { - firstLineWidth += Math.ceil((position.pw + position.leftSpanOffset) / 1000.0f * dWidth); - } else { - break; - } - } - endX += firstLineWidth - AndroidUtilities.dp(9); - } - } else { - endX += backgroundWidth - (mediaBackground ? 0 : AndroidUtilities.dp(9)); - } - int h; int h2; if (pinnedBottom) { @@ -15575,7 +16555,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int buttonX = getCurrentBackgroundLeft() + AndroidUtilities.dp(currentMessageObject.isOutOwner() || mediaBackground || drawPinnedBottom ? 2 : 8); float buttonY = layoutHeight - AndroidUtilities.dp(45.1f - h2); if (currentPosition != null && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) == 0 && !currentMessagesGroup.hasSibling) { - endX += AndroidUtilities.dp(14); buttonX -= AndroidUtilities.dp(10); } commentButtonRect.set( @@ -15781,13 +16760,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (captionLayout == null || selectionOnly && links.isEmpty() || (currentMessageObject.deleted && currentPosition != null) || alpha == 0) { return; } - if (currentMessageObject.isOutOwner()) { - Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextOut)); - Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkOut); - } else { - Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); - Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); - } + setupTextColors(); canvas.save(); float renderingAlpha = alpha; if (currentMessagesGroup != null) { @@ -15818,7 +16791,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int restore = Integer.MIN_VALUE; if (renderingAlpha != 1.0f) { - rect.set(captionX, captionY, captionX + captionLayout.getWidth(), captionY + captionLayout.getHeight()); + rect.set(captionX, captionY, captionX + captionLayout.textWidth, captionY + captionLayout.textHeight); restore = canvas.saveLayerAlpha(rect, (int) (255 * renderingAlpha), Canvas.ALL_SAVE_FLAG); } if (isRoundVideo && transitionParams.animateDrawBackground) { @@ -15844,60 +16817,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ); } } + canvas.save(); canvas.translate(captionX, captionY); - boolean translating = MessagesController.getInstance(currentAccount).getTranslateController().isTranslating(getMessageObject(), getCurrentMessagesGroup()); - if (true) { - if (translationLoadingFloat == null) { - translationLoadingFloat = new AnimatedFloat(((View) getParent()), 350, CubicBezierInterpolator.EASE_OUT_QUINT); - } - float translationLoading = translationLoadingFloat.set(translating ? 1 : 0); - if (translationLoading > 0) { - if (translationLoadingDrawable == null) { - translationLoadingDrawable = new LoadingDrawable(); - translationLoadingDrawable.setAppearByGradient(true); - if (translationLoadingPath == null) { - translationLoadingPath = new LinkPath(true); - } - translationLoadingDrawable.usePath(translationLoadingPath); - translationLoadingDrawable.setRadiiDp(5); - } - - if (translationLoadingDrawableLayout != captionLayout) { - translationLoadingDrawableLayout = captionLayout; - translationLoadingPath.setCurrentLayout(captionLayout, 0, 0); - captionLayout.getSelectionPath(0, captionLayout.getText().length(), translationLoadingPath); - translationLoadingDrawable.updateBounds(); - } - - if (translating && translationLoadingDrawable.isDisappearing() || translationLoadingDrawable.isDisappeared()) { - translationLoadingDrawable.reset(); - translationLoadingDrawable.resetDisappear(); - } else if (!translating && !translationLoadingDrawable.isDisappearing() && !translationLoadingDrawable.isDisappeared()) { - translationLoadingDrawable.disappear(); - } - - int color = getThemedColor(currentMessageObject != null && currentMessageObject.isOutOwner() ? Theme.key_chat_messageLinkOut : Theme.key_chat_messageLinkIn); - translationLoadingDrawable.setColors( - Theme.multAlpha(color, .05f), - Theme.multAlpha(color, .15f), - Theme.multAlpha(color, .1f), - Theme.multAlpha(color, .3f) - ); - translationLoadingDrawable.setAlpha((int) (0xFF * alpha * translationLoading)); - translationLoadingDrawable.draw(canvas); - invalidate(); - } - } if (links.draw(canvas)) { invalidate(); } drawProgressLoadingLink(canvas, -1); - if (!urlPathSelection.isEmpty()) { - for (int b = 0; b < urlPathSelection.size(); b++) { - canvas.drawPath(urlPathSelection.get(b), Theme.chat_textSearchSelectionPaint); - } - } if (highlightPath != null) { float t = (System.currentTimeMillis() - highlightPathStart) / 850f; if (t > 1) { @@ -15926,23 +16852,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ) ); } + canvas.restore(); if (!selectionOnly) { - try { - if (getDelegate() != null && getDelegate().getTextSelectionHelper() != null && getDelegate().getTextSelectionHelper().isSelected(currentMessageObject)) { - getDelegate().getTextSelectionHelper().drawCaption(currentMessageObject.isOutOwner(), captionLayout, canvas); - } - float top = parentBoundsTop - getY() - captionY; - float bottom = parentBoundsBottom - getY() - captionY; - - Emoji.emojiDrawingYOffset = -transitionYOffsetForDrawables; - - int spoilersColor = currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : captionLayout.getPaint().getColor(); - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, 0, captionPatchedSpoilersLayout, captionLayout, captionSpoilers, canvas, currentMessagesGroup != null); - - Emoji.emojiDrawingYOffset = 0; - } catch (Exception e) { - FileLog.e(e); - } + drawMessageText(captionX, captionY, canvas, captionLayout.textLayoutBlocks, captionLayout.textXOffset, origin, alpha, true, false, true); } if (restore != Integer.MIN_VALUE) { canvas.restoreToCount(restore); @@ -16015,43 +16927,49 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } progressLoadingLinkDrawables.add(location); if (progressLoadingLink != null) { - final int count = Math.max(0, currentMessageObject != null && currentMessageObject.textLayoutBlocks != null ? currentMessageObject.textLayoutBlocks.size() : 0); - for (int i = -2; i < count; ++i) { - float yOffset = 0; - Layout layout; - if (i == -2) { - layout = descriptionLayout; - } else if (i == -1) { - layout = captionLayout; - } else { - layout = currentMessageObject.textLayoutBlocks.get(i).textLayout; - yOffset = currentMessageObject.textLayoutBlocks.get(i).textYOffset; - } + boolean b = + findProgressLoadingLink(location, path, descriptionLayout, 0, -2) || + (captionLayout != null && findProgressLoadingLink(location, path, captionLayout.textLayoutBlocks)) || + (currentMessageObject != null && findProgressLoadingLink(location, path, currentMessageObject.textLayoutBlocks)); + } + } - if (layout != null && layout.getText() instanceof Spanned) { - Spanned spanned = (Spanned) layout.getText(); - CharacterStyle[] spans = spanned.getSpans(0, spanned.length(), CharacterStyle.class); - if (spans != null) { - for (int j = 0; j < spans.length; ++j) { - if (spans[j] == progressLoadingLink) { - location.blockNum = i; - break; - } - } - } + private boolean findProgressLoadingLink(LoadingDrawableLocation location, LinkPath path, ArrayList textLayoutBlocks) { + if (textLayoutBlocks == null) { + return false; + } + for (int i = 0; i < textLayoutBlocks.size(); ++i) { + if (findProgressLoadingLink(location, path, textLayoutBlocks.get(i).textLayout, textLayoutBlocks.get(i).textYOffset, i)) { + return true; + } + } + return false; + } - if (location.blockNum == i) { - path.rewind(); - int start = spanned.getSpanStart(progressLoadingLink); - int end = spanned.getSpanEnd(progressLoadingLink); - path.setCurrentLayout(layout, start, yOffset); - layout.getSelectionPath(start, end, path); - progressLoadingLinkCurrentDrawable.updateBounds(); - return; + private boolean findProgressLoadingLink(LoadingDrawableLocation location, LinkPath path, Layout layout, float yOffset, int blockNum) { + if (layout != null && layout.getText() instanceof Spanned) { + Spanned spanned = (Spanned) layout.getText(); + CharacterStyle[] spans = spanned.getSpans(0, spanned.length(), CharacterStyle.class); + if (spans != null) { + for (int j = 0; j < spans.length; ++j) { + if (spans[j] == progressLoadingLink) { + location.blockNum = blockNum; + break; } } } + + if (location.blockNum == blockNum) { + path.rewind(); + int start = spanned.getSpanStart(progressLoadingLink); + int end = spanned.getSpanEnd(progressLoadingLink); + path.setCurrentLayout(layout, start, yOffset); + layout.getSelectionPath(start, end, path); + progressLoadingLinkCurrentDrawable.updateBounds(); + return true; + } } + return false; } public boolean needDrawTime() { @@ -16109,7 +17027,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (transitionParams.animateBackgroundBoundsInner) { + if (transitionParams.animateBackgroundBoundsInner && !(currentMessageObject != null && currentMessageObject.preview)) { drawOverlays(canvas); } } @@ -16315,14 +17233,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); canvas.translate(drawTimeX = timeTitleTimeX + additionalX, drawTimeY = timeY - AndroidUtilities.dp(7.3f) - timeLayout.getHeight()); - timeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(timeLayout, canvas); canvas.restore(); Theme.chat_timePaint.setAlpha(255); } else { if (currentMessageObject.isSponsored()) { timeYOffset = -AndroidUtilities.dp(48); if (hasNewLineForTime) { - timeYOffset -= AndroidUtilities.dp(16); + timeYOffset -= AndroidUtilities.dp(4); } } else { timeYOffset = -(drawCommentButton ? AndroidUtilities.dp(43) : 0); @@ -16390,23 +17308,23 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_timePaint.setAlpha((int) (oldAlpha * transitionParams.animateChangeProgress)); transitionParams.animateEditedLayout.draw(canvas); Theme.chat_timePaint.setAlpha(oldAlpha); - transitionParams.animateTimeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(transitionParams.animateTimeLayout, canvas); } else { int oldAlpha = Theme.chat_timePaint.getAlpha(); canvas.save(); canvas.translate(transitionParams.animateFromTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); Theme.chat_timePaint.setAlpha((int) (oldAlpha * (1f - transitionParams.animateChangeProgress))); - transitionParams.animateTimeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(transitionParams.animateTimeLayout, canvas); canvas.restore(); canvas.translate(timeTitleTimeX + additionalX, layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); Theme.chat_timePaint.setAlpha((int) (oldAlpha * (transitionParams.animateChangeProgress))); - timeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(timeLayout, canvas); Theme.chat_timePaint.setAlpha(oldAlpha); } } else { canvas.translate(drawTimeX = timeTitleTimeX + additionalX, drawTimeY = layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 7.5f : 6.5f) - timeLayout.getHeight() + timeYOffset); - timeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(timeLayout, canvas); } canvas.restore(); } @@ -16491,7 +17409,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate Theme.chat_msgUnlockDrawable.setBounds(0, 0, Theme.chat_msgUnlockDrawable.getIntrinsicWidth(), Theme.chat_msgUnlockDrawable.getIntrinsicHeight()); Theme.chat_msgUnlockDrawable.draw(canvas); canvas.translate(AndroidUtilities.dp(6) + Theme.chat_msgUnlockDrawable.getIntrinsicWidth(), 0); - unlockLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(unlockLayout, canvas); canvas.restore(); if (videoInfoLayout != null && photoImage.getVisible() && imageBackgroundSideColor == 0) { @@ -16510,7 +17428,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); canvas.translate(x + (bigRadius ? 2 : 0), y); - videoInfoLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(videoInfoLayout, canvas); canvas.restore(); } } @@ -16776,14 +17694,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.save(); Theme.chat_timePaint.setAlpha((int) (timeAlpha * (1.0 - transitionParams.animateChangeProgress))); canvas.translate(viewsX + w + AndroidUtilities.dp(3), y); - transitionParams.animateViewsLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(transitionParams.animateViewsLayout, canvas); canvas.restore(); Theme.chat_timePaint.setAlpha((int) (timeAlpha * transitionParams.animateChangeProgress)); } canvas.save(); canvas.translate(viewsX + w + AndroidUtilities.dp(3), y); - viewsLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(viewsLayout, canvas); canvas.restore(); if (useScale) { canvas.restore(); @@ -17056,7 +17974,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.type == MessageObject.TYPE_VIDEO || currentMessageObject.type == MessageObject.TYPE_PHOTO || currentMessageObject.type == MessageObject.TYPE_EXTENDED_MEDIA_PREVIEW || documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO || documentAttachType == DOCUMENT_ATTACH_TYPE_GIF) { if (photoImage.getVisible()) { - if (!currentMessageObject.needDrawBluredPreview()) { + if (!currentMessageObject.needDrawBluredPreview() && !currentMessageObject.preview && !isSmallImage) { if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { int oldAlpha = ((BitmapDrawable) Theme.chat_msgMediaMenuDrawable).getPaint().getAlpha(); if (drawMediaCheckBox) { @@ -17109,95 +18027,99 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - boolean bigRadius = false; - if (documentAttachType != DOCUMENT_ATTACH_TYPE_ROUND && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER && currentMessageObject.type != MessageObject.TYPE_EMOJIS) { - bigRadius = SharedConfig.bubbleRadius >= 10; - } - Theme.chat_infoPaint.setColor(getThemedColor(Theme.key_chat_mediaInfoText)); - int x1 = (int) (photoImage.getImageX() + AndroidUtilities.dp(4)); - int y1 = (int) (photoImage.getImageY() + AndroidUtilities.dp(4)); + loadingProgressAlpha *= (1f - isSmallImage()); - int imageW; - int infoW; - if (autoPlayingMedia && (!playing || animatingNoSound != 0)) { - imageW = (int) ((Theme.chat_msgNoSoundDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4)) * animatingNoSoundProgress); - } else { - imageW = 0; - } - if (drawLoadingProgress && loadingProgressLayout != null) { - imageW = 0; - infoW = (int) loadingProgressLayout.getLineWidth(0); + if (loadingProgressAlpha > 0) { + boolean bigRadius = false; + if (documentAttachType != DOCUMENT_ATTACH_TYPE_ROUND && documentAttachType != DOCUMENT_ATTACH_TYPE_STICKER && currentMessageObject.type != MessageObject.TYPE_EMOJIS) { + bigRadius = SharedConfig.bubbleRadius >= 10; + } + Theme.chat_infoPaint.setColor(getThemedColor(Theme.key_chat_mediaInfoText)); + int x1 = (int) (photoImage.getImageX() + AndroidUtilities.dp(4)); + int y1 = (int) (photoImage.getImageY() + AndroidUtilities.dp(4)); + + int imageW; + int infoW; + if (autoPlayingMedia && (!playing || animatingNoSound != 0)) { + imageW = (int) ((Theme.chat_msgNoSoundDrawable.getIntrinsicWidth() + AndroidUtilities.dp(4)) * animatingNoSoundProgress); + } else { + imageW = 0; + } + if (drawLoadingProgress && loadingProgressLayout != null) { + imageW = 0; + infoW = (int) loadingProgressLayout.getLineWidth(0); // infoW = loadingProgressLayout.getCurrentWidth(); - } else { - infoW = infoWidth; - } + } else { + infoW = infoWidth; + } - int w = (int) Math.ceil(infoW + AndroidUtilities.dp(bigRadius ? 12 : 8) + imageW + (Math.max(infoW + (infoWidth == infoW ? imageW : 0), docTitleWidth) + (canStreamVideo ? AndroidUtilities.dp(32) : 0) - infoW - imageW) * alpha); + int w = (int) Math.ceil(infoW + AndroidUtilities.dp(bigRadius ? 12 : 8) + imageW + (Math.max(infoW + (infoWidth == infoW ? imageW : 0), docTitleWidth) + (canStreamVideo ? AndroidUtilities.dp(32) : 0) - infoW - imageW) * alpha); - if (alpha != 0 && docTitleLayout == null) { - alpha = 0; - } + if (alpha != 0 && docTitleLayout == null) { + alpha = 0; + } - canvas.save(); - int oldAlpha = getThemedPaint(Theme.key_paint_chatTimeBackground).getAlpha(); - getThemedPaint(Theme.key_paint_chatTimeBackground).setAlpha((int) (oldAlpha * controlsAlpha * loadingProgressAlpha * (currentMessageObject.needDrawBluredPreview() ? .4f : 1f))); - rect.set(x1, y1, x1 + w, y1 + AndroidUtilities.dp(16.5f + 15.5f * alpha)); - int[] rad = photoImage.getRoundRadius(); - int r = Math.min(AndroidUtilities.dp(8), Math.max(rad[0], rad[1])); - if (currentMessageObject.needDrawBluredPreview()) { - rectPath.reset(); - rectPath.addRoundRect(rect, r, r, Path.Direction.CW); canvas.save(); - canvas.clipPath(rectPath); - float wasAlpha = photoImage.getAlpha(); - photoImage.setAlpha(.5f * wasAlpha); - photoImage.draw(canvas); - photoImage.setAlpha(wasAlpha); - canvas.restore(); - canvas.drawRoundRect(rect, r, r, getThemedPaint(Theme.key_paint_chatTimeBackground)); - } else if (drawDocTitleLayout || (drawLoadingProgress && loadingProgressLayout != null) || (!drawLoadingProgress && infoLayout != null)) { - canvas.scale(loadingProgressAlpha, loadingProgressAlpha, x1, y1); - canvas.drawRoundRect(rect, r, r, getThemedPaint(Theme.key_paint_chatTimeBackground)); - } else { - canvas.scale(loadingProgressAlpha, loadingProgressAlpha, x1, y1); - } + int oldAlpha = getThemedPaint(Theme.key_paint_chatTimeBackground).getAlpha(); + getThemedPaint(Theme.key_paint_chatTimeBackground).setAlpha((int) (oldAlpha * controlsAlpha * loadingProgressAlpha * (currentMessageObject.needDrawBluredPreview() ? .4f : 1f))); + rect.set(x1, y1, x1 + w, y1 + AndroidUtilities.dp(16.5f + 15.5f * alpha)); + int[] rad = photoImage.getRoundRadius(); + int r = Math.min(AndroidUtilities.dp(8), Math.max(rad[0], rad[1])); + if (currentMessageObject.needDrawBluredPreview()) { + rectPath.reset(); + rectPath.addRoundRect(rect, r, r, Path.Direction.CW); + canvas.save(); + canvas.clipPath(rectPath); + float wasAlpha = photoImage.getAlpha(); + photoImage.setAlpha(.5f * wasAlpha); + photoImage.draw(canvas); + photoImage.setAlpha(wasAlpha); + canvas.restore(); + canvas.drawRoundRect(rect, r, r, getThemedPaint(Theme.key_paint_chatTimeBackground)); + } else if (drawDocTitleLayout || (drawLoadingProgress && loadingProgressLayout != null) || (!drawLoadingProgress && infoLayout != null)) { + canvas.scale(loadingProgressAlpha, loadingProgressAlpha, x1, y1); + canvas.drawRoundRect(rect, r, r, getThemedPaint(Theme.key_paint_chatTimeBackground)); + } else { + canvas.scale(loadingProgressAlpha, loadingProgressAlpha, x1, y1); + } - Theme.chat_infoPaint.setAlpha((int) (255 * controlsAlpha * loadingProgressAlpha)); - Theme.chat_infoBoldPaint.setColor(Theme.chat_infoPaint.getColor()); + Theme.chat_infoPaint.setAlpha((int) (255 * controlsAlpha * loadingProgressAlpha)); + Theme.chat_infoBoldPaint.setColor(Theme.chat_infoPaint.getColor()); - canvas.translate(noSoundCenterX = (int) (photoImage.getImageX() + AndroidUtilities.dp((bigRadius ? 10 : 8) + (canStreamVideo ? 30 * alpha : 0))), photoImage.getImageY() + AndroidUtilities.dp(5.5f + 0.2f * alpha)); - if (infoLayout != null && (!drawLoadingProgress || drawDocTitleLayout)) { - infoLayout.draw(canvas); - } - if (imageW != 0 && (!drawLoadingProgress || drawDocTitleLayout)) { - canvas.save(); - Theme.chat_msgNoSoundDrawable.setAlpha((int) (255 * animatingNoSoundProgress * animatingNoSoundProgress * controlsAlpha)); - int size = AndroidUtilities.dp(14 * animatingNoSoundProgress); - int y = (AndroidUtilities.dp(14) - size) / 2; - int offset = infoWidth + AndroidUtilities.dp(4); - canvas.translate(offset, 0); - Theme.chat_msgNoSoundDrawable.setBounds(0, y, size, y + size); - Theme.chat_msgNoSoundDrawable.draw(canvas); - noSoundCenterX += offset + size / 2; - canvas.restore(); - } - if (drawLoadingProgress && loadingProgressLayout != null) { - canvas.save(); - if (drawDocTitleLayout) { + canvas.translate(noSoundCenterX = (int) (photoImage.getImageX() + AndroidUtilities.dp((bigRadius ? 10 : 8) + (canStreamVideo ? 30 * alpha : 0))), photoImage.getImageY() + AndroidUtilities.dp(5.5f + 0.2f * alpha)); + if (infoLayout != null && (!drawLoadingProgress || drawDocTitleLayout)) { + infoLayout.draw(canvas); + } + if (imageW != 0 && (!drawLoadingProgress || drawDocTitleLayout)) { + canvas.save(); + Theme.chat_msgNoSoundDrawable.setAlpha((int) (255 * animatingNoSoundProgress * animatingNoSoundProgress * controlsAlpha)); + int size = AndroidUtilities.dp(14 * animatingNoSoundProgress); + int y = (AndroidUtilities.dp(14) - size) / 2; + int offset = infoWidth + AndroidUtilities.dp(4); + canvas.translate(offset, 0); + Theme.chat_msgNoSoundDrawable.setBounds(0, y, size, y + size); + Theme.chat_msgNoSoundDrawable.draw(canvas); + noSoundCenterX += offset + size / 2; + canvas.restore(); + } + if (drawLoadingProgress && loadingProgressLayout != null) { + canvas.save(); + if (drawDocTitleLayout) { + Theme.chat_infoPaint.setAlpha((int) (255 * controlsAlpha * alpha)); + canvas.translate(0, AndroidUtilities.dp(14.3f * alpha)); + } +// loadingProgressLayout.copyStylesFrom(Theme.chat_infoPaint); + loadingProgressLayout.draw(canvas); + canvas.restore(); + } else if (drawDocTitleLayout) { Theme.chat_infoPaint.setAlpha((int) (255 * controlsAlpha * alpha)); canvas.translate(0, AndroidUtilities.dp(14.3f * alpha)); + docTitleLayout.draw(canvas); } -// loadingProgressLayout.copyStylesFrom(Theme.chat_infoPaint); - loadingProgressLayout.draw(canvas); canvas.restore(); - } else if (drawDocTitleLayout) { - Theme.chat_infoPaint.setAlpha((int) (255 * controlsAlpha * alpha)); - canvas.translate(0, AndroidUtilities.dp(14.3f * alpha)); - docTitleLayout.draw(canvas); + Theme.chat_infoPaint.setAlpha(255); + getThemedPaint(Theme.key_paint_chatTimeBackground).setAlpha(oldAlpha); } - canvas.restore(); - Theme.chat_infoPaint.setAlpha(255); - getThemedPaint(Theme.key_paint_chatTimeBackground).setAlpha(oldAlpha); } } if (animatingDrawVideoImageButton == 1) { @@ -17391,7 +18313,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isOutOwner()) { x = layoutWidth - backgroundWidth + AndroidUtilities.dp(16); } else { - if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { x = AndroidUtilities.dp(74); } else { x = AndroidUtilities.dp(25); @@ -17468,7 +18390,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isOutOwner()) { x = layoutWidth - backgroundWidth + AndroidUtilities.dp(11); } else { - if (isChat && !isThreadPost && currentMessageObject.needDrawAvatar()) { + if ((isChat && !isThreadPost || currentMessageObject.forceAvatar) && currentMessageObject.needDrawAvatar()) { x = AndroidUtilities.dp(68); } else { x = AndroidUtilities.dp(20); @@ -17777,32 +18699,40 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawCommentButton) { instantY -= AndroidUtilities.dp(shouldDrawTimeOnMedia() ? 39.3f : 41); } - Paint backPaint = Theme.chat_instantViewRectPaint; if (currentMessageObject.isOutOwner()) { Theme.chat_instantViewPaint.setColor(getThemedColor(Theme.key_chat_outPreviewInstantText)); - backPaint.setColor(getThemedColor(Theme.key_chat_outPreviewInstantText)); + Theme.chat_instantViewButtonPaint.setColor(Theme.multAlpha(getThemedColor(Theme.key_chat_outPreviewInstantText), .10f)); } else { Theme.chat_instantViewPaint.setColor(getThemedColor(Theme.key_chat_inPreviewInstantText)); - backPaint.setColor(getThemedColor(Theme.key_chat_inPreviewInstantText)); + Theme.chat_instantViewButtonPaint.setColor(Theme.multAlpha(getThemedColor(Theme.key_chat_inPreviewInstantText), .10f)); } instantButtonRect.set(textX, instantY, textX + instantWidth, instantY + AndroidUtilities.dp(36)); + float scale = instantButtonBounce.getScale(.02f); + boolean scaleRestore = scale != 1; + if (scaleRestore) { + canvas.save(); + canvas.scale(scale, scale, instantButtonRect.centerX(), instantButtonRect.centerY()); + } if (Build.VERSION.SDK_INT >= 21) { selectorDrawableMaskType[0] = 0; selectorDrawable[0].setBounds(textX, instantY, textX + instantWidth, instantY + AndroidUtilities.dp(36)); selectorDrawable[0].draw(canvas); } - canvas.drawRoundRect(instantButtonRect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), backPaint); + canvas.drawRoundRect(instantButtonRect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Theme.chat_instantViewButtonPaint); if (instantViewLayout != null) { canvas.save(); canvas.translate(textX + instantTextX, instantY + AndroidUtilities.dp(10.5f)); instantViewLayout.draw(canvas); canvas.restore(); } + if (scaleRestore) { + canvas.restore(); + } } } - if (drawImageButton && photoImage.getVisible()) { + if (drawImageButton && photoImage.getVisible() && !(currentMessageObject != null && currentMessageObject.preview)) { if (controlsAlpha != 1.0f) { radialProgress.setOverrideAlpha(controlsAlpha); } @@ -18253,19 +19183,30 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate invalidate(); } - public int computeHeight(MessageObject object, MessageObject.GroupedMessages groupedMessages) { + public int computedGroupCaptionY; + public MessageObject.TextLayoutBlocks computedCaptionLayout; + public int computeHeight(MessageObject object, MessageObject.GroupedMessages groupedMessages, boolean withCaption) { photoImage.setIgnoreImageSet(true); avatarImage.setIgnoreImageSet(true); replyImageReceiver.setIgnoreImageSet(true); locationImageReceiver.setIgnoreImageSet(true); if (groupedMessages != null && groupedMessages.messages.size() != 1) { + if (groupedMessages.messages.size() != groupedMessages.positions.size()) { + groupedMessages.calculate(); + } + computedGroupCaptionY = 0; int h = 0; for (int i = 0; i < groupedMessages.messages.size(); i++) { MessageObject o = groupedMessages.messages.get(i); MessageObject.GroupedMessagePosition position = groupedMessages.positions.get(o); if (position != null && (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { setMessageContent(o, groupedMessages, false, false); + if (withCaption && !TextUtils.isEmpty(currentCaption)) { + updateCaptionLayout(); + computedGroupCaptionY = (int) (h + captionY); + computedCaptionLayout = captionLayout; + } h += totalHeight + keyboardHeight; } } @@ -18277,6 +19218,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate avatarImage.setIgnoreImageSet(false); replyImageReceiver.setIgnoreImageSet(false); locationImageReceiver.setIgnoreImageSet(false); + updateCaptionLayout(); return totalHeight + keyboardHeight; } @@ -18348,7 +19290,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject == null) { return; } - int checkBoxOffset = !currentMessageObject.isOutOwner() ? checkBoxTranslation : 0; + int checkBoxOffset = !currentMessageObject.isOutOwner() || currentMessageObject.hasWideCode ? checkBoxTranslation : 0; setTranslationX(slidingOffsetX + animationOffsetX + checkBoxOffset); } @@ -18441,7 +19383,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (drawForwardedName) { for (int a = 0; a < 2; a++) { - if (forwardedNameLayout[a] != null) { + if (forwardedNameLayout[a] != null && forwardedNameLayout[a].getText() != null) { sb.append(forwardedNameLayout[a].getText()); sb.append(a == 0 ? " " : "\n"); } @@ -18770,25 +19712,30 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return null; } Spannable buffer = (Spannable) currentMessageObject.caption; - ClickableSpan link = getLinkById(virtualViewId, true); + ClickableSpan link = getLinkById(virtualViewId, false); if (link == null) { return null; } int[] linkPos = getRealSpanStartAndEnd(buffer, link); String content = buffer.subSequence(linkPos[0], linkPos[1]).toString(); info.setText(content); - int length = captionLayout.getText().length(); - - captionLayout.getSelectionPath(linkPos[0], linkPos[1], linkPath); - linkPath.computeBounds(rectF, true); - rect.set((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom); - rect.offset((int) captionX, (int) captionY); - info.setBoundsInParent(rect); - if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { - accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + for (MessageObject.TextLayoutBlock block : captionLayout.textLayoutBlocks) { + int length = block.textLayout.getText().length(); + if (block.charactersOffset <= linkPos[0] && block.charactersOffset + length >= linkPos[1]) { + block.textLayout.getSelectionPath(linkPos[0] - block.charactersOffset, linkPos[1] - block.charactersOffset, linkPath); + linkPath.computeBounds(rectF, true); + rect.set((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom); + rect.offset(0, (int) block.textYOffset); + rect.offset(textX, textY); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + break; + } } - rect.offset(pos[0], pos[1]); - info.setBoundsInScreen(rect); info.setClassName("android.widget.TextView"); info.setEnabled(true); @@ -19084,7 +20031,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate delegate.didPressSideButton(ChatMessageCell.this); } } else if (virtualViewId == REPLY) { - if (delegate != null && (!isThreadChat || currentMessageObject.getReplyTopMsgId() != 0) && currentMessageObject.hasValidReplyMessageObject()) { + if (delegate != null && (!isThreadChat || currentMessageObject.getReplyTopMsgId() != 0) && (currentMessageObject.hasValidReplyMessageObject() || isReplyQuote || currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.reply_to != null && currentMessageObject.messageOwner.reply_to.reply_from != null)) { delegate.didPressReplyMessage(ChatMessageCell.this, currentMessageObject.getReplyMsgId()); } } else if (virtualViewId == FORWARD) { @@ -19228,6 +20175,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return 0; } + public int getMediaOffsetY() { + if (transitionParams.animateMediaOffsetY) { + return AndroidUtilities.lerp(transitionParams.animateFromMediaOffsetY, mediaOffsetY, transitionParams.animateChangeProgress); + } + return mediaOffsetY; + } + public int getTextX() { return textX; } @@ -19268,6 +20222,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean animateReplyY; public float lastDrawReplyY; public float animateFromReplyY; + public boolean lastDrawingSmallImage; private boolean lastIsPinned; private boolean animatePinned; @@ -19332,13 +20287,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean transformGroupToSingleMessage; public Rect lastDrawingBackgroundRect = new Rect(); - boolean animateMessageText; + public boolean animateMessageText; private ArrayList animateOutTextBlocks; private ArrayList lastDrawingTextBlocks; private float animateOutTextXOffset; private AnimatedEmojiSpan.EmojiGroupedSpans animateOutAnimateEmoji; + private float lastDrawingReplyTextHeight; + private float animateFromReplyTextHeight; private StaticLayout animateReplyTextLayout; private AnimatedEmojiSpan.EmojiGroupedSpans animateOutAnimateEmojiReply; @@ -19351,8 +20308,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private boolean lastDrawingEdited; boolean animateReplaceCaptionLayout; - private StaticLayout animateOutCaptionLayout; - private StaticLayout lastDrawingCaptionLayout; + private MessageObject.TextLayoutBlocks animateOutCaptionLayout; + private MessageObject.TextLayoutBlocks lastDrawingCaptionLayout; public boolean lastDrawTime; public int lastTimeX; public int animateFromTimeX; @@ -19363,6 +20320,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean lastUseTranscribeButton; public boolean animateUseTranscribeButton; + public float photoImageFromWidth, photoImageFromHeight; + public float photoImageFromCenterX, photoImageFromCenterY; + public boolean animateSmallImage; + + public boolean lastDrawingLinkAbove; + public boolean animateLinkAbove; + + public int lastDrawingLinkPreviewHeight; + public int animateFromLinkPreviewHeight; + public boolean animateLinkPreviewHeight; + public boolean animateDrawingTimeAlpha; public float animateChangeProgress = 1f; @@ -19375,6 +20343,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private float animateFromButtonY; private boolean animateButton; + private int lastMediaOffsetY; + private int animateFromMediaOffsetY; + private boolean animateMediaOffsetY; + public int lastStatusDrawableParams = -1; private int lastViewsCount; @@ -19396,6 +20368,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public float animateFromTextY; public float lastTextXOffset; + public int lastDrawingLinkPreviewY; + public int animateFromLinkPreviewY; + public boolean animateLinkPreviewY; + public int lastTopOffset; public boolean animateForwardedLayout; public int animateForwardedNamesOffset; @@ -19435,6 +20411,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!botButtons.isEmpty()) { lastDrawBotButtons.addAll(botButtons); } + lastDrawingSmallImage = isSmallImage; + lastDrawingLinkPreviewHeight = linkPreviewHeight; + lastDrawingLinkAbove = linkPreviewAbove; if (commentLayout != null) { lastCommentsCount = getRepliesCount(); @@ -19461,6 +20440,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastButtonX = buttonX; lastButtonY = buttonY; + lastMediaOffsetY = mediaOffsetY; lastDrawTime = !forceNotDrawTime; lastTimeX = timeX; @@ -19476,6 +20456,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastDrawingTextY = textY; lastDrawingTextX = textX; + lastDrawingLinkPreviewY = linkPreviewY; lastDrawnForwardedNameLayout[0] = forwardedNameLayout[0]; lastDrawnForwardedNameLayout[1] = forwardedNameLayout[1]; @@ -19484,9 +20465,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastForwardedNamesOffset = namesOffset; lastForwardNameWidth = forwardedNameWidth; lastBackgroundLeft = getCurrentBackgroundLeft(); - lastBackgroundRight = currentBackgroundDrawable.getBounds().right; + if (currentBackgroundDrawable != null) { + lastBackgroundRight = currentBackgroundDrawable.getBounds().right; + } lastTextXOffset = currentMessageObject.textXOffset; + lastDrawingReplyTextHeight = replyTextHeight; lastDrawnReplyTextLayout = replyTextLayout; lastReplyTextXOffset = replyTextOffset; @@ -19547,6 +20531,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate CharSequence newText = replyTextLayout != null ? replyTextLayout.getText() : null; CharSequence oldText = lastDrawnReplyTextLayout != null ? lastDrawnReplyTextLayout.getText() : null; if (!TextUtils.equals(newText, oldText)) { + animateFromReplyTextHeight = lastDrawingReplyTextHeight; animateReplyTextLayout = lastDrawnReplyTextLayout; animateReplyTextOffset = lastReplyTextXOffset; animateOutAnimateEmojiReply = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, false, animateOutAnimateEmojiReply, true, lastDrawnReplyTextLayout); @@ -19594,6 +20579,29 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate changed = true; } + animateSmallImage = false; + if (isSmallImage != lastDrawingSmallImage) { + animateSmallImage = true; + photoImageFromWidth = lastDrawingImageW; + photoImageFromHeight = lastDrawingImageH; + photoImageFromCenterX = lastDrawingImageX + lastDrawingImageW / 2f; + photoImageFromCenterY = lastDrawingImageY + lastDrawingImageH / 2f; + changed = true; + } + + animateLinkAbove = false; + if (linkPreviewAbove != lastDrawingLinkAbove) { + animateLinkAbove = true; + changed = true; + } + + animateLinkPreviewHeight = false; + if (hasLinkPreview && linkPreviewHeight != lastDrawingLinkPreviewHeight) { + animateLinkPreviewHeight = true; + animateFromLinkPreviewHeight = lastDrawingLinkPreviewHeight; + changed = true; + } + animateUseTranscribeButton = false; if (useTranscribeButton != lastUseTranscribeButton) { animateUseTranscribeButton = true; @@ -19601,13 +20609,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (captionLayout != lastDrawingCaptionLayout) { - String oldCaption = lastDrawingCaptionLayout == null ? null : lastDrawingCaptionLayout.getText().toString(); - String currentCaption = captionLayout == null ? null : captionLayout.getText().toString(); + String oldCaption = lastDrawingCaptionLayout == null ? null : lastDrawingCaptionLayout.text.toString(); + String currentCaption = captionLayout == null ? null : captionLayout.text.toString(); if ((currentCaption == null) != (oldCaption == null) || (oldCaption != null && !oldCaption.equals(currentCaption))) { animateReplaceCaptionLayout = true; animateOutCaptionLayout = lastDrawingCaptionLayout; - animateOutAnimateEmoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, null, animateOutCaptionLayout); - animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, animatedEmojiStack, captionLayout); + animateOutAnimateEmoji = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, null, animateOutCaptionLayout == null ? null : animateOutCaptionLayout.textLayoutBlocks); + animatedEmojiStack = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, ChatMessageCell.this, animatedEmojiStack, captionLayout == null ? null : captionLayout.textLayoutBlocks); changed = true; } else { updateCaptionLayout(); @@ -19646,7 +20654,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { if (buttonX != lastButtonX || buttonY != lastButtonY) { animateFromButtonX = lastButtonX; animateFromButtonY = lastButtonY; @@ -19654,6 +20662,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate changed = true; } } + + if (mediaOffsetY != lastMediaOffsetY) { + animateFromMediaOffsetY = lastMediaOffsetY; + animateMediaOffsetY = true; + changed = true; + } boolean timeDrawablesIsChanged = false; @@ -19740,6 +20754,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate changed = true; } + if (lastDrawingLinkPreviewY != linkPreviewY) { + animateLinkPreviewY = true; + animateFromLinkPreviewY = lastDrawingLinkPreviewY; + changed = true; + } + if (currentMessageObject != null) { if (lastDrawnForwardedName != currentMessageObject.needDrawForwarded()) { animateForwardedLayout = true; @@ -19820,6 +20840,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate animateDrawingTimeAlpha = false; transitionBotButtons.clear(); animateButton = false; + animateMediaOffsetY = false; animateReplyTextLayout = null; animateReplies = false; @@ -19833,10 +20854,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate shouldAnimateTimeX = false; animateDrawBackground = false; animateSign = false; + animateSmallImage = false; + animateLinkAbove = false; animateDrawingTimeAlpha = false; animateLocationIsExpired = false; animatePlayingRound = false; animateText = false; + animateLinkPreviewY = false; animateForwardedLayout = false; animatingForwardedNameLayout[0] = null; animatingForwardedNameLayout[1] = null; 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 09c303b65..51b04233d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -52,6 +52,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; +import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.DownloadController; @@ -77,6 +78,7 @@ import org.telegram.messenger.fakepasscode.Utils; 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.Theme; import org.telegram.ui.Adapters.DialogsAdapter; import org.telegram.ui.Components.AnimatedEmojiDrawable; @@ -93,6 +95,7 @@ import org.telegram.ui.Components.Forum.ForumBubbleDrawable; import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.PullForegroundDrawable; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.StaticLayoutEx; @@ -107,7 +110,6 @@ import org.telegram.ui.Components.VectorAvatarThumbDrawable; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.DialogsActivity; import org.telegram.ui.RightSlidingDialogContainer; -import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.StoryViewer; @@ -166,6 +168,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private TimerDrawable timerDrawable; private Paint timerPaint; private Paint timerPaint2; + SharedResources sharedResources; + public final StoriesUtilities.AvatarStoryParams storyParams = new StoriesUtilities.AvatarStoryParams(false) { @Override public void openStory(long dialogId, Runnable onDone) { @@ -193,6 +197,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava private Path thumbPath; private SpoilerEffect thumbSpoiler = new SpoilerEffect(); private boolean drawForwardIcon; + private boolean visibleOnScreen = true; + private boolean updateLayout; + private boolean wasDrawnOnline; public void setMoving(boolean moving) { this.moving = moving; @@ -259,6 +266,20 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } + public void setSharedResources(SharedResources sharedResources) { + this.sharedResources = sharedResources; + } + + public void setVisible(boolean visibleOnScreen) { + if (this.visibleOnScreen == visibleOnScreen) { + return; + } + this.visibleOnScreen = visibleOnScreen; + if (visibleOnScreen) { + invalidate(); + } + } + public static class FixedWidthSpan extends ReplacementSpan { private int width; @@ -754,8 +775,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (checkBox != null) { checkBox.measure( - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.EXACTLY) ); } if (isTopic) { @@ -810,7 +831,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava checkBox.layout(x, y, x + checkBox.getMeasuredWidth(), y + checkBox.getMeasuredHeight()); } int size = getMeasuredHeight() + getMeasuredWidth() << 16; - if (size != lastSize) { + if (size != lastSize || updateLayout) { + updateLayout = false; lastSize = size; try { buildLayout(); @@ -972,21 +994,25 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava buttonLayout = null; } - String messageFormat; + int messageFormatType; if (Build.VERSION.SDK_INT >= 18) { if ((!useForceThreeLines && !SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0) || isForumCell()) { - messageFormat = "%2$s: \u2068%1$s\u2069"; + //1 - "%2$s: \u2068%1$s\u2069"; + messageFormatType = 1; hasNameInMessage = true; } else { - messageFormat = "\u2068%1$s\u2069"; + //2 - "\u2068%1$s\u2069"; + messageFormatType = 2; hasNameInMessage = false; } } else { if ((!useForceThreeLines && !SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0) || isForumCell()) { - messageFormat = "%2$s: %1$s"; + //3 - "%2$s: %1$s"; + messageFormatType = 3; hasNameInMessage = true; } else { - messageFormat = "%1$s"; + //4 - "%1$s"; + messageFormatType = 4; hasNameInMessage = false; } } @@ -1050,7 +1076,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava SpannableStringBuilder stringBuilder; if (customDialog.isMedia) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, message.messageText)); + stringBuilder = formatInternal(messageFormatType, message.messageText, null); stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_attachMessage, resourcesProvider), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { String mess = customDialog.message; @@ -1058,9 +1084,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava mess = mess.substring(0, 150); } if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess, messageNameString)); + stringBuilder = formatInternal(messageFormatType, mess, messageNameString); } else { - stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, mess.replace('\n', ' '), messageNameString)); + stringBuilder = formatInternal(messageFormatType, mess.replace('\n', ' '), messageNameString); } } messageString = Emoji.replaceEmoji(stringBuilder, Theme.dialogs_messagePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(20), false); @@ -1192,7 +1218,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava draftMessage = null; } - if (draftMessage != null && (TextUtils.isEmpty(draftMessage.message) && draftMessage.reply_to_msg_id == 0 || lastDate > draftMessage.date && unreadCount != 0) || + if (draftMessage != null && (TextUtils.isEmpty(draftMessage.message) && (draftMessage.reply_to == null || draftMessage.reply_to.reply_to_msg_id == 0) || lastDate > draftMessage.date && unreadCount != 0) || ChatObject.isChannel(chat) && !chat.megagroup && !chat.creator && (chat.admin_rights == null || !chat.admin_rights.post_messages) || chat != null && (chat.left || chat.kicked) || forbidDraft || ChatObject.isForum(chat) && !isTopic) { draftMessage = null; @@ -1205,7 +1231,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava messageNameString = getMessageNameString(); messageString = formatTopicsNames(); String restrictionReason = message != null ? MessagesController.getRestrictionReason(message.messageOwner.restriction_reason) : null; - buttonString = message != null ? getMessageStringFormatted(messageFormat, restrictionReason, messageNameString, true) : ""; + buttonString = message != null ? getMessageStringFormatted(messageFormatType, restrictionReason, messageNameString, true) : ""; if (applyName && buttonString.length() >= 0 && messageNameString != null) { SpannableStringBuilder spannableStringBuilder = SpannableStringBuilder.valueOf(buttonString); spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_name, resourcesProvider), 0, Math.min(spannableStringBuilder.length(), messageNameString.length() + 1), 0); @@ -1261,7 +1287,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava MediaDataController.addAnimatedEmojiSpans(draftMessage.entities, messSpan, currentMessagePaint == null ? null : currentMessagePaint.getFontMetricsInt()); } - SpannableStringBuilder stringBuilder = AndroidUtilities.formatSpannable(messageFormat, AndroidUtilities.replaceNewLines(messSpan), messageNameString); + SpannableStringBuilder stringBuilder = formatInternal(messageFormatType, AndroidUtilities.replaceNewLines(messSpan), messageNameString); if (!useForceThreeLines && !SharedConfig.useThreeLinesLayout) { stringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_chats_draft, resourcesProvider), 0, messageNameString.length() + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } @@ -1291,7 +1317,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } else { if (dialogsType == DialogsActivity.DIALOGS_TYPE_FORWARD && UserObject.isUserSelf(user)) { - messageString = LocaleController.getString("SavedMessagesInfo", R.string.SavedMessagesInfo); + messageString = LocaleController.getString(parentFragment != null && parentFragment.isQuote ? R.string.SavedMessagesInfoQuote : R.string.SavedMessagesInfo); showChecks = false; drawTime = false; } else { @@ -1364,7 +1390,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava showChecks = false; drawTime = false; } else if (dialogsType == DialogsActivity.DIALOGS_TYPE_FORWARD && UserObject.isUserSelf(user)) { - messageString = LocaleController.getString("SavedMessagesInfo", R.string.SavedMessagesInfo); + messageString = LocaleController.getString(parentFragment != null && parentFragment.isQuote ? R.string.SavedMessagesInfoQuote : R.string.SavedMessagesInfo); showChecks = false; drawTime = false; } else if (!useForceThreeLines && !SharedConfig.useThreeLinesLayout && currentDialogFolderId != 0) { @@ -1400,7 +1426,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } checkMessage = false; - SpannableStringBuilder stringBuilder = getMessageStringFormatted(messageFormat, restrictionReason, messageNameString, false); + SpannableStringBuilder stringBuilder = getMessageStringFormatted(messageFormatType, restrictionReason, messageNameString, false); int thumbInsertIndex = 0; if (!useFromUserAsAvatar && (!useForceThreeLines && !SharedConfig.useThreeLinesLayout || currentDialogFolderId != 0 && stringBuilder.length() > 0)) { @@ -1499,7 +1525,10 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; } else { - if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { + if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGiveaway) { + TLRPC.TL_messageMediaGiveaway mediaPoll = (TLRPC.TL_messageMediaGiveaway) message.messageOwner.media; + messageString = LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway);; + } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaPoll) { TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) message.messageOwner.media; messageString = "\uD83D\uDCCA " + mediaPoll.poll.question; } else if (message.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { @@ -1731,7 +1760,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava topicIconInName = new Drawable[1]; } topicIconInName[0] = null; - nameString = showTopicIconInName ? ForumUtilities.getTopicSpannedName(forumTopic, Theme.dialogs_namePaint[paintIndex], topicIconInName) : forumTopic.title; + nameString = showTopicIconInName ? ForumUtilities.getTopicSpannedName(forumTopic, Theme.dialogs_namePaint[paintIndex], topicIconInName, false) : forumTopic.title; } else { nameString = UserConfig.getChatTitleOverride(currentAccount, chat); } @@ -2163,8 +2192,8 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava // Removing links and bold spans to get rid of underlining and boldness if (messageStringFinal instanceof Spannable) { Spannable messageStringSpannable = (Spannable) messageStringFinal; - for (CharacterStyle span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), CharacterStyle.class)) { - if (span instanceof ClickableSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { + for (Object span : messageStringSpannable.getSpans(0, messageStringSpannable.length(), Object.class)) { + if (span instanceof ClickableSpan || span instanceof CodeHighlighting.Span || span instanceof CodeHighlighting.ColorSpan || span instanceof QuoteSpan || span instanceof QuoteSpan.QuoteStyleSpan || (span instanceof StyleSpan && ((StyleSpan) span).getStyle() == android.graphics.Typeface.BOLD)) { messageStringSpannable.removeSpan(span); } } @@ -2351,6 +2380,29 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava updateThumbsPosition(); } + private SpannableStringBuilder formatInternal(int messageFormatType, CharSequence s1, CharSequence s2) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + switch (messageFormatType) { + case 1: + //"%2$s: \u2068%1$s\u2069" + spannableStringBuilder.append(s2).append(": \u2068").append(s1).append("\u2069"); + break; + case 2: + //"\u2068%1$s\u2069" + spannableStringBuilder.append("\u2068").append(s1).append("\u2069"); + break; + case 3: + //"%2$s: %1$s" + spannableStringBuilder.append(s2).append(": ").append(s1); + break; + case 4: + //"%1$s" + spannableStringBuilder.append(s1); + break; + } + return spannableStringBuilder; + } + private void updateThumbsPosition() { if (thumbsCount > 0) { StaticLayout layout = isForumCell() ? buttonLayout : messageLayout; @@ -2404,80 +2456,21 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava int topMessageTopicEndIndex; private CharSequence formatTopicsNames() { - topMessageTopicStartIndex = 0; - topMessageTopicEndIndex = 0; - if (chat != null) { - List topics = MessagesController.getInstance(currentAccount).getTopicsController().getTopics(chat.id); - - boolean hasDivider = false; - if (topics != null && !topics.isEmpty()) { - topics = new ArrayList<>(topics); - Collections.sort(topics, Comparator.comparingInt(o -> -o.top_message)); - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); - int topMessageTopicId = 0; - int boldLen = 0; - if (message != null) { - topMessageTopicId = MessageObject.getTopicId(message.messageOwner, true); - TLRPC.TL_forumTopic topic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(chat.id, topMessageTopicId); - if (topic != null) { - CharSequence topicString = ForumUtilities.getTopicSpannedName(topic, currentMessagePaint); - spannableStringBuilder.append(topicString); - if (topic.unread_count > 0) { - boldLen = topicString.length(); - } - topMessageTopicStartIndex = 0; - topMessageTopicEndIndex = topicString.length(); - - if (message.isOutOwner()) { - lastTopicMessageUnread = topic.read_inbox_max_id < message.getId(); - } else { - lastTopicMessageUnread = topic.unread_count > 0; - } - } else { - lastTopicMessageUnread = false; - } - if (lastTopicMessageUnread) { - spannableStringBuilder.append(" "); - spannableStringBuilder.setSpan(new FixedWidthSpan(AndroidUtilities.dp(3)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); - hasDivider = true; - } - } - - boolean firstApplay = true; - for (int i = 0; i < Math.min(5, topics.size()); i++) { - if (topics.get(i).id == topMessageTopicId) { - continue; - } - - if (spannableStringBuilder.length() != 0) { - if (firstApplay && hasDivider) { - spannableStringBuilder.append(" "); - } else { - spannableStringBuilder.append(", "); - } - } - firstApplay = false; - CharSequence topicString = ForumUtilities.getTopicSpannedName(topics.get(i), currentMessagePaint); - spannableStringBuilder.append(topicString); - } - if (boldLen > 0) { - spannableStringBuilder.setSpan( - new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.key_chats_name, null), - 0, Math.min(spannableStringBuilder.length(), boldLen + 2), 0 - ); - } - return spannableStringBuilder; - } - - if (!MessagesController.getInstance(currentAccount).getTopicsController().endIsReached(chat.id)) { - MessagesController.getInstance(currentAccount).getTopicsController().preloadTopics(chat.id); - return LocaleController.getString("Loading", R.string.Loading); - } else { - return "no created topics"; + ForumFormattedNames forumFormattedNames = null; + if (sharedResources != null) { + forumFormattedNames = sharedResources.formattedTopicNames.get(getDialogId()); + } + if (forumFormattedNames == null) { + forumFormattedNames = new ForumFormattedNames(); + if (sharedResources != null) { + sharedResources.formattedTopicNames.put(getDialogId(), forumFormattedNames); } } - - return null; + forumFormattedNames.formatTopicsNames(currentAccount, message, chat); + topMessageTopicStartIndex = forumFormattedNames.topMessageTopicStartIndex; + topMessageTopicEndIndex = forumFormattedNames.topMessageTopicEndIndex; + lastTopicMessageUnread = forumFormattedNames.lastTopicMessageUnread; + return forumFormattedNames.formattedNames; } public boolean isForumCell() { @@ -2639,9 +2632,11 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava public boolean update(int mask, boolean animated) { boolean requestLayout = false; boolean rebuildLayout = false; + boolean invalidate = false; boolean oldIsForumCell = isForumCell(); drawAvatarSelector = false; ttlPeriod = 0; + if (customDialog != null) { lastMessageDate = customDialog.date; lastUnreadState = customDialog.unread_count != 0; @@ -2728,9 +2723,11 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (mask != 0) { boolean continueUpdate = false; - if (user != null && (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { + if (user != null && !MessagesController.isSupportUser(user) && !user.bot && (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { user = MessagesController.getInstance(currentAccount).getUser(user.id); - invalidate(); + if (wasDrawnOnline != isOnline()) { + invalidate = true; + } } if (user != null && (mask & MessagesController.UPDATE_MASK_EMOJI_STATUS) != 0) { user = MessagesController.getInstance(currentAccount).getUser(user.id); @@ -2742,7 +2739,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava nameLayoutEllipsizeByGradient = true; emojiStatus.set(PremiumGradient.getInstance().premiumStarDrawableMini, animated); } - invalidate(); + invalidate = true; } if (isDialogCell || isTopic) { if ((mask & MessagesController.UPDATE_MASK_USER_PRINT) != 0) { @@ -2835,7 +2832,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } if (!continueUpdate) { - invalidate(); + //if (invalidate) { + invalidate(); + // } return requestLayout; } } @@ -3015,8 +3014,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } if (!isTopic && (getMeasuredWidth() != 0 || getMeasuredHeight() != 0)) { rebuildLayout = true; - } else { - //requestLayout(); + } + if (!invalidate) { + boolean currentStoriesIsEmpty = storyParams.currentState == StoriesUtilities.STATE_EMPTY; + boolean newStateStoriesIsEmpty = StoriesUtilities.getPredictiveUnreadState(MessagesController.getInstance(currentAccount).getStoriesController(), getDialogId()) == StoriesUtilities.STATE_EMPTY; + if (!newStateStoriesIsEmpty || (!currentStoriesIsEmpty && newStateStoriesIsEmpty)) { + invalidate = true; + } } if (!animated) { @@ -3025,13 +3029,18 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava countAnimator.cancel(); } } - - invalidate(); + // if (invalidate) { + invalidate(); + // } if (isForumCell() != oldIsForumCell) { requestLayout = true; } if (rebuildLayout) { - buildLayout(); + if (attachedToWindow) { + buildLayout(); + } else { + updateLayout = true; + } } return requestLayout; } @@ -3083,6 +3092,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (currentDialogId == 0 && customDialog == null) { return; } + if (!visibleOnScreen && !drawingForBlur) { + return; + } boolean needInvalidate = false; @@ -3391,7 +3403,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } canvas.save(); canvas.translate(nameLeft + nameLayoutTranslateX, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 10 : 13)); - nameLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(nameLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, nameLayout, animatedEmojiStackName, -.075f, null, 0, 0, 0, 1f); canvas.restore(); if (nameLayoutEllipsizeByGradient && !nameLayoutFits) { @@ -3411,7 +3423,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (timeLayout != null && currentDialogFolderId == 0) { canvas.save(); canvas.translate(timeLeft, timeTop); - timeLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(timeLayout, canvas); canvas.restore(); } @@ -3436,7 +3448,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava canvas.save(); canvas.translate(messageNameLeft, messageNameTop); try { - messageNameLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(messageNameLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, messageNameLayout, animatedEmojiStack2, -.075f, null, 0, 0, 0, 1f); } catch (Exception e) { FileLog.e(e); @@ -3470,7 +3482,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava try { canvas.save(); SpoilerEffect.clipOutCanvas(canvas, spoilers); - messageLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(messageLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, messageLayout, animatedEmojiStack, -.075f, spoilers, 0, 0, 0, 1f); canvas.restore(); @@ -3483,7 +3495,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava FileLog.e(e); } } else { - messageLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(messageLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, messageLayout, animatedEmojiStack, -.075f, null, 0, 0, 0, 1f); } messageLayout.getPaint().setAlpha(oldAlpha); @@ -3578,7 +3590,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava try { canvas.save(); SpoilerEffect.clipOutCanvas(canvas, spoilers2); - buttonLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(buttonLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, buttonLayout, animatedEmojiStack3, -.075f, spoilers2, 0, 0, 0, 1f); canvas.restore(); @@ -3591,7 +3603,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava FileLog.e(e); } } else { - buttonLayout.draw(canvas); + SpoilerEffect.layoutDrawMaybe(buttonLayout, canvas); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, buttonLayout, animatedEmojiStack3, -.075f, null, 0, 0, 0, 1f); } canvas.restore(); @@ -3782,16 +3794,16 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava thumbBackgroundPaint.setColor(0x00000000); } AndroidUtilities.rectTmp.set( - thumbImage[i].getImageX(), - thumbImage[i].getImageY(), - thumbImage[i].getImageX2(), - thumbImage[i].getImageY2() + thumbImage[i].getImageX(), + thumbImage[i].getImageY(), + thumbImage[i].getImageX2(), + thumbImage[i].getImageY2() ); canvas.drawRoundRect( - AndroidUtilities.rectTmp, - thumbImage[i].getRoundRadius()[0], - thumbImage[i].getRoundRadius()[1], - thumbBackgroundPaint + AndroidUtilities.rectTmp, + thumbImage[i].getRoundRadius()[0], + thumbImage[i].getRoundRadius()[1], + thumbBackgroundPaint ); thumbImage[i].draw(canvas); if (drawSpoiler[i]) { @@ -4059,6 +4071,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } if (user != null && !MessagesController.isSupportUser(user) && !user.bot) { boolean isOnline = isOnline(); + wasDrawnOnline = isOnline; if (isOnline || onlineProgress != 0) { int top = (int) (storyParams.originalAvatarRect.bottom - AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 6 : 8)); int left; @@ -4646,7 +4659,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (groupMessages != null && groupMessages.size() > 1 && TextUtils.isEmpty(restrictionReason) && currentDialogFolderId == 0 && encryptedChat == null) { thumbsCount = 0; hasVideoThumb = false; - Collections.sort(groupMessages, (a, b) -> a.getId() - b.getId()); + Collections.sort(groupMessages, Comparator.comparingInt(MessageObject::getId)); for (int i = 0; i < Math.min(3, groupMessages.size()); ++i) { MessageObject message = groupMessages.get(i); if (message != null && !message.needDrawBluredPreview() && (message.isPhoto() || message.isNewGif() || message.isVideo() || message.isRoundVideo() || message.isStoryMedia())) { @@ -4672,7 +4685,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava ArrayList photoThumbs = message.photoThumbs; TLObject photoThumbsObject = message.photoThumbsObject; if (message.isStoryMedia()) { - TLRPC.StoryItem storyItem = message.messageOwner.media.storyItem; + TL_stories.StoryItem storyItem = message.messageOwner.media.storyItem; if (storyItem != null && storyItem.media != null) { if (storyItem.media.document != null) { photoThumbs = storyItem.media.document.thumbs; @@ -4748,13 +4761,13 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } } - public SpannableStringBuilder getMessageStringFormatted(String messageFormat, String restrictionReason, CharSequence messageNameString, boolean applyThumbs) { + public SpannableStringBuilder getMessageStringFormatted(int messageFormatType, String restrictionReason, CharSequence messageNameString, boolean applyThumbs) { SpannableStringBuilder stringBuilder; MessageObject captionMessage = getCaptionMessage(); CharSequence msgText = message != null ? message.messageText : null; applyName = true; if (!TextUtils.isEmpty(restrictionReason)) { - stringBuilder = SpannableStringBuilder.valueOf(AndroidUtilities.formatSpannable(messageFormat, restrictionReason, messageNameString)); + stringBuilder = formatInternal(messageFormatType, restrictionReason, messageNameString); } else if (message.messageOwner instanceof TLRPC.TL_messageService) { CharSequence mess; if (message.messageTextShort != null && (!(message.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate) || !isTopic)) { @@ -4763,7 +4776,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava mess = message.messageText; } if (MessageObject.isTopicActionMessage(message)) { - stringBuilder = AndroidUtilities.formatSpannable(messageFormat, mess, messageNameString); + stringBuilder = formatInternal(messageFormatType, mess, messageNameString); if (message.topicIconDrawable[0] instanceof ForumBubbleDrawable) { TLRPC.TL_forumTopic topic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(-message.getDialogId(), MessageObject.getTopicId(message.messageOwner, true)); if (topic != null) { @@ -4823,7 +4836,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (applyThumbs) { charSequence = applyThumbs(charSequence); } - stringBuilder = AndroidUtilities.formatSpannable(messageFormat, charSequence, messageNameString); + stringBuilder = formatInternal(messageFormatType, charSequence, messageNameString); } } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; @@ -4866,7 +4879,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (applyThumbs) { message = applyThumbs(innerMessage); } - stringBuilder = AndroidUtilities.formatSpannable(messageFormat, message, messageNameString); + stringBuilder = formatInternal(messageFormatType, message, messageNameString); if (!isForumCell()) { try { stringBuilder.setSpan(new ForegroundColorSpanThemable(colorKey, resourcesProvider), hasNameInMessage ? messageNameString.length() + 2 : 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); @@ -4907,9 +4920,9 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava if (applyThumbs) { mess = applyThumbs(mess); } - stringBuilder = AndroidUtilities.formatSpannable(messageFormat, mess, messageNameString); + stringBuilder = formatInternal(messageFormatType, mess, messageNameString); } else { - stringBuilder = SpannableStringBuilder.valueOf(""); + stringBuilder = new SpannableStringBuilder(); } return stringBuilder; } @@ -5057,7 +5070,7 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } else if (isDialogCell) { draftMessage = MediaDataController.getInstance(currentAccount).getDraft(currentDialogId, 0); } - int draftHash = draftMessage == null ? 0 : draftMessage.message.hashCode() + (draftMessage.reply_to_msg_id << 16); + int draftHash = draftMessage == null ? 0 : draftMessage.message.hashCode() + (draftMessage.reply_to != null ? (draftMessage.reply_to.reply_to_msg_id << 16) : 0); boolean hasCall = chat != null && chat.call_active && chat.call_not_empty; boolean translated = MessagesController.getInstance(currentAccount).getTranslateController().isTranslatingDialog(currentDialogId); if (lastDrawnSizeHash == sizeHash && @@ -5144,4 +5157,103 @@ public class DialogCell extends BaseCell implements StoriesListPlaceProvider.Ava } super.invalidate(l, t, r, b); } + + public static class SharedResources { + LongSparseArray formattedTopicNames = new LongSparseArray<>(); + } + + private static class ForumFormattedNames { + int lastMessageId; + + int topMessageTopicStartIndex; + int topMessageTopicEndIndex; + boolean lastTopicMessageUnread; + boolean isLoadingState; + CharSequence formattedNames; + + private void formatTopicsNames(int currentAccount, MessageObject message, TLRPC.Chat chat) { + int messageId = message == null || chat == null ? 0 : message.getId(); + if (lastMessageId == messageId && !isLoadingState) { + return; + } + topMessageTopicStartIndex = 0; + topMessageTopicEndIndex = 0; + lastTopicMessageUnread = false; + isLoadingState = false; + lastMessageId = messageId; + Paint currentMessagePaint = Theme.dialogs_messagePaint[0]; + if (chat != null) { + List topics = MessagesController.getInstance(currentAccount).getTopicsController().getTopics(chat.id); + + boolean hasDivider = false; + if (topics != null && !topics.isEmpty()) { + topics = new ArrayList<>(topics); + Collections.sort(topics, Comparator.comparingInt(o -> -o.top_message)); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + int topMessageTopicId = 0; + int boldLen = 0; + if (message != null) { + topMessageTopicId = MessageObject.getTopicId(message.messageOwner, true); + TLRPC.TL_forumTopic topic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(chat.id, topMessageTopicId); + if (topic != null) { + CharSequence topicString = ForumUtilities.getTopicSpannedName(topic, currentMessagePaint, false); + spannableStringBuilder.append(topicString); + if (topic.unread_count > 0) { + boldLen = topicString.length(); + } + topMessageTopicStartIndex = 0; + topMessageTopicEndIndex = topicString.length(); + + if (message.isOutOwner()) { + lastTopicMessageUnread = false; + } else { + lastTopicMessageUnread = topic.unread_count > 0; + } + } else { + lastTopicMessageUnread = false; + } + if (lastTopicMessageUnread) { + spannableStringBuilder.append(" "); + spannableStringBuilder.setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(3)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); + hasDivider = true; + } + } + + boolean firstApplay = true; + for (int i = 0; i < Math.min(4, topics.size()); i++) { + if (topics.get(i).id == topMessageTopicId) { + continue; + } + + if (spannableStringBuilder.length() != 0) { + if (firstApplay && hasDivider) { + spannableStringBuilder.append(" "); + } else { + spannableStringBuilder.append(", "); + } + } + firstApplay = false; + CharSequence topicString = ForumUtilities.getTopicSpannedName(topics.get(i), currentMessagePaint, false); + spannableStringBuilder.append(topicString); + } + if (boldLen > 0) { + spannableStringBuilder.setSpan( + new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf"), 0, Theme.key_chats_name, null), + 0, Math.min(spannableStringBuilder.length(), boldLen + 2), 0 + ); + } + formattedNames = spannableStringBuilder; + return; + } + + if (!MessagesController.getInstance(currentAccount).getTopicsController().endIsReached(chat.id)) { + MessagesController.getInstance(currentAccount).getTopicsController().preloadTopics(chat.id); + formattedNames = LocaleController.getString("Loading", R.string.Loading); + isLoadingState = true; + } else { + formattedNames = "no created topics"; + } + } + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java index b75b2bc20..c32605d25 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ExpiredStoryView.java @@ -48,6 +48,9 @@ public class ExpiredStoryView { String from = LocaleController.getString("From", R.string.From); int fromWidth = (int) Math.ceil(Theme.chat_forwardNamePaint.measureText(from + " ")); + if (fromName == null) { + fromName = ""; + } fromName = (String) TextUtils.ellipsize(fromName.replace('\n', ' '), Theme.chat_replyNamePaint, forwardedNameWidth - fromWidth, TextUtils.TruncateAt.END); String fromString = LocaleController.getString("FromFormatted", R.string.FromFormatted); int idx = fromString.indexOf("%1$s"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java index 2231f56de..e0f749ef7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java @@ -34,6 +34,7 @@ public class GraySectionCell extends FrameLayout { private TextView textView; private AnimatedTextView rightTextView; private final Theme.ResourcesProvider resourcesProvider; + private int layerHeight = 32; public GraySectionCell(Context context) { this(context, null); @@ -70,7 +71,14 @@ public class GraySectionCell extends FrameLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(32), MeasureSpec.EXACTLY)); + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(layerHeight), MeasureSpec.EXACTLY)); + } + + public void setLayerHeight(int dp){ + layerHeight = dp; + requestLayout(); } public void setTextColor(int key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatTextCell.java index f5bdbfcda..d77097e37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatTextCell.java @@ -71,7 +71,11 @@ public class ManageChatTextCell extends FrameLayout { textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + 24), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); - setMeasuredDimension(width, AndroidUtilities.dp(56) + (divider ? 1 : 0)); + setMeasuredDimension(width, getFullHeight() + (divider ? 1 : 0)); + } + + protected int getFullHeight() { + return AndroidUtilities.dp(56); } @Override 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 48c7a1fac..7d34934d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -827,7 +827,7 @@ public class ProfileSearchCell extends BaseCell implements NotificationCenter.No @Override public boolean onTouchEvent(MotionEvent event) { - if (user != null && avatarStoryParams.checkOnTouchEvent(event, this)) { + if ((user != null || chat != null) && avatarStoryParams.checkOnTouchEvent(event, this)) { return true; } if (actionButton != null && actionButton.checkTouchEvent(event)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java index 482ed9f30..014c8e44d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java @@ -118,7 +118,7 @@ public class ShareDialogCell extends FrameLayout { }); addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 19, currentType == TYPE_CREATE ? -40 : 42, 0, 0)); - setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector), AndroidUtilities.dp(2), AndroidUtilities.dp(2))); + setBackground(Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), AndroidUtilities.dp(2), AndroidUtilities.dp(2))); } @Override @@ -189,7 +189,7 @@ public class ShareDialogCell extends FrameLayout { } if (visible) { - topicTextView.setText(ForumUtilities.getTopicSpannedName(topic, topicTextView.getTextPaint())); + topicTextView.setText(ForumUtilities.getTopicSpannedName(topic, topicTextView.getTextPaint(), false)); topicTextView.requestLayout(); } if (animate) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java index dc11ff06a..f54eeb602 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -30,6 +30,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.core.math.MathUtils; @@ -45,6 +46,8 @@ import org.telegram.messenger.R; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CanvasButton; import org.telegram.ui.Components.CheckBoxBase; import org.telegram.ui.Components.CombinedDrawable; @@ -68,10 +71,16 @@ public class SharedPhotoVideoCell2 extends FrameLayout { SharedPhotoVideoCell2 crossfadeView; float imageAlpha = 1f; float imageScale = 1f; + boolean showVideoLayout; StaticLayout videoInfoLayot; - boolean drawVideoIcon = true; String videoText; + boolean drawVideoIcon = true; + + boolean drawViews; + AnimatedFloat viewsAlpha = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + AnimatedTextView.AnimatedTextDrawable viewsText = new AnimatedTextView.AnimatedTextDrawable(false, true, true); + CheckBoxBase checkBoxBase; SharedResources sharedResources; private boolean attached; @@ -120,6 +129,12 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } }); + viewsText.setCallback(this); + viewsText.setTextSize(dp(12)); + viewsText.setTextColor(Color.WHITE); + viewsText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + viewsText.setOverrideFullWidth(AndroidUtilities.displaySize.x); + setWillNotDraw(false); } @@ -164,6 +179,9 @@ public class SharedPhotoVideoCell2 extends FrameLayout { imageReceiver.onDetachedFromWindow(); blurImageReceiver.onDetachedFromWindow(); videoText = null; + drawViews = false; + viewsAlpha.set(0f, true); + viewsText.setText("", false); videoInfoLayot = null; showVideoLayout = false; gradientDrawableLoading = false; @@ -194,6 +212,15 @@ public class SharedPhotoVideoCell2 extends FrameLayout { videoInfoLayot = null; showVideoLayout = false; imageReceiver.clearDecorators(); + if (isStory && messageObject.storyItem.views != null) { + drawViews = messageObject.storyItem.views.views_count > 0; + viewsText.setText(AndroidUtilities.formatWholeNumber(messageObject.storyItem.views.views_count, 0), false); + } else { + drawViews = false; + viewsAlpha.set(0f, true); + viewsText.setText("", false); + } + viewsAlpha.set(drawViews ? 1f : 0f, true); if (!TextUtils.isEmpty(restrictionReason)) { showImageStub = true; } else if (messageObject.storyItem != null && messageObject.storyItem.media instanceof TLRPC.TL_messageMediaUnsupported) { @@ -417,8 +444,8 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } bounds.set(imageReceiver.getImageX(), imageReceiver.getImageY(), imageReceiver.getImageX2(), imageReceiver.getImageY2()); - bounds.set(leftpadding, padding, leftpadding + imageWidth - rightpadding, padding + imageHeight); drawDuration(canvas, bounds, 1f); + drawViews(canvas, bounds, 1f); if (checkBoxBase != null && (style == STYLE_CACHE || checkBoxBase.getProgress() != 0)) { canvas.save(); @@ -492,6 +519,59 @@ public class SharedPhotoVideoCell2 extends FrameLayout { canvas.restore(); } + public void updateViews() { + if (isStory && currentMessageObject != null && currentMessageObject.storyItem != null && currentMessageObject.storyItem.views != null) { + drawViews = currentMessageObject.storyItem.views.views_count > 0; + viewsText.setText(AndroidUtilities.formatWholeNumber(currentMessageObject.storyItem.views.views_count, 0), true); + } else { + drawViews = false; + viewsText.setText("", false); + } + } + + public void drawViews(Canvas canvas, RectF bounds, float alpha) { + if (!isStory || imageReceiver != null && !imageReceiver.getVisible() || currentParentColumnsCount >= 5) { + return; + } + + float a = viewsAlpha.set(drawViews); + alpha *= a; + + if (alpha < 1) { + alpha = (float) Math.pow(alpha, 8); + } + + if (a <= 0) { + return; + } + + canvas.save(); + canvas.translate(bounds.left, bounds.top); + canvas.clipRect(0, 0, bounds.width(), bounds.height()); + + float width = dp(18 + 8) + viewsText.getCurrentWidth(); + + canvas.translate(bounds.width() - dp(5) - width, dp(1) + bounds.height() - dp(17) - dp(4)); + AndroidUtilities.rectTmp.set(0, 0, width, dp(17)); + int oldAlpha = Theme.chat_timeBackgroundPaint.getAlpha(); + Theme.chat_timeBackgroundPaint.setAlpha((int) (oldAlpha * alpha)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(4), dp(4), Theme.chat_timeBackgroundPaint); + Theme.chat_timeBackgroundPaint.setAlpha(oldAlpha); + + canvas.save(); + canvas.translate(dp(3), (dp(17) - sharedResources.viewDrawable.getBounds().height()) / 2f); + sharedResources.viewDrawable.setAlpha((int) (255 * imageAlpha * alpha)); + sharedResources.viewDrawable.draw(canvas); + canvas.restore(); + + canvas.translate(dp(4 + 18), 0); + viewsText.setBounds(0, 0, (int) width, dp(17)); + viewsText.setAlpha((int) (0xFF * alpha)); + viewsText.draw(canvas); + + canvas.restore(); + } + public boolean canRevealSpoiler() { return currentMessageObject != null && currentMessageObject.hasMediaSpoilers() && spoilerRevealProgress == 0f && !currentMessageObject.isMediaSpoilersRevealedInSharedMedia; } @@ -704,6 +784,7 @@ public class SharedPhotoVideoCell2 extends FrameLayout { TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Paint backgroundPaint = new Paint(); Drawable playDrawable; + Drawable viewDrawable; Paint highlightPaint = new Paint(); SparseArray imageFilters = new SparseArray<>(); @@ -713,6 +794,8 @@ public class SharedPhotoVideoCell2 extends FrameLayout { textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); playDrawable = ContextCompat.getDrawable(context, R.drawable.play_mini_video); playDrawable.setBounds(0, 0, playDrawable.getIntrinsicWidth(), playDrawable.getIntrinsicHeight()); + viewDrawable = ContextCompat.getDrawable(context, R.drawable.filled_views); + viewDrawable.setBounds(0, 0, (int) (viewDrawable.getIntrinsicWidth() * .7f), (int) (viewDrawable.getIntrinsicHeight() * .7f)); backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder, resourcesProvider)); } @@ -735,4 +818,9 @@ public class SharedPhotoVideoCell2 extends FrameLayout { } return super.onTouchEvent(event); } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return viewsText == who || super.verifyDrawable(who); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java index bf0c9d647..b11c1f6eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java @@ -188,6 +188,10 @@ public class TextInfoPrivacyCell extends FrameLayout { } } + public void setTextGravity(int gravity) { + textView.setGravity(gravity); + } + @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java index ea575db55..bb562c087 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -19,6 +19,7 @@ import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; +import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.util.SparseIntArray; @@ -76,7 +77,7 @@ public abstract class TextSelectionHelper= 0 && offset < text.length() && text.charAt(offset) != '\n') { + AndroidUtilities.cancelRunOnUIThread(startSelectionRunnable); AndroidUtilities.runOnUIThread(startSelectionRunnable, longpressDelay); tryCapture = true; } @@ -502,6 +506,11 @@ public abstract class TextSelectionHelper { + textSelectionOverlay.invalidate(); + showActions(); + }; + private void showActions() { if (textSelectionOverlay == null) { return; @@ -586,6 +595,14 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.M && actionMode != null) { @@ -1386,19 +1410,21 @@ public abstract class TextSelectionHelper= charSequence.length() - 1) { - menu.getItem(1).setVisible(false); + menu.getItem(2).setVisible(false); } else { - menu.getItem(1).setVisible(true); + menu.getItem(2).setVisible(true); } } if (onTranslateListener != null && LanguageDetector.hasSupport() && getSelectedText() != null) { @@ -1421,7 +1447,7 @@ public abstract class TextSelectionHelper showActions()); - } - hideActions(); - return true; - default: - clear(); + } + selectionStart = 0; + selectionEnd = text.length(); + hideActions(); + invalidate(); + AndroidUtilities.cancelRunOnUIThread(showActionsRunnable); + AndroidUtilities.runOnUIThread(showActionsRunnable); + return true; + } else if (itemId == TRANSLATE) { + if (onTranslateListener != null) { + String translateToLanguage = LocaleController.getInstance().getCurrentLocale().getLanguage(); + onTranslateListener.run(getSelectedText(), translateFromLanguage, translateToLanguage, () -> showActions()); + } + hideActions(); + return true; + } else if (itemId == R.id.menu_quote) { + quoteText(); + hideActions(); + return true; + } else { + clear(); } return true; } @@ -1545,6 +1576,26 @@ public abstract class TextSelectionHelper 0 && end < text.length() && !Character.isWhitespace(text.charAt(end - 1))) { - rect = new Rect(l, layout.getLineTop(startLine), r + halfR, layout.getLineBottom(startLine)); + rect = new Rect((int) Math.max(minX, l) - halfR, layout.getLineTop(startLine), (int) Math.max(minX, r) + halfR, layout.getLineBottom(startLine)); } } - drawLine(layout, startLine, selectionStart, end, !hasStart, true); + drawLine(layout, startLine, selectionStart, end, !hasStart, true, minX); if (rect != null) { AndroidUtilities.rectTmp.set(rect); selectionPath.addRect(AndroidUtilities.rectTmp, Path.Direction.CW); @@ -1625,9 +1676,9 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O; if (restore) { @@ -1676,7 +1727,7 @@ public abstract class TextSelectionHelper { + public boolean isTouched() { + return movingHandle; + } + SparseArray animatorSparseArray = new SparseArray<>(); - private boolean isDescription; + public boolean isDescription; private boolean maybeIsDescription; public static int TYPE_MESSAGE = 0; public static int TYPE_CAPTION = 1; public static int TYPE_DESCRIPTION = 2; + public void select(ChatMessageCell cell, int start, int end) { + if (cell == null) { + return; + } + selectedView = cell; + selectedCellId = selectedView.getMessageObject().getId(); + selectionStart = start; + selectionEnd = end; + invalidate(); + if (super.callback != null) { + super.callback.onStateChanged(true); + } + movingDirectionSettling = true; + movingOffsetY = 0; + movingOffsetX = 0; + onOffsetChanged(); + allowDiscard = false; + if (textSelectionOverlay != null) { + textSelectionOverlay.setVisibility(View.VISIBLE); + } + showHandleViews(); + } + @Override protected int getLineHeight() { if (selectedView != null && selectedView.getMessageObject() != null) { @@ -1862,7 +1940,7 @@ public abstract class TextSelectionHelper 0) { + MessageObject.TextLayoutBlocks captionLayout = chatMessageCell.getCaptionLayout(); + MessageObject.TextLayoutBlock block = captionLayout.textLayoutBlocks.get(captionLayout.textLayoutBlocks.size() - 1); + textArea.set( + maybeTextX, maybeTextY, + maybeTextX + block.textLayout.getWidth(), + (int) (maybeTextY + block.textYOffset + block.padTop + block.textLayout.getHeight()) + ); } else if (messageObject != null && messageObject.textLayoutBlocks != null && messageObject.textLayoutBlocks.size() > 0) { MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(messageObject.textLayoutBlocks.size() - 1); textArea.set( maybeTextX, maybeTextY, maybeTextX + block.textLayout.getWidth(), - (int) (maybeTextY + block.textYOffset + block.textLayout.getHeight()) + (int) (maybeTextY + block.textYOffset + block.padTop + block.textLayout.getHeight()) ); } else { this.maybeSelectedView = null; @@ -1911,7 +1993,7 @@ public abstract class TextSelectionHelper= block.textYOffset && y <= block.textYOffset + block.padTop + block.height) { + layoutBlock.layout = block.textLayout; + layoutBlock.yOffset = block.textYOffset + block.padTop; + layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0); + layoutBlock.charOffset = block.charactersOffset; + return; + } + } return; } for (int i = 0; i < messageObject.textLayoutBlocks.size(); i++) { MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(i); - if (y >= block.textYOffset && y <= block.textYOffset + block.height) { + if (y >= block.textYOffset && y <= block.textYOffset + block.padTop + block.height) { layoutBlock.layout = block.textLayout; - layoutBlock.yOffset = block.textYOffset; - layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) : 0); + layoutBlock.yOffset = block.textYOffset + block.padTop; + layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0); layoutBlock.charOffset = block.charactersOffset; return; } @@ -2094,9 +2208,27 @@ public abstract class TextSelectionHelper= 0 && blockOffset <= block.textLayout.getText().length()) { + layoutBlock.layout = block.textLayout; + layoutBlock.yOffset = block.textYOffset + block.padTop; + layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(captionLayout.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0); + layoutBlock.charOffset = block.charactersOffset; + return; + } + } + layoutBlock.layout = null; return; } @@ -2108,7 +2240,7 @@ public abstract class TextSelectionHelper= 0 && blockOffset <= block.textLayout.getText().length()) { layoutBlock.layout = block.textLayout; - layoutBlock.yOffset = block.textYOffset; - layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) : 0); + layoutBlock.yOffset = block.textYOffset + block.padTop; + layoutBlock.xOffset = -(block.isRtl() ? (int) Math.ceil(messageObject.textXOffset) - (block.quote ? AndroidUtilities.dp(10) : 0) : 0); layoutBlock.charOffset = block.charactersOffset; return; } @@ -2181,7 +2313,7 @@ public abstract class TextSelectionHelper startViewChildPosition && i < endViewChildPosition) { - drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false); + drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false, 0); } } else if (position == startViewPosition && startViewChildPosition == i) { - drawSelection(canvas, layoutBlock.getLayout(), startViewOffset, textLen, true, false); + drawSelection(canvas, layoutBlock.getLayout(), startViewOffset, textLen, true, false, 0); } else if (position == endViewPosition && endViewChildPosition == i) { - drawSelection(canvas, layoutBlock.getLayout(), 0, endOffset, false, true); + drawSelection(canvas, layoutBlock.getLayout(), 0, endOffset, false, true, 0); } else if (position > startViewPosition && position < endViewPosition || (position == startViewPosition && i > startViewChildPosition) || (position == endViewPosition && i < endViewChildPosition)) { - drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false); + drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false, 0); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java index b514d4109..0c230d428 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java @@ -22,13 +22,18 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; 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.AnimatedColor; +import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackgroundGradientDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; @@ -37,6 +42,7 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; public class ThemePreviewMessagesCell extends LinearLayout { public final static int TYPE_REACTIONS_DOUBLE_TAP = 2; + public final static int TYPE_PEER_COLOR = 3; private final Runnable invalidateRunnable = this::invalidate; @@ -52,8 +58,22 @@ public class ThemePreviewMessagesCell extends LinearLayout { public BaseFragment fragment; - @SuppressLint("ClickableViewAccessibility") + private int progress = -1; + private final Runnable cancelProgress = () -> { + progress = -1; + for (int i = 0; i < cells.length; ++i) { + if (cells[i] != null) { + cells[i].invalidate(); + } + } + }; + public ThemePreviewMessagesCell(Context context, INavigationLayout layout, int type) { + this(context, layout, type, 0); + } + + @SuppressLint("ClickableViewAccessibility") + public ThemePreviewMessagesCell(Context context, INavigationLayout layout, int type, long dialogId) { super(context); this.type = type; int currentAccount = UserConfig.selectedAccount; @@ -69,7 +89,72 @@ public class ThemePreviewMessagesCell extends LinearLayout { MessageObject message1 = null; MessageObject message2 = null; - if (type == TYPE_REACTIONS_DOUBLE_TAP) { + if (type == TYPE_PEER_COLOR) { + final boolean isChannel = dialogId < 0; + + ChatActionCell actionCell = new ChatActionCell(context); + actionCell.setCustomText(LocaleController.getString(R.string.UserColorPreviewTitle)); + addView(actionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 2, 0, 5)); + + TLRPC.Message message = new TLRPC.TL_message(); + message.message = LocaleController.getString(isChannel ? R.string.ChannelColorPreview : R.string.UserColorPreview); + message.reply_to = new TLRPC.TL_messageReplyHeader(); + message.reply_to.flags |= 1; + if (dialogId == 0) { + message.reply_to.reply_to_peer_id = new TLRPC.TL_peerUser(); + message.reply_to.reply_to_peer_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + } else { + message.reply_to.reply_to_peer_id = new TLRPC.TL_peerChannel(); + message.reply_to.reply_to_peer_id.channel_id = -dialogId; + } + message.replyMessage = new TLRPC.Message(); + message.replyMessage.media = new TLRPC.TL_messageMediaEmpty(); + if (dialogId == 0) { + message.replyMessage.from_id = new TLRPC.TL_peerUser(); + message.replyMessage.from_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + message.replyMessage.peer_id = new TLRPC.TL_peerUser(); + message.replyMessage.peer_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + } else { + message.replyMessage.from_id = new TLRPC.TL_peerChannel(); + message.replyMessage.from_id.channel_id = -dialogId; + message.replyMessage.peer_id = new TLRPC.TL_peerChannel(); + message.replyMessage.peer_id.channel_id = -dialogId; + } + message.replyMessage.message = LocaleController.getString(isChannel ? R.string.ChannelColorPreviewReply : R.string.UserColorPreviewReply); + message.media = new TLRPC.TL_messageMediaWebPage(); + message.media.webpage = new TLRPC.TL_webPage(); + message.media.webpage.embed_url = "https://telegram.org/"; + message.media.webpage.flags |= 2; + message.media.webpage.site_name = LocaleController.getString(R.string.AppName); + message.media.webpage.flags |= 4; + message.media.webpage.title = LocaleController.getString(isChannel ? R.string.ChannelColorPreviewLinkTitle : R.string.UserColorPreviewLinkTitle); + message.media.webpage.flags |= 8; + message.media.webpage.description = LocaleController.getString(isChannel ? R.string.ChannelColorPreviewLinkDescription : R.string.UserColorPreviewLinkDescription); + message.date = date + 60; + message.dialog_id = 1; + message.flags = 259; + if (dialogId == 0) { + message.from_id = new TLRPC.TL_peerUser(); + message.from_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + } else { + message.from_id = new TLRPC.TL_peerChannel(); + message.from_id.channel_id = -dialogId; + } + message.id = 1; + message.out = false; + if (dialogId == 0) { + message.peer_id = new TLRPC.TL_peerUser(); + message.peer_id.user_id = 0; + } else { + message.peer_id = new TLRPC.TL_peerChannel(); + message.peer_id.channel_id = -dialogId; + } + + message1 = new MessageObject(UserConfig.selectedAccount, message, true, false); + message1.forceAvatar = true; + message1.resetLayout(); + message1.eventId = 1; + } else if (type == TYPE_REACTIONS_DOUBLE_TAP) { TLRPC.Message message = new TLRPC.TL_message(); message.message = LocaleController.getString("DoubleTapPreviewMessage", R.string.DoubleTapPreviewMessage); message.date = date + 60; @@ -88,6 +173,8 @@ public class ThemePreviewMessagesCell extends LinearLayout { message1.eventId = 1; message1.customName = LocaleController.getString("DoubleTapPreviewSenderName", R.string.DoubleTapPreviewSenderName); message1.customAvatarDrawable = ContextCompat.getDrawable(context, R.drawable.dino_pic); + message1.overrideLinkColor = 5; + message1.overrideLinkEmoji = 0; } else { TLRPC.Message message = new TLRPC.TL_message(); if (type == 0) { @@ -156,6 +243,8 @@ public class ThemePreviewMessagesCell extends LinearLayout { message.peer_id.user_id = 0; message1 = new MessageObject(UserConfig.selectedAccount, message, true, false); message1.resetLayout(); + message1.overrideLinkColor = 5; + message1.overrideLinkEmoji = 0; message1.eventId = 1; message = new TLRPC.TL_message(); @@ -170,6 +259,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { message.from_id = new TLRPC.TL_peerUser(); message.id = 1; message.reply_to = new TLRPC.TL_messageReplyHeader(); + message.reply_to.flags |= 16; message.reply_to.reply_to_msg_id = 5; message.media = new TLRPC.TL_messageMediaEmpty(); message.out = false; @@ -177,7 +267,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { message.peer_id.user_id = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); message2 = new MessageObject(UserConfig.selectedAccount, message, true, false); if (type == 0) { - message2.customReplyName = LocaleController.getString("FontSizePreviewName", R.string.FontSizePreviewName); +// message2.customReplyName = LocaleController.getString("FontSizePreviewName", R.string.FontSizePreviewName); } else { message2.customReplyName = LocaleController.getString("NewThemePreviewName", R.string.NewThemePreviewName); } @@ -191,7 +281,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { private GestureDetector gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onDoubleTap(MotionEvent e) { - if (MediaDataController.getInstance(currentAccount).getDoubleTapReaction() == null) { + if (type != TYPE_REACTIONS_DOUBLE_TAP || MediaDataController.getInstance(currentAccount).getDoubleTapReaction() == null) { return false; } boolean added = getMessageObject().selectReaction(ReactionsLayoutInBubble.VisibleReaction.fromEmojicon(MediaDataController.getInstance(currentAccount).getDoubleTapReaction()), false, false); @@ -235,12 +325,42 @@ public class ThemePreviewMessagesCell extends LinearLayout { @Override public boolean onTouchEvent(MotionEvent event) { + if (type == TYPE_PEER_COLOR) { + return super.onTouchEvent(event); + } gestureDetector.onTouchEvent(event); return true; } + private final AnimatedColor color1 = new AnimatedColor(this, 0, 180, CubicBezierInterpolator.EASE_OUT); + private final AnimatedColor color2 = new AnimatedColor(this, 0, 180, CubicBezierInterpolator.EASE_OUT); + @Override protected void dispatchDraw(Canvas canvas) { + if (getMessageObject() != null && getMessageObject().overrideLinkColor >= 0) { + final int colorId = getMessageObject().overrideLinkColor; + final int color1, color2; + if (colorId >= 14) { + MessagesController messagesController = MessagesController.getInstance(UserConfig.selectedAccount); + MessagesController.PeerColors peerColors = messagesController != null ? messagesController.peerColors : null; + MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null; + if (peerColor != null) { + final int peerColorValue = messagesController.peerColors.getColor(colorId).getColor1(); + color1 = getThemedColor(Theme.keys_avatar_background[AvatarDrawable.getPeerColorIndex(peerColorValue)]); + color2 = getThemedColor(Theme.keys_avatar_background2[AvatarDrawable.getPeerColorIndex(peerColorValue)]); + } else { + color1 = getThemedColor(Theme.keys_avatar_background[AvatarDrawable.getColorIndex(colorId)]); + color2 = getThemedColor(Theme.keys_avatar_background2[AvatarDrawable.getColorIndex(colorId)]); + } + } else { + color1 = getThemedColor(Theme.keys_avatar_background[AvatarDrawable.getColorIndex(colorId)]); + color2 = getThemedColor(Theme.keys_avatar_background2[AvatarDrawable.getColorIndex(colorId)]); + } + avatarDrawable.setColor(this.color1.set(color1), this.color2.set(color2)); + } else { + color1.set(avatarDrawable.getColor()); + color2.set(avatarDrawable.getColor2()); + } if (getAvatarImage() != null && getAvatarImage().getImageHeight() != 0) { getAvatarImage().setImageCoords(getAvatarImage().getImageX(), getMeasuredHeight() - getAvatarImage().getImageHeight() - AndroidUtilities.dp(4), getAvatarImage().getImageWidth(), getAvatarImage().getImageHeight()); getAvatarImage().setRoundRadius((int) (getAvatarImage().getImageHeight() / 2f)); @@ -253,6 +373,46 @@ public class ThemePreviewMessagesCell extends LinearLayout { }; cells[a].setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + @Override + public boolean canPerformActions() { + return allowLoadingOnTouch(); + } + + @Override + public void didPressReplyMessage(ChatMessageCell cell, int id) { + if (allowLoadingOnTouch()) { + progress = ChatActivity.PROGRESS_REPLY; + cell.invalidate(); + + AndroidUtilities.cancelRunOnUIThread(cancelProgress); + AndroidUtilities.runOnUIThread(cancelProgress, 5000); + } + } + + @Override + public void needOpenWebView(MessageObject message, String url, String title, String description, String originalUrl, int w, int h) { + if (allowLoadingOnTouch()) { + progress = ChatActivity.PROGRESS_INSTANT; + AndroidUtilities.cancelRunOnUIThread(cancelProgress); + AndroidUtilities.runOnUIThread(cancelProgress, 5000); + } + } + + @Override + public void didPressInstantButton(ChatMessageCell cell, int type) { + if (allowLoadingOnTouch()) { + progress = ChatActivity.PROGRESS_INSTANT; + cell.invalidate(); + + AndroidUtilities.cancelRunOnUIThread(cancelProgress); + AndroidUtilities.runOnUIThread(cancelProgress, 5000); + } + } + + @Override + public boolean isProgressLoading(ChatMessageCell cell, int type) { + return type == progress; + } }); cells[a].isChat = type == TYPE_REACTIONS_DOUBLE_TAP; cells[a].setFullyDraw(true); @@ -354,6 +514,10 @@ public class ThemePreviewMessagesCell extends LinearLayout { shadowDrawable.draw(canvas); } + private boolean allowLoadingOnTouch() { + return type == TYPE_PEER_COLOR || type == 0; + } + @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); @@ -369,7 +533,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - if (type == TYPE_REACTIONS_DOUBLE_TAP) { + if (type == TYPE_REACTIONS_DOUBLE_TAP || allowLoadingOnTouch()) { return super.onInterceptTouchEvent(ev); } return false; @@ -377,7 +541,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { @Override public boolean dispatchTouchEvent(MotionEvent ev) { - if (type == TYPE_REACTIONS_DOUBLE_TAP) { + if (type == TYPE_REACTIONS_DOUBLE_TAP || allowLoadingOnTouch()) { return super.dispatchTouchEvent(ev); } return false; @@ -390,7 +554,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { @Override public boolean onTouchEvent(MotionEvent event) { - if (type == TYPE_REACTIONS_DOUBLE_TAP) { + if (type == TYPE_REACTIONS_DOUBLE_TAP || allowLoadingOnTouch()) { return super.onTouchEvent(event); } return false; 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 faaff2413..c826cefc0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -53,8 +53,8 @@ import org.telegram.ui.Stories.StoriesUtilities; public class UserCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { public BackupImageView avatarImageView; - private SimpleTextView nameTextView; - private SimpleTextView statusTextView; + protected SimpleTextView nameTextView; + protected SimpleTextView statusTextView; private ImageView imageView; private CheckBox checkBox; private CheckBoxSquare checkBoxBig; @@ -62,9 +62,9 @@ public class UserCell extends FrameLayout implements NotificationCenter.Notifica private TextView addButton; private Drawable premiumDrawable; private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emojiStatus; - private Theme.ResourcesProvider resourcesProvider; + protected Theme.ResourcesProvider resourcesProvider; - private AvatarDrawable avatarDrawable; + protected AvatarDrawable avatarDrawable; private boolean storiable; private Object currentObject; private TLRPC.EncryptedChat encryptedChat; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 670334cfa..16fddf5a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -3143,6 +3143,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerViaBotNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyLine)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyLine2)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_stickerReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inReplyNameText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outReplyNameText)); @@ -3213,8 +3214,8 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_inVenueInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVenueInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaInfoText)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_urlPaint, null, null, Theme.key_chat_linkSelectBackground)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_textSelectBackground)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_urlPaint, null, null, Theme.key_chat_inReplyLine)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_outReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoader)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outMediaIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoaderSelected)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java index 9a3d3805c..3ef7b9c67 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelBoostLayout.java @@ -1,10 +1,13 @@ package org.telegram.ui; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.tgnet.TLRPC.TL_payments_checkedGiftCode.NO_USER_ID; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.text.TextUtils; @@ -22,33 +25,43 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.FixedHeightEmptyCell; import org.telegram.ui.Cells.ManageChatTextCell; import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; -import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Charts.view_data.ChartHeaderView; +import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkActionView; import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.Premium.LimitPreviewView; +import org.telegram.ui.Components.Premium.boosts.BoostPagerBottomSheet; +import org.telegram.ui.Components.Premium.boosts.GiftInfoBottomSheet; +import org.telegram.ui.Components.Premium.boosts.cells.statistics.GiftedUserCell; +import org.telegram.ui.Components.Premium.boosts.cells.statistics.GiveawayCell; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; -import org.telegram.ui.Stories.ChannelBoostUtilities; +import org.telegram.ui.Components.ScrollSlidingTextTabStrip; import java.util.ArrayList; import java.util.Locale; import java.util.Objects; +import java.util.concurrent.CountDownLatch; public class ChannelBoostLayout extends FrameLayout { @@ -62,21 +75,36 @@ public class ChannelBoostLayout extends FrameLayout { private final static int EMPTY_VIEW_8DP = 7; private final static int NO_USERS_HINT = 8; private final static int SHOW_MORE_VIEW_TYPE = 9; + private final static int SHOW_BOOST_BY_GIFTS = 10; + private final static int SHOW_PREPARED_GIVE_AWAY = 11; + private final static int HEADER_VIEW_TYPE_SMALL = 12; + private final static int HEADER_VIEW_TYPE_TABS = 13; + + private static final int TAB_BOOSTS = 0; + private static final int TAB_GIFTS = 1; private final long dialogId; int currentAccount = UserConfig.selectedAccount; BaseFragment fragment; - TLRPC.TL_stories_boostsStatus boostsStatus; + TL_stories.TL_premium_boostsStatus boostsStatus; private final Theme.ResourcesProvider resourcesProvider; + private ScrollSlidingTextTabStrip boostsTabs; - ArrayList boosters = new ArrayList<>(); - boolean hasNext; - int nextRemaining; - ArrayList items = new ArrayList<>(); + private final ArrayList boosters = new ArrayList<>(); + private final ArrayList gifts = new ArrayList<>(); + private boolean hasBoostsNext; + private int nextBoostRemaining; + private boolean hasGiftsNext; + private int nextGiftsRemaining; + private final ArrayList items = new ArrayList<>(); + private int selectedTab = TAB_BOOSTS; AdapterWithDiffUtils adapter = new AdapterWithDiffUtils() { + private int remTotalBoosts = -1; + private int remTotalGifts = -1; + @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { return items.get(holder.getAdapterPosition()).selectable; @@ -88,7 +116,7 @@ public class ChannelBoostLayout extends FrameLayout { View view; switch (viewType) { case BOOST_VIEW: - LimitPreviewView limitPreviewView = new LimitPreviewView(getContext(), R.drawable.filled_limit_boost, 10, 0, resourcesProvider); + LimitPreviewView limitPreviewView = new LimitPreviewView(getContext(), R.drawable.filled_limit_boost, 0, 0, resourcesProvider); limitPreviewView.isStatistic = true; view = limitPreviewView; Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); @@ -101,7 +129,7 @@ public class ChannelBoostLayout extends FrameLayout { limitPreviewView.setBoosts(boostsStatus, false); break; case DIVIDER_TEXT_VIEW_TYPE: - view = new TextInfoPrivacyCell(parent.getContext(), 12, resourcesProvider); + view = new TextInfoPrivacyCell(parent.getContext(), 20, resourcesProvider); shadowDrawable = Theme.getThemedDrawable(getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)); combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); @@ -118,15 +146,62 @@ public class ChannelBoostLayout extends FrameLayout { view = new ChartHeaderView(getContext()); view.setPadding(view.getPaddingLeft(), AndroidUtilities.dp(16), view.getRight(), AndroidUtilities.dp(16)); break; + case HEADER_VIEW_TYPE_SMALL: + view = new ChartHeaderView(getContext()); + view.setPadding(view.getPaddingLeft(), AndroidUtilities.dp(16), view.getRight(), AndroidUtilities.dp(8)); + break; + case HEADER_VIEW_TYPE_TABS: + boostsTabs = new ScrollSlidingTextTabStrip(fragment.getContext(), resourcesProvider); + boostsTabs.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + boostsTabs.setColors(Theme.key_profile_tabSelectedLine, Theme.key_profile_tabSelectedText, Theme.key_profile_tabText, Theme.key_profile_tabSelector); + FrameLayout frameLayoutWrapper = new FrameLayout(fragment.getContext()) { + private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + dividerPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + canvas.drawRect(0, getHeight() - 2, getWidth(), getHeight(), dividerPaint); + } + }; + boostsTabs.setDelegate(new ScrollSlidingTextTabStrip.ScrollSlidingTabStripDelegate() { + @Override + public void onPageSelected(int id, boolean forward) { + selectedTab = id; + updateRows(true); + } + + @Override + public void onSamePageSelected() { + + } + + @Override + public void onPageScrolled(float progress) { + + } + }); + frameLayoutWrapper.addView(boostsTabs, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 48)); + view = frameLayoutWrapper; + break; + case SHOW_BOOST_BY_GIFTS: + TextCell textCell = new TextCell(getContext()); + textCell.setTextAndIcon(LocaleController.formatString("BoostingGetBoostsViaGifts", R.string.BoostingGetBoostsViaGifts), R.drawable.msg_gift_premium, false); + textCell.offsetFromImage = 64; + textCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); + view = textCell; + break; case LINK_VIEW_TYPE: LinkActionView linkActionView = new LinkActionView(getContext(), fragment, null, 0, false, false); view = linkActionView; linkActionView.hideOptions(); - linkActionView.setLink(ChannelBoostUtilities.createLink(currentAccount, dialogId)); view.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), AndroidUtilities.dp(24)); break; + case SHOW_PREPARED_GIVE_AWAY: + view = new GiveawayCell(getContext(), 0, 0, false); + break; case USER_VIEW_TYPE: - view = new UserCell(getContext(), 0, 0, false); + view = new GiftedUserCell(getContext(), 0, 0, false); break; case EMPTY_VIEW_8DP: view = new FixedHeightEmptyCell(getContext(), 8); @@ -143,13 +218,18 @@ public class ChannelBoostLayout extends FrameLayout { textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); textView.setGravity(Gravity.CENTER); - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 7, 0, 0)); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 0, 0)); view = frameLayout; break; case SHOW_MORE_VIEW_TYPE: - ManageChatTextCell actionCell = new ManageChatTextCell(getContext()); + ManageChatTextCell actionCell = new ManageChatTextCell(getContext()) { + @Override + protected int getFullHeight() { + return AndroidUtilities.dp(50); + } + }; actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); - // actionCell.setText(LocaleController.getString("ShowMore", R.string.ShowMore), null, R.drawable.arrow_more, false); + // actionCell.setText(LocaleController.getString("ShowMore", R.string.ShowMore), null, R.drawable.arrow_more, false); view = actionCell; break; default: @@ -163,34 +243,69 @@ public class ChannelBoostLayout extends FrameLayout { public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == BOOST_VIEW) { - } else if (holder.getItemViewType() == HEADER_VIEW_TYPE) { + } else if (holder.getItemViewType() == HEADER_VIEW_TYPE || holder.getItemViewType() == HEADER_VIEW_TYPE_SMALL) { ChartHeaderView headerCell = (ChartHeaderView) holder.itemView; headerCell.setTitle(items.get(position).title); headerCell.showDate(false); + if (holder.getItemViewType() == HEADER_VIEW_TYPE_SMALL) { + headerCell.setPadding(AndroidUtilities.dp(3), headerCell.getPaddingTop(), headerCell.getPaddingRight(), headerCell.getPaddingBottom()); + } } else if (holder.getItemViewType() == OVERVIEW_TYPE) { StatisticActivity.OverviewCell overviewCell = (StatisticActivity.OverviewCell) holder.itemView; overviewCell.setData(0, Integer.toString(boostsStatus.level), null, LocaleController.getString("BoostsLevel2", R.string.BoostsLevel2)); - if (boostsStatus.premium_audience != null && boostsStatus.premium_audience.total == 0) { + if (boostsStatus.premium_audience != null && boostsStatus.premium_audience.total != 0) { float percent = (((float) boostsStatus.premium_audience.part / (float) boostsStatus.premium_audience.total) * 100f); - overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f",percent) + "%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers)); + overviewCell.setData(1, "~" + (int) boostsStatus.premium_audience.part, String.format(Locale.US, "%.1f", percent) + "%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers)); } else { overviewCell.setData(1, "~0", "0%", LocaleController.getString("PremiumSubscribers", R.string.PremiumSubscribers)); } overviewCell.setData(2, String.valueOf(boostsStatus.boosts), null, LocaleController.getString("BoostsExisting", R.string.BoostsExisting)); - overviewCell.setData(3, String.valueOf(boostsStatus.next_level_boosts - boostsStatus.boosts), null, LocaleController.getString("BoostsToLevel", R.string.BoostsToLevel)); + overviewCell.setData(3, String.valueOf(Math.max(0, boostsStatus.next_level_boosts - boostsStatus.boosts)), null, LocaleController.getString("BoostsToLevel", R.string.BoostsToLevel)); } else if (holder.getItemViewType() == USER_VIEW_TYPE) { - TLRPC.TL_booster booster = items.get(position).booster; + TL_stories.TL_boost booster = items.get(position).booster; TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(booster.user_id); - UserCell userCell = (UserCell) holder.itemView; - String str = LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.formatDate(booster.expires)); - userCell.setData(user, ContactsController.formatName(user), str, 0); + GiftedUserCell userCell = (GiftedUserCell) holder.itemView; + String str = booster.multiplier > 1 + ? LocaleController.formatString("BoostsExpireOn", R.string.BoostsExpireOn, LocaleController.formatDate(booster.expires)) + : LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.formatDate(booster.expires)); + userCell.setData(user, ContactsController.formatName(user), str, 0, !items.get(position).isLast); + userCell.setStatus(booster); + userCell.setAvatarPadding(5); } else if (holder.getItemViewType() == DIVIDER_TEXT_VIEW_TYPE) { TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; privacyCell.setText(items.get(position).title); } else if (holder.getItemViewType() == SHOW_MORE_VIEW_TYPE) { ManageChatTextCell actionCell = (ManageChatTextCell) holder.itemView; - actionCell.setText(LocaleController.formatPluralString("ShowVotes", nextRemaining), null, R.drawable.arrow_more, false); + if (selectedTab == TAB_BOOSTS) { + actionCell.setText(LocaleController.formatPluralString("BoostingShowMoreBoosts", nextBoostRemaining), null, R.drawable.arrow_more, false); + } else { + actionCell.setText(LocaleController.formatPluralString("BoostingShowMoreGifts", nextGiftsRemaining), null, R.drawable.arrow_more, false); + } + } else if (holder.getItemViewType() == LINK_VIEW_TYPE) { + LinkActionView linkActionView = (LinkActionView) holder.itemView; + linkActionView.setLink(items.get(position).title); + } else if (holder.getItemViewType() == SHOW_PREPARED_GIVE_AWAY) { + ItemInternal item = items.get(position); + TL_stories.TL_prepaidGiveaway prepaidGiveaway = item.prepaidGiveaway; + GiveawayCell giveawayCell = (GiveawayCell) holder.itemView; + String name = LocaleController.formatString("TelegramPremiumCount", R.string.TelegramPremiumCount, prepaidGiveaway.quantity); + String info = LocaleController.formatString("SubscriptionsCount", R.string.SubscriptionsCount, LocaleController.formatPluralString("GiftMonths", prepaidGiveaway.months)); + giveawayCell.setData(prepaidGiveaway, name, info, 0, !item.isLast); + giveawayCell.setImage(prepaidGiveaway); + giveawayCell.setAvatarPadding(5); + } else if (holder.getItemViewType() == HEADER_VIEW_TYPE_TABS) { + if (remTotalBoosts != totalBoosts || remTotalGifts != totalGifts) { + remTotalBoosts = totalBoosts; + remTotalGifts = totalGifts; + boostsTabs.removeTabs(); + boostsTabs.addTextTab(TAB_BOOSTS, LocaleController.formatPluralString("BoostingBoostsCount", totalBoosts)); + if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && totalGifts > 0 && totalGifts != totalBoosts) { + boostsTabs.addTextTab(TAB_GIFTS, LocaleController.formatPluralString("BoostingGiftsCount", totalGifts)); + } + boostsTabs.setInitialTabId(selectedTab); + boostsTabs.finishAddingTabs(); + } } } @@ -208,6 +323,7 @@ public class ChannelBoostLayout extends FrameLayout { RecyclerListView listView; boolean usersLoading; private LinearLayout progressLayout; + private TLRPC.Chat currentChat; public ChannelBoostLayout(BaseFragment fragment, long dialogId, Theme.ResourcesProvider resourcesProvider) { super(fragment.getContext()); @@ -215,6 +331,7 @@ public class ChannelBoostLayout extends FrameLayout { Context context = fragment.getContext(); this.resourcesProvider = resourcesProvider; this.dialogId = dialogId; + this.currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); listView = new RecyclerListView(context); listView.setLayoutManager(new LinearLayoutManager(context)); DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator(); @@ -222,12 +339,42 @@ public class ChannelBoostLayout extends FrameLayout { defaultItemAnimator.setDelayAnimations(false); listView.setItemAnimator(defaultItemAnimator); listView.setOnItemClickListener((view, position) -> { - if (view instanceof UserCell) { - UserCell cell = (UserCell) view; - fragment.presentFragment(ProfileActivity.of(cell.getDialogId())); + if (view instanceof GiftedUserCell) { + GiftedUserCell cell = (GiftedUserCell) view; + TL_stories.TL_boost boost = cell.getBoost(); + if (((boost.gift || boost.giveaway) && boost.user_id >= 0) || boost.unclaimed) { + TLRPC.TL_payments_checkedGiftCode giftCode = new TLRPC.TL_payments_checkedGiftCode(); + giftCode.giveaway_msg_id = boost.giveaway_msg_id; + giftCode.to_id = boost.user_id; + giftCode.from_id = MessagesController.getInstance(UserConfig.selectedAccount).getPeer(-currentChat.id); + giftCode.date = boost.date; + giftCode.via_giveaway = boost.giveaway; + giftCode.months = (boost.expires - boost.date) / 30 / 86400; + if (boost.unclaimed) { + giftCode.to_id = NO_USER_ID; + } else { + giftCode.boost = boost; + } + new GiftInfoBottomSheet(fragment, false, true, giftCode, boost.used_gift_slug).show(); + } else if (boost.giveaway && boost.user_id == NO_USER_ID) { + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); + layout.setAnimation(R.raw.chats_infotip, 36, 36); + layout.textView.setText(LocaleController.getString("BoostingRecipientWillBeSelected", R.string.BoostingRecipientWillBeSelected)); + layout.textView.setSingleLine(false); + layout.textView.setMaxLines(2); + Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); + } else if (!boost.gift && !boost.giveaway) { + fragment.presentFragment(ProfileActivity.of(cell.getDialogId())); + } + } + if (view instanceof TextCell) { + BoostPagerBottomSheet.show(fragment, dialogId, resourcesProvider); + } + if (view instanceof GiveawayCell) { + BoostPagerBottomSheet.show(fragment, resourcesProvider, dialogId, ((GiveawayCell) view).getPrepaidGiveaway()); } if (items.get(position).viewType == SHOW_MORE_VIEW_TYPE) { - loadUsers(); + loadUsers(selectedTab == TAB_GIFTS); } }); addView(listView); @@ -240,33 +387,64 @@ public class ChannelBoostLayout extends FrameLayout { progressLayout.animate().alpha(1f).setDuration(200).setStartDelay(500).start(); } - private void updateRows(boolean animated) { + public void updateRows(boolean animated) { ArrayList oldItems = new ArrayList<>(items); items.clear(); if (boostsStatus != null) { items.add(new ItemInternal(BOOST_VIEW, false)); items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("StatisticOverview", R.string.StatisticOverview))); - items.add(new ItemInternal(OVERVIEW_TYPE, true)); + items.add(new ItemInternal(OVERVIEW_TYPE, false)); items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false)); - - items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("Boosters", R.string.Boosters))); - if (boosters.isEmpty()) { - items.add(new ItemInternal(NO_USERS_HINT, false)); - items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false)); - } else { - for (int i = 0; i < boosters.size(); i++) { - items.add(new ItemInternal(USER_VIEW_TYPE, boosters.get(i))); + if (boostsStatus.prepaid_giveaways.size() > 0) { + items.add(new ItemInternal(HEADER_VIEW_TYPE_SMALL, LocaleController.getString("BoostingPreparedGiveaways", R.string.BoostingPreparedGiveaways))); + for (int i = 0; i < boostsStatus.prepaid_giveaways.size(); i++) { + TL_stories.TL_prepaidGiveaway prepaidGiveaway = boostsStatus.prepaid_giveaways.get(i); + items.add(new ItemInternal(SHOW_PREPARED_GIVE_AWAY, prepaidGiveaway, i == boostsStatus.prepaid_giveaways.size() - 1)); } - if (hasNext) { - items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, false)); - } else { - items.add(new ItemInternal(EMPTY_VIEW_8DP, false)); - } - items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription))); + items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingSelectPaidGiveaway", R.string.BoostingSelectPaidGiveaway))); } + + items.add(new ItemInternal(HEADER_VIEW_TYPE_TABS, LocaleController.getString("Boosters", R.string.Boosters))); + if (selectedTab == TAB_BOOSTS) { + if (boosters.isEmpty()) { + items.add(new ItemInternal(NO_USERS_HINT, false)); + items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false)); + } else { + for (int i = 0; i < boosters.size(); i++) { + items.add(new ItemInternal(USER_VIEW_TYPE, boosters.get(i), i == boosters.size() - 1 && !hasBoostsNext, selectedTab)); + } + if (hasBoostsNext) { + items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, true)); + } else { + items.add(new ItemInternal(EMPTY_VIEW_8DP, false)); + } + items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription))); + } + } else { + if (gifts.isEmpty()) { + items.add(new ItemInternal(NO_USERS_HINT, false)); + items.add(new ItemInternal(DIVIDER_VIEW_TYPE, false)); + } else { + for (int i = 0; i < gifts.size(); i++) { + items.add(new ItemInternal(USER_VIEW_TYPE, gifts.get(i), i == gifts.size() - 1 && !hasGiftsNext, selectedTab)); + } + if (hasGiftsNext) { + items.add(new ItemInternal(SHOW_MORE_VIEW_TYPE, true)); + } else { + items.add(new ItemInternal(EMPTY_VIEW_8DP, false)); + } + items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostersInfoDescription", R.string.BoostersInfoDescription))); + } + } + items.add(new ItemInternal(HEADER_VIEW_TYPE, LocaleController.getString("LinkForBoosting", R.string.LinkForBoosting))); - items.add(new ItemInternal(LINK_VIEW_TYPE, false)); + items.add(new ItemInternal(LINK_VIEW_TYPE, boostsStatus.boost_url)); + if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable && ChatObject.hasAdminRights(currentChat) && ChatObject.canPost(currentChat)) { + items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingShareThisLink", R.string.BoostingShareThisLink))); + items.add(new ItemInternal(SHOW_BOOST_BY_GIFTS, true)); + items.add(new ItemInternal(DIVIDER_TEXT_VIEW_TYPE, LocaleController.getString("BoostingGetMoreBoosts", R.string.BoostingGetMoreBoosts))); + } } if (animated) { adapter.setItems(oldItems, items); @@ -286,29 +464,107 @@ public class ChannelBoostLayout extends FrameLayout { } }); updateRows(true); - loadUsers(); + loadUsers(null); })); } + private String lastBoostsOffset = ""; + private String lastGiftsOffset = ""; + private int limitGifts = 5; + private int limitBoosts = 5; + private int totalGifts; + private int totalBoosts; - private void loadUsers() { + private void loadUsers(Boolean isGift) { if (usersLoading) { return; } usersLoading = true; - TLRPC.TL_stories_getBoostersList listReq = new TLRPC.TL_stories_getBoostersList(); - listReq.limit = 25; - listReq.offset = ""; - listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); - ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - usersLoading = false; - if (response != null) { - TLRPC.TL_stories_boostersList list = (TLRPC.TL_stories_boostersList) response; - MessagesController.getInstance(currentAccount).putUsers(list.users, false); - boosters.addAll(list.boosters); - hasNext = !TextUtils.isEmpty(list.next_offset) && boosters.size() < list.count; - nextRemaining = list.count - boosters.size(); + if (isGift == null) { + Utilities.globalQueue.postRunnable(() -> { + CountDownLatch latch = new CountDownLatch(2); + loadOnlyBoosts(latch, null); + loadOnlyGifts(latch, null); + try { + latch.await(); + } catch (InterruptedException ignore) { + + } + AndroidUtilities.runOnUIThread(() -> { + usersLoading = false; + updateRows(true); + }); + }); + } else if (isGift) { + loadOnlyGifts(null, () -> { + usersLoading = false; updateRows(true); + }); + } else { + loadOnlyBoosts(null, () -> { + usersLoading = false; + updateRows(true); + }); + } + } + + private void loadOnlyBoosts(CountDownLatch latch, Runnable after) { + TL_stories.TL_premium_getBoostsList listReq = new TL_stories.TL_premium_getBoostsList(); + listReq.limit = limitBoosts; + listReq.offset = lastBoostsOffset; + listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + + ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (latch != null) { + latch.countDown(); + } + if (response != null) { + limitBoosts = 20; + TL_stories.TL_premium_boostsList list = (TL_stories.TL_premium_boostsList) response; + MessagesController.getInstance(currentAccount).putUsers(list.users, false); + lastBoostsOffset = list.next_offset; + boosters.addAll(list.boosts); + int shownBoosts = 0; + for (TL_stories.TL_boost booster : boosters) { + shownBoosts += booster.multiplier > 0 ? booster.multiplier : 1; + } + nextBoostRemaining = Math.max(0, list.count - shownBoosts); + hasBoostsNext = !TextUtils.isEmpty(list.next_offset) && nextBoostRemaining > 0; + totalBoosts = list.count; + if (after != null) { + after.run(); + } + } + }), ConnectionsManager.RequestFlagFailOnServerErrors); + } + + private void loadOnlyGifts(CountDownLatch latch, Runnable after) { + TL_stories.TL_premium_getBoostsList listReq = new TL_stories.TL_premium_getBoostsList(); + listReq.limit = limitGifts; + listReq.gifts = true; + listReq.offset = lastGiftsOffset; + listReq.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + + ConnectionsManager.getInstance(currentAccount).sendRequest(listReq, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (latch != null) { + latch.countDown(); + } + if (response != null) { + limitGifts = 20; + TL_stories.TL_premium_boostsList list = (TL_stories.TL_premium_boostsList) response; + MessagesController.getInstance(currentAccount).putUsers(list.users, false); + lastGiftsOffset = list.next_offset; + gifts.addAll(list.boosts); + int shownGifts = 0; + for (TL_stories.TL_boost booster : gifts) { + shownGifts += booster.multiplier > 0 ? booster.multiplier : 1; + } + nextGiftsRemaining = Math.max(0, list.count - shownGifts); + hasGiftsNext = !TextUtils.isEmpty(list.next_offset) && nextGiftsRemaining > 0; + totalGifts = list.count; + if (after != null) { + after.run(); + } } }), ConnectionsManager.RequestFlagFailOnServerErrors); } @@ -316,16 +572,27 @@ public class ChannelBoostLayout extends FrameLayout { private class ItemInternal extends AdapterWithDiffUtils.Item { String title; - TLRPC.TL_booster booster; + TL_stories.TL_boost booster; + TL_stories.TL_prepaidGiveaway prepaidGiveaway; + boolean isLast; + int tab; public ItemInternal(int viewType, String title) { super(viewType, false); this.title = title; } - public ItemInternal(int viewType, TLRPC.TL_booster booster) { - super(viewType, false); + public ItemInternal(int viewType, TL_stories.TL_boost booster, boolean isLast, int tab) { + super(viewType, true); this.booster = booster; + this.isLast = isLast; + this.tab = tab; + } + + public ItemInternal(int viewType, TL_stories.TL_prepaidGiveaway prepaidGiveaway, boolean isLast) { + super(viewType, true); + this.prepaidGiveaway = prepaidGiveaway; + this.isLast = isLast; } public ItemInternal(int viewType, boolean selectable) { @@ -337,8 +604,10 @@ public class ChannelBoostLayout extends FrameLayout { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ItemInternal that = (ItemInternal) o; - if (booster != null && that.booster != null) { - return booster.user_id == that.booster.user_id; + if (prepaidGiveaway != null && that.prepaidGiveaway != null) { + return prepaidGiveaway.id == that.prepaidGiveaway.id && isLast == that.isLast; + } else if (booster != null && that.booster != null) { + return booster.id.hashCode() == that.booster.id.hashCode() && isLast == that.isLast && tab == that.tab; } else { return true; } @@ -346,9 +615,8 @@ public class ChannelBoostLayout extends FrameLayout { @Override public int hashCode() { - return Objects.hash(title, booster); + return Objects.hash(title, booster, prepaidGiveaway, isLast, tab); } - } public void createEmptyView(Context context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index 0628947af..398516dc8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -59,6 +59,7 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; +import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.CharacterStyle; @@ -66,6 +67,7 @@ import android.text.style.ClickableSpan; 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; @@ -114,7 +116,6 @@ import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; -import com.google.android.exoplayer2.util.Consumer; import com.google.zxing.common.detector.MathUtils; import org.telegram.PhoneFormat.PhoneFormat; @@ -127,6 +128,7 @@ import org.telegram.messenger.ChatMessageSharedResources; import org.telegram.messenger.ChatMessagesMetadataController; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; +import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.DownloadController; @@ -135,7 +137,6 @@ import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.FlagSecureReason; -import org.telegram.messenger.ForwardingMessagesParams; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LanguageDetector; @@ -144,6 +145,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagePreviewParams; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; @@ -167,6 +169,7 @@ import org.telegram.messenger.voip.VoIPService; 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.ActionBar; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -241,7 +244,6 @@ import org.telegram.ui.Components.FireworksOverlay; import org.telegram.ui.Components.FloatingDebug.FloatingDebugController; import org.telegram.ui.Components.FloatingDebug.FloatingDebugProvider; import org.telegram.ui.Components.Forum.ForumUtilities; -import org.telegram.ui.Components.ForwardingPreviewView; import org.telegram.ui.Components.FragmentContextView; import org.telegram.ui.Components.GigagroupConvertAlert; import org.telegram.ui.Components.HideViewAfterAnimation; @@ -256,6 +258,7 @@ import org.telegram.ui.Components.LinkSpanDrawable; import org.telegram.ui.Components.MentionsContainerView; import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.MessageContainsEmojiButton; +import org.telegram.ui.Components.MessagePreviewView; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.PhonebookShareAlert; @@ -266,7 +269,10 @@ import org.telegram.ui.Components.PopupSwipeBackLayout; import org.telegram.ui.Components.Premium.GiftPremiumBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.Premium.boosts.GiftInfoBottomSheet; import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.ReactedHeaderView; import org.telegram.ui.Components.ReactedUsersListView; @@ -324,7 +330,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; @@ -557,6 +563,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessagesSearchAdapter messagesSearchAdapter; private AnimatorSet messagesSearchListViewAnimation; + public static final int MODE_DEFAULT = 0; public static final int MODE_SCHEDULED = 1; public static final int MODE_PINNED = 2; @@ -607,6 +614,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int topViewWasVisible; private ArrayList pinnedMessageIds = new ArrayList<>(); + private int maxPinnedMessageId; private HashMap pinnedMessageObjects = new HashMap<>(); private SparseArray loadingPinnedMessages = new SparseArray<>(); private int currentPinnedMessageId; @@ -625,6 +633,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private AnimatorSet editButtonAnimation; private AnimatorSet forwardButtonAnimation; + SparseIntArray dateObjectsStableIds = new SparseIntArray(); private static int lastStableId = 10; private boolean openSearchKeyboard; @@ -642,13 +651,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessageObject selectedObjectToEditCaption; private MessageObject selectedObject; private MessageObject.GroupedMessages selectedObjectGroup; - private ForwardingMessagesParams forwardingMessages; + private boolean forbidForwardingWithDismiss; + public MessagePreviewParams messagePreviewParams; private CharSequence formwardingNameText; private MessageObject forwardingMessage; private MessageObject.GroupedMessages forwardingMessageGroup; + private MessageObject.GroupedMessages replyingQuoteGroup; + public MessageObject replyingTopMessage; + private ReplyQuote replyingQuote; + private boolean ignoreDraft; private MessageObject replyingMessageObject; private int editingMessageObjectReqId; - private MessageObject editingMessageObject; + public MessageObject editingMessageObject; private boolean paused = true; private boolean pausedOnLastMessage; private boolean wasPaused; @@ -666,7 +680,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private TLRPC.PhotoSize pinnedImageThumbLocation; private TLObject pinnedImageLocationObject; private int linkSearchRequestId; - private TLRPC.WebPage foundWebPage; + public TLRPC.WebPage foundWebPage; private ArrayList foundUrls; private String pendingLinkSearchString; private Runnable pendingWebPageTimeoutRunnable; @@ -802,6 +816,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private MessageObject unreadMessageObject; private MessageObject scrollToMessage; public int highlightMessageId = Integer.MAX_VALUE; + public boolean showNoQuoteAlert; + public String highlightMessageQuote; private int scrollToMessagePosition = -10000; private Runnable unselectRunnable; @@ -910,7 +926,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean openImport; private float chatListViewPaddingTop; - private float chatListViewPaddingTopOnlyTopViews; private int chatListViewPaddingVisibleOffset; private int contentPaddingTop; @@ -1246,7 +1261,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - ForwardingPreviewView forwardingPreviewView; + MessagePreviewView forwardingPreviewView; private PhotoViewer.PhotoViewerProvider photoViewerProvider = new PhotoViewer.EmptyPhotoViewerProvider() { @@ -1346,8 +1361,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int text_strike = 55; private final static int text_underline = 56; private final static int text_spoiler = 57; + private final static int text_quote = 58; - private final static int view_as_topics = 58; + private final static int view_as_topics = 59; private final static int search = 40; private final static int delete_messages = 140; @@ -1357,6 +1373,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int open_forum = 61; private final static int translate = 62; + private final static int scheduled = 63; private final static int id_chat_compose_panel = 1000; @@ -1625,14 +1642,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (message != null) { scheduledMessagesCount++; } - if (forwardingMessages != null && !forwardingMessages.messages.isEmpty()) { - scheduledMessagesCount += forwardingMessages.messages.size(); + if (messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty()) { + scheduledMessagesCount += messagePreviewParams.forwardMessages.messages.size(); } updateScheduledInterface(false); } - if (!TextUtils.isEmpty(message) && forwardingMessages != null && !forwardingMessages.messages.isEmpty()) { + if (!TextUtils.isEmpty(message) && messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty() && messagePreviewParams.quote == null) { ArrayList messagesToForward = new ArrayList<>(); - forwardingMessages.getSelectedMessages(messagesToForward); + messagePreviewParams.forwardMessages.getSelectedMessages(messagesToForward); boolean showReplyHint = messagesToForward.size() > 0; TLRPC.Peer toPeer = getMessagesController().getPeer(dialog_id); for (int i = 0; i < messagesToForward.size(); ++i) { @@ -1644,10 +1661,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (showReplyHint) { - checkTopUndoView(); - if (topUndoView != null) { - topUndoView.showWithAction(0, UndoView.ACTION_HINT_SWIPE_TO_REPLY, null, null); - } + Bulletin bulletin = BulletinFactory.of(ChatActivity.this) + .createSimpleBulletin( + R.raw.hint_swipe_reply, + LocaleController.getString(R.string.SwipeToReplyHint), + LocaleController.getString(R.string.SwipeToReplyHintMessage) + ); + RLottieImageView imageView = ((Bulletin.TwoLineLottieLayout) bulletin.getLayout()).imageView; + imageView.setScaleX(1.8f); + imageView.setScaleY(1.8f); + bulletin.show(true); } } if (ChatObject.isForum(currentChat) && !isTopic && replyingMessageObject != null) { @@ -1801,7 +1824,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } @Override - public void onTextChanged(final CharSequence text, boolean bigChange) { + public void onTextChanged(final CharSequence text, boolean bigChange, boolean fromDraft) { MediaController.getInstance().setInputFieldHasText(!TextUtils.isEmpty(text) || chatActivityEnterView.isEditingMessage()); if (mentionContainer != null && mentionContainer.getAdapter() != null) { mentionContainer.getAdapter().searchUsernameOrHashtag(text, chatActivityEnterView.getCursorPosition(), messages, false, false); @@ -1814,6 +1837,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (bigChange) { searchLinks(text, true); } else { + checkEditLinkRemoved(text); waitingForCharaterEnterRunnable = new Runnable() { @Override public void run() { @@ -1830,11 +1854,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emojiAnimationsOverlay.cancelAllAnimations(); } ReactionsEffectOverlay.dismissAll(); - if (TextUtils.isEmpty(text)) { - hideSendButtonHints(); - AndroidUtilities.cancelRunOnUIThread(showScheduledHintRunnable); - } else if (!bigChange){ - showScheduledHint(); + if (!fromDraft) { + if ((scheduledOrNoSoundHint != null && scheduledOrNoSoundHint.getVisibility() == View.VISIBLE) + || (scheduledHint != null && scheduledHint.getVisibility() == View.VISIBLE)) { + hideSendButtonHints(); + } else { + showScheduledHint(); + } } } @@ -2024,6 +2050,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean hasScheduledMessages() { + if (getMessagesController().isForum(getDialogId()) && !isTopic) { + return false; + } return scheduledMessagesCount > 0 && chatMode == 0; } @@ -2086,13 +2115,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean hasForwardingMessages() { - return forwardingMessages != null && !forwardingMessages.messages.isEmpty(); + return messagePreviewParams != null && messagePreviewParams.forwardMessages != null && !messagePreviewParams.forwardMessages.messages.isEmpty(); } @Override public void onKeyboardRequested() { checkAdjustResize(); } + + @Override + public ReplyQuote getReplyQuote() { + return replyingQuote; + } } private final ChatScrollCallback chatScrollHelperCallback = new ChatScrollCallback(); @@ -2119,7 +2153,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }; private final Runnable showScheduledHintRunnable = () -> { - if (getParentActivity() == null || fragmentView == null || chatActivityEnterView == null) { + if (getParentActivity() == null || fragmentView == null || chatActivityEnterView == null || forwardingPreviewView != null) { return; } View anchor = chatActivityEnterView.getSendButton(); @@ -2392,6 +2426,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().addObserver(this, NotificationCenter.messageTranslating); getNotificationCenter().addObserver(this, NotificationCenter.onReceivedChannelDifference); + getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); super.onFragmentCreate(); @@ -2577,7 +2612,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getMessagesController().loadMessages(dialog_id, mergeDialogId, loadInfo, initialMessagesSize, startLoadFromMessageId, 0, true, 0, classGuid, 2, 0, chatMode, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } } - if (chatMode == 0 && !isThreadChat()) { + if (chatMode == 0 && (!isThreadChat() || isTopic)) { waitingForLoad.add(lastLoadIndex); getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); } @@ -2759,6 +2794,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslated); getNotificationCenter().removeObserver(this, NotificationCenter.messageTranslating); getNotificationCenter().removeObserver(this, NotificationCenter.onReceivedChannelDifference); + getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); if (currentEncryptedChat != null) { getNotificationCenter().removeObserver(this, NotificationCenter.didVerifyMessagesStickers); } @@ -2844,6 +2880,63 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } return null; } + + @Override + protected boolean canShowQuote() { + return ( + chatActivity != null && chatActivity.getCurrentEncryptedChat() == null && !chatActivity.textSelectionHelper.isDescription && + selectedView != null && selectedView.getMessageObject() != null && selectedView.getMessageObject().type != MessageObject.TYPE_STORY && + !selectedView.getMessageObject().isVoiceTranscriptionOpen() && !selectedView.getMessageObject().isInvoice() && + !chatActivity.getMessagesController().getTranslateController().isTranslatingDialog(chatActivity.dialog_id) + ); + } + + @Override + protected void onQuoteClick(MessageObject messageObject, int start, int end, CharSequence text) { + if (messageObject == null) { + return; + } + if (chatActivity != null) { + end = Math.min(end, start + chatActivity.getMessagesController().quoteLengthMax); + if (messageObject.getGroupId() != 0) { + MessageObject.GroupedMessages group = chatActivity.getGroup(messageObject.getGroupId()); + if (group != null) { + messageObject = group.captionMessage; + } + } + if (messageObject == null) { + return; + } + ReplyQuote quote = ReplyQuote.from(messageObject, start, end); + if (quote.getText() == null) { + return; + } + if (chatActivity.chatActivityEnterView == null || chatActivity.chatActivityEnterView.getVisibility() != View.VISIBLE) { + chatActivity.replyingQuote = quote; + chatActivity.replyingMessageObject = messageObject; + chatActivity.forbidForwardingWithDismiss = false; + chatActivity.messagePreviewParams = new MessagePreviewParams(chatActivity.currentEncryptedChat != null, chatActivity.getMessagesController().isChatNoForwards(chatActivity.currentChat)); + chatActivity.messagePreviewParams.updateReply(chatActivity.replyingMessageObject, chatActivity.getGroup(messageObject.getGroupId()), chatActivity.getDialogId(), chatActivity.replyingQuote); + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); + args.putBoolean("quote", true); + args.putInt("messagesCount", 1); + args.putBoolean("canSelectTopics", true); + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(chatActivity); + chatActivity.presentFragment(fragment); + } else { + if (chatActivity.actionBar != null && chatActivity.actionBar.isActionModeShowed()) { + chatActivity.clearSelectionMode(); + } + chatActivity.showFieldPanelForReplyQuote(messageObject, quote); + if (chatActivity.chatActivityEnterView != null) { + chatActivity.chatActivityEnterView.openKeyboard(); + } + } + } + } } @Override @@ -3090,7 +3183,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); } else if (id == chat_menu_attach) { ActionBarMenuSubItem attach = new ActionBarMenuSubItem(context, false, true, true, getResourceProvider()); - attach.setTextAndIcon(LocaleController.getString("AttachMenu", R.string.AttachMenu), R.drawable.input_attach); + attach.setTextAndIcon(LocaleController.getString(R.string.AttachMenu), R.drawable.input_attach); attach.setOnClickListener(view -> { headerItem.closeSubMenu(); if (chatAttachAlert != null) { @@ -3129,6 +3222,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); chatActivityEnterView.getEditField().makeSelectedSpoiler(); } + } else if (id == text_quote) { + if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { + chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); + chatActivityEnterView.getEditField().makeSelectedQuote(); + } } else if (id == text_mono) { if (chatActivityEnterView != null && chatActivityEnterView.getEditField() != null) { chatActivityEnterView.getEditField().setSelectionOverride(editTextStart, editTextEnd); @@ -3623,7 +3721,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not saveItem = headerItem.lazilyAddSubItem(save, R.drawable.msg_fave, LocaleController.getString("Save", R.string.Save)); } } - if (ChatObject.isForum(currentChat) && isTopic && getParentLayout() != null && getParentLayout().getFragmentStack() != null) { + if (ChatObject.isForum(currentChat) && isTopic && getParentLayout() != null && getParentLayout().getFragmentStack() != null && chatMode == MODE_DEFAULT) { boolean hasMyForum = false; for (int i = 0; i < getParentLayout().getFragmentStack().size(); ++i) { BaseFragment fragment = getParentLayout().getFragmentStack().get(i); @@ -3637,7 +3735,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not openForumItem = headerItem.lazilyAddSubItem(open_forum, R.drawable.msg_discussion, LocaleController.getString("OpenAllTopics", R.string.OpenAllTopics)); } } - if (currentChat != null && forumTopic != null) { + if (currentChat != null && forumTopic != null && chatMode == 0) { closeTopicItem = headerItem.lazilyAddSubItem(topic_close, R.drawable.msg_topic_close, LocaleController.getString("CloseTopic", R.string.CloseTopic)); closeTopicItem.setVisibility(currentChat != null && ChatObject.canManageTopic(currentAccount, currentChat, forumTopic) && forumTopic != null && !forumTopic.closed ? View.VISIBLE : View.GONE); } @@ -4042,7 +4140,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int alpha = (int) (iconProgress * 0xFF); Drawable replyIconDrawable = getThemedDrawable(Theme.key_drawable_replyIcon); replyIconDrawable.setAlpha(alpha); - replyIconDrawable.setBounds((int) (x - AndroidUtilities.dp(7) * scale), (int) (y - AndroidUtilities.dp(6) * scale), (int) (x + AndroidUtilities.dp(7) * scale), (int) (y + AndroidUtilities.dp(5) * scale)); + replyIconDrawable.setBounds((int) (x - AndroidUtilities.dp(12) * scale), (int) (y - AndroidUtilities.dp(12) * scale), (int) (x + AndroidUtilities.dp(12) * scale), (int) (y + AndroidUtilities.dp(12) * scale)); replyIconDrawable.draw(canvas); replyIconDrawable.setAlpha(255); @@ -5390,9 +5488,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public int getStartForFixGap() { int padding = (int) chatListViewPaddingTop; - if (isThreadChat() && (!isTopic || topicStarterMessageObject != null) && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { - padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); - } return padding; } @@ -5535,9 +5630,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < n; i++) { View child = chatListView.getChildAt(i); float padding = chatListViewPaddingTop; - if (isThreadChat() && (!isTopic || topicStarterMessageObject != null) && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { - padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); - } if (chatListView.getChildAdapterPosition(child) == chatAdapter.getItemCount() - 1) { int dyLocal = dy; if (child.getTop() - dy > padding) { @@ -6113,9 +6205,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Object parent = mentionContainer.getAdapter().getItemParent(position); String query = MessageObject.findAnimatedEmojiEmoticon(document); if (chatMode == MODE_SCHEDULED) { - AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, scheduleDate, false, parent), themeDelegate); + AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, null, notify, scheduleDate, false, parent), themeDelegate); } else { - getSendMessagesHelper().sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, sendAnimationData, true, 0, false, parent); + getSendMessagesHelper().sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, sendAnimationData, true, 0, false, parent); } hideFieldPanel(false); chatActivityEnterView.addStickerToRecent(document); @@ -6535,6 +6627,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } + @Override + public void openKeyboard() { + if (forwardingPreviewView != null) { + return; + } + super.openKeyboard(); + } + @Override public void checkAnimation() { if (actionBar.isActionModeShowed() || reportType >= 0) { @@ -6552,6 +6652,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterViewAnimateFromTop != 0 && t != chatActivityEnterViewAnimateFromTop && lastContentViewHeight == contentView.getMeasuredHeight()) { int dy = animatedTop + chatActivityEnterViewAnimateFromTop - t; animatedTop = dy; + messageEditTextContainer.invalidate(); if (changeBoundAnimator != null) { changeBoundAnimator.removeAllListeners(); changeBoundAnimator.cancel(); @@ -6585,6 +6686,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } + messageEditTextContainer.invalidate(); invalidate(); }); changeBoundAnimator.addListener(new AnimatorListenerAdapter() { @@ -6721,12 +6823,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterTopView.addReplyView(replyLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.NO_GRAVITY, 0, 0, 52, 0)); replyLayout.setOnClickListener(v -> { - if (forwardingMessages != null && !forwardingMessages.messages.isEmpty()) { - SharedConfig.forwardingOptionsHintHintShowed(); - openForwardingPreview(); - } else if (replyingMessageObject != null && (!isThreadChat() || replyingMessageObject.getId() != threadMessageId)) { - scrollToMessageId(replyingMessageObject.getId(), 0, true, 0, true, 0); - } else if (editingMessageObject != null) { + if (fieldPanelShown == 1 && editingMessageObject != null) { if (editingMessageObject.canEditMedia() && editingMessageObjectReqId == 0) { if (chatAttachAlert == null) { createChatAttachView(); @@ -6736,6 +6833,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { scrollToMessageId(editingMessageObject.getId(), 0, true, 0, true, 0); } + } else if (messagePreviewParams != null) { + forbidForwardingWithDismiss = false; + if (fieldPanelShown == 2) { + forbidForwardingWithDismiss = messagePreviewParams.quote == null; + SharedConfig.replyingOptionsHintHintShowed(); + openForwardingPreview(MessagePreviewView.TAB_REPLY); + } else if (fieldPanelShown == 3) { + SharedConfig.forwardingOptionsHintHintShowed(); + openForwardingPreview(MessagePreviewView.TAB_FORWARD); + } else if (fieldPanelShown == 4) { + openForwardingPreview(MessagePreviewView.TAB_LINK); + } } }); @@ -6753,16 +6862,31 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterTopView.addView(replyCloseImageView, LayoutHelper.createFrame(52, 46, Gravity.RIGHT | Gravity.TOP, 0, 0.5f, 0, 0)); replyCloseImageView.setOnClickListener(v -> { - if (forwardingMessages == null || forwardingMessages.messages.isEmpty()) { + if (fieldPanelShown == 2) { + replyingQuote = null; + replyingMessageObject = null; + if (messagePreviewParams != null) { + messagePreviewParams.updateReply(null, null, dialog_id, null); + } + fallbackFieldPanel(); + } else if (fieldPanelShown == 3) { + openAnotherForward(); + } else if (fieldPanelShown == 4) { + foundWebPage = null; + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, null, replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + chatActivityEnterView.setWebPage(null, false); + editResetMediaManual(); + fallbackFieldPanel(); + } else { if (ChatObject.isForum(currentChat) && !isTopic && replyingMessageObject != null) { int topicId = MessageObject.getTopicId(replyingMessageObject.messageOwner, true); if (topicId != 0) { getMediaDataController().cleanDraft(dialog_id, topicId, false); } } - showFieldPanel(false, null, null, null, foundWebPage, true, 0, true, true); - } else { - openAnotherForward(); + showFieldPanel(false, null, null, null, null, true, 0, null, true, true); } }); @@ -7222,7 +7346,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkInstantSearch(); if (replyingMessageObject != null) { - chatActivityEnterView.setReplyingMessageObject(replyingMessageObject); + chatActivityEnterView.setReplyingMessageObject(replyingMessageObject, replyingQuote); } ViewGroup decorView; @@ -8047,6 +8171,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ActionBarMenuItem item = editTextItem.createView(); item.addSubItem(text_spoiler, LocaleController.getString("Spoiler", R.string.Spoiler)); + item.addSubItem(text_quote, LocaleController.getString("Quote", R.string.Quote)); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); item.addSubItem(text_bold, stringBuilder); @@ -8155,56 +8280,173 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.invalidate(); } } - } - private void openForwardingPreview() { - boolean keyboardVisible = chatActivityEnterView.isKeyboardVisible(); - forwardingPreviewView = new ForwardingPreviewView(contentView.getContext(), forwardingMessages, currentUser, currentChat, currentAccount, themeDelegate) { + public void fallbackFieldPanel() { + if (foundWebPage != null) { + showFieldPanelForWebPage(true, foundWebPage, false); + } else if (replyingQuote != null) { + showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); + } else if (replyingMessageObject != null && replyingMessageObject != threadMessageObject) { + showFieldPanelForReply(replyingMessageObject); + } else if (messagePreviewParams != null && messagePreviewParams.forwardMessages != null) { + showFieldPanelForForward(true, messagePreviewParams.forwardMessages.messages); + } else if (editingMessageObject != null) { + showFieldPanelForEdit(true, editingMessageObject); + } else { + showFieldPanelForWebPage(false, null, true); + } + } + + private boolean keyboardWasVisible; + private void openForwardingPreview(int startTab) { + if (messagePreviewParams == null || forwardingPreviewView != null) { + return; + } + if (messagePreviewParams.linkMessage != null) { + messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + + + if (messagePreviewParams.isEmpty()) { + return; + } + +// if (chatActivityEnterView != null) { +// chatActivityEnterView.freezeEmojiView(false); +// } + keyboardWasVisible = chatActivityEnterView.isKeyboardVisible(); + forwardingPreviewView = new MessagePreviewView(contentView.getContext(), this, messagePreviewParams, currentUser, currentChat, currentAccount, themeDelegate, startTab, replyingQuote != null && replyingQuote.outdated) { + + @Override + protected void removeLink() { + dismiss(true); + foundWebPage = null; + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(null, false); + } + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, null, replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + fallbackFieldPanel(); + } + + @Override + protected void removeQuote() { + dismiss(true); + replyingQuote = null; + showFieldPanelForReply(replyingMessageObject); + } + + @Override + protected void removeReply() { + dismiss(true); + replyingMessageObject = null; + replyingQuote = null; + messagePreviewParams.updateReply(null, null, dialog_id, null); + fallbackFieldPanel(); + } + + @Override + protected void removeForward() { + super.removeForward(); + dismiss(true); + messagePreviewParams.updateForward(null, dialog_id); + fallbackFieldPanel(); + } + + @Override + protected void onFullDismiss(boolean canShowKeyboard) { + if (messagePreviewParams != null) { + messagePreviewParams.attach(null); + } + if (canShowKeyboard) { + AndroidUtilities.runOnUIThread(() -> { + if (chatActivityEnterView != null) { + chatActivityEnterView.freezeEmojiView(false); + } + }, 15); + } + } + + @Override + protected void onQuoteSelectedPart() { + if (replyingQuote == null) { + replyingQuote = messagePreviewParams.quote; + } + } + @Override protected void onDismiss(boolean canShowKeyboard) { + forwardingPreviewView = null; checkShowBlur(true); - if (forwardingMessages != null) { - ArrayList selectedMessage = new ArrayList<>(); - forwardingMessages.getSelectedMessages(selectedMessage); - showFieldPanelForForward(true, selectedMessage); + if (messagePreviewParams != null) { + if (replyingQuote == null) { + replyingQuote = messagePreviewParams.quote; + } + if (messagePreviewParams.quote == null) { + replyingQuote = null; + } + if (replyingQuote != null) { + replyingQuote.outdated = false; + replyingQuote.start = messagePreviewParams.quoteStart; + replyingQuote.end = messagePreviewParams.quoteEnd; + replyingQuote.update(); + if (fieldPanelShown == 2) { + showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); + } + } else { + ArrayList selectedMessage = new ArrayList<>(); + if (messagePreviewParams.forwardMessages != null) { + messagePreviewParams.forwardMessages.getSelectedMessages(selectedMessage); + } + fallbackFieldPanel(); + } } + forbidForwardingWithDismiss = false; - if (keyboardVisible && canShowKeyboard) { + if (keyboardWasVisible && canShowKeyboard) { AndroidUtilities.runOnUIThread(() -> { if (chatActivityEnterView != null) { chatActivityEnterView.openKeyboard(); } }, 50); + keyboardWasVisible = false; } AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); } @Override - protected void selectAnotherChat() { - super.selectAnotherChat(); + protected void selectAnotherChat(boolean forward) { dismiss(false); - if (forwardingMessages != null) { + if (messagePreviewParams != null) { + if (!forward) { + ignoreDraft = true; + } int hasPoll = 0; boolean hasInvoice = false; - for (int a = 0, N = forwardingMessages.messages.size(); a < N; a++) { - MessageObject messageObject = forwardingMessages.messages.get(a); - if (messageObject.isPoll()) { - if (hasPoll != 2) { - hasPoll = messageObject.isPublicPoll() ? 2 : 1; + if (messagePreviewParams.forwardMessages != null) { + for (int a = 0, N = messagePreviewParams.forwardMessages.messages.size(); a < N; a++) { + MessageObject messageObject = messagePreviewParams.forwardMessages.messages.get(a); + if (messageObject.isPoll()) { + if (hasPoll != 2) { + hasPoll = messageObject.isPublicPoll() ? 2 : 1; + } + } else if (messageObject.isInvoice()) { + hasInvoice = true; } - } else if (messageObject.isInvoice()) { - hasInvoice = true; + selectedMessagesIds[0].put(messageObject.getId(), messageObject); } - selectedMessagesIds[0].put(messageObject.getId(), messageObject); } Bundle args = new Bundle(); args.putBoolean("onlySelect", true); args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); + args.putBoolean("quote", !forward); + args.putBoolean("reply_to", !forward && messagePreviewParams.replyMessage != null && messagePreviewParams.quote == null); args.putInt("hasPoll", hasPoll); args.putBoolean("hasInvoice", hasInvoice); - args.putInt("messagesCount", forwardingMessages.messages.size()); + args.putInt("messagesCount", messagePreviewParams.forwardMessages == null ? 0 : messagePreviewParams.forwardMessages.messages.size()); args.putBoolean("canSelectTopics", true); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate(ChatActivity.this); @@ -8219,6 +8461,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.getSendButton().callOnClick(); } }; + messagePreviewParams.attach(forwardingPreviewView); TLRPC.Peer defPeer = chatInfo != null ? chatInfo.default_send_as : null; if (defPeer == null && sendAsPeersObj != null && !sendAsPeersObj.peers.isEmpty()) { defPeer = sendAsPeersObj.peers.get(0).peer; @@ -8227,7 +8470,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkShowBlur(true); contentView.addView(forwardingPreviewView); - if (keyboardVisible) { + if (keyboardWasVisible) { + chatActivityEnterView.freezeEmojiView(true); chatActivityEnterView.showEmojiView(); openKeyboardOnAttachMenuClose = true; } @@ -8690,14 +8934,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void openAnotherForward() { - if (forwardingMessages == null || forwardingMessages.messages == null) { + if (messagePreviewParams == null || messagePreviewParams.isEmpty() || messagePreviewParams.forwardMessages == null || messagePreviewParams.forwardMessages.messages == null) { return; } boolean fewSenders = false; long lastPeerId = 0; long dialogId = 0; - for (int a = 0, N = forwardingMessages.messages.size(); a < N; a++) { - MessageObject message = forwardingMessages.messages.get(a); + for (int a = 0, N = messagePreviewParams.forwardMessages.messages.size(); a < N; a++) { + MessageObject message = messagePreviewParams.forwardMessages.messages.get(a); if (lastPeerId == 0) { dialogId = message.getDialogId(); lastPeerId = message.getFromChatId(); @@ -8714,25 +8958,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (user == null) { return; } - message = LocaleController.formatString("CancelForwardPrivate", R.string.CancelForwardPrivate, LocaleController.formatPluralString("MessagesBold", forwardingMessages.messages.size()), ContactsController.formatName(user.first_name, user.last_name)); + message = LocaleController.formatString("CancelForwardPrivate", R.string.CancelForwardPrivate, LocaleController.formatPluralString("MessagesBold", messagePreviewParams.forwardMessages.messages.size()), ContactsController.formatName(user.first_name, user.last_name)); } else { TLRPC.Chat chat = getMessagesController().getChat(-dialogId); if (chat == null) { return; } - message = LocaleController.formatString("CancelForwardChat", R.string.CancelForwardChat, LocaleController.formatPluralString("MessagesBold", forwardingMessages.messages.size()), chat == null ? "" : chat.title); + message = LocaleController.formatString("CancelForwardChat", R.string.CancelForwardChat, LocaleController.formatPluralString("MessagesBold", messagePreviewParams.forwardMessages.messages.size()), chat == null ? "" : chat.title); } builder.setMessage(AndroidUtilities.replaceTags(message)); - builder.setTitle(LocaleController.formatPluralString("messages", forwardingMessages.messages.size())); + builder.setTitle(LocaleController.formatPluralString("messages", messagePreviewParams.forwardMessages.messages.size())); builder.setPositiveButton(LocaleController.getString("CancelForwarding", R.string.CancelForwarding), (dialogInterface, i) -> { - if (forwardingMessages != null) { - forwardingMessages = null; + forbidForwardingWithDismiss = false; + if (messagePreviewParams != null) { + messagePreviewParams.updateForward(null, dialog_id); } - showFieldPanel(false, null, null, null, foundWebPage, true, 0, true, true); + fallbackFieldPanel(); }); builder.setNegativeButton(LocaleController.getString("ShowForwardingOptions", R.string.ShowForwardingOptions), (dialogInterface, i) -> { - openForwardingPreview(); + openForwardingPreview(MessagePreviewView.TAB_FORWARD); }); AlertDialog dialog = builder.create(); showDialog(dialog); @@ -8907,7 +9152,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public int getPreviewHeight() { if (chatMode == MODE_PINNED && messages.size() == 2) { - return getHeightForMessage(messages.get(0)) + AndroidUtilities.dp(80) + ActionBar.getCurrentActionBarHeight(); + return getHeightForMessage(messages.get(0), false) + AndroidUtilities.dp(80) + ActionBar.getCurrentActionBarHeight(); } return super.getPreviewHeight(); } @@ -9010,13 +9255,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { pinnedViewH = Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); } + if (isThreadChat() && (!isTopic || pinnedOnlyStarterMessage())) { + pinnedViewH = 0; + } float pendingViewH = 0; View pendingRequestsView = pendingRequestsDelegate != null ? pendingRequestsDelegate.getView() : null; if (pendingRequestsView != null && pendingRequestsView.getVisibility() == View.VISIBLE) { pendingViewH = Math.max(0, pendingRequestsView.getHeight() + pendingRequestsDelegate.getViewEnterOffset()); } float oldPadding = chatListViewPaddingTop; - chatListViewPaddingTopOnlyTopViews = topPanelViewH + pinnedViewH; chatListViewPaddingTop = AndroidUtilities.dp(4) + contentPaddingTop + topPanelViewH + pinnedViewH + pendingViewH; chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; @@ -9101,9 +9348,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int adapterPosition = chatListView.getChildAdapterPosition(child); if (adapterPosition == chatAdapter.getItemCount() - 1) { float padding = chatListViewPaddingTop; - if (isThreadChat() && (!isTopic || topicStarterMessageObject != null) && pinnedMessageView != null && pinnedMessageView.getVisibility() == View.VISIBLE) { - padding -= Math.max(0, AndroidUtilities.dp(48) + pinnedMessageEnterOffset); - } if (child.getTop() > padding) { chatListView.scrollBy(0, (int) (child.getTop() - padding)); } @@ -9519,7 +9763,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); params.put("bot_name", mentionContainer.getAdapter().getContextBotName()); - SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), result, params, dialog_id, replyingMessageObject, getThreadMessage(), null, notify, scheduleDate); + SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), result, params, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, notify, scheduleDate); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); getMediaDataController().increaseInlineRaiting(uid); @@ -9610,7 +9854,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), getResourceProvider()); webViewSheet.setParentActivity(getParentActivity()); webViewSheet.requestWebView(currentAccount, currentUser != null ? currentUser.id : currentChat.id, mentionContainer.getAdapter().getFoundContextBot().id, object.text, object.url, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, false, BotWebViewSheet.FLAG_FROM_INLINE_SWITCH); - webViewSheet.show(); + showDialog(webViewSheet); }; if (approved) { open.run(); @@ -9722,7 +9966,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); updateStickersOrder = photos.get(0).updateStickersOrder; } - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate, updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate, updateStickersOrder, null); } afterMessageSend(); chatActivityEnterView.setFieldText(""); @@ -9875,6 +10119,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void afterMessageSend() { + if (threadMessageId == 0 || isTopic) { + if (isTopic) { + replyingMessageObject = threadMessageObject; + } else { + replyingMessageObject = null; + } + replyingQuote = null; + chatActivityEnterView.setReplyingMessageObject(null, null); + } hideFieldPanel(false); if (chatMode == 0) { getMediaDataController().cleanDraft(dialog_id, threadMessageId, true); @@ -9959,6 +10212,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } bundle.putInt("chatMode", MODE_SCHEDULED); ChatActivity fragment = new ChatActivity(bundle); + if (isTopic) { + ForumUtilities.applyTopic(fragment, MessagesStorage.TopicKey.of(getDialogId(), getTopicId())); + } fragment.chatActivityDelegate = new ChatActivityDelegate() { @Override public void openReplyMessage(int mid) { @@ -10154,7 +10410,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void showScheduledHint() { boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); - if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3) { + if (scheduledHintShown || scheduledOrNoSoundHintShown || disableNoSound || SharedConfig.scheduledHintShows >= 3 || chatActivityEnterView.isEditingMessage()) { return; } AndroidUtilities.cancelRunOnUIThread(showScheduledHintRunnable); @@ -10165,7 +10421,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean disableNoSound = (UserObject.isUserSelf(currentUser) || (chatInfo != null && chatInfo.slowmode_next_send_date > 0) && chatMode == 0); long scheduledOrNoSoundHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledOrNoSoundHintSeenAt; long scheduledHintTimeFromLastSeen = System.currentTimeMillis() - SharedConfig.scheduledHintSeenAt; - if (disableNoSound || SharedConfig.scheduledOrNoSoundHintShows >= 3 || scheduledOrNoSoundHintTimeFromLastSeen < 86400000L || scheduledHintTimeFromLastSeen < 86400000L) { + if (disableNoSound || SharedConfig.scheduledOrNoSoundHintShows >= 3 || scheduledOrNoSoundHintTimeFromLastSeen < 86400000L || scheduledHintTimeFromLastSeen < 86400000L || chatActivityEnterView.isEditingMessage()) { return; } AndroidUtilities.cancelRunOnUIThread(showScheduledOrNoSoundRunnable); @@ -10345,7 +10601,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!canShowText && text != null) { - canShowText = text.length() > 200; + canShowText = true; // text.length() > 200; } if (!canShowText || SharedConfig.textSelectionHintShows > 2 || textSelectionHintWasShowed || lastTouchY > chatActivityEnterView.getTop() - AndroidUtilities.dp(60)) { return; @@ -10831,7 +11087,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not caption = null; } getSendMessagesHelper().sendMessage(fmessages, dialog_id, false, false, true, 0); - SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, notify, scheduleDate, null); + SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, editingMessageObject, notify, scheduleDate, null); afterMessageSend(); } } @@ -10839,7 +11095,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didSelectPhotos(ArrayList photos, boolean notify, int scheduleDate) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, true, false, editingMessageObject, notify, scheduleDate, photos.get(0).updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, true, false, editingMessageObject, notify, scheduleDate, photos.get(0).updateStickersOrder, null); afterMessageSend(); if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { @@ -10871,7 +11127,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0; a < photos.size(); a++) { SendMessagesHelper.SendingMediaInfo info = photos.get(a); if (info.inlineResult != null && info.videoEditedInfo == null) { - SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), info.inlineResult, info.params, dialog_id, replyingMessageObject, getThreadMessage(), null, notify, scheduleDate); + SendMessagesHelper.prepareSendingBotContextResult(this, getAccountInstance(), info.inlineResult, info.params, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, notify, scheduleDate); photos.remove(a); a--; } @@ -10880,7 +11136,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, false, true, editingMessageObject, notify, scheduleDate, photos.get(0).updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, false, true, editingMessageObject, notify, scheduleDate, photos.get(0).updateStickersOrder, null); afterMessageSend(); if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { @@ -10910,10 +11166,44 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return dialog != chatAttachAlert && dialog != chatThemeBottomSheet && super.dismissDialogOnPause(dialog); } - private void searchLinks(final CharSequence charSequence, final boolean force) { + int waitingForWebpageId; + private void cancelSearchLinks() { + if (linkSearchRequestId != 0) { + getConnectionsManager().cancelRequest(linkSearchRequestId, true); + } + } + + private void editResetMediaManual() { + if (editingMessageObject != null && editingMessageObject.messageOwner != null && editingMessageObject.messageOwner.media != null) { + editingMessageObject.messageOwner.media.manual = false; + } + } + + public void checkEditLinkRemoved(final CharSequence charSequence) { + final boolean manual = editingMessageObject != null && editingMessageObject.messageOwner != null && editingMessageObject.messageOwner.media != null && editingMessageObject.messageOwner.media.webpage != null && !(editingMessageObject.messageOwner.media.webpage instanceof TLRPC.TL_webPageEmpty) && editingMessageObject.messageOwner.media.manual; + if (messagePreviewParams != null && editingMessageObject != null && (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS) && foundWebPage != null) { + if (messagePreviewParams.hasLink(charSequence, foundWebPage.url)) { + return; + } + if (manual) { + foundWebPage = null; + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(null, true); + } + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + editResetMediaManual(); + fallbackFieldPanel(); + } + } + } + + public void searchLinks(final CharSequence charSequence, final boolean force) { if (currentEncryptedChat != null && getMessagesController().secretWebpagePreview == 0 || editingMessageObject != null && !editingMessageObject.isWebpage()) { return; } + checkEditLinkRemoved(charSequence); if (force && foundWebPage != null) { if (foundWebPage.url != null) { int index = TextUtils.indexOf(charSequence, foundWebPage.url); @@ -10930,12 +11220,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not lastChar = !lenEqual ? charSequence.charAt(index + foundWebPage.url.length()) : 0; } if (index != -1 && (lenEqual || lastChar == ' ' || lastChar == ',' || lastChar == '.' || lastChar == '!' || lastChar == '/')) { + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } return; } } pendingLinkSearchString = null; foundUrls = null; -// showFieldPanelForWebPage(false, foundWebPage, false); + foundWebPage = null; + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(null, true); + } + fallbackFieldPanel(); + editResetMediaManual(); } final MessagesController messagesController = getMessagesController(); Utilities.searchQueue.postRunnable(() -> { @@ -10985,10 +11283,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not foundUrls = urls; if (urls == null) { AndroidUtilities.runOnUIThread(() -> { - if (foundWebPage != null) { - showFieldPanelForWebPage(false, foundWebPage, false); - foundWebPage = null; - } + foundWebPage = null; + fallbackFieldPanel(); }); return; } @@ -10998,10 +11294,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not String text = charSequence.toString().toLowerCase(); if (charSequence.length() < 13 || !text.contains("http://") && !text.contains("https://")) { AndroidUtilities.runOnUIThread(() -> { - if (foundWebPage != null) { - showFieldPanelForWebPage(false, foundWebPage, false); - foundWebPage = null; - } + foundWebPage = null; + fallbackFieldPanel(); }); return; } @@ -11037,39 +11331,133 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (foundWebPage != null && req.message.equals(foundWebPage.displayedText)) { return; } - linkSearchRequestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - linkSearchRequestId = 0; - if (error == null) { - if (response instanceof TLRPC.TL_messageMediaWebPage) { - foundWebPage = ((TLRPC.TL_messageMediaWebPage) response).webpage; - foundWebPage.display_url = req.message; - if (foundWebPage instanceof TLRPC.TL_webPage || foundWebPage instanceof TLRPC.TL_webPagePending) { - if (foundWebPage instanceof TLRPC.TL_webPagePending) { - pendingLinkSearchString = req.message; - } - if (currentEncryptedChat != null && foundWebPage instanceof TLRPC.TL_webPagePending) { - foundWebPage.url = req.message; - } - showFieldPanelForWebPage(true, foundWebPage, false); - } else { - if (foundWebPage != null) { - showFieldPanelForWebPage(false, foundWebPage, false); - foundWebPage = null; - } + final int myId = ++waitingForWebpageId; + requestLinkPreviewCached(req, (success, webpage) -> AndroidUtilities.runOnUIThread(() -> { + if (waitingForWebpageId != myId) { + return; + } + if (success) { + foundWebPage = webpage; + foundWebPage.display_url = req.message; + if (foundWebPage instanceof TLRPC.TL_webPage || foundWebPage instanceof TLRPC.TL_webPagePending) { + if (foundWebPage instanceof TLRPC.TL_webPagePending) { + pendingLinkSearchString = req.message; } + if (currentEncryptedChat != null && foundWebPage instanceof TLRPC.TL_webPagePending) { + foundWebPage.url = req.message; + } + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + showFieldPanelForWebPage(true, foundWebPage, false); } else { if (foundWebPage != null) { - showFieldPanelForWebPage(false, foundWebPage, false); foundWebPage = null; + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + fallbackFieldPanel(); } } + } else { + foundWebPage = null; + fallbackFieldPanel(); } })); - - getConnectionsManager().bindRequestToGuid(linkSearchRequestId, classGuid); }); } + private HashMap lastLinkPreviewResults; + + private void requestLinkPreviewCached(TLRPC.TL_messages_getWebPagePreview req, Utilities.Callback2 done) { + if (lastLinkPreviewResults == null) { + lastLinkPreviewResults = new HashMap<>(); + } + TLRPC.WebPage result = lastLinkPreviewResults.get(req.message); + if (result != null) { + done.run(true, result); + } else { + requestLinkPreview(req, (success, webpage) -> { + if (success && !(webpage instanceof TLRPC.TL_webPagePending)) { + Iterator keys = lastLinkPreviewResults.keySet().iterator(); + while (keys.hasNext() && lastLinkPreviewResults.size() > 5) { + keys.next(); + keys.remove(); + } + lastLinkPreviewResults.put(req.message, webpage); + } + done.run(success, webpage); + }); + } + } + + private void requestLinkPreview(TLRPC.TL_messages_getWebPagePreview req, Utilities.Callback2 done) { + cancelSearchLinks(); + linkSearchRequestId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + linkSearchRequestId = 0; + if (response instanceof TLRPC.TL_messageMediaWebPage) { + TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) response; + if (media.webpage != null && "telegram_story".equals(media.webpage.type)) { + TLRPC.TL_webPageAttributeStory _attrStory = null; + if (media.webpage.attributes != null) { + for (int i = 0; i < media.webpage.attributes.size(); ++i) { + if (media.webpage.attributes.get(i) instanceof TLRPC.TL_webPageAttributeStory) { + _attrStory = (TLRPC.TL_webPageAttributeStory) media.webpage.attributes.get(i); + break; + } + } + } + if (_attrStory == null) { + done.run(false, null); + return; + } + if (_attrStory != null && _attrStory.storyItem != null) { + done.run(true, media.webpage); + return; + } + final TLRPC.TL_webPageAttributeStory attrStory = _attrStory; + getMessagesStorage().getStorageQueue().postRunnable(() -> { + try { + LongSparseArray> array = new LongSparseArray<>(); + TLRPC.TL_message message = new TLRPC.TL_message(); + message.message = ""; + message.id = 0; + message.media = media; + ArrayList list = new ArrayList<>(); + list.add(new MessageObject(currentAccount, message, false, false)); + array.put(DialogObject.getPeerDialogId(attrStory.peer), list); + getMessagesController().getStoriesController().getStoriesStorage().fillMessagesWithStories(array, () -> { + MessageObject result = null; + if (array.size() == 1 && array.valueAt(0) != null && array.valueAt(0).size() == 1) { + result = array.valueAt(0).get(0); + } + if (result != null && result.messageOwner != null && result.messageOwner.media != null && result.messageOwner.media.webpage != null && result.messageOwner.media.webpage.attributes != null) { + for (int i = 0; i < result.messageOwner.media.webpage.attributes.size(); ++i) { + TLRPC.WebPageAttribute attr = result.messageOwner.media.webpage.attributes.get(i); + if (attr instanceof TLRPC.TL_webPageAttributeStory) { + if (((TLRPC.TL_webPageAttributeStory) attr).storyItem != null) { + final TLRPC.WebPage webpage = result.messageOwner.media.webpage; + AndroidUtilities.runOnUIThread(() -> { done.run(true, webpage); }); + return; + } + } + } + } + AndroidUtilities.runOnUIThread(() -> { done.run(false, null); }); + }, classGuid, false); + } catch (Exception ignore) {} + }); + } else { + done.run(media.webpage != null, media.webpage); + } + } else { + done.run(false, null); + } + })); + + getConnectionsManager().bindRequestToGuid(linkSearchRequestId, classGuid); + } + private void forwardMessages(ArrayList arrayList, boolean fromMyName, boolean hideCaption, boolean notify, int scheduleDate) { if (arrayList == null || arrayList.isEmpty()) { return; @@ -11119,37 +11507,209 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + public static class ReplyQuote { + public final long peerId; + public MessageObject message; + public int start, end; + public boolean outdated; + + public String text; + public ArrayList entities; + public int offset, length; + + private ReplyQuote(long peerId, @NonNull MessageObject message, int start, int end) { + this.peerId = peerId; + this.message = message; + this.start = start; + this.end = end; + + update(); + } + + public static ReplyQuote from(MessageObject messageObject, String text) { + if (messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.message == null || text == null) { + return null; + } + int start = messageObject.messageOwner.message.indexOf(text); + if (start < 0) { + return null; + } + return new ReplyQuote( + messageObject.getDialogId(), + messageObject, + start, start + text.length() + ); + } + + public static ReplyQuote from(MessageObject messageObject) { + if (messageObject == null || messageObject.messageOwner == null || messageObject.messageOwner.message == null) { + return null; + } + return from(messageObject, 0, Math.min(MessagesController.getInstance(messageObject.currentAccount).quoteLengthMax, messageObject.messageOwner.message.length())); + } + + public static ReplyQuote from(MessageObject messageObject, int start, int end) { + if (messageObject == null) { + return null; + } + return new ReplyQuote( + messageObject.getDialogId(), + messageObject, + start, end + ); + } + + private boolean update() { + if (message == null || message.messageOwner == null || message.messageOwner.message == null) { + FileLog.e("ReplyQuote: message is null"); + return false; + } + if (end < start || end > message.messageOwner.message.length() || start > message.messageOwner.message.length() || start < 0 || end < 0) { + FileLog.e("ReplyQuote: start/end are invalid (" + start + ", " + end + ", len=" + message.messageOwner.message.length() + ")"); + return false; + } + final String fulltext = message.messageOwner.message; + int realStart = Math.max(0, start); + while (realStart < end && Character.isWhitespace(fulltext.charAt(realStart))) realStart++; + int realEnd = Math.min(end, fulltext.length()); + while (realEnd > realStart && Character.isWhitespace(fulltext.charAt(realEnd - 1))) realEnd--; + if (realStart == realEnd) { + FileLog.e("ReplyQuote: message is full of whitespace"); + return false; + } + text = message.messageOwner.message.substring(realStart, realEnd); + if (entities != null) { + entities.clear(); + } + if (message.messageOwner.entities != null && !message.messageOwner.entities.isEmpty()) { + for (int i = 0; i < message.messageOwner.entities.size(); ++i) { + TLRPC.MessageEntity entity = message.messageOwner.entities.get(i); + if (!AndroidUtilities.intersect1dInclusive(realStart, realEnd, entity.offset, entity.offset + entity.length)) { + continue; + } + + TLRPC.MessageEntity newEntity; + if (entity instanceof TLRPC.TL_messageEntityBold) { + newEntity = new TLRPC.TL_messageEntityBold(); + } else if (entity instanceof TLRPC.TL_messageEntityItalic) { + newEntity = new TLRPC.TL_messageEntityItalic(); + } else if (entity instanceof TLRPC.TL_messageEntityUnderline) { + newEntity = new TLRPC.TL_messageEntityUnderline(); + } else if (entity instanceof TLRPC.TL_messageEntityStrike) { + newEntity = new TLRPC.TL_messageEntityStrike(); + } else if (entity instanceof TLRPC.TL_messageEntitySpoiler) { + newEntity = new TLRPC.TL_messageEntitySpoiler(); + } else if (entity instanceof TLRPC.TL_messageEntityCustomEmoji) { + newEntity = new TLRPC.TL_messageEntityCustomEmoji(); + ((TLRPC.TL_messageEntityCustomEmoji) newEntity).document_id = ((TLRPC.TL_messageEntityCustomEmoji) entity).document_id; + ((TLRPC.TL_messageEntityCustomEmoji) newEntity).document = ((TLRPC.TL_messageEntityCustomEmoji) entity).document; + } else { + continue; + } + + int entityStart = entity.offset - realStart; + int entityEnd = entity.offset + entity.length - realStart; + if (entityStart < 0 && entityEnd < 0 || entityStart > realEnd && entityEnd > realEnd) { + continue; + } + + newEntity.offset = Math.max(0, entityStart); + newEntity.length = Math.min(entityEnd, realEnd - realStart) - newEntity.offset; + + if (entities == null) { + entities = new ArrayList<>(); + } + entities.add(newEntity); + } + } + + offset = realStart; + length = realEnd - realStart; + return true; + } + + // returns whether quote alert should be shown + public boolean checkEdit(MessageObject message) { + if (message == null || message.messageOwner == null || message.messageOwner.message == null) { + FileLog.e("ReplyQuote.checkEdit: message is null"); + return outdated = false; + } + if (end < start || end > message.messageOwner.message.length() || start > message.messageOwner.message.length() || start < 0 || end < 0) { + FileLog.e("ReplyQuote.checkEdit: start/end are invalid (" + start + ", " + end + ", len=" + message.messageOwner.message.length() + ")"); + return outdated = false; + } + String newText = message.messageOwner.message.substring(start, end); + if (TextUtils.equals(text, newText)) { + this.message = message; + update(); // maybe some entities changed + return outdated = false; + } + int newStart = message.messageOwner.message.indexOf(text); + if (newStart >= 0) { + this.message = message; + end = end - start + newStart; + start = newStart; + update(); + return outdated = false; + } + this.message = message; + start = 0; + end = message.messageOwner.message.length(); + update(); + return outdated = true; + } + + public String getText() { + return text; + } + + public ArrayList getEntities() { + return entities; + } + + public boolean limited() { + return text != null && message != null && text.length() > MessagesController.getInstance(message.currentAccount).quoteLengthMax; + } + } + public void hideFieldPanel(boolean animated) { - showFieldPanel(false, null, null, null, null, true, 0, false, animated); + showFieldPanel(false, null, null, null, null, true, 0, null, false, animated); } public void hideFieldPanel(boolean notify, int scheduleDate, boolean animated) { - showFieldPanel(false, null, null, null, null, notify, scheduleDate, false, animated); + showFieldPanel(false, null, null, null, null, notify, scheduleDate, null, false, animated); } public void showFieldPanelForWebPage(boolean show, TLRPC.WebPage webPage, boolean cancel) { - showFieldPanel(show, null, null, null, webPage, true, 0, cancel, true); + showFieldPanel(show, null, null, null, webPage, true, 0, null, cancel, true); } public void showFieldPanelForForward(boolean show, ArrayList messageObjectsToForward) { - showFieldPanel(show, null, null, messageObjectsToForward, null, true, 0, false, true); + showFieldPanel(show, null, null, messageObjectsToForward, null, true, 0, null, false, true); } public void showFieldPanelForReply(MessageObject messageObjectToReply) { - showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, false, true); + showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, null, false, true); + } + + public void showFieldPanelForReplyQuote(MessageObject messageObjectToReply, ReplyQuote quote) { + showFieldPanel(true, messageObjectToReply, null, null, null, true, 0, quote, false, true); } public void showFieldPanelForEdit(boolean show, MessageObject messageObjectToEdit) { - showFieldPanel(show, null, messageObjectToEdit, null, null, true, 0, false, true); + showFieldPanel(show, null, messageObjectToEdit, null, null, true, 0, null, false, true); } - public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, boolean cancel, boolean animated) { + private int fieldPanelShown; + + public void showFieldPanel(boolean show, MessageObject messageObjectToReply, MessageObject messageObjectToEdit, ArrayList messageObjectsToForward, TLRPC.WebPage webPage, boolean notify, int scheduleDate, ReplyQuote quote, boolean cancel, boolean animated) { if (chatActivityEnterView == null) { return; } - boolean showHint = false, showReplyHint = false; + boolean showHint = false; if (show) { if (messageObjectToReply == null && messageObjectsToForward == null && messageObjectToEdit == null && webPage == null) { + messagePreviewParams = null; return; } hideHints(false); @@ -11163,30 +11723,34 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, 100); } boolean openKeyboard = false; - if (messageObjectToReply != null && messageObjectToReply.getDialogId() != dialog_id) { - messageObjectsToForward = new ArrayList<>(); - messageObjectsToForward.add(messageObjectToReply); - messageObjectToReply = null; - openKeyboard = true; - } +// if (messageObjectToReply != null && messageObjectToReply.getDialogId() != dialog_id && quote == null) { +// messageObjectsToForward = new ArrayList<>(); +// messageObjectsToForward.add(messageObjectToReply); +// messageObjectToReply = null; +// openKeyboard = true; +// } chatActivityEnterTopView.setEditMode(false); if (messageObjectToEdit != null) { - forwardingMessages = null; + fieldPanelShown = 1; + forbidForwardingWithDismiss = false; + if (messagePreviewParams != null) { + messagePreviewParams.updateForward(null, dialog_id); + messagePreviewParams.updateReply(null, null, dialog_id, null); + } if (threadMessageId == 0 || isTopic) { if (isTopic) { replyingMessageObject = threadMessageObject; } else { replyingMessageObject = null; } - chatActivityEnterView.setReplyingMessageObject(null); + replyingQuote = null; + chatActivityEnterView.setReplyingMessageObject(null, null); updateBottomOverlay(); } + boolean wereNoEdit = editingMessageObject == null; editingMessageObject = messageObjectToEdit; final boolean mediaEmpty = messageObjectToEdit.isMediaEmpty(); chatActivityEnterView.setEditingMessageObject(messageObjectToEdit, !mediaEmpty); - if (foundWebPage != null) { - return; - } chatActivityEnterView.setForceShowSendButton(false, false); final boolean canEditMedia = messageObjectToEdit.canEditMedia(); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelEdit", R.string.AccDescrCancelEdit)); @@ -11239,24 +11803,62 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(cs)); } } + if (wereNoEdit) { + if (messageObjectToEdit.messageOwner != null && messageObjectToEdit.messageOwner.media != null && messageObjectToEdit.messageOwner.media.webpage != null) { + foundWebPage = messageObjectToEdit.messageOwner.media.webpage; + chatActivityEnterView.setWebPage(foundWebPage, false); + showFieldPanelForWebPage(true, foundWebPage, false); + return; + } else { + foundWebPage = null; + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, null, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(null, false); + } + } + } } else if (messageObjectToReply != null) { editingMessageObject = null; replyingMessageObject = messageObjectToReply; - chatActivityEnterView.setReplyingMessageObject(messageObjectToReply); - chatActivityEnterView.setEditingMessageObject(null, false); - if (foundWebPage != null) { - return; + replyingQuote = quote; + if (replyingQuote != null && replyingQuote.getText() == null) { + replyingQuote = null; } + chatActivityEnterView.setReplyingMessageObject(messageObjectToReply, quote); + chatActivityEnterView.setEditingMessageObject(null, false); + forbidForwardingWithDismiss = false; + if (messagePreviewParams == null) { + messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat)); + messagePreviewParams.attach(forwardingPreviewView); + } + messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); + if (messagePreviewParams.isEmpty() && editingMessageObject == null) { + messagePreviewParams = null; + } + fieldPanelShown = 2; String restrictionReason = MessagesController.getRestrictionReason(messageObjectToReply.messageOwner.restriction_reason); chatActivityEnterView.setForceShowSendButton(false, false); - String name; - if (messageObjectToReply.isFromUser()) { + CharSequence name = null; + if (messageObjectToReply.isForwarded()) { + if (messageObjectToReply.messageOwner.fwd_from.from_id != null) { + name = MessageObject.peerNameWithIcon(currentAccount, messageObjectToReply.messageOwner.fwd_from.from_id); + } else { + name = null; + } + } + if (name == null && messageObjectToReply.isFromUser()) { if (messageObjectToReply.messageOwner.from_id.channel_id != 0) { TLRPC.Chat chat = getMessagesController().getChat(messageObjectToReply.messageOwner.from_id.channel_id); if (chat == null) { return; } - name = getUserConfig().getChatTitleOverride(chat); + if (quote != null) { + name = TextUtils.concat(ChatObject.isChannelAndNotMegaGroup(chat) ? MessageObject.channelSpan() : MessageObject.groupSpan(), " ", getUserConfig().getChatTitleOverride(chat)); + } else { + name = getUserConfig().getChatTitleOverride(chat); + } } else { TLRPC.User user = getMessagesController().getUser(messageObjectToReply.messageOwner.from_id.user_id); if (user == null) { @@ -11264,7 +11866,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } name = UserObject.getUserName(user, currentAccount); } - } else { + } else if (name == null) { TLRPC.Chat chat; if (ChatObject.isChannel(currentChat) && currentChat.megagroup && messageObjectToReply.isForwardedChannelPost()) { chat = getMessagesController().getChat(messageObjectToReply.messageOwner.fwd_from.from_id.channel_id); @@ -11274,16 +11876,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chat == null) { return; } - name = getUserConfig().getChatTitleOverride(chat); + if (quote != null) { + name = TextUtils.concat(ChatObject.isChannelAndNotMegaGroup(chat) ? MessageObject.channelSpan() : MessageObject.groupSpan(), " ", getUserConfig().getChatTitleOverride(chat)); + } else { + name = getUserConfig().getChatTitleOverride(chat); + } } - replyIconImageView.setImageResource(R.drawable.msg_panel_reply); - replyNameTextView.setText(name); + CharSequence nameText; + if (quote != null) { + replyIconImageView.setImageResource(R.drawable.filled_reply_quote); + nameText = AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.ReplyToQuote), name == null ? "" : name); + } else { + replyIconImageView.setImageResource(R.drawable.filled_reply_settings); + nameText = LocaleController.formatString(R.string.ReplyTo, name == null ? "" : name); + } + nameText = Emoji.replaceEmoji(nameText, replyNameTextView.getPaint().getFontMetricsInt(), false); + replyNameTextView.setText(nameText); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrReplying", R.string.AccDescrReplying)); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelReply", R.string.AccDescrCancelReply)); + replyObjectHintTextView.setText(LocaleController.getString(R.string.TapForReplyOptions)); + if (!SharedConfig.replyingOptionsHintShown) { + showHint = true; + } + CharSequence replyObjectText = null; CharSequence sourceText = null; - if (!TextUtils.isEmpty(restrictionReason)) { + ArrayList entities = messageObjectToReply != null && messageObjectToReply.messageOwner != null ? messageObjectToReply.messageOwner.entities : null; + if (replyingQuote != null) { + if (replyingQuote.outdated) { + replyObjectText = new SpannableStringBuilder(LocaleController.getString(R.string.QuoteOutdated)); + ((SpannableStringBuilder) replyObjectText).setSpan(new TypefaceSpan(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM_ITALIC)), 0, replyObjectText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + replyObjectText = new SpannableStringBuilder(replyingQuote.getText()); + entities = replyingQuote.getEntities(); + replyObjectText = AndroidUtilities.replaceNewLines(replyObjectText); + if (entities != null) { + replyObjectText = MessageObject.replaceAnimatedEmoji(replyObjectText, entities, replyObjectTextView.getPaint().getFontMetricsInt()); + } + replyObjectText = Emoji.replaceEmoji(replyObjectText, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); + } + } else if (!TextUtils.isEmpty(restrictionReason)) { replyObjectText = restrictionReason; sourceText = restrictionReason; } else if (MessageObject.isTopicActionMessage(messageObjectToReply)) { @@ -11295,7 +11928,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } AnimatedEmojiSpan.applyFontMetricsForString(replyObjectText, replyObjectTextView.getPaint()); } else if (messageObjectToReply.replyToForumTopic != null) { - replyObjectText = ForumUtilities.getTopicSpannedName(messageObjectToReply.replyToForumTopic, replyObjectTextView.getPaint()); + replyObjectText = ForumUtilities.getTopicSpannedName(messageObjectToReply.replyToForumTopic, replyObjectTextView.getPaint(), false); } else if (messageObjectToReply.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { replyObjectText = Emoji.replaceEmoji(messageObjectToReply.messageOwner.media.game.title, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false); sourceText = messageObjectToReply.messageOwner.media.game.title; @@ -11313,7 +11946,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (replyObjectText != null) { if (replyObjectText instanceof Spannable && sourceText != null) { - MediaDataController.addTextStyleRuns(messageObjectToReply.messageOwner.entities, sourceText, (Spannable) replyObjectText); + MediaDataController.addTextStyleRuns(entities, sourceText, (Spannable) replyObjectText); } replyObjectTextView.setText(AnimatedEmojiSpan.cloneSpans(replyObjectText)); @@ -11323,26 +11956,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObjectsToForward.isEmpty()) { return; } - if (threadMessageId == 0 || isTopic) { - if (isTopic) { - replyingMessageObject = threadMessageObject; - } else { - replyingMessageObject = null; - } - chatActivityEnterView.setReplyingMessageObject(replyingMessageObject); - updateBottomOverlay(); + fieldPanelShown = 3; + if (messagePreviewParams == null) { + messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat)); + messagePreviewParams.attach(forwardingPreviewView); + } + messagePreviewParams.updateForward(messageObjectsToForward, dialog_id); + if (messagePreviewParams.isEmpty() && editingMessageObject == null) { + messagePreviewParams = null; } editingMessageObject = null; chatActivityEnterView.setEditingMessageObject(null, false); - if (forwardingMessages == null) { - forwardingMessages = new ForwardingMessagesParams(messageObjectsToForward, dialog_id); - } - if (foundWebPage != null) { - return; - } + forbidForwardingWithDismiss = false; chatActivityEnterView.setForceShowSendButton(true, false); ArrayList uids = new ArrayList<>(); - replyIconImageView.setImageResource(R.drawable.msg_panel_forward); + replyIconImageView.setImageResource(R.drawable.filled_forward); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrForwarding", R.string.AccDescrForwarding)); replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelForward", R.string.AccDescrCancelForward)); MessageObject object = messageObjectsToForward.get(0); @@ -11378,6 +12006,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not type = -1; } } + int userNamesCount = 0; StringBuilder userNames = new StringBuilder(); for (int a = 0; a < uids.size(); a++) { Long uid = uids.get(a); @@ -11397,6 +12026,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { userNames.append(getUserConfig().getChatTitleOverride(chat)); } + userNamesCount++; } else if (uids.size() == 2 || userNames.length() == 0) { if (userNames.length() > 0) { userNames.append(", "); @@ -11412,60 +12042,66 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { userNames.append(getUserConfig().getChatTitleOverride(chat)); } + userNamesCount++; } else { userNames.append(" "); userNames.append(LocaleController.formatPluralString("AndOther", uids.size() - 1)); + userNamesCount++; break; } } formwardingNameText = userNames; - if (type == -1 || type == 0 || type == 10 || type == 11 || type == MessageObject.TYPE_EMOJIS) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardMessagesCount", messageObjectsToForward.size())); - } else if (type == 1) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardPhoto", messageObjectsToForward.size())); - if (messageObjectsToForward.size() == 1) { - messageObjectToReply = messageObjectsToForward.get(0); - } - } else if (type == 4) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardLocation", messageObjectsToForward.size())); - } else if (type == 3) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardVideo", messageObjectsToForward.size())); + CharSequence text = ""; + if (type == -1 || type == MessageObject.TYPE_TEXT || type == MessageObject.TYPE_DATE || type == MessageObject.TYPE_ACTION_PHOTO || type == MessageObject.TYPE_EMOJIS) { + text = LocaleController.formatPluralString("PreviewForwardMessagesCount", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_PHOTO) { + text = LocaleController.formatPluralString("PreviewForwardPhoto", messageObjectsToForward.size()); if (messageObjectsToForward.size() == 1) { messageObjectToReply = messageObjectsToForward.get(0); } - } else if (type == 12) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardContact", messageObjectsToForward.size())); - } else if (type == 2) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardAudio", messageObjectsToForward.size())); + } else if (type == MessageObject.TYPE_GIVEAWAY) { + text = LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway);; + } else if (type == MessageObject.TYPE_GEO) { + text = LocaleController.formatPluralString("PreviewForwardLocation", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_VIDEO) { + text = LocaleController.formatPluralString("PreviewForwardVideo", messageObjectsToForward.size()); + if (messageObjectsToForward.size() == 1) { + messageObjectToReply = messageObjectsToForward.get(0); + } + } else if (type == MessageObject.TYPE_CONTACT) { + text = LocaleController.formatPluralString("PreviewForwardContact", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_VOICE) { + text = LocaleController.formatPluralString("PreviewForwardAudio", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_ROUND_VIDEO) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardRound", messageObjectsToForward.size())); - } else if (type == 14) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardMusic", messageObjectsToForward.size())); + text = LocaleController.formatPluralString("PreviewForwardRound", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_MUSIC) { + text = LocaleController.formatPluralString("PreviewForwardMusic", messageObjectsToForward.size()); } else if (type == MessageObject.TYPE_STICKER || type == MessageObject.TYPE_ANIMATED_STICKER) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardSticker", messageObjectsToForward.size())); - } else if (type == 17) { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardPoll", messageObjectsToForward.size())); - } else if (type == 8 || type == 9) { - if (messageObjectsToForward.size() == 1 & type == 9) { + text = LocaleController.formatPluralString("PreviewForwardSticker", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_POLL) { + text = LocaleController.formatPluralString("PreviewForwardPoll", messageObjectsToForward.size()); + } else if (type == MessageObject.TYPE_GIF || type == MessageObject.TYPE_FILE) { + if (messageObjectsToForward.size() == 1 & type == MessageObject.TYPE_FILE) { messageObjectToReply = messageObjectsToForward.get(0); } - if (messageObjectsToForward.size() == 1 && type == 8) { - replyNameTextView.setText(LocaleController.getString("AttachGif", R.string.AttachGif)); + if (messageObjectsToForward.size() == 1 && type == MessageObject.TYPE_GIF) { + text = LocaleController.getString("AttachGif", R.string.AttachGif); } else { - replyNameTextView.setText(LocaleController.formatPluralString("PreviewForwardFile", messageObjectsToForward.size())); + text = LocaleController.formatPluralString("PreviewForwardFile", messageObjectsToForward.size()); } } else if (type == MessageObject.TYPE_STORY) { if (messageObjectsToForward.size() == 1) { - replyNameTextView.setText(LocaleController.getString("Story", R.string.Story)); + text = LocaleController.getString(R.string.Story); } else { - replyNameTextView.setText(LocaleController.formatPluralString("Stories", messageObjectsToForward.size())); + text = LocaleController.formatPluralString("Stories", messageObjectsToForward.size()); } } + replyNameTextView.setText(text); - if (forwardingMessages.hideForwardSendersName) { + if (messagePreviewParams != null && messagePreviewParams.hideForwardSendersName) { replyObjectTextView.setText(LocaleController.getString("HiddenSendersNameDescription", R.string.HiddenSendersNameDescription)); } else { - if ((type == -1 || type == 0 || type == 10 || type == 11 || type == MessageObject.TYPE_EMOJIS) && (messageObjectsToForward.size() == 1 && messageObjectsToForward.get(0).messageText != null)) { + if ((type == -1 || type == MessageObject.TYPE_TEXT || type == MessageObject.TYPE_DATE || type == MessageObject.TYPE_ACTION_PHOTO || type == MessageObject.TYPE_EMOJIS) && (messageObjectsToForward.size() == 1 && messageObjectsToForward.get(0).messageText != null)) { MessageObject messageObject = messageObjectsToForward.get(0); CharSequence mess = new SpannableStringBuilder(messageObject.messageText.toString()); if (mess.length() > 150) { @@ -11478,16 +12114,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not mess = MessageObject.replaceAnimatedEmoji(mess, messageObject.messageOwner.entities, replyObjectTextView.getPaint().getFontMetricsInt()); } } + if (userNamesCount == 1) { + mess = TextUtils.concat(userNames, ": ", mess); + } replyObjectTextView.setText(mess); } else { replyObjectTextView.setText(LocaleController.formatString("ForwardingFromNames", R.string.ForwardingFromNames, userNames)); } } + replyObjectHintTextView.setText(LocaleController.getString(R.string.TapForForwardingOptions)); if (!SharedConfig.forwardingOptionsHintShown) { showHint = true; } } else { - replyIconImageView.setImageResource(R.drawable.msg_link); + fieldPanelShown = 4; + replyIconImageView.setImageResource(R.drawable.filled_link); + if (messagePreviewParams == null) { + messagePreviewParams = new MessagePreviewParams(currentEncryptedChat != null, getMessagesController().isChatNoForwards(currentChat)); + messagePreviewParams.attach(forwardingPreviewView); + } + messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + if (messagePreviewParams.isEmpty() && editingMessageObject == null) { + messagePreviewParams = null; + } if (webPage instanceof TLRPC.TL_webPagePending) { replyNameTextView.setText(LocaleController.getString("GettingLinkInfo", R.string.GettingLinkInfo)); replyObjectTextView.setText(pendingLinkSearchString); @@ -11553,7 +12202,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (photoSize == thumbPhotoSize) { thumbPhotoSize = null; } - if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || thumbMediaMessageObject.isAnyKindOfSticker() || thumbMediaMessageObject.isSecretMedia() || thumbMediaMessageObject.isWebpageDocument()) { + if (photoSize == null || photoSize instanceof TLRPC.TL_photoSizeEmpty || photoSize.location instanceof TLRPC.TL_fileLocationUnavailable || thumbMediaMessageObject.isAnyKindOfSticker() || thumbMediaMessageObject.isSecretMedia() || thumbMediaMessageObject.isWebpageDocument() || forwardingPreviewView != null) { replyImageView.setImageBitmap(null); replyImageLocation = null; replyImageLocationObject = null; @@ -11580,7 +12229,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyObjectTextView.setLayoutParams(layoutParams3); chatActivityEnterView.showTopView(true, openKeyboard); } else { - if (replyingMessageObject == null && forwardingMessages == null && foundWebPage == null && editingMessageObject == null && !chatActivityEnterView.isTopViewVisible()) { + fieldPanelShown = 0; + if (replyingMessageObject == null && messagePreviewParams == null && foundWebPage == null && editingMessageObject == null && !chatActivityEnterView.isTopViewVisible()) { + messagePreviewParams = null; return; } if (replyingMessageObject != null && replyingMessageObject.messageOwner.reply_markup instanceof TLRPC.TL_replyKeyboardForceReply) { @@ -11591,25 +12242,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (foundWebPage != null) { foundWebPage = null; chatActivityEnterView.setWebPage(null, !cancel); - if (webPage != null && (replyingMessageObject != null || forwardingMessages != null || editingMessageObject != null)) { - showFieldPanel(true, replyingMessageObject, editingMessageObject, forwardingMessages != null ? forwardingMessages.messages : null, null, notify, scheduleDate, false, true); - return; - } } - if (forwardingMessages != null) { - ArrayList messagesToForward = new ArrayList<>(); - forwardingMessages.getSelectedMessages(messagesToForward); - forwardMessages(messagesToForward, forwardingMessages.hideForwardSendersName, forwardingMessages.hideCaption, notify, scheduleDate != 0 && scheduleDate != 0x7ffffffe ? scheduleDate + 1 : scheduleDate); - forwardingMessages = null; + if (messagePreviewParams != null && messagePreviewParams.forwardMessages != null) { + forbidForwardingWithDismiss = false; +// if (messagePreviewParams.quote == null) { + ArrayList messagesToForward = new ArrayList<>(); + if (messagePreviewParams.forwardMessages != null) { + messagePreviewParams.forwardMessages.getSelectedMessages(messagesToForward); + } + forwardMessages(messagesToForward, messagePreviewParams.hideForwardSendersName, messagePreviewParams.hideCaption, notify, scheduleDate != 0 && scheduleDate != 0x7ffffffe ? scheduleDate + 1 : scheduleDate); +// } + } + if (forwardingPreviewView == null) { + messagePreviewParams = null; } chatActivityEnterView.setForceShowSendButton(false, animated); if (!waitingForSendingMessageLoad) { chatActivityEnterView.hideTopView(animated); } - chatActivityEnterView.setReplyingMessageObject(threadMessageObject); + chatActivityEnterView.setReplyingMessageObject(threadMessageObject, null); chatActivityEnterView.setEditingMessageObject(null, false); topViewWasVisible = 0; replyingMessageObject = threadMessageObject; + replyingQuote = null; editingMessageObject = null; replyImageLocation = null; replyImageLocationObject = null; @@ -11640,12 +12295,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not replyObjectTextView.setAlpha(1f); replyObjectHintTextView.setAlpha(0); } - - if (showReplyHint) { - - } else { - - } } private void moveScrollToLastMessage(boolean skipSponsored) { @@ -11663,10 +12312,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject == null || messageObject.isOut() || !messageObject.isSecretMedia() || messageObject.messageOwner.destroyTime != 0 || messageObject.messageOwner.ttl <= 0) { return null; } - final boolean delete = messageObject.messageOwner.ttl != 0x7FFFFFFF; - final int ttl = messageObject.messageOwner.ttl == 0x7FFFFFFF ? 0 : messageObject.messageOwner.ttl; - messageObject.messageOwner.destroyTime = ttl + getConnectionsManager().getCurrentTime(); if (readNow) { + final boolean delete = messageObject.messageOwner.ttl != 0x7FFFFFFF; + final int ttl = messageObject.messageOwner.ttl == 0x7FFFFFFF ? 0 : messageObject.messageOwner.ttl; + messageObject.messageOwner.destroyTime = ttl + getConnectionsManager().getCurrentTime(); if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, ttl); } else { @@ -11675,6 +12324,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return null; } else { return () -> { + final boolean delete = messageObject.messageOwner.ttl != 0x7FFFFFFF; + final int ttl = messageObject.messageOwner.ttl == 0x7FFFFFFF ? 0 : messageObject.messageOwner.ttl; + messageObject.messageOwner.destroyTime = ttl + getConnectionsManager().getCurrentTime(); + messageObject.messageOwner.destroyTimeMillis = ttl * 1000L + getConnectionsManager().getCurrentTimeMillis(); if (currentEncryptedChat != null) { getMessagesController().markMessageAsRead(dialog_id, messageObject.messageOwner.random_id, ttl); } else { @@ -12173,7 +12826,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } currentPinnedMessageId = 0; - if (!pinnedMessageIds.isEmpty()) { + if (!pinnedMessageIds.isEmpty() || (isTopic && maxPinnedMessageId != 0)) { if (maxVisibleId == Integer.MIN_VALUE) { if (startLoadFromMessageId != 0) { maxVisibleId = startLoadFromMessageId; @@ -12202,8 +12855,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } currentPinnedMessageId = findClosest(pinnedMessageIds, forceNextPinnedMessageId != 0 ? forceNextPinnedMessageId : maxVisibleId, currentPinnedMessageIndex); - if (!inMenuMode && !loadingPinnedMessagesList && !pinnedEndReached && !pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2) { - getMediaDataController().loadPinnedMessages(dialog_id, pinnedMessageIds.get(pinnedMessageIds.size() - 1), 0); + if (!inMenuMode && !loadingPinnedMessagesList && !pinnedEndReached && (isTopic || (!pinnedMessageIds.isEmpty() && currentPinnedMessageIndex[0] > pinnedMessageIds.size() - 2))) { + getMediaDataController().loadPinnedMessages(dialog_id, maxPinnedMessageId, 0); loadingPinnedMessagesList = true; } } @@ -12300,7 +12953,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not hideFloatingDateView(true); floatingDateViewOffset = 0; } - if (isThreadChat()) { + if (isThreadChat() && (!isTopic || pinnedOnlyStarterMessage())) { if (previousThreadMessageVisible != threadMessageVisible) { AndroidUtilities.runOnUIThread(() -> { updatePinnedMessageView(openAnimationStartTime != 0 && SystemClock.elapsedRealtime() >= openAnimationStartTime + 150); @@ -12410,6 +13063,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private boolean pinnedOnlyStarterMessage() { + return pinnedMessageIds.size() == 1 && topicStarterMessageObject != null && pinnedMessageIds.get(0) == topicStarterMessageObject.getId(); + } + private void inlineUpdate1() { if (prevSetUnreadCount != newUnreadMessageCount) { prevSetUnreadCount = newUnreadMessageCount; @@ -12443,13 +13100,82 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private int getScrollOffsetForMessage(MessageObject object) { - return getScrollOffsetForMessage(getHeightForMessage(object)); + return getScrollOffsetForMessage(getHeightForMessage(object, !TextUtils.isEmpty(highlightMessageQuote))) - scrollOffsetForQuote(object); } private int getScrollOffsetForMessage(int messageHeight) { return (int) Math.max(-AndroidUtilities.dp(2), (chatListView.getMeasuredHeight() - blurredViewBottomOffset - chatListViewPaddingTop - messageHeight) / 2); } - private int getHeightForMessage(MessageObject object) { + private int scrollOffsetForQuote(MessageObject object) { + if (TextUtils.isEmpty(highlightMessageQuote) || object == null) { + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + return 0; + } + + int offsetY; + CharSequence text; + ArrayList textLayoutBlocks; + if (object.getGroupId() != 0) { + MessageObject.GroupedMessages group = getGroup(object.getGroupId()); + if (dummyMessageCell == null || dummyMessageCell.computedCaptionLayout == null || group == null || group.captionMessage == null) { + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + return 0; + } + offsetY = dummyMessageCell.computedGroupCaptionY; + text = group.captionMessage.caption; + textLayoutBlocks = dummyMessageCell.computedCaptionLayout.textLayoutBlocks; + } else if (!TextUtils.isEmpty(object.caption) && dummyMessageCell != null && dummyMessageCell.captionLayout != null) { + offsetY = (int) dummyMessageCell.captionY; + text = object.caption; + textLayoutBlocks = dummyMessageCell.captionLayout.textLayoutBlocks; + } else { + offsetY = 0; + text = object.messageText; + textLayoutBlocks = object.textLayoutBlocks; + if (dummyMessageCell != null && dummyMessageCell.linkPreviewAbove) { + offsetY += dummyMessageCell.linkPreviewHeight + AndroidUtilities.dp(10); + } + } + if (dummyMessageCell != null) { + dummyMessageCell.computedGroupCaptionY = 0; + dummyMessageCell.computedCaptionLayout = null; + } + if (textLayoutBlocks == null || text == null) { + return 0; + } + + int index = text.toString().indexOf(highlightMessageQuote); + if (index < 0) { + return 0; + } + + for (int i = 0; i < textLayoutBlocks.size(); ++i) { + MessageObject.TextLayoutBlock block = textLayoutBlocks.get(i); + StaticLayout layout = block.textLayout; + String layoutText = layout.getText().toString(); + if (index > block.charactersOffset) { + final float y; + if (index - block.charactersOffset > layoutText.length() - 1) { + y = offsetY + (int) (block.textYOffset + block.padTop + block.height); + } else { + y = offsetY + block.textYOffset + block.padTop + layout.getLineTop(layout.getLineForOffset(index - block.charactersOffset)); + } + if (y > AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)) { + return (int) (y - AndroidUtilities.displaySize.y * (isKeyboardVisible() ? .7f : .5f)); + } + return 0; + } + } + return 0; + } + + private int getHeightForMessage(MessageObject object, boolean withGroupCaption) { if (getParentActivity() == null) { return 0; } @@ -12459,7 +13185,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dummyMessageCell.isChat = currentChat != null || UserObject.isUserSelf(currentUser); dummyMessageCell.isBot = currentUser != null && currentUser.bot; dummyMessageCell.isMegagroup = ChatObject.isChannel(currentChat) && currentChat.megagroup; - return dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId())); + return dummyMessageCell.computeHeight(object, groupedMessagesMap.get(object.getGroupId()), withGroupCaption); } private void startMessageUnselect() { @@ -12468,18 +13194,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } unselectRunnable = () -> { highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; + showNoQuoteAlert = false; updateVisibleRows(); unselectRunnable = null; }; - AndroidUtilities.runOnUIThread(unselectRunnable, 1000); + AndroidUtilities.runOnUIThread(unselectRunnable, highlightMessageQuote != null ? 2500 : 1000); } private void removeSelectedMessageHighlight() { + if (highlightMessageQuote != null) { + return; + } if (unselectRunnable != null) { AndroidUtilities.cancelRunOnUIThread(unselectRunnable); unselectRunnable = null; } highlightMessageId = Integer.MAX_VALUE; + highlightMessageQuote = null; } private AlertDialog progressDialog; @@ -12494,6 +13226,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public static final int PROGRESS_LINK = 1; public static final int PROGRESS_INSTANT = 2; public static final int PROGRESS_BOT_BUTTON = 3; + public static final int PROGRESS_GIFT = 4; private int progressDialogAtMessageId; private int progressDialogAtMessageType; @@ -12602,6 +13335,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); boolean found = false; + int offsetY = 0; int count = chatListView.getChildCount(); for (int a = 0; a < count; a++) { View view = chatListView.getChildAt(a); @@ -12611,6 +13345,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messageObject != null && messageObject.getId() == object.getId()) { found = true; view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + offsetY = scrollOffsetForQuote(messageObject); } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; @@ -12622,7 +13357,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (found) { - int yOffset = getScrollOffsetForMessage(view.getHeight()); + int yOffset = getScrollOffsetForMessage(view.getHeight()) - offsetY; int scrollY = (int) (view.getTop() - chatListViewPaddingTop - yOffset); int maxScrollOffset = chatListView.computeVerticalScrollRange() - chatListView.computeVerticalScrollOffset() - chatListView.computeVerticalScrollExtent(); if (maxScrollOffset < 0) { @@ -13043,6 +13778,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + if (parentLayout != null && parentLayout.isSheet()) { + adjustPanLayoutHelper.setResizableView((FrameLayout) parentLayout.getView().getParent().getParent().getParent().getParent()); + } adjustPanLayoutHelper.onAttach(); chatActivityEnterView.setAdjustPanLayoutHelper(adjustPanLayoutHelper); MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); @@ -13906,7 +14644,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not textSelectionHelper.setKeyboardSize(0); } child.measure(contentWidthSpec, View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.EXACTLY)); - } else if (child == forwardingPreviewView) { + } else if (child instanceof MessagePreviewView) { int contentWidthSpec = View.MeasureSpec.makeMeasureSpec(widthSize, View.MeasureSpec.EXACTLY); int h = allHeight - AndroidUtilities.statusBarHeight; if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { @@ -14065,7 +14803,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not childTop -= blurredViewTopOffset; } else if (chatActivityEnterView != null && child == chatActivityEnterView.botCommandsMenuContainer) { childTop -= inputFieldHeight; - } else if (child == forwardingPreviewView) { + } else if (child instanceof MessagePreviewView) { childTop = AndroidUtilities.statusBarHeight; } child.layout(childLeft, childTop, childLeft + width, childTop + height); @@ -14822,6 +15560,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int type = getMessageType(message); + if (message != null && message.isAnyGift()) { + return; + } if (type < 2 || type == 20 || type == MessageObject.TYPE_SUGGEST_PHOTO || (message != null && message.isWallpaperAction())) { return; } @@ -15038,7 +15779,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, this); } else { fillEditingMediaWithCaption(caption, null); - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, null, 0, editingMessageObject, true, 0, false, false, null); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), videoPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, null, 0, editingMessageObject, true, 0, false, false, null); afterMessageSend(); } } @@ -15149,7 +15890,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not entry.reset(); } fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, forceDocument, true, null, notify, scheduleDate, photos.get(0).updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, forceDocument, true, null, notify, scheduleDate, photos.get(0).updateStickersOrder, null); afterMessageSend(); if (chatActivityEnterView != null) { chatActivityEnterView.setFieldText(""); @@ -15271,7 +16012,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (fileLocation != null && message.photoThumbs != null) { for (int b = 0; b < message.photoThumbs.size(); b++) { TLRPC.PhotoSize photoSize = message.photoThumbs.get(b); - if (photoSize.location != null && photoSize.location.volume_id == fileLocation.volume_id && photoSize.location.local_id == fileLocation.local_id) { + if (photoSize.location != null && photoSize.location.local_id == fileLocation.local_id) { imageReceiver = cell.getPhotoImage(); break; } @@ -15369,9 +16110,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } fillEditingMediaWithCaption(null, null); if (sendAsUri) { - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0, null); + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, editingMessageObject, true, 0, null); } else { - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0, null); + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, editingMessageObject, true, 0, null); } hideFieldPanel(false); } @@ -15410,11 +16151,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (editingMessageObject == null && chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, 0, editingMessageObject, notify, scheduleDate); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), replyingQuote, null, null, null, null, 0, editingMessageObject, notify, scheduleDate); }, themeDelegate); } else { fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, null, 0, editingMessageObject, true, 0); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), null, uri, dialog_id, replyingMessageObject, getThreadMessage(), replyingQuote, null, null, null, null, 0, editingMessageObject, true, 0); } } afterMessageSend(); @@ -15598,13 +16339,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (chatMode != mode) { if (chatMode != MODE_SCHEDULED) { + if (isTopic) { + ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); + } scheduledMessagesCount = messArr.size(); updateScheduledInterface(true); } return; + } else if (chatMode == MODE_SCHEDULED && isTopic) { + ForumUtilities.filterMessagesByTopic(threadMessageId, messArr); } boolean createUnreadLoading = false; boolean showDateAfter = waitingForReplyMessageLoad; + SparseArray oldMessagesDict = null; if (waitingForReplyMessageLoad) { if (chatMode != MODE_SCHEDULED && !createUnreadMessageAfterIdLoading) { boolean found = false; @@ -15632,6 +16379,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean needSelect = needSelectFromMessageId; int unreadAfterId = createUnreadMessageAfterId; createUnreadLoading = createUnreadMessageAfterIdLoading; + oldMessagesDict = messagesDict[0].clone(); clearChatData(); if (chatMode == 0) { createUnreadMessageAfterId = unreadAfterId; @@ -15755,7 +16503,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { if (isTopic) { if (first_unread_id == 0) { - for (int i = messArr.size() - 1; i >= 0; i--) { + for (int i = messArr.size() - 1; i >= 0; i--) { if (messArr.get(i).getId() > threadMaxInboxReadId) { first_unread_id = messArr.get(i).getId(); break; @@ -15971,7 +16719,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (approximateHeightSum <= AndroidUtilities.displaySize.y / 2) { - approximateHeightSum += getHeightForMessage(obj); + approximateHeightSum += getHeightForMessage(obj, false); } if (currentUser != null) { if (currentUser.self) { @@ -16053,6 +16801,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } MessageObject oldMessage = messagesDict[loadIndex].get(messageId); + if (oldMessage == null && oldMessagesDict != null) { + oldMessage = oldMessagesDict.get(messageId); + } messagesDict[loadIndex].put(messageId, obj); ArrayList dayArray = messagesByDays.get(obj.dateKey); @@ -16085,7 +16836,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dateObj.type = MessageObject.TYPE_DATE; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = lastStableId++; + dateObj.stableId = getStableIdForDateObject(dateMsg.date); if (load_type == 1) { messages.add(0, dateObj); } else { @@ -16147,7 +16898,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not newRowsCount++; dayArray.add(obj); if (oldMessage != null) { - obj.stableId = oldMessage.stableId; + obj.copyStableParams(oldMessage); } else { obj.stableId = lastStableId++; } @@ -16158,16 +16909,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messages.get(messages.size() - 1).stableId = lastStableId++; messages.add(messages.size() - 1, obj); } -// if (obj.isStoryMention()) { -// MessageObject msg = obj.makeStoryMentionAction(lastStableId++); -// newRowsCount++; -// if (load_type == 1) { -// messages.add(0, msg); -// } else { -// messages.get(messages.size() - 1).stableId = lastStableId++; -// messages.add(messages.size() - 1, msg); -// } -// } MessageObject prevObj; if (currentEncryptedChat == null) { @@ -16333,11 +17074,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrollToMessage != null) { addSponsoredMessages(!isFirstLoading); int yOffset; + boolean opt = false; boolean bottom = true; if (startLoadFromMessageOffset != Integer.MAX_VALUE) { yOffset = -startLoadFromMessageOffset - chatListView.getPaddingBottom(); startLoadFromMessageOffset = Integer.MAX_VALUE; } else if (scrollToMessagePosition == -9000) { + opt = true; yOffset = getScrollOffsetForMessage(scrollToMessage); bottom = false; } else if (scrollToMessagePosition == -10000) { @@ -16350,6 +17093,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not yOffset = scrollToMessagePosition; } yOffset += AndroidUtilities.dp(50); // in case pinned message view is visible + if (!opt) { + yOffset -= scrollOffsetForQuote(scrollToMessage); + } if (!postponedScroll) { if (!messages.isEmpty()) { if (chatAdapter.loadingUpRow >= 0 && !messages.isEmpty() && (messages.get(messages.size() - 1) == scrollToMessage || messages.get(messages.size() - 2) == scrollToMessage)) { @@ -16608,6 +17354,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setBotInfo(botInfo); } } + + checkNewMessagesOnQuoteEdit(true); } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); @@ -16667,7 +17415,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.updateDefaultSendAsPeer) { long chatId = (long) args[0]; - if (chatId == dialog_id) { + if (chatId == dialog_id && chatActivityEnterView != null) { chatActivityEnterView.updateSendAsButton(true); } } else if (id == NotificationCenter.updateInterfaces) { @@ -16729,7 +17477,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (did == dialog_id) { boolean scheduled = (Boolean) args[2]; if (scheduled != (chatMode == MODE_SCHEDULED)) { - if (chatMode != MODE_SCHEDULED && !isPaused && forwardingMessages == null) { + if (chatMode != MODE_SCHEDULED && !isPaused && messagePreviewParams == null) { if (!arr.isEmpty() && arr.get(0).getId() < 0) { openScheduledMessages(); } @@ -17007,11 +17755,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Integer msgId = (Integer) args[0]; MessageObject obj = messagesDict[0].get(msgId); if (isThreadChat() && pendingSendMessagesDict.size() > 0) { - MessageObject object = pendingSendMessagesDict.get(msgId); - if (object != null) { - Integer newMsgId = (Integer) args[1]; - pendingSendMessagesDict.put(newMsgId, object); - } + MessageObject object = pendingSendMessagesDict.get(msgId); + if (object != null) { + Integer newMsgId = (Integer) args[1]; + pendingSendMessagesDict.put(newMsgId, object); + } } if (obj != null) { checkChecksHint(); @@ -17845,12 +18593,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.replaceMessagesObjects) { long did = (long) args[0]; + final ArrayList messageObjects = (ArrayList) args[1]; + if (replyingMessageObject != null) { + for (int i = 0; i < messageObjects.size(); ++i) { + MessageObject messageObject = messageObjects.get(i); + if (messageObject == null) continue; + if (replyingMessageObject.getId() == messageObject.getId() && replyingMessageObject.getDialogId() == did) { + replyingMessageObject = messageObject; + if (replyingQuote != null) { + replyingQuote.checkEdit(messageObject); + } + if (messagePreviewParams != null) { + messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); + } + fallbackFieldPanel(); + break; + } + } + } + if (messagePreviewParams != null) { + messagePreviewParams.checkEdits(messageObjects); + } if (did != dialog_id && did != mergeDialogId) { return; } int loadIndex = did == dialog_id ? 0 : 1; doOnIdle(() -> { - ArrayList messageObjects = (ArrayList) args[1]; replaceMessageObjects(messageObjects, loadIndex, false); }); } else if (id == NotificationCenter.notificationsSettingsUpdated) { @@ -17941,6 +18709,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (replaceObjects == null) { totalPinnedMessagesCount++; } + updated = true; } } else { if (!pinnedMessageObjects.containsKey(mid)) { @@ -17951,6 +18720,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (replaceObjects == null) { totalPinnedMessagesCount--; } + updated = true; } loadedPinnedMessagesCount = pinnedMessageIds.size(); if (chatAdapter != null) { @@ -17981,6 +18751,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { updateMessagesVisiblePart(false); } + updatePinnedListButton(true); } if (chatMode == MODE_PINNED) { if (pin) { @@ -18039,7 +18810,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int a = 0; a < hashMap.size(); a++) { TLRPC.WebPage webPage = hashMap.valueAt(a); if (webPage.id == foundWebPage.id) { - showFieldPanelForWebPage(!(webPage instanceof TLRPC.TL_webPageEmpty), webPage, false); + if (webPage instanceof TLRPC.TL_webPageEmpty) { + foundWebPage = null; + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(foundWebPage, false); + } + fallbackFieldPanel(); + } else { + foundWebPage = webPage; + if (messagePreviewParams != null) { + messagePreviewParams.updateLink(currentAccount, foundWebPage, chatActivityEnterView.getFieldText(), replyingMessageObject == threadMessageObject ? null : replyingMessageObject, replyingQuote, editingMessageObject); + } + if (chatActivityEnterView != null) { + chatActivityEnterView.setWebPage(foundWebPage, false); + } + showFieldPanelForWebPage(true, foundWebPage, false); + } break; } } @@ -18324,16 +19113,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedMessageIds = pinnedMessages; pinnedMessageObjects = (HashMap) args[2]; } + maxPinnedMessageId = pinnedMessageIds.size() > 0 ? pinnedMessageIds.get(pinnedMessageIds.size() - 1) : 0; int fallbackId = pinnedMessageIds.isEmpty() ? 0 : pinnedMessageIds.get(0); if (isTopic) { + int size = pinnedMessageIds.size(); for (int i = 0; i < pinnedMessageIds.size(); i++) { int messageId = pinnedMessages.get(i); - if (pinnedMessageObjects.get(messageId) == null) { + MessageObject messageObject = pinnedMessageObjects.get(messageId); + if (messageObject == null) { pinnedMessageIds.remove(i); i--; continue; } - int messageTopicId = MessageObject.getTopicId(pinnedMessageObjects.get(messageId).messageOwner, true); + + int messageTopicId = MessageObject.getTopicId(messageObject.messageOwner, true); if (getTopicId() != messageTopicId) { pinnedMessageObjects.remove(messageId); pinnedMessageIds.remove(i); @@ -18512,9 +19305,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.scheduledMessagesUpdated) { long did = (Long) args[0]; + boolean fromCache = (boolean) args[2]; if (dialog_id == did) { - scheduledMessagesCount = (Integer) args[1]; - updateScheduledInterface(openAnimationEnded); + if (!isTopic) { + scheduledMessagesCount = (Integer) args[1]; + updateScheduledInterface(openAnimationEnded); + } else if (chatMode == 0) { +// waitingForLoad.add(lastLoadIndex); +// getMessagesController().loadMessages(dialog_id, mergeDialogId, false, 1, 0, 0, true, 0, classGuid, 2, 0, MODE_SCHEDULED, threadMessageId, replyMaxReadId, lastLoadIndex++, isTopic); + } } } else if (id == NotificationCenter.diceStickersDidLoad) { if (chatListView == null) { @@ -18722,9 +19521,36 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not waitingForGetDifference = false; firstLoadMessages(); } + } else if (id == NotificationCenter.storiesUpdated) { + if (avatarContainer != null) { + avatarContainer.avatarImageView.invalidate(); + } } } + private AlertDialog quoteMessageUpdateAlert; + public void showQuoteMessageUpdate() { + if (quoteMessageUpdateAlert != null) { + return; + } + String sender = replyingMessageObject != null ? getMessagesController().getFullName(replyingMessageObject.getSenderId()) : ""; + quoteMessageUpdateAlert = new AlertDialog.Builder(getContext(), getResourceProvider()) + .setTitle(LocaleController.getString(R.string.UpdatedQuoteTitle)) + .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.UpdatedQuoteMessage, sender))) + .setPositiveButton(LocaleController.getString(R.string.Edit), (d, w) -> { + if (messagePreviewParams != null && messagePreviewParams.quote != null) { + openForwardingPreview(MessagePreviewView.TAB_REPLY); + } + }) + .setNegativeButton(LocaleController.getString(R.string.Cancel), (d, w) -> { + hideFieldPanel(true); + }) + .setOnDismissListener(d -> { + quoteMessageUpdateAlert = null; + }) + .show(); + } + private int getScrollingOffsetForView(View v) { return chatListView.getMeasuredHeight() - v.getBottom() - chatListView.getPaddingBottom(); } @@ -19306,7 +20132,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (messages.get(i).type == type && messages.get(i).getId() < 0) { messagesDict[0].remove(messages.get(i).getId()); messagesDict[0].put(messageObject.getId(), messageObject); - messageObject.stableId = messages.get(i).stableId; + messageObject.copyStableParams(messages.get(i)); if (type == MessageObject.TYPE_ACTION_WALLPAPER) { messageObject.messageOwner.action.wallpaper = messages.get(i).messageOwner.action.wallpaper; } else if (type == MessageObject.TYPE_SUGGEST_PHOTO) { @@ -19328,7 +20154,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pendingSendMessagesDict.put(messageId, messageObject); pendingSendMessages.add(0, messageObject); } - if (messageObject.isDice() && !messageObject.isForwarded() || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { + if ((messageObject.isDice() && !messageObject.isForwarded()) || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium || messageObject.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode) { messageObject.wasUnread = true; } if (chatMode == MODE_SCHEDULED && messageObject.hasValidGroupId() && messagesDict[0].indexOfKey(messageObject.getId()) >= 0) { @@ -19426,6 +20252,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean needMoveScrollToLastMessage = false; boolean reloadMegagroup = false; + if (justCreatedTopic) { + forwardEndReached[0] = true; + } if (!forwardEndReached[0]) { int currentMaxDate = Integer.MIN_VALUE; @@ -19767,7 +20596,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not dateObj.type = 10; dateObj.contentType = 1; dateObj.isDateObject = true; - dateObj.stableId = lastStableId++; + dateObj.stableId = getStableIdForDateObject(dateMsg.date); messages.add(placeToPaste, dateObj); if (chatAdapter != null) { chatAdapter.notifyItemInserted(placeToPaste); @@ -19960,6 +20789,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private int getStableIdForDateObject(int date) { + int id = dateObjectsStableIds.get(date, -1); + if (id == -1) { + id = lastStableId++; + dateObjectsStableIds.put(date, id); + } + return id; + } + private void saveScrollPosition() { if (chatListView == null || chatLayoutManager == null || chatLayoutManager.hasPendingScrollPosition()) { return; @@ -20011,6 +20849,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (channelId != 0) { return; } + if (replyingMessageObject != null && markAsDeletedMessages.contains(replyingMessageObject.getId())) { + replyingMessageObject = null; + replyingQuote = null; + fallbackFieldPanel(); + } + boolean updated = false; LongSparseArray newGroups = null; LongSparseArray newGroupsSizes = null; @@ -20276,7 +21120,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (old.isWebpage() && messageObject.isWebpage()) { TLRPC.TL_messageMediaWebPage media = (TLRPC.TL_messageMediaWebPage) MessageObject.getMedia(old.messageOwner); if (media.webpage != null && "telegram_story".equals(media.webpage.type)) { - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; for (int i = 0; i < media.webpage.attributes.size(); ++i) { TLRPC.WebPageAttribute attr = media.webpage.attributes.get(i); if (attr instanceof TLRPC.TL_webPageAttributeStory) { @@ -20290,7 +21134,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not TLRPC.WebPageAttribute attr = newMedia.webpage.attributes.get(i); if (attr instanceof TLRPC.TL_webPageAttributeStory) { TLRPC.TL_webPageAttributeStory storyAttr = (TLRPC.TL_webPageAttributeStory) attr; - if (!(storyAttr.storyItem instanceof TLRPC.TL_storyItem)) { + if (!(storyAttr.storyItem instanceof TL_stories.TL_storyItem)) { storyAttr.storyItem = storyItem; } break; @@ -20563,6 +21407,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); } + if (keyboardWasVisible) { + if (chatActivityEnterView != null) { + chatActivityEnterView.openKeyboardInternal(); + chatActivityEnterView.freezeEmojiView(false); + } + keyboardWasVisible = false; + } } @Override @@ -20827,6 +21678,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not botRequest.enabled = true; botRequest.write_allowed = true; ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { + attachMenuBot.inactive = attachMenuBot.side_menu_disclaimer_needed = false; if (error2 == null) { MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); openAttachBotLayout(user.id, attachMenuBotStartCommand, false); @@ -20850,6 +21702,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not botRequest.write_allowed = allowWrite.get(); ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { if (error2 == null) { + attachMenuBot.inactive = attachMenuBot.side_menu_disclaimer_needed = false; MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); openAttachBotLayout(user.id, attachMenuBotStartCommand, false); @@ -20917,11 +21770,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } } - fillActionModeMenu(menu, currentEncryptedChat); + fillActionModeMenu(menu, currentEncryptedChat, true); return true; } - public static void fillActionModeMenu(Menu menu, TLRPC.EncryptedChat encryptedChat) { + public static void fillActionModeMenu(Menu menu, TLRPC.EncryptedChat encryptedChat, boolean chat) { if (menu.findItem(R.id.menu_bold) != null) { return; } @@ -20929,6 +21782,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not menu.removeItem(android.R.id.shareText); } int order = 6; + if (chat) { + menu.add(R.id.menu_groupbolditalic, R.id.menu_quote, order++, LocaleController.getString("Quote", R.string.Quote)); + } menu.add(R.id.menu_groupbolditalic, R.id.menu_spoiler, order++, LocaleController.getString("Spoiler", R.string.Spoiler)); SpannableStringBuilder stringBuilder = new SpannableStringBuilder(LocaleController.getString("Bold", R.string.Bold)); @@ -22354,6 +23210,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if ((shownTranslateTopic || shownRestartTopic) && !show) { showReport = showGeo = showShare = showBlock = showAdd = showArchive = showAddMembersToGroup = false; + showEmojiStatusReport = null; show = true; } if (reportSpamButton != null) { @@ -22896,7 +23753,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public int getTopOffset(int tag) { - return (actionBar != null ? actionBar.getMeasuredHeight() + (int) actionBar.getTranslationY() : 0) + Math.max(0, contentPaddingTop); + return (actionBar != null ? actionBar.getMeasuredHeight() + actionBar.getTop() : 0) + Math.max(0, contentPaddingTop); } @Override @@ -23051,7 +23908,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.onPause(); } if (chatMode == 0) { - CharSequence[] message = new CharSequence[]{draftMessage}; + CharSequence[] message = new CharSequence[]{ignoreDraft ? null : draftMessage}; ArrayList entities = getMediaDataController().getEntities(message, currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101); int draftThreadId; if (ChatObject.isForum(currentChat) && !isTopic && replyMessage != null) { @@ -23063,7 +23920,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { draftThreadId = threadMessageId; } - getMediaDataController().saveDraft(dialog_id, draftThreadId, message[0], entities, (replyMessage != null && !replyMessage.isTopicMainMessage && replyMessage.replyToForumTopic == null) ? replyMessage.messageOwner : null, !searchWebpage); + getMediaDataController().saveDraft(dialog_id, draftThreadId, message[0], entities, (replyMessage != null && !replyMessage.isTopicMainMessage && replyMessage.replyToForumTopic == null && !ignoreDraft) ? replyMessage.messageOwner : null, replyingQuote, !searchWebpage, false); getMessagesController().cancelTyping(0, dialog_id, threadMessageId); if (!pausedOnLastMessage && !firstLoading && (!isThreadChat() || isTopic)) { @@ -23186,7 +24043,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { draftMessage = getMediaDataController().getDraft(dialog_id, threadMessageId); } - TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null; + TLRPC.Message draftReplyMessage = draftMessage != null && draftMessage.reply_to != null && draftMessage.reply_to.reply_to_msg_id != 0 ? getMediaDataController().getDraftMessage(dialog_id, topicId != null ? topicId : threadMessageId) : null; if (chatActivityEnterView.getFieldText() == null) { if (draftMessage != null) { chatActivityEnterView.setWebPage(null, !draftMessage.no_webpage); @@ -23255,7 +24112,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not message = draftMessage.message; } - chatActivityEnterView.setFieldText(message); + chatActivityEnterView.setFieldText(message, true, true); if (getArguments().getBoolean("hasUrl", false)) { chatActivityEnterView.setSelection(draftMessage.message.indexOf('\n') + 1); AndroidUtilities.runOnUIThread(() -> { @@ -23272,7 +24129,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if ((replyingMessageObject == null || threadMessageObject == replyingMessageObject) && draftReplyMessage != null && !(threadMessageObject != null && threadMessageObject.getId() == draftReplyMessage.id)) { replyingMessageObject = new MessageObject(currentAccount, draftReplyMessage, getMessagesController().getUsers(), false, false); - showFieldPanelForReply(replyingMessageObject); + if (draftMessage.reply_to != null && (draftMessage.reply_to.flags & 64) != 0) { + replyingQuote = ReplyQuote.from(replyingMessageObject, draftMessage.reply_to.quote_text); + } + checkNewMessagesOnQuoteEdit(false); + if (replyingQuote != null) { + showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); + } else { + showFieldPanelForReply(replyingMessageObject); + } updateBottomOverlay(); } else if (topicId != null && topicId != 0 && currentChat != null) { TLRPC.TL_forumTopic topic = getMessagesController().getTopicsController().findTopic(currentChat.id, topicId); @@ -23285,6 +24150,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + private void checkNewMessagesOnQuoteEdit(boolean update) { + if (replyingMessageObject == null) return; + for (int i = 0; i < messages.size(); ++i) { + MessageObject msg = messages.get(i); + if (msg == null) continue; + if (msg.getId() == replyingMessageObject.getId() && msg.getDialogId() == replyingMessageObject.getDialogId()) { + replyingMessageObject = msg; + if (replyingQuote != null) { + replyingQuote.checkEdit(msg); + } + if (update) { + if (messagePreviewParams != null) { + messagePreviewParams.updateReply(replyingMessageObject, replyingQuoteGroup != null ? replyingQuoteGroup : getGroup(replyingMessageObject.getGroupId()), dialog_id, replyingQuote); + } + fallbackFieldPanel(); + } + break; + } + } + } + private void updateInformationForScreenshotDetector() { if (currentUser == null) { return; @@ -23597,7 +24483,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (message == null) { return false; } - if (!single && message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium) { + if (!single && (message.messageOwner.action instanceof TLRPC.TL_messageActionGiftPremium || message.messageOwner.action instanceof TLRPC.TL_messageActionGiftCode)) { return false; } final int type = getMessageType(message); @@ -23918,7 +24804,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.msg_fave); } } - if (allowChatActions) { + if (allowChatActions || ChatObject.isChannelAndNotMegaGroup(currentChat)) { items.add(LocaleController.getString("Reply", R.string.Reply)); options.add(OPTION_REPLY); icons.add(R.drawable.msg_reply); @@ -24115,7 +25001,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && (!selectedObject.needDrawBluredPreview() || selectedObject.hasExtendedMediaPreview()) && !selectedObject.isLiveLocation() && selectedObject.type != MessageObject.TYPE_PHONE_CALL && !noforwards && - selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() + selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM && selectedObject.type != MessageObject.TYPE_GIFT_PREMIUM_CHANNEL && selectedObject.type != MessageObject.TYPE_SUGGEST_PHOTO && !selectedObject.isWallpaperAction() && !message.isExpiredStory() && message.type != MessageObject.TYPE_STORY_MENTION) { items.add(LocaleController.getString("Forward", R.string.Forward)); options.add(OPTION_FORWARD); @@ -25421,12 +26307,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); - SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, null, true, 0, false, null); + SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, replyingQuote, null, true, 0, false, null); }); greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0)); } else if (currentEncryptedChat == null) { - if (isTopic) { + if (isTopic && chatMode == 0) { CreateTopicEmptyView createTopicEmptyView = new CreateTopicEmptyView(getContext(), contentView, themeDelegate); emptyViewContainer.addView(createTopicEmptyView, new FrameLayout.LayoutParams(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else if (!isThreadChat() && chatMode == 0 && ((currentUser != null && currentUser.self) || (currentChat != null && currentChat.creator && !ChatObject.isChannelAndNotMegaGroup(currentChat)))) { @@ -25437,7 +26323,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else { String emptyMessage = null; - if (isThreadChat()) { + if (isThreadChat() && chatMode == 0) { if (isComments) { emptyMessage = LocaleController.getString("NoComments", R.string.NoComments); } else { @@ -25454,7 +26340,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not greetingsViewContainer = new ChatGreetingsView(getContext(), currentUser, distance, currentAccount, preloadedGreetingsSticker, themeDelegate); greetingsViewContainer.setListener((sticker) -> { animatingDocuments.put(sticker, 0); - SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, null, true, 0, false, null); + SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, null, dialog_id, null, null, null, replyingQuote, null, true, 0, false, null); }); greetingsViewContainer.setBackground(Theme.createServiceDrawable(AndroidUtilities.dp(10), greetingsViewContainer, contentView, getThemedPaint(Theme.key_paint_chatActionBackground))); emptyViewContainer.addView(greetingsViewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 68, 0, 68, 0)); @@ -26055,7 +26941,28 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case OPTION_REPLY: { - showFieldPanelForReply(selectedObject); + if (selectedObject != null && currentChat != null && (ChatObject.isNotInChat(currentChat) && !isThreadChat() || ChatObject.isChannel(currentChat) && !ChatObject.canPost(currentChat) && !currentChat.megagroup || !ChatObject.canSendMessages(currentChat))) { + MessageObject messageObject = selectedObject; + if (messageObject.getGroupId() != 0) { + MessageObject.GroupedMessages group = getGroup(messageObject.getGroupId()); + if (group != null) { + messageObject = group.captionMessage; + } + } + replyingMessageObject = messageObject; + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); + args.putBoolean("quote", true); + args.putBoolean("reply_to", true); + args.putInt("messagesCount", 1); + args.putBoolean("canSelectTopics", true); + DialogsActivity fragment = new DialogsActivity(args); + fragment.setDelegate(this); + presentFragment(fragment); + } else { + showFieldPanelForReply(selectedObject); + } break; } case OPTION_ADD_TO_STICKERS_OR_MASKS: { @@ -26507,7 +27414,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean didSelectDialogs(DialogsActivity fragment, ArrayList dids, CharSequence message, boolean param, TopicsFragment topicsFragment) { - if (forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { + if ((messagePreviewParams == null && (!fragment.isQuote || replyingMessageObject == null) || fragment.isQuote && replyingMessageObject == null) && forwardingMessage == null && selectedMessagesIds[0].size() == 0 && selectedMessagesIds[1].size() == 0) { return false; } ArrayList fmessages = new ArrayList<>(); @@ -26559,8 +27466,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); } - if (dids.size() > 1 || dids.get(0).dialogId == getUserConfig().getClientUserId() || message != null) { - forwardingMessages = null; + if (!fragment.isQuote && (dids.size() > 1 || dids.get(0).dialogId == getUserConfig().getClientUserId() || message != null)) { + messagePreviewParams = null; hideFieldPanel(false); for (int a = 0; a < dids.size(); a++) { long did = dids.get(a).dialogId; @@ -26606,7 +27513,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (presentFragment(chatActivity, true)) { - chatActivity.showFieldPanelForForward(true, fmessages); + if (fragment.isQuote && replyingMessageObject != null) { + if (chatActivityEnterView != null && chatActivity.chatActivityEnterView != null) { + chatActivity.chatActivityEnterView.setFieldText( + chatActivityEnterView.getFieldText() + ); + } + if (replyingQuoteGroup != null) { + chatActivity.replyingQuoteGroup = replyingQuoteGroup; + } else if (replyingMessageObject != null) { + chatActivity.replyingQuoteGroup = getGroup(replyingMessageObject.getGroupId()); + } + if (replyingTopMessage != null) { + chatActivity.replyingTopMessage = replyingTopMessage; + } else if (threadMessageObject != null) { + chatActivity.replyingTopMessage = threadMessageObject; + } + chatActivity.showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); + } else { + chatActivity.showFieldPanelForForward(true, fmessages); + } if (!AndroidUtilities.isTablet()) { removeSelfFromStack(); } @@ -26630,12 +27556,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } moveScrollToLastMessage(false); - showFieldPanelForForward(true, fmessages); + if (fragment.isQuote && replyingMessageObject != null) { + showFieldPanelForReplyQuote(replyingMessageObject, replyingQuote); + } else { + showFieldPanelForForward(true, fmessages); + } if (AndroidUtilities.isTablet()) { hideActionMode(); updatePinnedMessageView(true); } updateVisibleRows(); + if (keyboardWasVisible && chatActivityEnterView != null) { + chatActivityEnterView.openKeyboardInternal(); + chatActivityEnterView.freezeEmojiView(false); + keyboardWasVisible = false; + } } } return true; @@ -26754,7 +27689,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updatePinnedTopicStarterMessage() { - topicStarterMessageObject = isTopic && !pinnedMessageObjects.isEmpty() && pinnedMessageIds.size() == 1 ? pinnedMessageObjects.get(pinnedMessageIds.get(0)) : null; + topicStarterMessageObject = isTopic && !pinnedMessageObjects.isEmpty() && pinnedMessageIds.size() == 1 && pinnedMessageIds.get(0) == getTopicId() + 1 ? pinnedMessageObjects.get(pinnedMessageIds.get(0)) : null; if (isTopic && topicStarterMessageObject != null && topicStarterMessageObject.messageOwner != null && forumTopic != null && !MessageObject.peersEqual(forumTopic.from_id, topicStarterMessageObject.messageOwner.from_id) && !MessageObject.peersEqual(currentChat, topicStarterMessageObject.messageOwner.from_id)) { topicStarterMessageObject = null; } @@ -26764,6 +27699,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not highlightMessageId = id; } + public void setHighlightQuote(int id, String quote) { + highlightMessageId = id; + highlightMessageQuote = quote; + showNoQuoteAlert = true; + } + + public void showNoQuoteFound() { + BulletinFactory.of(this).createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.QuoteNotFound)).show(true); + } + public boolean isThreadChat() { return threadMessageObject != null; } @@ -26808,6 +27753,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean disableSelection = false; boolean selected = false; if (actionBar.isActionModeShowed() || reportType >= 0) { + highlightMessageQuote = null; cell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(messageObject), true); int idx = messageObject.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[idx].indexOfKey(messageObject.getId()) >= 0) { @@ -26837,7 +27783,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } - if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && getMediaDataController().isMessageFound(messageObject.getId(), messageObject.getDialogId() == mergeDialogId) && getMediaDataController().getLastSearchQuery() != null) { + if (cell.isHighlighted() && highlightMessageQuote != null) { + if (!cell.setHighlightedText(highlightMessageQuote, true) && showNoQuoteAlert) { + showNoQuoteFound(); + } + showNoQuoteAlert = false; + } else if (searchContainer != null && searchContainer.getVisibility() == View.VISIBLE && getMediaDataController().isMessageFound(messageObject.getId(), messageObject.getDialogId() == mergeDialogId) && getMediaDataController().getLastSearchQuery() != null) { cell.setHighlightedText(getMediaDataController().getLastSearchQuery()); } else { cell.setHighlightedText(null); @@ -26977,7 +27928,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public boolean canScheduleMessage() { - return currentEncryptedChat == null && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE) && !isThreadChat(); + if (getMessagesController().isForum(getDialogId()) && !isTopic) { + return false; + } + return currentEncryptedChat == null && (bottomOverlayChat == null || bottomOverlayChat.getVisibility() != View.VISIBLE) && (!isThreadChat() || isTopic); } public boolean canSendMessage() { @@ -27000,6 +27954,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return replyingMessageObject; } + public ChatActivity.ReplyQuote getReplyQuote() { + return replyingQuote; + } + public int getThreadId() { return threadMessageId; } @@ -27071,15 +28029,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not fillEditingMediaWithCaption(photoEntry.caption, photoEntry.entities); if (photoEntry.isVideo) { if (videoEditedInfo != null) { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, dialog_id, replyingMessageObject, getThreadMessage(), null, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } else { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, getThreadMessage(), null, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } } else { if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } } afterMessageSend(); @@ -28138,7 +29096,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean isSwipeBackEnabled(MotionEvent event) { - return swipeBackEnabled; + return swipeBackEnabled && (forwardingPreviewView == null || !forwardingPreviewView.isShowing()); } public class ChatActivityAdapter extends RecyclerAnimationScrollHelper.AnimatableAdapter { @@ -28285,6 +29243,35 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not .setOutboundGift(cell.getMessageObject().isOut())); } + @Override + public void didOpenPremiumGiftChannel(ChatActionCell cell, String slug, boolean animateConfetti) { + 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_GIFT; + progressDialogLinkSpan = null; + cell.getMessageObject().flickerLoading = true; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(() -> { + ChatActivity.this.resetProgressDialogLoading(); + cell.getMessageObject().flickerLoading = false; + cell.invalidate(); + }, 250); + } + } + }; + GiftInfoBottomSheet.show(getBaseFragment(), slug, progressDialogCurrent); + } + @Override public void needShowEffectOverlay(ChatActionCell cell, TLRPC.Document document, TLRPC.VideoSize videoSize) { emojiAnimationsOverlay.showAnimationForActionCell(cell, document, videoSize); @@ -28652,6 +29639,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messageCell.setMessageObject(message, groupedMessages, pinnedBottom, pinnedTop); messageCell.setSpoilersSuppressed(chatListView.getScrollState() != RecyclerView.SCROLL_STATE_IDLE); messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && message.getId() == highlightMessageId); + if (messageCell.isHighlighted() && highlightMessageQuote != null) { + messageCell.setHighlightedText(highlightMessageQuote, true); + } if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } @@ -28949,6 +29939,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean selected = false; boolean disableSelection = false; if (actionBar.isActionModeShowed() || reportType >= 0) { + highlightMessageQuote = null; messageCell.setCheckBoxVisible(threadMessageObjects == null || !threadMessageObjects.contains(message), false); int idx = message.getDialogId() == dialog_id ? 0 : 1; if (selectedMessagesIds[idx].indexOfKey(message.getId()) >= 0) { @@ -28973,7 +29964,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!inPreviewMode || !messageCell.isHighlighted()) { - messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && messageCell.getMessageObject().getId() == highlightMessageId); + messageCell.setHighlighted(highlightMessageId != Integer.MAX_VALUE && (messageCell.getMessageObject().getId() == highlightMessageId || messageCell.getCurrentMessagesGroup() != null && messageCell.getCurrentMessagesGroup().contains(highlightMessageId))); + if (messageCell.isHighlighted() && highlightMessageQuote != null) { + if (!messageCell.setHighlightedText(highlightMessageQuote, true) && showNoQuoteAlert) { + showNoQuoteFound(); + } + showNoQuoteAlert = false; + } if (highlightMessageId != Integer.MAX_VALUE) { startMessageUnselect(); } @@ -29616,6 +30613,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + @Override + public void didPressSponsoredClose() { + showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + } + @Override public void didPressUserAvatar(ChatMessageCell cell, TLRPC.User user, float touchX, float touchY) { if (actionBar.isActionModeShowed() || reportType >= 0) { @@ -30071,6 +31073,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not didPressMessageUrl(url, longPress, cell.getMessageObject(), cell); } + @Override + public void didPressCode(ChatMessageCell cell, CharacterStyle _span, boolean longPress) { + if (!(_span instanceof CodeHighlighting.Span)) { + return; + } + final CodeHighlighting.Span span = (CodeHighlighting.Span) _span; + SpannableStringBuilder text = new SpannableStringBuilder(span.code); + text.setSpan(new CodeHighlighting.Span(false, 0, null, span.lng, span.code), 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + AndroidUtilities.addToClipboard(text); + createUndoView(); + undoView.showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); + } + @Override public boolean didPressAnimatedEmoji(ChatMessageCell cell, AnimatedEmojiSpan span) { if (getMessagesController().premiumLocked || span == null || span.standard) { @@ -30128,6 +31143,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } + @Override + public void didPressWebPage(ChatMessageCell cell, TLRPC.WebPage webpage, String url, boolean safe) { + if (url == null) { + return; + } + Uri uri = Uri.parse(url); + if (uri == null) { + return; + } + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(true); + } + progressDialogCurrent = cell == null || cell.getMessageObject() == null ? null : new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_INSTANT; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }; + if (!safe && !Browser.isInternalUri(uri, null)) { + AlertsCreator.showOpenUrlAlert(ChatActivity.this, url, true, true, true, !safe, progressDialogCurrent, themeDelegate); + } else { + Browser.openUrl(getContext(), uri, true, true, false, progressDialogCurrent); + } + } + @Override public void didPressReplyMessage(ChatMessageCell cell, int id) { if (UserObject.isReplyUser(currentUser)) { @@ -30136,10 +31186,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } MessageObject messageObject = cell.getMessageObject(); if (messageObject.isReplyToStory() && messageObject.messageOwner.replyStory != null) { - if (messageObject.messageOwner.replyStory instanceof TLRPC.TL_storyItemDeleted) { + if (messageObject.messageOwner.replyStory instanceof TL_stories.TL_storyItemDeleted) { BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.story_bomb1, LocaleController.getString("StoryNotFound", R.string.StoryNotFound)).show(); } else { - TLRPC.StoryItem storyItem = messageObject.messageOwner.replyStory; + TL_stories.StoryItem storyItem = messageObject.messageOwner.replyStory; storyItem.dialogId = messageObject.messageOwner.reply_to.user_id; storyItem.messageId = messageObject.getId(); storyItem.messageType = 3; @@ -30150,10 +31200,95 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityDelegate.openReplyMessage(id); finishFragment(); } else { - scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { - progressDialogAtMessageId = messageObject.getId(); - progressDialogAtMessageType = PROGRESS_REPLY; - }); + String quote = null; + if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { + quote = messageObject.messageOwner.reply_to.quote_text; + } + long did = dialog_id; + boolean couldBeDifferentTopic = false; + if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null) { + if (messageObject.messageOwner.reply_to.reply_to_peer_id != null) { + if (!(messageObject.messageOwner.reply_to.reply_to_peer_id instanceof TLRPC.TL_peerUser)) { + did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_to_peer_id); + couldBeDifferentTopic = true; + } else if (DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_to_peer_id) != dialog_id) { + did = Long.MAX_VALUE; + } + } else if (messageObject.messageOwner.reply_to.reply_from != null) { + did = Long.MAX_VALUE; + if (messageObject.messageOwner.reply_to.reply_from.from_id != null) { + if (!(messageObject.messageOwner.reply_to.reply_from.from_id instanceof TLRPC.TL_peerUser)) { + did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_from.from_id); + } + } else if (messageObject.messageOwner.reply_to.reply_from.saved_from_peer != null) { + did = DialogObject.getPeerDialogId(messageObject.messageOwner.reply_to.reply_from.saved_from_peer); + } + } + } + TLRPC.Chat chat = null; + if (did < 0) { + chat = getMessagesController().getChat(-did); + } + if (did == Long.MAX_VALUE || did != dialog_id && chat != null && !ChatObject.isPublic(chat) && (chat.left || chat.kicked)) { + if (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && !TextUtils.isEmpty(messageObject.messageOwner.reply_to.quote_text) && messageObject.replyTextEllipsized && !messageObject.replyTextRevealed && !messageObject.shouldDrawWithoutBackground()) { + messageObject.replyTextRevealed = true; + updateMessageAnimated(messageObject, true); + } else { + int str; + if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { + if (chat != null && chat.megagroup) { + str = R.string.QuotePrivateGroup; + } else if (ChatObject.isChannel(chat)) { + str = R.string.QuotePrivateChannel; + } else { + str = R.string.QuotePrivate; + } + } else { + if (chat != null && chat.megagroup) { + str = R.string.ReplyPrivateGroup; + } else if (ChatObject.isChannel(chat)) { + str = R.string.ReplyPrivateChannel; + } else { + str = R.string.ReplyPrivate; + } + } + BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.error, LocaleController.getString(str)).show(true); + } + return; + } + if ((did != dialog_id || ChatObject.isForum(currentChat) && couldBeDifferentTopic) && did != Long.MAX_VALUE) { + if (LaunchActivity.instance != null) { + if (progressDialogCurrent != null) { + progressDialogCurrent.cancel(); + progressDialogCurrent = null; + } + LaunchActivity.instance.openMessage(did, id, quote, progressDialogCurrent = new Browser.Progress() { + @Override + public void init() { + progressDialogAtMessageId = cell.getMessageObject().getId(); + progressDialogAtMessageType = PROGRESS_REPLY; + progressDialogLinkSpan = null; + cell.invalidate(); + } + + @Override + public void end(boolean replaced) { + if (!replaced) { + AndroidUtilities.runOnUIThread(ChatActivity.this::resetProgressDialogLoading, 250); + } + } + }, messageObject.getId()); + } + } else { + if (messageObject.messageOwner != null && messageObject.messageOwner.reply_to != null && messageObject.messageOwner.reply_to.quote) { + highlightMessageQuote = messageObject.messageOwner.reply_to.quote_text; + showNoQuoteAlert = true; + } + scrollToMessageId(id, messageObject.getId(), true, messageObject.getDialogId() == mergeDialogId ? 1 : 0, true, 0, () -> { + progressDialogAtMessageId = messageObject.getId(); + progressDialogAtMessageType = PROGRESS_REPLY; + }); + } } } @@ -30214,8 +31349,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void didPressImage(ChatMessageCell cell, float x, float y) { MessageObject message = cell.getMessageObject(); if (message.type == MessageObject.TYPE_STORY) { - if (message.messageOwner.media.storyItem != null && !(message.messageOwner.media.storyItem instanceof TLRPC.TL_storyItemDeleted)) { - TLRPC.StoryItem storyItem = message.messageOwner.media.storyItem; + if (message.messageOwner.media.storyItem != null && !(message.messageOwner.media.storyItem instanceof TL_stories.TL_storyItemDeleted)) { + TL_stories.StoryItem storyItem = message.messageOwner.media.storyItem; storyItem.dialogId = DialogObject.getPeerDialogId(message.messageOwner.media.peer); storyItem.messageId = message.getId(); storyItem.messageType = 2; @@ -30348,7 +31483,28 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didPressInstantButton(ChatMessageCell cell, int type) { MessageObject messageObject = cell.getMessageObject(); - if (type == 8) { + if (type == 19) { + 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); + } + } + }; + BoostDialogs.openGiveAwayStatusDialog(messageObject, progressDialogCurrent, getContext(), getResourceProvider()); + } else if (type == 8) { PollVotesAlert.showForPoll(ChatActivity.this, messageObject); } else if (type == 0) { if (messageObject.messageOwner.media != null && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.cached_page != null) { @@ -30433,12 +31589,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } }; - Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, progressDialogCurrent); + Browser.openUrl(getParentActivity(), Uri.parse(webPage.url), true, true, messageObject != null && MessageObject.getMedia(messageObject.messageOwner) != null && !MessageObject.getMedia(messageObject.messageOwner).safe, progressDialogCurrent); } } } } + @Override + public void didPressGiveawayChatButton(ChatMessageCell cell, int pressedPos) { + TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) cell.getMessageObject().messageOwner.media; + long channelId = giveaway.channels.get(pressedPos); + if (dialog_id != -channelId) { + presentFragment(ChatActivity.of(-channelId)); + } else { + ViewGroup v = getChatListView(); + AndroidUtilities.shakeViewSpring(v, 5); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + } + } + @Override public void didPressCommentButton(ChatMessageCell cell) { MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); @@ -31100,8 +32269,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outVenueInfoSelectedText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_mediaInfoText)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_urlPaint, null, null, Theme.key_chat_linkSelectBackground)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_outUrlPaint, null, null, Theme.key_chat_outLinkSelectBackground)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_textSelectBackground)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_outUrlPaint, null, null, Theme.key_chat_outReplyLine)); + themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, Theme.chat_textSearchSelectionPaint, null, null, Theme.key_chat_inReplyLine)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoader)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outMediaIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, null, null, Theme.key_chat_outLoaderSelected)); @@ -31699,7 +32868,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public Runnable onThemeChange; - public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.ThemeDelegate, ForwardingPreviewView.ResourcesDelegate { + public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.ThemeDelegate, MessagePreviewView.ResourcesDelegate { private final HashMap currentDrawables = new HashMap<>(); private final HashMap currentPaints = new HashMap<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatBackgroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatBackgroundDrawable.java index bd0f5cadd..b5371b5aa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatBackgroundDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatBackgroundDrawable.java @@ -30,6 +30,7 @@ import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.Components.BackgroundGradientDrawable; import org.telegram.ui.Components.MotionBackgroundDrawable; +import java.util.ArrayList; import java.util.Objects; public class ChatBackgroundDrawable extends Drawable { @@ -222,22 +223,36 @@ public class ChatBackgroundDrawable extends Drawable { return 0; } - boolean attached; - - public void onAttachedToWindow() { - if (attached) { - return; - } - attached = true; - imageReceiver.onAttachedToWindow(); + private boolean attached; + private final ArrayList attachedViews = new ArrayList<>(); + private boolean isAttached() { + return attachedViews.size() > 0; } - public void onDetachedFromWindow() { - if (!attached) { - return; + public void onAttachedToWindow(View view) { + if (!attachedViews.contains(view)) { + attachedViews.add(view); + } + if (isAttached() && !attached) { + attached = true; + imageReceiver.onAttachedToWindow(); + } else if (!isAttached() && attached) { + attached = false; + imageReceiver.onDetachedFromWindow(); + } + } + + public void onDetachedFromWindow(View view) { + if (!attachedViews.contains(view)) { + attachedViews.remove(view); + } + if (isAttached() && !attached) { + attached = true; + imageReceiver.onAttachedToWindow(); + } else if (!isAttached() && attached) { + attached = false; + imageReceiver.onDetachedFromWindow(); } - attached = false; - imageReceiver.onDetachedFromWindow(); } public Drawable getDrawable() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index 1d4f2a86d..caf03b89b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -121,6 +121,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image private TextCell locationCell; private TextCell typeCell; private TextCell linkedCell; + private PeerColorActivity.ChangeNameColorCell colorCell; private TextCell historyCell; private TextCell reactionsCell; private TextInfoPrivacyCell settingsSectionCell; @@ -387,6 +388,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image nameTextView.onResume(); nameTextView.getEditText().requestFocus(); } + updateColorCell(); AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); updateFields(true, true); imageUpdater.onResume(); @@ -880,6 +882,15 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image }); } + if (ChatObject.isChannelAndNotMegaGroup(currentChat) && ChatObject.canChangeChatInfo(currentChat)) { + colorCell = new PeerColorActivity.ChangeNameColorCell(true, context, getResourceProvider()); + colorCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); + typeEditContainer.addView(colorCell, LayoutHelper.createLinear(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + colorCell.setOnClickListener(v -> { + presentFragment(new PeerColorActivity(-currentChat.id).setOnApplied(this)); + }); + } + if (!isChannel && ChatObject.canBlockUsers(currentChat) && (ChatObject.isChannel(currentChat) || currentChat.creator)) { historyCell = new TextCell(context); historyCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); @@ -964,6 +975,8 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image updateFields(false, true); }); } + + updateColorCell(); } ActionBarMenu menu = actionBar.createMenu(); @@ -1881,6 +1894,12 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } } + private void updateColorCell() { + if (colorCell != null) { + colorCell.set(currentChat, (historyCell != null && historyCell.getVisibility() == View.VISIBLE) || (signCell != null && signCell.getVisibility() == View.VISIBLE) || (forumsCell != null && forumsCell.getVisibility() == View.VISIBLE)); + } + } + private ValueAnimator updateHistoryShowAnimator; private void updateHistoryShow(boolean show, boolean animated) { final boolean finalShow = show; @@ -1889,6 +1908,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (historyCell.getAlpha() <= 0 && !show) { historyCell.setVisibility(View.GONE); + updateColorCell(); return; } else if (historyCell.getVisibility() == View.VISIBLE && historyCell.getAlpha() >= 1 && show) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java index b8434b95c..eaa47d0a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java @@ -55,6 +55,7 @@ import org.telegram.ui.Components.LoadingStickerDrawable; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; +import java.util.Iterator; public class ChatLinkActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -618,6 +619,11 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter TLRPC.messages_Chats res = (TLRPC.messages_Chats) response; getMessagesController().putChats(res.chats, false); chats = res.chats; + Iterator i = chats.iterator(); + while (i.hasNext()) { + if (ChatObject.isForum(i.next())) + i.remove(); + } } loadingChats = false; chatsLoaded = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 3a76893e8..2f1d8bf20 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -730,7 +730,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (position == sendMediaVideosRow) { defaultBannedRights.send_videos = !defaultBannedRights.send_videos; } else if (position == sendMediaStickerGifsRow) { - defaultBannedRights.send_stickers = !defaultBannedRights.send_stickers; + defaultBannedRights.send_stickers = defaultBannedRights.send_games = defaultBannedRights.send_gifs = defaultBannedRights.send_inline = !defaultBannedRights.send_stickers; } else if (position == sendMediaMusicRow) { defaultBannedRights.send_audios = !defaultBannedRights.send_audios; } else if (position == sendMediaFilesRow) { 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 24d506dbd..8f406ce1f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -92,6 +92,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; @@ -236,7 +237,7 @@ public class AlertsCreator { } public static Dialog processError(int currentAccount, TLRPC.TL_error error, BaseFragment fragment, TLObject request, Object... args) { - if (error.code == 406 || error.text == null) { + if (error == null || error.code == 406 || error.text == null) { return null; } if (request instanceof TLRPC.TL_messages_initHistoryImport || request instanceof TLRPC.TL_messages_checkHistoryImportPeer || request instanceof TLRPC.TL_messages_checkHistoryImport || request instanceof TLRPC.TL_messages_startHistoryImport) { @@ -477,7 +478,7 @@ public class AlertsCreator { } else if (error.text.startsWith("FLOOD_WAIT")) { showSimpleAlert(fragment, LocaleController.getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("FRESH_CHANGE_PHONE_FORBIDDEN")) { - showSimpleAlert(fragment, LocaleController.getString("FreshChangePhoneForbidden", R.string.FreshChangePhoneForbidden)); + showSimpleAlert(fragment, LocaleController.getString(R.string.FreshChangePhoneForbiddenTitle), LocaleController.getString("FreshChangePhoneForbidden", R.string.FreshChangePhoneForbidden)); } else { showSimpleAlert(fragment, error.text); } @@ -2773,7 +2774,7 @@ public class AlertsCreator { this(null); } - private ScheduleDatePickerColors(Theme.ResourcesProvider rp) { + public ScheduleDatePickerColors(Theme.ResourcesProvider rp) { this(rp != null ? rp.getColorOrDefault(Theme.key_dialogTextBlack) : Theme.getColor(Theme.key_dialogTextBlack), rp != null ? rp.getColorOrDefault(Theme.key_dialogBackground) : Theme.getColor(Theme.key_dialogBackground), rp != null ? rp.getColorOrDefault(Theme.key_sheet_other) : Theme.getColor(Theme.key_sheet_other), @@ -4248,8 +4249,8 @@ public class AlertsCreator { buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - buttonTextView.setText(LocaleController.getString("JumpToDate", R.string.JumpToDate)); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.getColor(Theme.key_featuredStickers_addButtonPressed, resourcesProvider))); + buttonTextView.setText(LocaleController.getString(R.string.JumpToDate)); + buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), Theme.getColor(Theme.key_featuredStickers_addButtonPressed, resourcesProvider))); container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16)); buttonTextView.setOnClickListener(v -> { checkCalendarDate(minDate, dayPicker, monthPicker, yearPicker); @@ -4361,7 +4362,7 @@ public class AlertsCreator { return; } if (storyId != 0) { - TLRPC.TL_stories_report request = new TLRPC.TL_stories_report(); + 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; @@ -4518,7 +4519,7 @@ public class AlertsCreator { TLObject req; TLRPC.InputPeer peer = MessagesController.getInstance(UserConfig.selectedAccount).getInputPeer(dialog_id); if (storyId != 0) { - TLRPC.TL_stories_report request = new TLRPC.TL_stories_report(); + 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 = ""; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index 7bdd189fc..1d8d97a1d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -961,6 +961,7 @@ public class AnimatedEmojiDrawable extends Drawable { } private Integer lastColor; + private int colorFilterLastColor; private ColorFilter colorFilter; public void setColor(Integer color) { @@ -968,7 +969,9 @@ public class AnimatedEmojiDrawable extends Drawable { return; } lastColor = color; - colorFilter = color != null ? new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN) : null; + if (color == null || colorFilterLastColor != color) { + colorFilter = color != null ? new PorterDuffColorFilter(colorFilterLastColor = color, PorterDuff.Mode.SRC_IN) : null; + } } public Integer getColor() { @@ -1048,13 +1051,17 @@ public class AnimatedEmojiDrawable extends Drawable { return drawables[0]; } - public void set(long documentId, boolean animated) { - set(documentId, cacheType, animated); + public boolean set(long documentId, boolean animated) { + return set(documentId, cacheType, animated); } - public void set(long documentId, int cacheType, boolean animated) { + public void resetAnimation() { + changeProgress.set(1, true); + } + + public boolean set(long documentId, int cacheType, boolean animated) { if (drawables[0] instanceof AnimatedEmojiDrawable && ((AnimatedEmojiDrawable) drawables[0]).getDocumentId() == documentId) { - return; + return false; } if (animated) { changeProgress.set(0, true); @@ -1082,8 +1089,10 @@ public class AnimatedEmojiDrawable extends Drawable { } lastColor = null; colorFilter = null; + colorFilterLastColor = 0; play(); invalidate(); + return true; } public void set(TLRPC.Document document, boolean animated) { @@ -1128,6 +1137,7 @@ public class AnimatedEmojiDrawable extends Drawable { } lastColor = null; colorFilter = null; + colorFilterLastColor = 0; play(); invalidate(); } @@ -1159,6 +1169,7 @@ public class AnimatedEmojiDrawable extends Drawable { } lastColor = null; colorFilter = null; + colorFilterLastColor = 0; play(); invalidate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java index be60a762f..b6d091c5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -71,8 +71,12 @@ public class AnimatedTextView extends View { public Part(StaticLayout layout, float offset, int toOppositeIndex) { this.layout = layout; - this.offset = offset; this.toOppositeIndex = toOppositeIndex; + layout(offset); + } + + public void layout(float offset) { + this.offset = offset; this.left = layout == null || layout.getLineCount() <= 0 ? 0 : layout.getLineLeft(0); this.width = layout == null || layout.getLineCount() <= 0 ? 0 : layout.getLineWidth(0); } @@ -796,7 +800,33 @@ public class AnimatedTextView extends View { } public void setTextSize(float textSizePx) { + final float lastTextPaint = textPaint.getTextSize(); textPaint.setTextSize(textSizePx); + if (Math.abs(lastTextPaint - textSizePx) > 0.5f) { + final int width = overrideFullWidth > 0 ? overrideFullWidth : bounds.width(); + if (currentParts != null) { + // relayout parts: + currentWidth = 0; + currentHeight = 0; + for (int i = 0; i < currentParts.length; ++i) { + StaticLayout layout = makeLayout(currentParts[i].layout.getText(), width - (int) Math.ceil(Math.min(currentWidth, oldWidth))); + currentParts[i] = new Part(layout, currentParts[i].offset, currentParts[i].toOppositeIndex); + currentWidth += currentParts[i].width; + currentHeight = Math.max(currentHeight, currentParts[i].layout.getHeight()); + } + } + if (oldParts != null) { + oldWidth = 0; + oldHeight = 0; + for (int i = 0; i < oldParts.length; ++i) { + StaticLayout layout = makeLayout(oldParts[i].layout.getText(), width - (int) Math.ceil(Math.min(currentWidth, oldWidth))); + oldParts[i] = new Part(layout, oldParts[i].offset, oldParts[i].toOppositeIndex); + oldWidth += oldParts[i].width; + oldHeight = Math.max(oldHeight, oldParts[i].layout.getHeight()); + } + } + invalidateSelf(); + } } public float getTextSize() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java index 1ffb415b1..b65d49c85 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioVisualizerDrawable.java @@ -114,6 +114,15 @@ public class AudioVisualizerDrawable { float rotation; + public void draw(Canvas canvas, float cx, float cy, int color, float alpha, Theme.ResourcesProvider resourcesProvider) { + if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { + return; + } + p1.setColor(color); + p1.setAlpha((int) (ALPHA * alpha)); + this.draw(canvas, cx, cy); + } + public void draw(Canvas canvas, float cx, float cy, boolean outOwner, float alpha, Theme.ResourcesProvider resourcesProvider) { if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java index 45006fe53..f2a053486 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarConstructorFragment.java @@ -882,6 +882,7 @@ public class AvatarConstructorFragment extends BaseFragment { backgroundGradient.color4 = defaultColors[i][3]; gradients.add(backgroundGradient); } + useLayoutPositionOnClick = true; setOnItemClickListener((view, position) -> { if (view instanceof GradientSelectorView && !((GradientSelectorView) view).isCustom) { selectedItemId = ((GradientSelectorView) view).backgroundGradient.stableId; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java index 07e0542cf..32dc207b3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -9,6 +9,7 @@ package org.telegram.ui.Components; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LinearGradient; import android.graphics.Paint; @@ -23,11 +24,14 @@ import android.text.TextPaint; import android.text.TextUtils; import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; -import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLObject; @@ -61,6 +65,7 @@ public class AvatarDrawable extends Drawable { private int gradientTop2, gradientBottom2; private int gradientColor21, gradientColor22; private LinearGradient gradient2; + private boolean drawAvatarBackground = true; public static final int AVATAR_TYPE_NORMAL = 0; public static final int AVATAR_TYPE_SAVED = 1; @@ -79,6 +84,10 @@ public class AvatarDrawable extends Drawable { public static final int AVATAR_TYPE_REGISTER = 13; public static final int AVATAR_TYPE_OTHER_CHATS = 14; public static final int AVATAR_TYPE_CLOSE_FRIENDS = 15; + public static final int AVATAR_TYPE_GIFT = 16; + public static final int AVATAR_TYPE_COUNTRY = 17; + public static final int AVATAR_TYPE_UNCLAIMED = 18; + public static final int AVATAR_TYPE_TO_BE_DISTRIBUTED = 19; private int alpha = 255; private Theme.ResourcesProvider resourcesProvider; @@ -133,9 +142,11 @@ public class AvatarDrawable extends Drawable { public AvatarDrawable(TLRPC.Chat chat, boolean profile) { this(); isProfile = profile; - if (chat != null) { - setInfo(chat.id, chat.title, null, null); - } + setInfo(chat); + } + + public void setDrawAvatarBackground(boolean drawAvatarBackground) { + this.drawAvatarBackground = drawAvatarBackground; } public AvatarDrawable(TLRPC.Chat chat, boolean profile, int accountNum) { @@ -154,8 +165,21 @@ public class AvatarDrawable extends Drawable { isProfile = value; } + public static int getPeerColorIndex(int color) { + float[] tempHSV = Theme.getTempHsv(5); + Color.colorToHSV(color, tempHSV); + final int hue = (int) tempHSV[0]; + if (hue >= 345 || hue < 29) return 0; // red + if (hue < 67) return 1; // orange + if (hue < 140) return 3; // green + if (hue < 199) return 4; // cyan + if (hue < 234) return 5; // blue + if (hue < 301) return 2; // violet + return 6; // pink + } + public static int getColorIndex(long id) { - if (id >= 0 && id < 7) { + if (id >= 0 && id < Theme.keys_avatar_background.length) { return (int) id; } return (int) Math.abs(id % Theme.keys_avatar_background.length); @@ -185,13 +209,86 @@ public class AvatarDrawable extends Drawable { return Theme.getColor(Theme.key_avatar_backgroundActionBarBlue, resourcesProvider); } + public static String colorName(int color) { + final int[] resIds = new int[] { R.string.ColorRed, R.string.ColorOrange, R.string.ColorViolet, R.string.ColorGreen, R.string.ColorCyan, R.string.ColorBlue, R.string.ColorPink }; + return LocaleController.getString(resIds[color % resIds.length]); + } + public static int getNameColorNameForId(long id) { return Theme.keys_avatar_nameInMessage[getColorIndex(id)]; } + public static boolean isNameColorKeyHasComposite(int color) { + return color >= Theme.keys_avatar_nameInMessage.length && color < Theme.keys_avatar_nameInMessage.length + Theme.keys_avatar_composite_nameInMessage.length; + } + + public static int getNameColorKey1For(TLRPC.User user) { + if (user == null) { + return Theme.keys_avatar_nameInMessage[0]; + } + if ((user.flags2 & 128) != 0) { + return getNameColorKey1For(user.color); + } + return getNameColorNameForId(user.id); + } + + public static int getNameColorKey2For(TLRPC.User user) { + if (user == null) { + return Theme.keys_avatar_nameInMessage[0]; + } + if ((user.flags2 & 128) != 0) { + return getNameColorKey2For(user.color); + } + return getNameColorNameForId(user.id); + } + + public static int getNameColorKey1For(TLRPC.Chat chat) { + if (chat == null) { + return Theme.keys_avatar_nameInMessage[0]; + } + if ((chat.flags2 & 64) != 0) { + return getNameColorKey1For(chat.color); + } + return getNameColorNameForId(chat.id); + } + + public static int getNameColorKey2For(TLRPC.Chat chat) { + if (chat == null) { + return Theme.keys_avatar_nameInMessage[0]; + } + if ((chat.flags2 & 64) != 0) { + return getNameColorKey2For(chat.color); + } + return getNameColorNameForId(chat.id); + } + + public static int getNameColorKey1For(int color) { + color = color % (Theme.keys_avatar_nameInMessage.length + Theme.keys_avatar_composite_nameInMessage.length); + if (color >= 0 && color < Theme.keys_avatar_nameInMessage.length) { + return Theme.keys_avatar_nameInMessage[color]; + } + color -= Theme.keys_avatar_nameInMessage.length; + if (color >= 0 && color < Theme.keys_avatar_composite_nameInMessage.length) { + return Theme.keys_avatar_composite_nameInMessage[color]; + } + return Theme.keys_avatar_nameInMessage[0]; + } + + public static int getNameColorKey2For(int color) { + color = color % (Theme.keys_avatar_nameInMessage.length + Theme.keys_avatar_composite_nameInMessage2.length); + if (color >= 0 && color < Theme.keys_avatar_nameInMessage.length) { + return Theme.keys_avatar_nameInMessage[color]; + } + color -= Theme.keys_avatar_nameInMessage.length; + if (color >= 0 && color < Theme.keys_avatar_composite_nameInMessage2.length) { + return Theme.keys_avatar_composite_nameInMessage2[color]; + } + return Theme.keys_avatar_nameInMessage[0]; + } + public void setInfo(TLRPC.User user) { if (user != null) { - setInfo(user.id, user.first_name, user.last_name, null); + setInfo(user.id, user.first_name, user.last_name, null, (user.flags2 & 128) != 0 ? user.color : null); drawDeleted = UserObject.isDeleted(user); } } @@ -274,6 +371,10 @@ public class AvatarDrawable extends Drawable { hasGradient = true; color = getThemedColor(Theme.keys_avatar_background[getColorIndex(5)]); color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(5)]); + } else if (avatarType == AVATAR_TYPE_COUNTRY) { + hasGradient = true; + color = getThemedColor(Theme.keys_avatar_background[getColorIndex(5)]); + color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(5)]); } else { hasGradient = true; color = getThemedColor(Theme.keys_avatar_background[getColorIndex(4)]); @@ -292,13 +393,13 @@ public class AvatarDrawable extends Drawable { public void setInfo(TLRPC.Chat chat) { if (chat != null) { - setInfo(chat.id, chat.title, null, null); + setInfo(chat.id, chat.title, null, null, (chat.flags2 & 64) != 0 ? chat.color : null); } } public void setInfo(TLRPC.ChatInvite chat) { if (chat != null) { - setInfo(0, chat.title, null, null); + setInfo(0, chat.title, null, null, chat.chat != null && (chat.chat.flags2 & 64) != 0 ? chat.chat.color : null); } } @@ -326,7 +427,7 @@ public class AvatarDrawable extends Drawable { } public void setInfo(long id, String firstName, String lastName) { - setInfo(id, firstName, lastName, null); + setInfo(id, firstName, lastName, null, null); } public int getColor() { @@ -346,10 +447,31 @@ public class AvatarDrawable extends Drawable { } public void setInfo(long id, String firstName, String lastName, String custom) { + setInfo(id, firstName, lastName, custom, null); + } + + public void setInfo(long id, String firstName, String lastName, String custom, Integer customColor) { hasGradient = true; invalidateTextLayout = true; - color = getThemedColor(Theme.keys_avatar_background[getColorIndex(id)]); - color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(id)]); + if (customColor != null) { + if (customColor >= 14) { + MessagesController messagesController = MessagesController.getInstance(UserConfig.selectedAccount); + if (messagesController != null && messagesController.peerColors != null && messagesController.peerColors.getColor(customColor) != null) { + final int peerColor = messagesController.peerColors.getColor(customColor).getColor1(); + color = getThemedColor(Theme.keys_avatar_background[getPeerColorIndex(peerColor)]); + color2 = getThemedColor(Theme.keys_avatar_background2[getPeerColorIndex(peerColor)]); + } else { + color = getThemedColor(Theme.keys_avatar_background[getColorIndex(customColor)]); + color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(customColor)]); + } + } else { + color = getThemedColor(Theme.keys_avatar_background[getColorIndex(customColor)]); + color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(customColor)]); + } + } else { + color = getThemedColor(Theme.keys_avatar_background[getColorIndex(id)]); + color2 = getThemedColor(Theme.keys_avatar_background2[getColorIndex(id)]); + } needApplyColorAccent = id == 5; // Tinting manually set blue color avatarType = AVATAR_TYPE_NORMAL; @@ -419,11 +541,14 @@ public class AvatarDrawable extends Drawable { } canvas.save(); canvas.translate(bounds.left, bounds.top); - if (roundRadius > 0) { - AndroidUtilities.rectTmp.set(0, 0, size, size); - canvas.drawRoundRect(AndroidUtilities.rectTmp, roundRadius, roundRadius, Theme.avatar_backgroundPaint); - } else { - canvas.drawCircle(size / 2.0f, size / 2.0f, size / 2.0f, Theme.avatar_backgroundPaint); + + if (drawAvatarBackground) { + if (roundRadius > 0) { + AndroidUtilities.rectTmp.set(0, 0, size, size); + canvas.drawRoundRect(AndroidUtilities.rectTmp, roundRadius, roundRadius, Theme.avatar_backgroundPaint); + } else { + canvas.drawCircle(size / 2.0f, size / 2.0f, size / 2.0f, Theme.avatar_backgroundPaint); + } } if (avatarType == AVATAR_TYPE_ARCHIVED) { @@ -481,6 +606,12 @@ public class AvatarDrawable extends Drawable { drawable = Theme.avatarDrawables[12]; } else if (avatarType == AVATAR_TYPE_CLOSE_FRIENDS) { drawable = Theme.avatarDrawables[13]; + } else if (avatarType == AVATAR_TYPE_GIFT) { + drawable = Theme.avatarDrawables[14]; + } else if (avatarType == AVATAR_TYPE_TO_BE_DISTRIBUTED) { + drawable = Theme.avatarDrawables[15]; + } else if (avatarType == AVATAR_TYPE_UNCLAIMED) { + drawable = Theme.avatarDrawables[16]; } else { drawable = Theme.avatarDrawables[9]; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java index 67d328129..9d08f1470 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java @@ -140,7 +140,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente acceptButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); addView(acceptButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 46, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 45)); acceptButton.setOnClickListener(view1 -> { - if (BuildVars.isStandaloneApp() || BuildVars.DEBUG_VERSION) { + if (ApplicationLoader.isStandaloneBuild() || BuildVars.DEBUG_VERSION) { if (!ApplicationLoader.applicationLoaderInstance.checkApkInstallPermissions(getContext())) { return; } @@ -301,7 +301,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoadFailed); NotificationCenter.getInstance(accountNum).addObserver(this, NotificationCenter.fileLoadProgressChanged); - if (check && BuildVars.isStandaloneApp()) { + if (check && ApplicationLoader.isStandaloneBuild()) { TLRPC.TL_help_getAppUpdate req = new TLRPC.TL_help_getAppUpdate(); try { req.source = ApplicationLoader.applicationContext.getPackageManager().getInstallerPackageName(ApplicationLoader.applicationContext.getPackageName()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java index 1deba47de..c26a0b3b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java @@ -121,6 +121,7 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific private long lastClickMs; private boolean isBackButtonVisible; + private boolean isSettingsButtonVisible; private boolean hasUserPermissions; private TLRPC.User botUser; @@ -340,11 +341,10 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific @Override public boolean onShowFileChooser(WebView webView, ValueCallback filePathCallback, FileChooserParams fileChooserParams) { - Context ctx = getContext(); - if (!(ctx instanceof Activity)) { + Activity activity = AndroidUtilities.findActivity(getContext()); + if (activity == null) { return false; } - Activity activity = (Activity) ctx; if (mFilePathCallback != null) { mFilePathCallback.onReceiveValue(null); @@ -518,7 +518,7 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific } private void onOpenUri(Uri uri, boolean tryInstantView, boolean suppressPopup) { - if (isRequestingPageOpen || System.currentTimeMillis() - lastClickMs > 10000 && suppressPopup) { + if (isRequestingPageOpen || System.currentTimeMillis() - lastClickMs > 1000 && suppressPopup) { return; } @@ -536,7 +536,7 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - delegate.onCloseRequested(() -> Browser.openUrl(getContext(), uri, true, tryInstantView)); + Browser.openUrl(getContext(), uri, true, tryInstantView); } else { Browser.openUrl(getContext(), uri, true, tryInstantView); } @@ -813,10 +813,6 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific flickerView.setImage(ImageLocation.getForDocument(botIcon.icon), null, (Drawable) null, cachedBot); setupFlickerParams(center); } - - if (settingsItem != null) { - settingsItem.setVisibility(cachedBot.has_settings ? VISIBLE : GONE); - } } else { TLRPC.TL_messages_getAttachMenuBot req = new TLRPC.TL_messages_getAttachMenuBot(); req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); @@ -836,12 +832,6 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific flickerView.setImage(ImageLocation.getForDocument(botIcon.icon), null, (Drawable) null, bot); setupFlickerParams(center); } - - if (settingsItem != null) { - settingsItem.setVisibility(bot.has_settings ? VISIBLE : GONE); - } - } else if (settingsItem != null) { - settingsItem.setVisibility(GONE); } })); } @@ -863,6 +853,13 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific public void reload() { NotificationCenter.getInstance(currentAccount).doOnIdle(() -> { + if (isSettingsButtonVisible) { + isSettingsButtonVisible = false; + if (delegate != null) { + delegate.onSetSettingsButtonVisible(isSettingsButtonVisible); + } + } + checkCreateWebView(); isPageLoaded = false; lastClickMs = 0; @@ -1349,6 +1346,20 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific } break; } + case "web_app_setup_settings_button": { + try { + JSONObject jsonData = new JSONObject(eventData); + boolean newVisible = jsonData.optBoolean("is_visible"); + if (newVisible != isSettingsButtonVisible) { + isSettingsButtonVisible = newVisible; + + delegate.onSetSettingsButtonVisible(isSettingsButtonVisible); + } + } catch (JSONException e) { + FileLog.e(e); + } + break; + } case "web_app_open_invoice": { try { JSONObject jsonData = new JSONObject(eventData); @@ -1687,19 +1698,14 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific private JSONObject buildThemeParams() { try { - JSONObject object = new JSONObject(); - object.put("bg_color", formatColor(Theme.key_windowBackgroundWhite)); - object.put("secondary_bg_color", formatColor(Theme.key_windowBackgroundGray)); - object.put("text_color", formatColor(Theme.key_windowBackgroundWhiteBlackText)); - object.put("hint_color", formatColor(Theme.key_windowBackgroundWhiteHintText)); - object.put("link_color", formatColor(Theme.key_windowBackgroundWhiteLinkText)); - object.put("button_color", formatColor(Theme.key_featuredStickers_addButton)); - object.put("button_text_color", formatColor(Theme.key_featuredStickers_buttonText)); - return new JSONObject().put("theme_params", object); + JSONObject object = BotWebViewSheet.makeThemeParams(resourcesProvider); + if (object != null) { + return new JSONObject().put("theme_params", object); + } } catch (Exception e) { FileLog.e(e); - return new JSONObject(); } + return new JSONObject(); } private int getColor(int colorKey) { @@ -1811,6 +1817,8 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific */ void onSetBackButtonVisible(boolean visible); + void onSetSettingsButtonVisible(boolean visible); + /** * Called when WebView is ready (Called web_app_ready or page load finished) */ @@ -1820,6 +1828,7 @@ public abstract class BotWebViewContainer extends FrameLayout implements Notific * @return If clipboard access is available to webapp */ default boolean isClipboardAvailable() { + return false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java index 3f799b0b2..6abc61426 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java @@ -32,6 +32,7 @@ import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLog; 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; @@ -141,6 +142,8 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification botMenuItem.setVisibility(GONE); botMenuItem.addSubItem(R.id.menu_reload_page, R.drawable.msg_retry, LocaleController.getString(R.string.BotWebViewReloadPage)); + settingsItem = botMenuItem.addSubItem(R.id.menu_settings, R.drawable.msg_settings, LocaleController.getString(R.string.BotWebViewSettings)); + settingsItem.setVisibility(View.GONE); } } @@ -302,6 +305,18 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification } } } + + @Override + public void onSetSettingsButtonVisible(boolean visible) { + if (settingsItem != null) { + settingsItem.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + + @Override + public boolean isClipboardAvailable() { + return MediaDataController.getInstance(currentAccount).botInAttachMenu(botId); + } }); linePaint.setStyle(Paint.Style.FILL_AND_STROKE); @@ -770,21 +785,15 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification req.url = botUrl; req.flags |= 2; - try { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("bg_color", getColor(Theme.key_windowBackgroundWhite)); - jsonObject.put("secondary_bg_color", getColor(Theme.key_windowBackgroundGray)); - jsonObject.put("text_color", getColor(key_windowBackgroundWhiteBlackText)); - jsonObject.put("hint_color", getColor(Theme.key_windowBackgroundWhiteHintText)); - jsonObject.put("link_color", getColor(Theme.key_windowBackgroundWhiteLinkText)); - jsonObject.put("button_color", getColor(Theme.key_featuredStickers_addButton)); - jsonObject.put("button_text_color", getColor(Theme.key_featuredStickers_buttonText)); - + Theme.ResourcesProvider resourcesProvider = null; + if (parentEnterView != null && parentEnterView.getParentFragment() != null) { + resourcesProvider = parentEnterView.getParentFragment().getResourceProvider(); + } + JSONObject themeParams = BotWebViewSheet.makeThemeParams(resourcesProvider); + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = jsonObject.toString(); + req.theme_params.data = themeParams.toString(); req.flags |= 4; - } catch (Exception e) { - FileLog.e(e); } req.from_bot_menu = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java index 50e582457..36ee96e2f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java @@ -184,7 +184,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi prolongWebView.query_id = queryId; prolongWebView.silent = silent; if (replyToMsgId != 0) { - prolongWebView.reply_to = SendMessagesHelper.creteReplyInput(replyToMsgId); + prolongWebView.reply_to = SendMessagesHelper.getInstance(currentAccount).createReplyInput(replyToMsgId); prolongWebView.flags |= 1; } ConnectionsManager.getInstance(currentAccount).sendRequest(prolongWebView, (response, error) -> AndroidUtilities.runOnUIThread(() -> { @@ -325,6 +325,13 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), visible ? R.drawable.ic_ab_back : R.drawable.ic_close_white); } + @Override + public void onSetSettingsButtonVisible(boolean visible) { + if (settingsItem != null) { + settingsItem.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + @Override public void onWebAppOpenInvoice(String slug, TLObject response) { BaseFragment parentFragment = ((LaunchActivity) parentActivity).getActionBarLayout().getLastFragment(); @@ -478,6 +485,11 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } return null; } + + @Override + public boolean isClipboardAvailable() { + return MediaDataController.getInstance(currentAccount).botInAttachMenu(botId); + } }); linePaint.setStyle(Paint.Style.FILL_AND_STROKE); @@ -832,6 +844,29 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } } + public static JSONObject makeThemeParams(Theme.ResourcesProvider resourcesProvider) { + try { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("bg_color", Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + jsonObject.put("section_bg_color", Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + jsonObject.put("secondary_bg_color", Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + jsonObject.put("text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + jsonObject.put("hint_color", Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourcesProvider)); + jsonObject.put("link_color", Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); + jsonObject.put("button_color", Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); + jsonObject.put("button_text_color", Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); + jsonObject.put("header_bg_color", Theme.getColor(Theme.key_actionBarDefault, resourcesProvider)); + jsonObject.put("accent_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider)); + jsonObject.put("section_header_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); + jsonObject.put("subtitle_text_color", Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); + jsonObject.put("destructive_text_color", Theme.getColor(Theme.key_text_RedRegular, resourcesProvider)); + return jsonObject; + } catch (Exception e) { + FileLog.e(e); + } + return null; + } + public void requestWebView(int currentAccount, long peerId, long botId, String buttonText, String buttonUrl, @WebViewType int type, int replyToMsgId, boolean silent, int flags) { requestWebView(currentAccount, peerId, botId, buttonText, buttonUrl, type, replyToMsgId, silent, null, null, false, null, null, flags); } @@ -868,6 +903,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi ActionBarMenuItem otherItem = menu.addItem(0, R.drawable.ic_ab_other); otherItem.addSubItem(R.id.menu_open_bot, R.drawable.msg_bot, LocaleController.getString(R.string.BotWebViewOpenBot)); settingsItem = otherItem.addSubItem(R.id.menu_settings, R.drawable.msg_settings, LocaleController.getString(R.string.BotWebViewSettings)); + settingsItem.setVisibility(View.GONE); otherItem.addSubItem(R.id.menu_reload_page, R.drawable.msg_retry, LocaleController.getString(R.string.BotWebViewReloadPage)); if (currentBot != null && (currentBot.show_in_side_menu || currentBot.show_in_attach_menu)) { otherItem.addSubItem(R.id.menu_delete_bot, R.drawable.msg_delete, LocaleController.getString(R.string.BotWebViewDeleteBot)); @@ -907,22 +943,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } }); - boolean hasThemeParams = true; - String themeParams = null; - try { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("bg_color", getColor(Theme.key_windowBackgroundWhite)); - jsonObject.put("secondary_bg_color", getColor(Theme.key_windowBackgroundGray)); - jsonObject.put("text_color", getColor(Theme.key_windowBackgroundWhiteBlackText)); - jsonObject.put("hint_color", getColor(Theme.key_windowBackgroundWhiteHintText)); - jsonObject.put("link_color", getColor(Theme.key_windowBackgroundWhiteLinkText)); - jsonObject.put("button_color", getColor(Theme.key_featuredStickers_addButton)); - jsonObject.put("button_text_color", getColor(Theme.key_featuredStickers_buttonText)); - themeParams = jsonObject.toString(); - } catch (Exception e) { - FileLog.e(e); - hasThemeParams = false; - } + final JSONObject themeParams = makeThemeParams(resourcesProvider); webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); @@ -936,9 +957,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi req.url = buttonUrl; req.flags |= 2; - if (hasThemeParams) { + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; + req.theme_params.data = themeParams.toString(); req.flags |= 4; } @@ -960,9 +981,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); req.platform = "android"; req.from_side_menu = (flags & FLAG_FROM_SIDE_MENU) != 0; - if (hasThemeParams) { + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; + req.theme_params.data = themeParams.toString(); req.flags |= 1; } if (!TextUtils.isEmpty(buttonUrl)) { @@ -994,13 +1015,13 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } if (replyToMsgId != 0) { - req.reply_to = SendMessagesHelper.creteReplyInput(replyToMsgId); + req.reply_to = SendMessagesHelper.getInstance(currentAccount).createReplyInput(replyToMsgId); req.flags |= 1; } - if (hasThemeParams) { + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; + req.theme_params.data = themeParams.toString(); req.flags |= 4; } @@ -1032,9 +1053,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi req.flags |= 2; } - if (hasThemeParams) { + if (themeParams != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; + req.theme_params.data = themeParams.toString(); req.flags |= 4; } 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 c7fee6d38..eb1e8d095 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -124,69 +124,20 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } }; } - recyclerListView = new RecyclerListView(context); + recyclerListView = new RecyclerListView(context, resourcesProvider); recyclerListView.setLayoutManager(new LinearLayoutManager(context)); if (nestedSizeNotifierLayout != null) { nestedSizeNotifierLayout.setBottomSheetContainerView(getContainer()); nestedSizeNotifierLayout.setTargetListView(recyclerListView); } - RecyclerListView.SelectionAdapter adapter = createAdapter(); - if (hasFixedSize) { recyclerListView.setHasFixedSize(true); - recyclerListView.setAdapter(adapter); + recyclerListView.setAdapter(createAdapter()); setCustomView(containerView); containerView.addView(recyclerListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } else { - recyclerListView.setAdapter(new RecyclerListView.SelectionAdapter() { - - @Override - public boolean isEnabled(RecyclerView.ViewHolder holder) { - return adapter.isEnabled(holder); - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if (viewType == -1000) { - View view = new View(context) { - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int h; - if (contentHeight == 0) { - h = AndroidUtilities.dp(300); - } else { - h = (int) (contentHeight * topPadding); - } - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); - } - }; - return new RecyclerListView.Holder(view); - } - return adapter.onCreateViewHolder(parent, viewType); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - if (position != 0) { - adapter.onBindViewHolder(holder, position - 1); - } - } - - @Override - public int getItemViewType(int position) { - if (position == 0) { - return -1000; - } - return adapter.getItemViewType(position - 1); - } - - @Override - public int getItemCount() { - return 1 + adapter.getItemCount(); - } - }); + resetAdapter(context); this.containerView = containerView; actionBar = new ActionBar(context) { @Override @@ -235,6 +186,58 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { updateStatusBar(); } + protected void resetAdapter(Context context) { + RecyclerListView.SelectionAdapter adapter = createAdapter(); + recyclerListView.setAdapter(new RecyclerListView.SelectionAdapter() { + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return adapter.isEnabled(holder); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == -1000) { + View view = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int h; + if (contentHeight == 0) { + h = AndroidUtilities.dp(300); + } else { + h = (int) (contentHeight * topPadding); + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); + } + }; + return new RecyclerListView.Holder(view); + } + return adapter.onCreateViewHolder(parent, viewType); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (position != 0) { + adapter.onBindViewHolder(holder, position - 1); + } + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return -1000; + } + return adapter.getItemViewType(position - 1); + } + + @Override + public int getItemCount() { + return 1 + adapter.getItemCount(); + } + }); + } + private void postDrawInternal(Canvas canvas, View parentView) { if (showShadow && shadowAlpha != 1f) { shadowAlpha += 16 / 150f; @@ -266,13 +269,21 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); - shadowDrawable.setBounds(0, top, parent.getMeasuredWidth(), parent.getMeasuredHeight()); + if (needPaddingShadow()) { + shadowDrawable.setBounds(0, top, parent.getMeasuredWidth(), parent.getMeasuredHeight()); + } else { + shadowDrawable.setBounds(-AndroidUtilities.dp(6), top, parent.getMeasuredWidth() + AndroidUtilities.dp(6), parent.getMeasuredHeight()); + } shadowDrawable.draw(canvas); onPreDraw(canvas, top, progressToFullView); } } + protected boolean needPaddingShadow() { + return true; + } + protected void onPreMeasure(int widthMeasureSpec, int heightMeasureSpec) { } @@ -282,7 +293,7 @@ public abstract class BottomSheetWithRecyclerListView extends BottomSheet { } private boolean isLightStatusBar() { - return ColorUtils.calculateLuminance(Theme.getColor(Theme.key_dialogBackground)) > 0.7f; + return ColorUtils.calculateLuminance(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)) > 0.7f; } public void onViewCreated(FrameLayout containerView) { 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 9c44539de..9fdc90d95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -604,6 +604,14 @@ public class Bulletin { return 0; } + default int getLeftPadding() { + return 0; + } + + default int getRightPadding() { + return 0; + } + default int getTopOffset(int tag) { return 0; } @@ -1011,7 +1019,7 @@ public class Bulletin { if (bulletin == null) { return; } - background.setBounds(AndroidUtilities.dp(8), AndroidUtilities.dp(8), getMeasuredWidth() - AndroidUtilities.dp(8), getMeasuredHeight() - AndroidUtilities.dp(8)); + background.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom()); if (isTransitionRunning() && delegate != null) { final float top = delegate.getTopOffset(bulletin.tag) - getY(); final float bottom = ((View) getParent()).getMeasuredHeight() - getBottomOffset() - getY(); 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 b0da22c3a..7f1f91282 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -176,8 +176,12 @@ public final class BulletinFactory { } public Bulletin createSimpleBulletin(int iconRawId, CharSequence text) { + return createSimpleBulletinWithIconSize(iconRawId, text, 36); + } + + public Bulletin createSimpleBulletinWithIconSize(int iconRawId, CharSequence text, int iconSize) { final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); - layout.setAnimation(iconRawId, 36, 36); + layout.setAnimation(iconRawId, iconSize, iconSize); layout.textView.setText(text); layout.textView.setSingleLine(false); layout.textView.setMaxLines(2); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonBounce.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonBounce.java index a2c44ec1a..7852b1cb2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonBounce.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ButtonBounce.java @@ -17,9 +17,7 @@ public class ButtonBounce { private long releaseDelay = 0; public ButtonBounce(View viewToInvalidate) { - view = viewToInvalidate; - durationPressMultiplier = durationReleaseMultiplier = 1f; - overshoot = 5.0f; + this(viewToInvalidate, 1f, 5.0f); } public ButtonBounce(View viewToInvalidate, float durationMultiplier, float overshoot) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java index f1fac0839..49e6efbbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CacheChart.java @@ -21,6 +21,7 @@ import android.graphics.RectF; import android.graphics.Shader; import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -649,7 +650,7 @@ public class CacheChart extends View { AndroidUtilities.roundPercents(tempFloat, tempPercents); if (type == TYPE_CACHE) { // putting "other" section to being the first one Arrays.sort(segments, (a, b) -> Long.compare(a.size, b.size)); - for (int i = 0; i < segments.length - 1; ++i) { + for (int i = 0; i <= segments.length; ++i) { if (segments[i].index == segments.length - 1) { int from = i, to = 0; SegmentSize temp = segments[to]; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CaptionPhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CaptionPhotoViewer.java index 630edd712..94e70a055 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CaptionPhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CaptionPhotoViewer.java @@ -46,6 +46,11 @@ public class CaptionPhotoViewer extends CaptionContainerView { private final HintView2 hint; private final Runnable applyCaption; + @Override + protected int getEditTextStyle() { + return EditTextEmoji.STYLE_PHOTOVIEWER; + } + public CaptionPhotoViewer(Context context, FrameLayout rootView, SizeNotifierFrameLayout sizeNotifierFrameLayout, FrameLayout containerView, Theme.ResourcesProvider resourcesProvider, BlurringShader.BlurManager blurManager, Runnable applyCaption) { super(context, rootView, sizeNotifierFrameLayout, containerView, resourcesProvider, blurManager); this.applyCaption = applyCaption; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityBotWebViewButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityBotWebViewButton.java index 4b52b1fb9..76cadd18e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityBotWebViewButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityBotWebViewButton.java @@ -69,7 +69,7 @@ public class ChatActivityBotWebViewButton extends FrameLayout { textView.setText(text); textView.setTextColor(textColor); buttonColor = color; - + backgroundColor = ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_messagePanelVoiceBackground), buttonColor, progress); rippleView.setBackground(Theme.createSelectorDrawable(BotWebViewContainer.getMainButtonRippleColor(buttonColor), 2)); invalidate(); 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 8323c5588..4e56c0ae3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -8,6 +8,8 @@ package org.telegram.ui.Components; +import static org.telegram.ui.LaunchActivity.getLastFragment; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -28,14 +30,17 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; +import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.media.AudioManager; import android.net.Uri; @@ -54,7 +59,9 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; +import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.ActionMode; @@ -105,8 +112,10 @@ import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; +import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; @@ -136,6 +145,7 @@ import org.telegram.messenger.fakepasscode.RemoveAfterReadingMessages; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; @@ -216,7 +226,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific void needSendTyping(); - void onTextChanged(CharSequence text, boolean bigChange); + void onTextChanged(CharSequence text, boolean bigChange, boolean fromDraft); void onTextSelectionChanged(int start, int end); @@ -304,7 +314,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return null; } - default TLRPC.StoryItem getReplyToStory() { + default TL_stories.StoryItem getReplyToStory() { + return null; + } + + default ChatActivity.ReplyQuote getReplyQuote() { return null; } @@ -456,6 +470,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private ChatActivityEnterViewAnimatedIconView emojiButton; @Nullable private ImageView expandStickersButton; + private boolean emojiViewFrozen; private EmojiView emojiView; private AnimatorSet panelAnimation; private boolean emojiViewVisible; @@ -492,7 +507,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private ImageView botButton; @Nullable private ImageView reactionsButton; - private FrameLayout messageEditTextContainer; + protected FrameLayout messageEditTextContainer; private FrameLayout textFieldContainer; private FrameLayout sendButtonContainer; @Nullable @@ -589,6 +604,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private boolean ignoreTextChange; private int innerTextChange; private MessageObject replyingMessageObject; + private ChatActivity.ReplyQuote replyingQuote; private MessageObject botMessageObject; private TLRPC.WebPage messageWebPage; private boolean messageWebPageSearch = true; @@ -769,16 +785,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } } else { - if (parentFragment != null) { - if (Build.VERSION.SDK_INT >= 23 && parentActivity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { - parentActivity.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 3); - return; - } + if (Build.VERSION.SDK_INT >= 23 && parentActivity.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { + parentActivity.requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO}, 3); + return; } delegate.needStartRecordAudio(1); startedDraggingX = -1; - TLRPC.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; + TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, recordingGuid, true); recordingAudioVideo = true; updateRecordInterface(RECORD_STATE_ENTER); @@ -1985,14 +1999,62 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } + private final Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final LinearGradient clipGradient = new LinearGradient(0, 0, 0, 16, new int[] { 0xffffffff, 0x00ffffff }, new float[] { 0, 1 }, Shader.TileMode.CLAMP); + private final Matrix clipMatrix = new Matrix(); + private final AnimatedFloat topGradientAlpha = new AnimatedFloat(this, 0, 280, CubicBezierInterpolator.EASE_OUT_QUINT); + private final AnimatedFloat bottomGradientAlpha = new AnimatedFloat(this, 0, 280, CubicBezierInterpolator.EASE_OUT_QUINT); + { + gradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + gradientPaint.setShader(clipGradient); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child == messageEditText) { + if (child != null && child == messageEditText) { + float topAlpha = topGradientAlpha.set(messageEditText.canScrollVertically(-1)); + float bottomAlpha = bottomGradientAlpha.set(messageEditText.canScrollVertically(1)); + if (topAlpha <= 0 && bottomAlpha <= 0) { + return super.drawChild(canvas, child, drawingTime); + } + canvas.saveLayerAlpha(0, 0, messageEditText.getX() + messageEditText.getMeasuredWidth() + AndroidUtilities.dp(5), messageEditText.getY() + messageEditText.getMeasuredHeight() + AndroidUtilities.dp(2), 0xFF, Canvas.ALL_SAVE_FLAG); + final boolean result = super.drawChild(canvas, child, drawingTime); canvas.save(); - canvas.clipRect(0, -getTop() - textFieldContainer.getTop() - ChatActivityEnterView.this.getTop(), getMeasuredWidth(), getMeasuredHeight() - AndroidUtilities.dp(6)); - boolean rez = super.drawChild(canvas, child, drawingTime); + + if (topAlpha > 0) { + AndroidUtilities.rectTmp.set( + messageEditText.getX() - AndroidUtilities.dp(5), + messageEditText.getY() + animatedTop, + messageEditText.getX() + messageEditText.getMeasuredWidth() + AndroidUtilities.dp(5), + messageEditText.getY() + animatedTop + AndroidUtilities.dp(13) + ); + clipMatrix.reset(); + clipMatrix.postScale(1f, AndroidUtilities.rectTmp.height() / 16f); + clipMatrix.postTranslate(AndroidUtilities.rectTmp.left, AndroidUtilities.rectTmp.top); + clipGradient.setLocalMatrix(clipMatrix); + gradientPaint.setAlpha((int) (0xFF * topAlpha)); + canvas.drawRect(AndroidUtilities.rectTmp, gradientPaint); + } + + if (bottomAlpha > 0) { + AndroidUtilities.rectTmp.set( + messageEditText.getX() - AndroidUtilities.dp(5), + messageEditText.getY() + messageEditText.getMeasuredHeight() - AndroidUtilities.dp(13 + 2), + messageEditText.getX() + messageEditText.getMeasuredWidth() + AndroidUtilities.dp(5), + messageEditText.getY() + messageEditText.getMeasuredHeight() + AndroidUtilities.dp(2) + ); + clipMatrix.reset(); + clipMatrix.postScale(1f, AndroidUtilities.rectTmp.height() / 16f); + clipMatrix.postRotate(180); + clipMatrix.postTranslate(AndroidUtilities.rectTmp.left, AndroidUtilities.rectTmp.bottom); + clipGradient.setLocalMatrix(clipMatrix); + gradientPaint.setAlpha((int) (0xFF * bottomAlpha)); + canvas.drawRect(AndroidUtilities.rectTmp, gradientPaint); + } + canvas.restore(); - return rez; + canvas.restore(); + return result; } if (shouldDrawRecordedAudioPanelInParent && child == recordedAudioPanel) { return true; @@ -3436,7 +3498,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), parentFragment.getResourceProvider()); webViewSheet.setParentActivity(parentActivity); webViewSheet.requestWebView(currentAccount, dialog_id, dialog_id, botMenuWebViewTitle, botMenuWebViewUrl, BotWebViewSheet.TYPE_BOT_MENU_BUTTON, 0, false); - webViewSheet.show(); + BaseFragment lastFragment = getLastFragment(); + if (lastFragment != null) { + lastFragment.showDialog(webViewSheet); + } else { + webViewSheet.show(); + } if (botCommandsMenuButton != null) { botCommandsMenuButton.setOpened(false); @@ -3905,11 +3972,15 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } private void send(InputContentInfoCompat inputContentInfo, boolean notify, int scheduleDate) { + if (replyingQuote != null && parentFragment != null && replyingQuote.outdated) { + parentFragment.showQuoteMessageUpdate(); + return; + } ClipDescription description = inputContentInfo.getDescription(); if (description.hasMimeType("image/gif")) { - SendMessagesHelper.prepareSendingDocument(accountInstance, null, null, inputContentInfo.getContentUri(), null, "image/gif", dialog_id, replyingMessageObject, getThreadMessage(), null, null, notify, 0, inputContentInfo); + SendMessagesHelper.prepareSendingDocument(accountInstance, null, null, inputContentInfo.getContentUri(), null, "image/gif", dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, null, notify, 0, inputContentInfo); } else { - SendMessagesHelper.prepareSendingPhoto(accountInstance, null, inputContentInfo.getContentUri(), dialog_id, replyingMessageObject, getThreadMessage(), null, null, null, inputContentInfo, 0, null, notify, 0); + SendMessagesHelper.prepareSendingPhoto(accountInstance, null, inputContentInfo.getContentUri(), dialog_id, replyingMessageObject, getThreadMessage(), replyingQuote, null, null, null, inputContentInfo, 0, null, notify, 0); } if (delegate != null) { delegate.onMessageSend(null, true, scheduleDate); @@ -4096,6 +4167,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific boolean sending; @Override public void sendButtonPressed(int index, VideoEditedInfo videoEditedInfo, boolean notify, int scheduleDate, boolean forceDocument) { + if (replyingQuote != null && parentFragment != null && replyingQuote.outdated) { + parentFragment.showQuoteMessageUpdate(); + return; + } ArrayList photos = new ArrayList<>(); SendMessagesHelper.SendingMediaInfo info = new SendMessagesHelper.SendingMediaInfo(); if (!photoEntry.isVideo && photoEntry.imagePath != null) { @@ -4115,7 +4190,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific photoEntry.reset(); sending = true; boolean updateStickersOrder = SendMessagesHelper.checkUpdateStickersOrder(info.caption); - SendMessagesHelper.prepareSendingMedia(accountInstance, photos, dialog_id, replyingMessageObject, getThreadMessage(), null, false, false, editingMessageObject, notify, scheduleDate, updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(accountInstance, photos, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, false, false, editingMessageObject, notify, scheduleDate, updateStickersOrder, null); if (delegate != null) { delegate.onMessageSend(null, true, scheduleDate); } @@ -4179,17 +4254,74 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return; } - messageEditText = new ChatActivityEditTextCaption(getContext(), resourcesProvider); + messageEditText = new ChatActivityEditTextCaption(getContext(), resourcesProvider) { + + float touchX, touchY; + boolean clickMaybe; + @Override + public boolean onTouchEvent(MotionEvent event) { + if (botCommandsMenuIsShowing()) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + touchX = event.getX(); + touchY = event.getY(); + clickMaybe = true; + } else if (clickMaybe && event.getAction() == MotionEvent.ACTION_MOVE) { + if (Math.abs(event.getX() - touchX) > AndroidUtilities.touchSlop || Math.abs(event.getY() - touchY) > AndroidUtilities.touchSlop) { + clickMaybe = false; + } + } else { + if (clickMaybe) { + if (delegate != null) { + delegate.onKeyboardRequested(); + } + if (messageEditText != null && !AndroidUtilities.showKeyboard(messageEditText)) { + messageEditText.clearFocus(); + messageEditText.requestFocus(); + } + } + } + return clickMaybe; + } else { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (delegate != null) { + delegate.onKeyboardRequested(); + } + } + return super.onTouchEvent(event); + } + } + + @Override + public void setOffsetY(float offset) { + super.setOffsetY(offset); + messageEditTextContainer.invalidate(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (parentFragment != null && parentFragment.getParentLayout() != null && parentFragment.getParentLayout().isSheet()) { + setWindowView(parentFragment.getParentLayout().getWindow().getDecorView()); + } else { + setWindowView(parentActivity.getWindow().getDecorView()); + } + } + }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { messageEditText.setFallbackLineSpacing(false); } + messageEditText.wrapCanvasToFixClipping = true; messageEditText.setDelegate(() -> { messageEditText.invalidateEffects(); if (delegate != null) { delegate.onTextSpansChanged(messageEditText.getText()); } }); - messageEditText.setWindowView(parentActivity.getWindow().getDecorView()); + if (parentFragment != null && parentFragment.getParentLayout() != null && parentFragment.getParentLayout().isSheet()) { + messageEditText.setWindowView(parentFragment.getParentLayout().getWindow().getDecorView()); + } else { + messageEditText.setWindowView(parentActivity.getWindow().getDecorView()); + } TLRPC.EncryptedChat encryptedChat = parentFragment != null ? parentFragment.getCurrentEncryptedChat() : null; messageEditText.setAllowTextEntitiesIntersection(supportsSendingNewEntities()); int flags = EditorInfo.IME_FLAG_NO_EXTRACT_UI; @@ -4344,7 +4476,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (before > count + 1 || (count - before) > 2 || TextUtils.isEmpty(charSequence)) { messageWebPageSearch = true; } - delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2); + delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2, false); } } if (innerTextChange != 2 && (count - before) > 1) { @@ -4380,7 +4512,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific for (int i = 0; i < spans.length; i++) { editable.removeSpan(spans[i]); } - Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false, null); + Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), false, null); processChange = false; } } @@ -4662,12 +4794,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private void showTopView(boolean animated, final boolean openKeyboard, boolean skipAwait) { if (topView == null || topViewShowed || getVisibility() != VISIBLE) { - if ((recordedAudioPanel == null || recordedAudioPanel.getVisibility() != VISIBLE) && (!forceShowSendButton || openKeyboard)) { + if ((recordedAudioPanel == null || recordedAudioPanel.getVisibility() != VISIBLE) && (!forceShowSendButton && (replyingQuote == null && replyingMessageObject == null) || openKeyboard)) { openKeyboard(); } return; } - boolean openKeyboardInternal = (recordedAudioPanel == null || recordedAudioPanel.getVisibility() != VISIBLE) && (!forceShowSendButton || openKeyboard) && (botReplyMarkup == null || editingMessageObject != null); + boolean openKeyboardInternal = (recordedAudioPanel == null || recordedAudioPanel.getVisibility() != VISIBLE) && (!forceShowSendButton && replyingQuote == null || openKeyboard) && (botReplyMarkup == null || editingMessageObject != null); if (!skipAwait && animated && openKeyboardInternal && !(keyboardVisible || isPopupShowing())) { openKeyboard(); if (showTopViewRunnable != null) { @@ -5290,23 +5422,26 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } - public void setReplyingMessageObject(MessageObject messageObject) { + public void setReplyingMessageObject(MessageObject messageObject, ChatActivity.ReplyQuote quote) { if (messageObject != null) { if (botMessageObject == null && botButtonsMessageObject != replyingMessageObject) { botMessageObject = botButtonsMessageObject; } replyingMessageObject = messageObject; + replyingQuote = quote; if (!(parentFragment != null && parentFragment.isTopic && parentFragment.getThreadMessage() == replyingMessageObject)) { setButtons(replyingMessageObject, true); } } else if (replyingMessageObject == botButtonsMessageObject) { replyingMessageObject = null; + replyingQuote = null; setButtons(botMessageObject, false); botMessageObject = null; } else { replyingMessageObject = null; + replyingQuote = null; } - TLRPC.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; + TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; MediaController.getInstance().setReplyingMessage(messageObject, getThreadMessage(), storyItem); updateFieldHint(false); } @@ -5797,17 +5932,47 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific text = AndroidUtilities.getTrimmedString(text); } CharSequence[] message = new CharSequence[]{text}; + if (TextUtils.isEmpty(message[0]) && (editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage || editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaEmpty || editingMessageObject.messageOwner.media == null)) { + AndroidUtilities.shakeViewSpring(messageEditText, -3); + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + return; + } ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(message, supportsSendingNewEntities()); if (!TextUtils.equals(message[0], editingMessageObject.messageText) || entities != null && !entities.isEmpty() || !editingMessageObject.messageOwner.entities.isEmpty() || editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { editingMessageObject.editingMessage = message[0]; editingMessageObject.editingMessageEntities = entities; editingMessageObject.editingMessageSearchWebPage = messageWebPageSearch; + if (parentFragment != null && parentFragment.messagePreviewParams != null) { + if (parentFragment.foundWebPage instanceof TLRPC.TL_webPagePending) { + editingMessageObject.editingMessageSearchWebPage = true; + } else if (parentFragment.messagePreviewParams.webpage != null) { + editingMessageObject.editingMessageSearchWebPage = false; + editingMessageObject.messageOwner.media = new TLRPC.TL_messageMediaWebPage(); + editingMessageObject.messageOwner.media.flags |= 512; + editingMessageObject.messageOwner.media.webpage = parentFragment.messagePreviewParams.webpage; + } else { + editingMessageObject.editingMessageSearchWebPage = false; + if (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS) { + editingMessageObject.messageOwner.media = new TLRPC.TL_messageMediaEmpty(); + editingMessageObject.messageOwner.media.flags |= 512; + } + } + editingMessageObject.messageOwner.invert_media = parentFragment.messagePreviewParams.webpageTop; + if (parentFragment.messagePreviewParams.hasMedia && editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) { + editingMessageObject.messageOwner.media.force_small_media = parentFragment.messagePreviewParams.webpageSmall; + editingMessageObject.messageOwner.media.force_large_media = !parentFragment.messagePreviewParams.webpageSmall; + } + } SendMessagesHelper.getInstance(currentAccount).editMessage(editingMessageObject, null, null, null, null, null, false, editingMessageObject.hasMediaSpoilers(), null); } setEditingMessageObject(null, false); } public boolean processSendingText(CharSequence text, boolean notify, int scheduleDate, Integer autoDeleteDelay) { + if (replyingQuote != null && parentFragment != null && replyingQuote.outdated) { + parentFragment.showQuoteMessageUpdate(); + return false; + } int[] emojiOnly = new int[1]; Emoji.parseEmojis(text, emojiOnly); boolean hasOnlyEmoji = emojiOnly[0] > 0; @@ -5882,9 +6047,29 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific boolean updateStickersOrder = false; updateStickersOrder = SendMessagesHelper.checkUpdateStickersOrder(text); - - SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message[0].toString(), dialog_id, replyingMessageObject, getThreadMessage(), messageWebPage, messageWebPageSearch, entities, null, null, notify, scheduleDate, sendAnimationData, updateStickersOrder, autoDeleteDelay); + MessageObject replyToTopMsg = getThreadMessage(); +// if (parentFragment != null && parentFragment.replyingTopMessage != null) { +// replyToTopMsg = parentFragment.replyingTopMessage; +// } + SendMessagesHelper.SendMessageParams params = SendMessagesHelper.SendMessageParams.of(message[0].toString(), dialog_id, replyingMessageObject, replyToTopMsg, messageWebPage, messageWebPageSearch, entities, null, null, notify, scheduleDate, sendAnimationData, updateStickersOrder, autoDeleteDelay); applyStoryToSendMessageParams(params); + params.invert_media = parentFragment != null && parentFragment.messagePreviewParams != null && parentFragment.messagePreviewParams.webpageTop; + if (messageWebPage != null) { + params.mediaWebPage = new TLRPC.TL_messageMediaWebPage(); + params.mediaWebPage.webpage = messageWebPage; + params.mediaWebPage.force_large_media = parentFragment != null && parentFragment.messagePreviewParams != null && !parentFragment.messagePreviewParams.webpageSmall; + params.mediaWebPage.force_small_media = parentFragment != null && parentFragment.messagePreviewParams != null && parentFragment.messagePreviewParams.webpageSmall; + + if (parentFragment != null) { + parentFragment.editingMessageObject = null; + parentFragment.foundWebPage = null; + if (parentFragment.messagePreviewParams != null) { + parentFragment.messagePreviewParams.updateLink(currentAccount, null, "", null, null, null); + } + setWebPage(null, true); + parentFragment.fallbackFieldPanel(); + } + } SendMessagesHelper.getInstance(currentAccount).sendMessage(params); start = end + 1; } while (end != text.length()); @@ -5900,6 +6085,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private void applyStoryToSendMessageParams(SendMessagesHelper.SendMessageParams params) { if (delegate != null) { params.replyToStoryItem = delegate.getReplyToStory(); + params.replyQuote = delegate.getReplyQuote(); } } @@ -7425,7 +7611,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageEditText.setSelection(messageEditText.getText().length()); ignoreTextChange = false; if (delegate != null) { - delegate.onTextChanged(messageEditText.getText(), true); + delegate.onTextChanged(messageEditText.getText(), true, false); } if (!keyboardVisible && currentPopupContentType == -1) { openKeyboard(); @@ -7516,10 +7702,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific entity.length++; } stringBuilder.setSpan(new URLSpanUserMention("" + ((TLRPC.TL_messageEntityMentionName) entity).user_id, 3), entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } else if (entity instanceof TLRPC.TL_messageEntityCode || entity instanceof TLRPC.TL_messageEntityPre) { + } else if (entity instanceof TLRPC.TL_messageEntityCode) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_MONO; MediaDataController.addStyleToText(new TextStyleSpan(run), entity.offset, entity.offset + entity.length, stringBuilder, true); + } else if (entity instanceof TLRPC.TL_messageEntityPre) { + continue; } else if (entity instanceof TLRPC.TL_messageEntityBold) { TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); run.flags |= TextStyleSpan.FLAG_STYLE_BOLD; @@ -7551,13 +7739,38 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific span = new AnimatedEmojiSpan(emojiEntity.document_id, fontMetricsInt); } stringBuilder.setSpan(span, entity.offset, entity.offset + entity.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (entity instanceof TLRPC.TL_messageEntityBlockquote) { + QuoteSpan.putQuoteToEditable(stringBuilder, entity.offset, entity.offset + entity.length); + } + } + } catch (Exception e) { + FileLog.e(e); + } + } + textToSetWithKeyboard = Emoji.replaceEmoji(new SpannableStringBuilder(stringBuilder), fontMetricsInt, false, null); + if (entities != null) { + try { + for (int a = entities.size() - 1; a >= 0; --a) { + TLRPC.MessageEntity entity = entities.get(a); + if (entity instanceof TLRPC.TL_messageEntityPre && entity.offset + entity.length <= textToSetWithKeyboard.length()) { + if (!(textToSetWithKeyboard instanceof Spannable)) { + textToSetWithKeyboard = new SpannableStringBuilder(textToSetWithKeyboard); + } +// CodeHighlighting.highlight((Spannable) textToSetWithKeyboard, entity.offset, entity.offset + entity.length, entity.language, 0, null, false); +// ((Spannable) textToSetWithKeyboard).setSpan( +// new CodeHighlighting.Span(false, 0, null, entity.language, textToSetWithKeyboard.subSequence(entity.offset, entity.offset + entity.length).toString(), false, false, entity.offset, entity.offset + entity.length), +// entity.offset, +// entity.offset + entity.length, +// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE +// ); + ((SpannableStringBuilder) textToSetWithKeyboard).insert(entity.offset + entity.length, "```\n"); + ((SpannableStringBuilder) textToSetWithKeyboard).insert(entity.offset, "```"+(entity.language == null ? "" : entity.language)+"\n"); } } } catch (Exception e) { FileLog.e(e); } } - textToSetWithKeyboard = Emoji.replaceEmoji(new SpannableStringBuilder(stringBuilder), fontMetricsInt, AndroidUtilities.dp(20), false, null); } else { textToSetWithKeyboard = ""; } @@ -7565,10 +7778,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific draftMessage = messageEditText != null && messageEditText.length() > 0 ? messageEditText.getText() : null; draftSearchWebpage = messageWebPageSearch; } - messageWebPageSearch = editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage; + messageWebPageSearch = !(editingMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && editingMessageObject.messageOwner.media.manual) && (editingMessageObject.type == MessageObject.TYPE_TEXT || editingMessageObject.type == MessageObject.TYPE_EMOJIS); if (!keyboardVisible) { + final CharSequence textToSetWithKeyboardFinal = textToSetWithKeyboard; AndroidUtilities.runOnUIThread(setTextFieldRunnable = () -> { - setFieldText(textToSetWithKeyboard); + setFieldText(textToSetWithKeyboardFinal); setTextFieldRunnable = null; }, 200); } else { @@ -7664,6 +7878,15 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific scheduledButton.setAlpha(1.0f); scheduledButton.setVisibility(VISIBLE); } + if (parentFragment != null) { + parentFragment.editingMessageObject = null; + parentFragment.foundWebPage = null; + if (parentFragment.messagePreviewParams != null) { + parentFragment.messagePreviewParams.updateLink(currentAccount, null, "", null, null, null); + } + setWebPage(null, true); + parentFragment.fallbackFieldPanel(); + } createMessageEditText(); if (messageEditText != null) { messageEditText.setText(draftMessage); @@ -7781,10 +8004,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } public void setFieldText(CharSequence text) { - setFieldText(text, true); + setFieldText(text, true, false); } public void setFieldText(CharSequence text, boolean ignoreChange) { + setFieldText(text, ignoreChange, false); + } + + public void setFieldText(CharSequence text, boolean ignoreChange, boolean fromDraft) { if (messageEditText == null) { return; } @@ -7793,7 +8020,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageEditText.setSelection(messageEditText.getText().length()); ignoreTextChange = false; if (ignoreChange && delegate != null) { - delegate.onTextChanged(messageEditText.getText(), true); + delegate.onTextChanged(messageEditText.getText(), true, fromDraft); } } @@ -7831,7 +8058,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific SpannableStringBuilder builder = new SpannableStringBuilder(messageEditText.getText()); builder.replace(start, start + len, text); if (parseEmoji) { - Emoji.replaceEmoji(builder, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + Emoji.replaceEmoji(builder, messageEditText.getPaint().getFontMetricsInt(), false, null); } messageEditText.setText(builder); messageEditText.setSelection(start + text.length()); @@ -8392,7 +8619,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific BotWebViewSheet webViewSheet = new BotWebViewSheet(getContext(), resourcesProvider); webViewSheet.setParentActivity(parentActivity); webViewSheet.requestWebView(currentAccount, messageObject.messageOwner.dialog_id, botId, button.text, button.url, button instanceof TLRPC.TL_keyboardButtonSimpleWebView ? BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON : BotWebViewSheet.TYPE_WEB_VIEW_BUTTON, replyMessageObject != null ? replyMessageObject.messageOwner.id : 0, false); - webViewSheet.show(); + BaseFragment lastFragment = getLastFragment(); + if (lastFragment != null) { + lastFragment.showDialog(webViewSheet); + } else { + webViewSheet.show(); + } } }; if (SharedPrefsHelper.isWebViewConfirmShown(currentAccount, botId)) { @@ -8579,7 +8811,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (emojiView != null) { return; } - emojiView = new EmojiView(parentFragment, allowAnimatedEmoji, true, true, getContext(), true, info, sizeNotifierLayout, shouldDrawBackground, resourcesProvider) { + emojiView = new EmojiView(parentFragment, allowAnimatedEmoji, true, true, getContext(), true, info, sizeNotifierLayout, shouldDrawBackground, resourcesProvider, emojiViewFrozen) { @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); @@ -8621,7 +8853,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } try { innerTextChange = 2; - CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), false, null); messageEditText.setText(messageEditText.getText().insert(i, localCharSequence)); int j = i + localCharSequence.length(); messageEditText.setSelection(j, j); @@ -8669,7 +8901,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific public void onAnimatedEmojiUnlockClick() { BaseFragment fragment = parentFragment; if (fragment == null) { - fragment = LaunchActivity.getLastFragment(); + fragment = getLastFragment(); } BottomSheet alert = new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_EMOJI, false); if (fragment != null) { @@ -8721,6 +8953,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific @Override public void onGifSelected(View view, Object gif, String query, Object parent, boolean notify, int scheduleDate) { + if (replyingQuote != null && parentFragment != null && replyingQuote.outdated) { + parentFragment.showQuoteMessageUpdate(); + return; + } if (isInScheduleMode() && scheduleDate == 0) { AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (n, s) -> onGifSelected(view, gif, query, parent, n, s), resourcesProvider); } else { @@ -8738,10 +8974,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } setStickersExpanded(false, true, false); } - TLRPC.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; + TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; if (gif instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) gif; - SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, null, notify, scheduleDate, false, parent); + SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, replyingQuote, null, notify, scheduleDate, false, parent); MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000), true); if (DialogObject.isEncryptedDialog(dialog_id)) { accountInstance.getMessagesController().saveGif(parent, document); @@ -8764,9 +9000,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific params.put("force_gif", "1"); if (storyItem == null) { - SendMessagesHelper.prepareSendingBotContextResult(parentFragment, accountInstance, result, params, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, notify, scheduleDate); + SendMessagesHelper.prepareSendingBotContextResult(parentFragment, accountInstance, result, params, dialog_id, replyingMessageObject, getThreadMessage(), null, replyingQuote, notify, scheduleDate); } else { - SendMessagesHelper.getInstance(currentAccount).sendSticker(result.document, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, null, notify, scheduleDate, false, parent); + SendMessagesHelper.getInstance(currentAccount).sendSticker(result.document, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, replyingQuote, null, notify, scheduleDate, false, parent); } if (searchingType != 0) { setSearchingTypeInternal(0, true); @@ -8811,7 +9047,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } BaseFragment fragment = parentFragment; if (fragment == null) { - fragment = LaunchActivity.getLastFragment(); + fragment = getLastFragment(); } if (fragment == null || parentActivity == null) { return; @@ -8891,7 +9127,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific public void showTrendingStickersAlert(TrendingStickersLayout layout) { BaseFragment fragment = parentFragment; if (fragment == null) { - fragment = LaunchActivity.getLastFragment(); + fragment = getLastFragment(); } if (fragment != null) { trendingStickersAlert = new TrendingStickersAlert(getContext(), fragment, layout, resourcesProvider) { @@ -9002,6 +9238,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific @Override public void onStickerSelected(TLRPC.Document sticker, String query, Object parent, MessageObject.SendAnimationData sendAnimationData, boolean clearsInputField, boolean notify, int scheduleDate) { + if (replyingQuote != null && parentFragment != null && replyingQuote.outdated) { + parentFragment.showQuoteMessageUpdate(); + return; + } if (isInScheduleMode() && scheduleDate == 0) { AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (n, s) -> onStickerSelected(sticker, query, parent, sendAnimationData, clearsInputField, n, s), resourcesProvider); } else { @@ -9018,8 +9258,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific emojiView.hideSearchKeyboard(); } setStickersExpanded(false, true, false); - TLRPC.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; - SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, sendAnimationData, notify, scheduleDate, parent instanceof TLRPC.TL_messages_stickerSet, parent); + TL_stories.StoryItem storyItem = delegate != null ? delegate.getReplyToStory() : null; + SendMessagesHelper.getInstance(currentAccount).sendSticker(sticker, query, dialog_id, replyingMessageObject, getThreadMessage(), storyItem, replyingQuote, sendAnimationData, notify, scheduleDate, parent instanceof TLRPC.TL_messages_stickerSet, parent); if (delegate != null) { delegate.onMessageSend(null, true, scheduleDate); } @@ -9447,7 +9687,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific this.searchingType = searchingType; } - private void openKeyboardInternal() { + public void openKeyboardInternal() { if (hasBotWebView() && botCommandsMenuIsShowing()) { return; } @@ -10866,11 +11106,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } private int getThemedColor(int key) { - if (resourcesProvider != null) { - return resourcesProvider.getColor(key); + if (resourcesProvider != null) { + return resourcesProvider.getColor(key); + } + return Theme.getColor(key); } - return Theme.getColor(key); -} private Paint getThemedPaint(String paintKey) { Paint paint = resourcesProvider != null ? resourcesProvider.getPaint(paintKey) : null; @@ -11009,4 +11249,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific COMMANDS, WEB_VIEW } + + public void freezeEmojiView(boolean freeze) { + emojiViewFrozen = freeze; + if (emojiView != null) { + emojiView.freeze(freeze); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java index 90b7b172f..11778a10b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -116,6 +116,7 @@ import org.telegram.ui.PhotoPickerSearchActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.DarkThemeResourceProvider; import org.telegram.ui.Stories.recorder.CaptionContainerView; +import org.telegram.ui.WebAppDisclaimerAlert; import java.io.File; import java.util.ArrayList; @@ -401,9 +402,16 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), visible ? R.drawable.ic_ab_back : R.drawable.ic_close_white); } + @Override + public void onSetSettingsButtonVisible(boolean visible) { + if (webViewLayout.settingsItem != null) { + webViewLayout.settingsItem.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + @Override public boolean isClipboardAvailable() { - return true; + return MediaDataController.getInstance(currentAccount).botInAttachMenu(id); } }); MessageObject replyingObject = ((ChatActivity) baseFragment).getChatActivityEnterView().getReplyingMessageObject(); @@ -2251,7 +2259,21 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } else if (view instanceof AttachBotButton) { AttachBotButton button = (AttachBotButton) view; if (button.attachMenuBot != null) { - showBotLayout(button.attachMenuBot.bot_id, true); + if (button.attachMenuBot.inactive) { + WebAppDisclaimerAlert.show(getContext(), (allowSendMessage) -> { + TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); + botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(button.attachMenuBot.bot_id); + botRequest.enabled = true; + botRequest.write_allowed = true; + ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { + button.attachMenuBot.inactive = button.attachMenuBot.side_menu_disclaimer_needed = false; + showBotLayout(button.attachMenuBot.bot_id, true); + MediaDataController.getInstance(currentAccount).updateAttachMenuBotsInCache(); + }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); + }, null); + } else { + showBotLayout(button.attachMenuBot.bot_id, true); + } } else { delegate.didSelectBot(button.currentUser); dismiss(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java index 9c22d68fd..168f5d70c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java @@ -32,7 +32,6 @@ import androidx.recyclerview.widget.ChatListItemAnimator; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; -import org.telegram.messenger.FileLog; import org.telegram.messenger.GenericProvider; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; @@ -72,7 +71,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private WebProgressView progressView; private WebViewSwipeContainer swipeContainer; private ActionBarMenuItem otherItem; - private ActionBarMenuSubItem settingsItem; + public ActionBarMenuSubItem settingsItem; private int measureOffsetY; @@ -95,7 +94,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert prolongWebView.query_id = queryId; prolongWebView.silent = silent; if (replyToMsgId != 0) { - prolongWebView.reply_to = SendMessagesHelper.creteReplyInput(replyToMsgId); + prolongWebView.reply_to = SendMessagesHelper.getInstance(currentAccount).createReplyInput(replyToMsgId); prolongWebView.flags |= 1; } @@ -125,6 +124,42 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private boolean hasCustomActionBarBackground; private int customActionBarBackground; + @Override + void onMenuItemClick(int id) { + if (id == -1) { + if (!webViewContainer.onBackPressed()) { + onCheckDismissByUser(); + } + } else if (id == R.id.menu_open_bot) { + Bundle bundle = new Bundle(); + bundle.putLong("user_id", botId); + parentAlert.baseFragment.presentFragment(new ChatActivity(bundle)); + parentAlert.dismiss(); + } else if (id == R.id.menu_reload_page) { + if (webViewContainer.getWebView() != null) { + webViewContainer.getWebView().animate().cancel(); + webViewContainer.getWebView().animate().alpha(0).start(); + } + + progressView.setLoadProgress(0); + progressView.setAlpha(1f); + progressView.setVisibility(VISIBLE); + + webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); + webViewContainer.reload(); + } else if (id == R.id.menu_delete_bot) { + for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) { + if (bot.bot_id == botId) { + parentAlert.onLongClickBotButton(bot, MessagesController.getInstance(currentAccount).getUser(botId)); + break; + } + } + } else if (id == R.id.menu_settings) { + webViewContainer.onSettingsButtonPressed(); + } + } + public ChatAttachAlertBotWebViewLayout(ChatAttachAlert alert, Context context, Theme.ResourcesProvider resourcesProvider) { super(alert, context, resourcesProvider); @@ -132,45 +167,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert otherItem = menu.addItem(0, R.drawable.ic_ab_other); otherItem.addSubItem(R.id.menu_open_bot, R.drawable.msg_bot, LocaleController.getString(R.string.BotWebViewOpenBot)); settingsItem = otherItem.addSubItem(R.id.menu_settings, R.drawable.msg_settings, LocaleController.getString(R.string.BotWebViewSettings)); + settingsItem.setVisibility(View.GONE); otherItem.addSubItem(R.id.menu_reload_page, R.drawable.msg_retry, LocaleController.getString(R.string.BotWebViewReloadPage)); otherItem.addSubItem(R.id.menu_delete_bot, R.drawable.msg_delete, LocaleController.getString(R.string.BotWebViewDeleteBot)); - parentAlert.actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { - @Override - public void onItemClick(int id) { - if (id == -1) { - if (!webViewContainer.onBackPressed()) { - onCheckDismissByUser(); - } - } else if (id == R.id.menu_open_bot) { - Bundle bundle = new Bundle(); - bundle.putLong("user_id", botId); - parentAlert.baseFragment.presentFragment(new ChatActivity(bundle)); - parentAlert.dismiss(); - } else if (id == R.id.menu_reload_page) { - if (webViewContainer.getWebView() != null) { - webViewContainer.getWebView().animate().cancel(); - webViewContainer.getWebView().animate().alpha(0).start(); - } - - progressView.setLoadProgress(0); - progressView.setAlpha(1f); - progressView.setVisibility(VISIBLE); - - webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); - webViewContainer.reload(); - } else if (id == R.id.menu_delete_bot) { - for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) { - if (bot.bot_id == botId) { - parentAlert.onLongClickBotButton(bot, MessagesController.getInstance(currentAccount).getUser(botId)); - break; - } - } - } else if (id == R.id.menu_settings) { - webViewContainer.onSettingsButtonPressed(); - } - } - }); webViewContainer = new BotWebViewContainer(context, resourcesProvider, getThemedColor(Theme.key_dialogBackground)) { @Override @@ -479,25 +478,15 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert } if (replyToMsgId != 0) { - req.reply_to = SendMessagesHelper.creteReplyInput(replyToMsgId); + req.reply_to = SendMessagesHelper.getInstance(currentAccount).createReplyInput(replyToMsgId); req.flags |= 1; } - try { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("bg_color", getThemedColor(Theme.key_dialogBackground)); - jsonObject.put("secondary_bg_color", getThemedColor(Theme.key_windowBackgroundGray)); - jsonObject.put("text_color", getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); - jsonObject.put("hint_color", getThemedColor(Theme.key_windowBackgroundWhiteHintText)); - jsonObject.put("link_color", getThemedColor(Theme.key_windowBackgroundWhiteLinkText)); - jsonObject.put("button_color", getThemedColor(Theme.key_featuredStickers_addButton)); - jsonObject.put("button_text_color", getThemedColor(Theme.key_featuredStickers_buttonText)); - + JSONObject theme_params = BotWebViewSheet.makeThemeParams(resourcesProvider); + if (theme_params != null) { req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = jsonObject.toString(); + req.theme_params.data = theme_params.toString(); req.flags |= 4; - } catch (Exception e) { - FileLog.e(e); } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java index baddb6750..a32bf9abf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -488,7 +488,9 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou if (o instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o; if (a == 0) { - photoEntry1.caption = PhotoViewer.getInstance().captionForAllMedia; + CharSequence[] caption = new CharSequence[] { PhotoViewer.getInstance().captionForAllMedia }; + photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(caption, false); + photoEntry1.caption = caption[0]; if (parentAlert.checkCaption(photoEntry1.caption)) { return; } @@ -1153,7 +1155,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou photoEntry.canDeleteAfter = true; openPhotoViewer(photoEntry, sameTakePictureOrientation, false); }); - cameraView.startTakePictureAnimation(); + cameraView.startTakePictureAnimation(true); } @@ -3150,16 +3152,24 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou void applyCaption(CharSequence text) { for (int a = 0; a < selectedPhotosOrder.size(); a++) { if (a == 0) { - Object o = selectedPhotos.get(selectedPhotosOrder.get(a)); + final Object key = selectedPhotosOrder.get(a); + Object o = selectedPhotos.get(key); if (o instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o; - photoEntry1.caption = text; - photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[]{text}, false); + photoEntry1 = photoEntry1.clone(); + CharSequence[] caption = new CharSequence[] { text }; + photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(caption, false); + photoEntry1.caption = caption[0]; + o = photoEntry1; } else if (o instanceof MediaController.SearchImage) { MediaController.SearchImage photoEntry1 = (MediaController.SearchImage) o; - photoEntry1.caption = text; - photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(new CharSequence[]{text}, false); + photoEntry1 = photoEntry1.clone(); + CharSequence[] caption = new CharSequence[] { text }; + photoEntry1.entities = MediaDataController.getInstance(UserConfig.selectedAccount).getEntities(caption, false); + photoEntry1.caption = caption[0]; + o = photoEntry1; } + selectedPhotos.put(key, o); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java index 83970d165..0e8a70926 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPollLayout.java @@ -943,7 +943,7 @@ public class ChatAttachAlertPollLayout extends ChatAttachAlert.AttachAlertLayout if (menu.findItem(android.R.id.copy) == null) { return; } - ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat()); + ChatActivity.fillActionModeMenu(menu, ((ChatActivity) parentAlert.baseFragment).getCurrentEncryptedChat(), true); } } }; 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 42c202803..9d9b0588a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -22,6 +22,7 @@ import android.os.Build; import android.os.Bundle; import android.text.TextUtils; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; @@ -52,7 +53,9 @@ import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.ProfileActivity; +import org.telegram.ui.Stories.StoriesListPlaceProvider; import org.telegram.ui.Stories.StoriesUtilities; +import org.telegram.ui.Stories.StoryViewer; import org.telegram.ui.TopicsFragment; import java.util.concurrent.atomic.AtomicReference; @@ -149,7 +152,21 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent final boolean avatarClickable = parentFragment != null && parentFragment.getChatMode() == 0 && !UserObject.isReplyUser(parentFragment.getCurrentUser()); avatarImageView = new BackupImageView(context) { - StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(true); + StoriesUtilities.AvatarStoryParams params = new StoriesUtilities.AvatarStoryParams(true) { + @Override + public void openStory(long dialogId, Runnable onDone) { + baseFragment.getOrCreateStoryViewer().open(getContext(), dialogId, (dialogId1, messageId, storyId, type, holder) -> { + holder.crossfadeToAvatarImage = holder.storyImage = imageReceiver; + holder.params = params; + holder.view = avatarImageView; + holder.alpha = avatarImageView.getAlpha(); + holder.clipTop = 0; + holder.clipBottom = AndroidUtilities.displaySize.y; + holder.clipParent = (View) getParent(); + return true; + }); + } + }; @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { @@ -176,6 +193,16 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent super.onDraw(canvas); } } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (allowDrawStories) { + if (params.checkOnTouchEvent(event, this)) { + return true; + } + } + return super.onTouchEvent(event); + } }; if (baseFragment instanceof ChatActivity || baseFragment instanceof TopicsFragment) { sharedMediaPreloader = new SharedMediaLayout.SharedMediaPreloader(baseFragment); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java index 8860a524e..cbcc69804 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -285,6 +285,9 @@ public class ClippingImageView extends View { bmp.release(); bitmapShader = null; } + if (bitmap != null && bitmap.isRecycled()) { + bitmap = null; + } bmp = bitmap; if (bitmap != null && bitmap.bitmap != null) { bitmapRect.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java index a8cb2bc9e..e8fd46939 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java @@ -34,6 +34,7 @@ public class ColoredImageSpan extends ReplacementSpan { public static final int ALIGN_BASELINE = 1; public static final int ALIGN_CENTER = 2; private final int verticalAlignment; + public float spaceScaleX = 1f; private float scaleX = 1f, scaleY = 1f; private Runnable checkColorDelegate; @@ -83,7 +84,7 @@ public class ColoredImageSpan extends ReplacementSpan { public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { if (sizeWidth != 0) return (int) (Math.abs(scaleX) * sizeWidth); - return (int) (Math.abs(scaleX) * (size != 0 ? size : drawable.getIntrinsicWidth())); + return (int) (Math.abs(scaleX) * Math.abs(spaceScaleX) * (size != 0 ? size : drawable.getIntrinsicWidth())); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java index c5e875976..e613baf67 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -31,11 +31,15 @@ import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; +import android.text.Editable; import android.text.Layout; +import android.text.Selection; +import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; import android.view.ActionMode; import android.view.Gravity; import android.view.Menu; @@ -47,6 +51,8 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.TextView; +import com.google.common.primitives.Chars; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; @@ -116,6 +122,7 @@ public class EditTextBoldCursor extends EditTextEffects { private float hintAlpha = 1.0f; private long hintLastUpdateTime; private boolean allowDrawCursor = true; + private boolean forceCursorEnd = false; private float cursorWidth = 2.0f; private boolean supportRtlHint; @@ -455,6 +462,11 @@ public class EditTextBoldCursor extends EditTextEffects { invalidate(); } + public void setForceCursorEnd(boolean cursorEnd) { + this.forceCursorEnd = cursorEnd; + invalidate(); + } + public void setCursorWidth(float width) { cursorWidth = width; } @@ -696,9 +708,6 @@ public class EditTextBoldCursor extends EditTextEffects { @Override public int getExtendedPaddingTop() { -// if (ignoreClipTop) { -// return 0; -// } if (ignoreTopCount != 0) { ignoreTopCount--; return 0; @@ -854,10 +863,10 @@ public class EditTextBoldCursor extends EditTextEffects { throw new RuntimeException(e); } } - ignoreTopCount = 1; - ignoreBottomCount = 1; +// ignoreTopCount = 1; +// ignoreBottomCount = 1; canvas.save(); - canvas.translate(0, topPadding); +// canvas.translate(0, topPadding); try { drawInMaim = true; super.onDraw(canvas); @@ -1024,7 +1033,7 @@ public class EditTextBoldCursor extends EditTextEffects { private boolean updateCursorPosition() { final Layout layout = getLayout(); - final int offset = getSelectionStart(); + final int offset = forceCursorEnd ? layout.getText().length() : getSelectionStart(); final int line = layout.getLineForOffset(offset); final int top = layout.getLineTop(line); final int bottom = layout.getLineTop(line + 1); @@ -1112,6 +1121,7 @@ public class EditTextBoldCursor extends EditTextEffects { cleanupFloatingActionModeViews(); floatingToolbar = new FloatingToolbar(getContext(), windowView != null ? windowView : attachedToWindow, getActionModeStyle(), getResourcesProvider()); floatingToolbar.setOnPremiumLockClick(onPremiumMenuLockClickListener); + floatingToolbar.setQuoteShowVisible(this::shouldShowQuoteButton); floatingActionMode = new FloatingActionMode(getContext(), new ActionModeCallback2Wrapper(callback), this, floatingToolbar); floatingToolbarPreDrawListener = () -> { if (floatingActionMode != null) { @@ -1130,6 +1140,18 @@ public class EditTextBoldCursor extends EditTextEffects { } } + private boolean shouldShowQuoteButton() { + if (!hasSelection() || getSelectionStart() < 0 || getSelectionEnd() < 0 || getSelectionStart() == getSelectionEnd()) { + return false; + } + Editable text = getText(); + if (text == null) { + return false; + } + QuoteSpan.QuoteStyleSpan[] spans = ((Spanned) text).getSpans(getSelectionStart(), getSelectionEnd(), QuoteSpan.QuoteStyleSpan.class); + return spans == null || spans.length == 0; + } + @Override public ActionMode startActionMode(ActionMode.Callback callback, int type) { if (Build.VERSION.SDK_INT >= 23 && (windowView != null || attachedToWindow != null)) { @@ -1209,4 +1231,8 @@ public class EditTextBoldCursor extends EditTextEffects { public void setOnPremiumMenuLockClickListener(Runnable listener) { onPremiumMenuLockClickListener = listener; } + + public Runnable getOnPremiumMenuLockClickListener() { + return onPremiumMenuLockClickListener; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java index 4ef732c56..dd63ce1ac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextCaption.java @@ -27,6 +27,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.CharacterStyle; +import android.util.Log; import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; @@ -41,6 +42,7 @@ import android.widget.FrameLayout; import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.CodeHighlighting; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -69,7 +71,6 @@ public class EditTextCaption extends EditTextBoldCursor { private int selectionStart = -1; private int selectionEnd = -1; private boolean allowTextEntitiesIntersection; - private float offsetY; private int lineCount; private boolean isInitLineCount; private final Theme.ResourcesProvider resourcesProvider; @@ -83,6 +84,7 @@ public class EditTextCaption extends EditTextBoldCursor { public EditTextCaption(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; + quoteColor = Theme.getColor(Theme.key_chat_inQuote, resourcesProvider); addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -167,6 +169,25 @@ public class EditTextCaption extends EditTextBoldCursor { applyTextStyleToSelection(new TextStyleSpan(run)); } + public void makeSelectedQuote() { + int start, end; + if (selectionStart >= 0 && selectionEnd >= 0) { + start = selectionStart; + end = selectionEnd; + selectionStart = selectionEnd = -1; + } else { + start = getSelectionStart(); + end = getSelectionEnd(); + } + final int setSelection = QuoteSpan.putQuoteToEditable(getText(), start, end); + if (setSelection >= 0) { + setSelection(setSelection); + resetFontMetricsCache(); + } + invalidateQuotes(true); + invalidateSpoilers(); + } + public void makeSelectedUrl() { AlertDialog.Builder builder; if (adaptiveCreateLinkDialog) { @@ -214,7 +235,7 @@ public class EditTextCaption extends EditTextBoldCursor { if (spans != null && spans.length > 0) { for (int a = 0; a < spans.length; a++) { CharacterStyle oldSpan = spans[a]; - if (!(oldSpan instanceof AnimatedEmojiSpan)) { + if (!(oldSpan instanceof AnimatedEmojiSpan) && !(oldSpan instanceof QuoteSpan.QuoteStyleSpan)) { int spanStart = editable.getSpanStart(oldSpan); int spanEnd = editable.getSpanEnd(oldSpan); editable.removeSpan(oldSpan); @@ -309,6 +330,22 @@ public class EditTextCaption extends EditTextBoldCursor { end = getSelectionEnd(); } MediaDataController.addStyleToText(span, start, end, getText(), allowTextEntitiesIntersection); + + if (span == null) { + Editable editable = getText(); + CodeHighlighting.Span[] code = editable.getSpans(start, end, CodeHighlighting.Span.class); + for (int i = 0; i < code.length; ++i) + editable.removeSpan(code[i]); + QuoteSpan[] quotes = editable.getSpans(start, end, QuoteSpan.class); + for (int i = 0; i < quotes.length; ++i) { + editable.removeSpan(quotes[i]); + editable.removeSpan(quotes[i].styleSpan); + } + if (quotes.length > 0) { + invalidateQuotes(true); + } + } + if (delegate != null) { delegate.onSpansChanged(); } @@ -405,7 +442,7 @@ public class EditTextCaption extends EditTextBoldCursor { } } - private boolean performMenuAction(int itemId) { + public boolean performMenuAction(int itemId) { if (itemId == R.id.menu_regular) { makeSelectedRegular(); return true; @@ -430,6 +467,9 @@ public class EditTextCaption extends EditTextBoldCursor { } else if (itemId == R.id.menu_spoiler) { makeSelectedSpoiler(); return true; + } else if (itemId == R.id.menu_quote) { + makeSelectedQuote(); + return true; } return false; } @@ -498,15 +538,6 @@ public class EditTextCaption extends EditTextBoldCursor { invalidate(); } - public void setOffsetY(float offset) { - this.offsetY = offset; - invalidate(); - } - - public float getOffsetY() { - return offsetY; - } - @Override protected void onDraw(Canvas canvas) { canvas.save(); @@ -574,7 +605,7 @@ public class EditTextCaption extends EditTextBoldCursor { try { String html = clipData.getItemAt(0).getHtmlText(); Spannable pasted = CopyUtilities.fromHTML(html); - Emoji.replaceEmoji(pasted, getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false, null); + Emoji.replaceEmoji(pasted, getPaint().getFontMetricsInt(), false, null); AnimatedEmojiSpan[] spans = pasted.getSpans(0, pasted.length(), AnimatedEmojiSpan.class); if (spans != null) { for (int k = 0; k < spans.length; ++k) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java index 122bc057b..ff5c92455 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEffects.java @@ -8,15 +8,19 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.Region; +import android.os.Build; import android.os.Looper; import android.text.Editable; import android.text.Layout; import android.text.Spannable; +import android.util.Log; +import android.util.TypedValue; import android.view.MotionEvent; import android.widget.EditText; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.Components.spoilers.SpoilersClickDetector; @@ -29,6 +33,7 @@ public class EditTextEffects extends EditText { private List spoilers = new ArrayList<>(); private Stack spoilersPool = new Stack<>(); + private ArrayList quoteBlocks = new ArrayList<>(); private boolean isSpoilersRevealed; private boolean shouldRevealSpoilersByTouch = true; private SpoilersClickDetector clickDetector; @@ -37,6 +42,8 @@ public class EditTextEffects extends EditText { private int selStart, selEnd; private float lastRippleX, lastRippleY; private boolean postedSpoilerTimeout; + public int quoteColor; + private AnimatedEmojiSpan.EmojiGroupedSpans animatedEmojiDrawables; private ColorFilter animatedEmojiColorFilter; public boolean drawAnimatedEmojiDrawables = true; @@ -144,6 +151,7 @@ public class EditTextEffects extends EditText { protected void onAttachedToWindow() { super.onAttachedToWindow(); updateAnimatedEmoji(false); + invalidateQuotes(false); } @Override @@ -180,6 +188,7 @@ public class EditTextEffects extends EditText { } } updateAnimatedEmoji(true); + invalidateQuotes(true); invalidate(); } @@ -202,7 +211,7 @@ public class EditTextEffects extends EditText { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); - updateAnimatedEmoji(false); + invalidateQuotes(false); } /** @@ -251,45 +260,85 @@ public class EditTextEffects extends EditText { } } + protected float offsetY; + + public void setOffsetY(float offset) { + this.offsetY = offset; + invalidate(); + } + + public float getOffsetY() { + return offsetY; + } + + public boolean wrapCanvasToFixClipping = Build.VERSION.SDK_INT < Build.VERSION_CODES.Q; + private NoClipCanvas wrappedCanvas; + @Override protected void onDraw(Canvas canvas) { canvas.save(); if (clipToPadding && getScrollY() != 0) { - canvas.clipRect(0, getScrollY(), getMeasuredWidth(), getMeasuredHeight() + getScrollY()); + canvas.clipRect(-AndroidUtilities.dp(3), getScrollY() - getExtendedPaddingTop() - offsetY, getMeasuredWidth(), getMeasuredHeight() + getScrollY() + getExtendedPaddingBottom() - offsetY); } path.rewind(); for (SpoilerEffect eff : spoilers) { Rect bounds = eff.getBounds(); path.addRect(bounds.left, bounds.top, bounds.right, bounds.bottom, Path.Direction.CW); } + canvas.translate(0, getExtendedPaddingTop()); canvas.clipPath(path, Region.Op.DIFFERENCE); + canvas.translate(0, -getExtendedPaddingTop()); + invalidateQuotes(false); + for (int i = 0; i < quoteBlocks.size(); ++i) { + quoteBlocks.get(i).draw(canvas, getExtendedPaddingTop(), getWidth(), quoteColor, 1f); + } updateAnimatedEmoji(false); - super.onDraw(canvas); + if (wrapCanvasToFixClipping) { + if (wrappedCanvas == null) { + wrappedCanvas = new NoClipCanvas(); + } + wrappedCanvas.canvas = canvas; + super.onDraw(wrappedCanvas); + } else { + super.onDraw(canvas); + } if (drawAnimatedEmojiDrawables && animatedEmojiDrawables != null) { canvas.save(); - canvas.translate(getPaddingLeft(), 0); + canvas.translate(getPaddingLeft(), getExtendedPaddingTop()); AnimatedEmojiSpan.drawAnimatedEmojis(canvas, getLayout(), animatedEmojiDrawables, 0, spoilers, computeVerticalScrollOffset() - AndroidUtilities.dp(6), computeVerticalScrollOffset() + computeVerticalScrollExtent(), 0, 1f, animatedEmojiColorFilter); canvas.restore(); } canvas.restore(); canvas.save(); + canvas.translate(0, getExtendedPaddingTop()); canvas.clipPath(path); path.rewind(); + canvas.translate(0, -getExtendedPaddingTop()); if (!spoilers.isEmpty()) spoilers.get(0).getRipplePath(path); canvas.clipPath(path); + canvas.translate(0, getExtendedPaddingTop()); canvas.translate(0, -getPaddingTop()); - super.onDraw(canvas); + if (wrapCanvasToFixClipping) { + if (wrappedCanvas == null) { + wrappedCanvas = new NoClipCanvas(); + } + wrappedCanvas.canvas = canvas; + super.onDraw(wrappedCanvas); + } else { + super.onDraw(canvas); + } canvas.restore(); - rect.set(0, getScrollY(), getWidth(), getScrollY() + getHeight() - getPaddingBottom()); + rect.set(0, (int) (getScrollY() - getExtendedPaddingTop() - offsetY), getWidth(), (int) (getMeasuredHeight() + getScrollY() + getExtendedPaddingBottom() - offsetY)); canvas.save(); + canvas.translate(0, getExtendedPaddingTop()); canvas.clipRect(rect); for (SpoilerEffect eff : spoilers) { Rect b = eff.getBounds(); if (rect.top <= b.bottom && rect.bottom >= b.top || b.top <= rect.bottom && b.bottom >= rect.top) { - eff.setColor(getPaint().getColor()); + eff.setColor(eff.insideQuote ? quoteColor : getPaint().getColor()); eff.draw(canvas); } } @@ -308,6 +357,36 @@ public class EditTextEffects extends EditText { } } + private int lastText2Length; + private int quoteUpdatesTries; + private boolean[] quoteUpdateLayout; + + public void invalidateQuotes(boolean force) { + int newTextLength = (getLayout() == null || getLayout().getText() == null) ? 0 : getLayout().getText().length(); + if (force || lastText2Length != newTextLength) { + quoteUpdatesTries = 2; + lastText2Length = newTextLength; + } + if (quoteUpdatesTries > 0) { + if (quoteUpdateLayout == null) { + quoteUpdateLayout = new boolean[1]; + } + quoteUpdateLayout[0] = false; + quoteBlocks = QuoteSpan.updateQuoteBlocks(getLayout(), quoteBlocks, quoteUpdateLayout); + if (quoteUpdateLayout[0]) { + resetFontMetricsCache(); + } + quoteUpdatesTries--; + } + } + + // really dirty workaround to reset fontmetrics cache (lineheightspan.chooseheight works only when text is inserted into the respected line) + protected void resetFontMetricsCache() { + float originalTextSize = getTextSize(); + setTextSize(TypedValue.COMPLEX_UNIT_PX, originalTextSize + 1); + setTextSize(TypedValue.COMPLEX_UNIT_PX, originalTextSize); + } + public void invalidateEffects() { Editable text = getText(); if (text != null) { @@ -335,7 +414,7 @@ public class EditTextEffects extends EditText { if (drawAnimatedEmojiDrawables && animatedEmojiDrawables != null) { animatedEmojiDrawables.recordPositions(false); } - SpoilerEffect.addSpoilers(this, spoilersPool, spoilers); + SpoilerEffect.addSpoilers(this, spoilersPool, spoilers, quoteBlocks); if (drawAnimatedEmojiDrawables && animatedEmojiDrawables != null) { animatedEmojiDrawables.recordPositions(true); } 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 1e86ec245..5c2ce835c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -5,8 +5,10 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.Activity; import android.app.Dialog; +import android.content.ComponentName; import android.content.Context; import android.content.ContextWrapper; +import android.content.Intent; import android.graphics.Canvas; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -23,7 +25,9 @@ import android.view.ContextMenu; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; +import android.view.MenuItem; import android.view.MotionEvent; +import android.view.SubMenu; import android.view.View; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; @@ -33,6 +37,7 @@ import android.widget.ImageView; import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -41,6 +46,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.XiaomiUtilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; @@ -61,6 +67,9 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not private SizeNotifierFrameLayout sizeNotifierLayout; private BaseFragment parentFragment; + private ItemOptions formatOptions; + private boolean shownFormatButton; + private int keyboardHeight; private int keyboardHeightLand; private boolean keyboardVisible; @@ -164,7 +173,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not @Override protected int getActionModeStyle() { - if (style == STYLE_STORY) { + if (style == STYLE_STORY || style == STYLE_PHOTOVIEWER) { return FloatingToolbar.STYLE_BLACK; } return super.getActionModeStyle(); @@ -172,8 +181,8 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not @Override protected void extendActionMode(ActionMode actionMode, Menu menu) { - if (style == STYLE_STORY || style == STYLE_PHOTOVIEWER) { - ChatActivity.fillActionModeMenu(menu, null); + if (allowEntities()) { + ChatActivity.fillActionModeMenu(menu, null, currentStyle == STYLE_PHOTOVIEWER); } super.extendActionMode(actionMode, menu); } @@ -184,6 +193,28 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not super.scrollTo(x, y); } } + + private Drawable lastIcon = null; + + @Override + protected void onSelectionChanged(int selStart, int selEnd) { + super.onSelectionChanged(selStart, selEnd); + + if (emojiIconDrawable != null) { + boolean selected = selEnd != selStart; + boolean showFormat = allowEntities() && selected && (XiaomiUtilities.isMIUI() || true); + if (shownFormatButton != showFormat) { + shownFormatButton = showFormat; + if (showFormat) { + lastIcon = emojiIconDrawable.getIcon(); + emojiIconDrawable.setIcon(R.drawable.msg_edit, true); + } else { + emojiIconDrawable.setIcon(lastIcon, true); + lastIcon = null; + } + } + } + } }; editText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI); editText.setInputType(editText.getInputType() | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); @@ -216,7 +247,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not editText.setHandlesColor(0xffffffff); editText.setHighlightColor(0x30ffffff); editText.setLinkTextColor(0xFF46A3EB); + editText.quoteColor = 0xffffffff; editText.setTextIsSelectable(true); + setClipChildren(false); + setClipToPadding(false); addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 40, 0, 24, 0)); } else { editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); @@ -259,7 +293,19 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not if (!emojiButton.isEnabled() || emojiButton.getAlpha() < 0.5f || (adjustPanLayoutHelper != null && adjustPanLayoutHelper.animationInProgress())) { return; } - if (!isPopupShowing()) { + if (shownFormatButton) { + if (formatOptions == null) { + editText.hideActionMode(); + ItemOptions itemOptions = ItemOptions.makeOptions(parent, resourcesProvider, emojiButton); + itemOptions.setMaxHeight(AndroidUtilities.dp(280)); + editText.extendActionMode(null, new MenuToItemOptions(itemOptions, editText::performMenuAction, editText.getOnPremiumMenuLockClickListener())); + itemOptions.forceTop(true); + itemOptions.show(); + } else { + formatOptions.dismiss(); + formatOptions = null; + } + } else if (!isPopupShowing()) { showPopup(1); emojiView.onOpen(editText.length() > 0); editText.requestFocus(); @@ -270,6 +316,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not emojiButton.setContentDescription(LocaleController.getString("Emoji", R.string.Emoji)); } + protected boolean allowEntities() { + return currentStyle == STYLE_STORY || currentStyle == STYLE_PHOTOVIEWER; + } + public void setSuggestionsEnabled(boolean enabled) { int inputType = editText.getInputType(); if (!enabled) { @@ -386,6 +436,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not editText.setCursorColor(0xffffffff); editText.setHandlesColor(0xffffffff); editText.setHighlightColor(0x30ffffff); + editText.quoteColor = 0xffffffff; } else { editText.setHintTextColor(getThemedColor(Theme.key_dialogTextHint)); editText.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); @@ -439,7 +490,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not animator.addUpdateListener(animation -> { float v = (float) animation.getAnimatedValue(); emojiView.setTranslationY(v); - if (finalHeight > 0 && currentStyle == STYLE_STORY) { + if (finalHeight > 0 && (currentStyle == STYLE_STORY || currentStyle == STYLE_PHOTOVIEWER)) { emojiView.setAlpha(1f - v / (float) finalHeight); } bottomPanelTranslationY(v - finalHeight); @@ -542,7 +593,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not animator.addUpdateListener(animation -> { float v = (float) animation.getAnimatedValue(); emojiView.setTranslationY(v); - if (emojiPadding > 0 && currentStyle == STYLE_STORY) { + if (emojiPadding > 0 && (currentStyle == STYLE_STORY || currentStyle == STYLE_PHOTOVIEWER)) { emojiView.setAlpha(1f - v / (float) emojiPadding); } bottomPanelTranslationY(v); @@ -612,10 +663,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not if (emojiView != null) { return; } - emojiView = new EmojiView(parentFragment, allowAnimatedEmoji, false, false, getContext(), false, null, null, currentStyle != STYLE_STORY, resourcesProvider) { + emojiView = new EmojiView(parentFragment, allowAnimatedEmoji, false, false, getContext(), false, null, null, currentStyle != STYLE_STORY && currentStyle != STYLE_PHOTOVIEWER, resourcesProvider, false) { @Override protected void dispatchDraw(Canvas canvas) { - if (currentStyle == STYLE_STORY) { + if (currentStyle == STYLE_STORY || currentStyle == STYLE_PHOTOVIEWER) { drawEmojiBackground(canvas, this); } super.dispatchDraw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java index b3f396c50..d4005f942 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiPacksAlert.java @@ -639,7 +639,7 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N if (drawable == null) { continue; } - drawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); // drawable.addView(this); ArrayList arrayList = viewsGroupedByLines.get(child.getTop()); if (arrayList == null) { @@ -773,7 +773,7 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N drawable.setAlpha(255); AndroidUtilities.rectTmp2.set(imageView.getLeft() + imageView.getPaddingLeft(), imageView.getPaddingTop(), imageView.getRight() - imageView.getPaddingRight(), imageView.getMeasuredHeight() - imageView.getPaddingBottom()); imageView.backgroundThreadDrawHolder[threadIndex].setBounds(AndroidUtilities.rectTmp2); - drawable.setColorFilter(Theme.getAnimatedEmojiColorFilter(resourcesProvider)); + drawable.setColorFilter(getAdaptiveEmojiColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon))); imageView.imageReceiver = drawable.getImageReceiver();; drawInBackgroundViews.add(imageView); } @@ -2043,4 +2043,13 @@ public class EmojiPacksAlert extends BottomSheet implements NotificationCenter.N return null; } } + + private ColorFilter adaptiveEmojiColorFilter; + private int adaptiveEmojiColor; + private ColorFilter getAdaptiveEmojiColorFilter(int color) { + if (color != adaptiveEmojiColor || adaptiveEmojiColorFilter == null) { + adaptiveEmojiColorFilter = new PorterDuffColorFilter(adaptiveEmojiColor = color, PorterDuff.Mode.SRC_IN); + } + return adaptiveEmojiColorFilter; + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java index 66357a354..4bbbd0c97 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiTabsStrip.java @@ -94,6 +94,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { public boolean animateAppear = true; + private int accentColor; private Runnable onSettingsOpenRunnable; private boolean wasDrawn; private int animatedEmojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_TAB_STRIP; @@ -101,11 +102,16 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { public boolean updateButtonDrawables = true; public EmojiTabsStrip(Context context, Theme.ResourcesProvider resourcesProvider, boolean includeRecent, boolean includeStandard, boolean includeAnimated, int type, Runnable onSettingsOpen) { + this(context, resourcesProvider, includeRecent, includeStandard, includeAnimated, type, onSettingsOpen, Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider)); + } + + public EmojiTabsStrip(Context context, Theme.ResourcesProvider resourcesProvider, boolean includeRecent, boolean includeStandard, boolean includeAnimated, int type, Runnable onSettingsOpen, int accentColor) { super(context); this.includeAnimated = includeAnimated; this.resourcesProvider = resourcesProvider; this.onSettingsOpenRunnable = onSettingsOpen; this.currentType = type; + this.accentColor = accentColor; contentView = new LinearLayout(context) { @@ -492,7 +498,7 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { currentPackButton.setAnimatedEmojiDocument(thumbDocument); } currentPackButton.updateSelect(selected == i, false); - if (currentType == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR) { + if (currentType == SelectAnimatedEmojiDialog.TYPE_AVATAR_CONSTRUCTOR || currentType == SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON) { currentPackButton.setLock(null); } else if (!isPremium && !free) { currentPackButton.setLock(true); @@ -648,6 +654,9 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { } private int selectorColor() { + if (currentType == SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON) { + return Theme.multAlpha(accentColor, .09f); + } return Theme.multAlpha(Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider), .18f); } @@ -1109,15 +1118,18 @@ public class EmojiTabsStrip extends ScrollableHorizontalScrollView { public void updateColor() { Theme.setSelectorDrawableColor(getBackground(), selectorColor(), false); setColor( - ColorUtils.blendARGB( - Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider), - Theme.getColor(Theme.key_chat_emojiPanelIconSelected, resourcesProvider), - selectT - ) + ColorUtils.blendARGB( + Theme.getColor(Theme.key_chat_emojiPanelIcon, resourcesProvider), + Theme.getColor(Theme.key_chat_emojiPanelIconSelected, resourcesProvider), + selectT + ) ); } private void setColor(int color) { + if (currentType == SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON) { + color = accentColor; + } PorterDuffColorFilter colorFilter = new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY); if (imageView != null && !isAnimatedEmoji) { imageView.setColorFilter(colorFilter); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java index 9f7a41a00..fcc0b5046 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -1453,13 +1453,17 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } - public EmojiView(BaseFragment fragment, boolean needAnimatedEmoji, boolean needStickers, boolean needGif, final Context context, boolean needSearch, final TLRPC.ChatFull chatFull, ViewGroup parentView, boolean shouldDrawBackground, Theme.ResourcesProvider resourcesProvider) { + public EmojiView(BaseFragment fragment, boolean needAnimatedEmoji, boolean needStickers, boolean needGif, final Context context, boolean needSearch, final TLRPC.ChatFull chatFull, ViewGroup parentView, boolean shouldDrawBackground, Theme.ResourcesProvider resourcesProvider, boolean frozenAtStart) { super(context); this.shouldDrawBackground = shouldDrawBackground; this.fragment = fragment; this.allowAnimatedEmoji = needAnimatedEmoji; this.resourcesProvider = resourcesProvider; + if (frozenAtStart) { + freeze(true); + } + int color = getThemedColor(Theme.key_chat_emojiBottomPanelIcon); color = Color.argb(30, Color.red(color), Color.green(color), Color.blue(color)); @@ -6504,6 +6508,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } private void updateItems() { + if (frozen) { + return; + } + int width = getMeasuredWidth(); if (width == 0) { width = AndroidUtilities.displaySize.x; @@ -7235,6 +7243,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } public void notifyDataSetChanged(boolean updateEmojipack) { + if (frozen) { + return; + } ArrayList prevRowHashCodes = new ArrayList<>(rowHashCodes); final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); @@ -7552,7 +7563,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific notifyDataSetChanged(); } } - }, null, true, false, true, 25); + }, null, SharedConfig.suggestAnimatedEmoji, false, true, 25); }; if (Emoji.fullyConsistsOfEmojis(query)) { StickerCategoriesListView.search.fetch(UserConfig.selectedAccount, query, list -> { @@ -8964,4 +8975,25 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific int type; View view; } + + private boolean frozen; + public void freeze(boolean freeze) { + final boolean wasFrozen = frozen; + this.frozen = freeze; + if (wasFrozen && !freeze) { + if (currentPage == 0) { + if (emojiAdapter != null) { + emojiAdapter.notifyDataSetChanged(); + } + } else if (currentPage == 1) { + if (gifAdapter != null) { + gifAdapter.notifyDataSetChanged(); + } + } else if (currentPage == 2) { + if (stickersGridAdapter != null) { + stickersGridAdapter.notifyDataSetChanged(); + } + } + } + } } \ No newline at end of file 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 9b92541ca..ac5ff8975 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -8,10 +8,12 @@ import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Shader; import android.os.SystemClock; +import android.text.TextPaint; import android.view.View; 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.Theme; @@ -591,7 +593,7 @@ public class FlickerLoadingView extends View { int radius = AndroidUtilities.dp(23); int rectRadius = AndroidUtilities.dp(4); while (h <= getMeasuredHeight()) { - canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(12)) + radius, h + AndroidUtilities.dp(8) + radius, radius, paint); + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(12) + radius), h + AndroidUtilities.dp(8) + radius, radius, paint); rectF.set(paddingLeft + AndroidUtilities.dp(74), h + AndroidUtilities.dp(12), paddingLeft + AndroidUtilities.dp(260), h + AndroidUtilities.dp(20)); checkRtl(rectF); @@ -601,6 +603,12 @@ public class FlickerLoadingView extends View { checkRtl(rectF); canvas.drawRoundRect(rectF, rectRadius, rectRadius, paint); + if (memberRequestButtonWidth > 0) { + rectF.set(paddingLeft + AndroidUtilities.dp(73), h + AndroidUtilities.dp(62), paddingLeft + AndroidUtilities.dp(73) + memberRequestButtonWidth, h + AndroidUtilities.dp(62 + 32)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, rectRadius, rectRadius, paint); + } + h += getCellHeight(getMeasuredWidth()); count++; if (isSingleCell && count >= itemsCount) { @@ -912,4 +920,12 @@ public class FlickerLoadingView extends View { public void setIgnoreHeightCheck(boolean ignore) { this.ignoreHeightCheck = ignore; } + + private float memberRequestButtonWidth; + public void setMemberRequestButton(boolean isChannel) { + TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + paint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + paint.setTextSize(AndroidUtilities.dp(14)); + memberRequestButtonWidth = AndroidUtilities.dp(17 + 17) + paint.measureText(isChannel ? LocaleController.getString("AddToChannel", R.string.AddToChannel) : LocaleController.getString("AddToGroup", R.string.AddToGroup)); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FolderBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FolderBottomSheet.java index 587db1bf3..00cac509b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FolderBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FolderBottomSheet.java @@ -48,6 +48,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.INavigationLayout; @@ -66,8 +67,8 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { private String slug; private int filterId = -1; - private TLRPC.chatlist_ChatlistInvite invite; - private TLRPC.TL_chatlists_chatlistUpdates updates; + private TL_chatlists.chatlist_ChatlistInvite invite; + private TL_chatlists.TL_chatlists_chatlistUpdates updates; private boolean deleting; private String title = ""; @@ -112,8 +113,8 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { final MessagesController.DialogFilter filter = f; Runnable showDeleteAlert = () -> { - TLRPC.TL_chatlists_getLeaveChatlistSuggestions req = new TLRPC.TL_chatlists_getLeaveChatlistSuggestions(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_getLeaveChatlistSuggestions req = new TL_chatlists.TL_chatlists_getLeaveChatlistSuggestions(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; fragment.getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { FolderBottomSheet sheet; @@ -212,7 +213,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { init(); } - public FolderBottomSheet(BaseFragment fragment, int filterId, TLRPC.TL_chatlists_chatlistUpdates updates) { + public FolderBottomSheet(BaseFragment fragment, int filterId, TL_chatlists.TL_chatlists_chatlistUpdates updates) { super(fragment, false, false); this.filterId = filterId; @@ -233,18 +234,18 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { init(); } - public FolderBottomSheet(BaseFragment fragment, String slug, TLRPC.chatlist_ChatlistInvite invite) { + public FolderBottomSheet(BaseFragment fragment, String slug, TL_chatlists.chatlist_ChatlistInvite invite) { super(fragment, false, false); this.slug = slug; this.invite = invite; selectedPeers.clear(); - if (invite instanceof TLRPC.TL_chatlists_chatlistInvite) { - title = ((TLRPC.TL_chatlists_chatlistInvite) invite).title; - peers = (ArrayList) FakePasscodeUtils.filterPeers(((TLRPC.TL_chatlists_chatlistInvite) invite).peers, getCurrentAccount()); - } else if (invite instanceof TLRPC.TL_chatlists_chatlistInviteAlready) { - TLRPC.TL_chatlists_chatlistInviteAlready inv = (TLRPC.TL_chatlists_chatlistInviteAlready) invite; + if (invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { + title = ((TL_chatlists.TL_chatlists_chatlistInvite) invite).title; + peers = (ArrayList) FakePasscodeUtils.filterPeers(((TL_chatlists.TL_chatlists_chatlistInvite) invite).peers, getCurrentAccount()); + } else if (invite instanceof TL_chatlists.TL_chatlists_chatlistInviteAlready) { + TL_chatlists.TL_chatlists_chatlistInviteAlready inv = (TL_chatlists.TL_chatlists_chatlistInviteAlready) invite; peers = (ArrayList) FakePasscodeUtils.filterPeers(inv.missing_peers, getCurrentAccount()); alreadyPeers = inv.already_peers; this.filterId = inv.filter_id; @@ -351,7 +352,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { return; } - if (selectedPeers.isEmpty() && invite instanceof TLRPC.TL_chatlists_chatlistInvite) { + if (selectedPeers.isEmpty() && invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { AndroidUtilities.shakeViewSpring(button, shiftDp = -shiftDp); BotWebViewVibrationEffect.APP_ERROR.vibrate(); return; @@ -368,32 +369,32 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { final Utilities.Callback after; TLObject reqObject; if (deleting) { - TLRPC.TL_chatlists_leaveChatlist req = new TLRPC.TL_chatlists_leaveChatlist(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_leaveChatlist req = new TL_chatlists.TL_chatlists_leaveChatlist(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; req.peers.addAll(inputPeers); reqObject = req; } else if (updates != null) { if (inputPeers.isEmpty()) { - TLRPC.TL_chatlists_hideChatlistUpdates req = new TLRPC.TL_chatlists_hideChatlistUpdates(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_hideChatlistUpdates req = new TL_chatlists.TL_chatlists_hideChatlistUpdates(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; getBaseFragment().getConnectionsManager().sendRequest(req, null); getBaseFragment().getMessagesController().invalidateChatlistFolderUpdate(filterId); dismiss(); return; } - TLRPC.TL_chatlists_joinChatlistUpdates req = new TLRPC.TL_chatlists_joinChatlistUpdates(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_joinChatlistUpdates req = new TL_chatlists.TL_chatlists_joinChatlistUpdates(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; req.peers.addAll(inputPeers); reqObject = req; } else { - if (invite instanceof TLRPC.TL_chatlists_chatlistInviteAlready && inputPeers.isEmpty()) { + if (invite instanceof TL_chatlists.TL_chatlists_chatlistInviteAlready && inputPeers.isEmpty()) { dismiss(); return; } - TLRPC.TL_chatlists_joinChatlistInvite req = new TLRPC.TL_chatlists_joinChatlistInvite(); + TL_chatlists.TL_chatlists_joinChatlistInvite req = new TL_chatlists.TL_chatlists_joinChatlistInvite(); req.slug = slug; req.peers.addAll(inputPeers); reqObject = req; @@ -449,7 +450,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { } } else if (parentLayout != null) { final Utilities.Callback bulletin = (fragment) -> { - if (updates != null || invite instanceof TLRPC.TL_chatlists_chatlistInviteAlready) { + if (updates != null || invite instanceof TL_chatlists.TL_chatlists_chatlistInviteAlready) { BulletinFactory.of(fragment) .createSimpleBulletin( R.raw.folder_in, @@ -545,7 +546,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { } final int newFilterId = foundFilterId; - if (invite instanceof TLRPC.TL_chatlists_chatlistInvite) { + if (invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { getBaseFragment().getMessagesController().loadRemoteFilters(true, success -> { FolderBottomSheet.this.success = success; dismiss(); @@ -645,13 +646,13 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { button.setText(count > 0 ? LocaleController.getString("FolderLinkButtonRemoveChats", R.string.FolderLinkButtonRemoveChats) : LocaleController.getString("FolderLinkButtonRemove", R.string.FolderLinkButtonRemove), animated); } else if (peers == null || peers.isEmpty()) { button.setText(LocaleController.getString("OK", R.string.OK), animated); - } else if (invite instanceof TLRPC.TL_chatlists_chatlistInvite) { + } else if (invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { button.setText(LocaleController.formatString("FolderLinkButtonAdd", R.string.FolderLinkButtonAdd, title), animated); } else { button.setText(count > 0 ? LocaleController.formatPluralString("FolderLinkButtonJoinPlural", count) : LocaleController.getString("FolderLinkButtonNone", R.string.FolderLinkButtonNone), animated); } button.setCount(count, animated); - if (invite instanceof TLRPC.TL_chatlists_chatlistInvite) { + if (invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { button.setEnabled(!selectedPeers.isEmpty()); } } @@ -907,7 +908,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { protected CharSequence getTitle() { if (deleting) { return LocaleController.getString("FolderLinkTitleRemove", R.string.FolderLinkTitleRemove); - } else if (invite instanceof TLRPC.TL_chatlists_chatlistInvite) { + } else if (invite instanceof TL_chatlists.TL_chatlists_chatlistInvite) { return LocaleController.getString("FolderLinkTitleAdd", R.string.FolderLinkTitleAdd); } else if (peers == null || peers.isEmpty()) { return LocaleController.getString("FolderLinkTitleAlready", R.string.FolderLinkTitleAlready); @@ -936,7 +937,7 @@ public class FolderBottomSheet extends BottomSheetWithRecyclerListView { public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = null; if (viewType == VIEW_TYPE_TITLE) { - view = titleCell = new TitleCell(getContext(), invite instanceof TLRPC.TL_chatlists_chatlistInviteAlready || updates != null, escapedTitle); + view = titleCell = new TitleCell(getContext(), invite instanceof TL_chatlists.TL_chatlists_chatlistInviteAlready || updates != null, escapedTitle); } else if (viewType == VIEW_TYPE_HINT) { view = new TextInfoPrivacyCell(getContext()); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java index 444dc970d..082d2dba3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumUtilities.java @@ -15,10 +15,14 @@ import android.text.Spanned; import android.text.TextUtils; import android.text.style.DynamicDrawableSpan; import android.text.style.ImageSpan; +import android.util.SparseArray; +import android.util.SparseIntArray; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.google.android.exoplayer2.util.Log; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ContactsController; @@ -46,6 +50,8 @@ import java.util.ArrayList; public class ForumUtilities { + static Drawable dialogGeneralIcon; + static SparseArray dialogForumDrawables = new SparseArray(); public static void setTopicIcon(BackupImageView backupImageView, TLRPC.TL_forumTopic forumTopic) { setTopicIcon(backupImageView, forumTopic, false, false, null); @@ -56,7 +62,7 @@ public class ForumUtilities { } if (forumTopic.id == 1) { backupImageView.setAnimatedEmojiDrawable(null); - backupImageView.setImageDrawable(createGeneralTopicDrawable(backupImageView.getContext(), 0.75f, Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider))); + backupImageView.setImageDrawable(createGeneralTopicDrawable(backupImageView.getContext(), 0.75f, Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider), false)); } else if (forumTopic.icon_emoji_id != 0) { backupImageView.setImageDrawable(null); if (backupImageView.animatedEmojiDrawable == null || forumTopic.icon_emoji_id != backupImageView.animatedEmojiDrawable.getDocumentId()) { @@ -66,19 +72,31 @@ public class ForumUtilities { } } else { backupImageView.setAnimatedEmojiDrawable(null); - backupImageView.setImageDrawable(createTopicDrawable(forumTopic)); + backupImageView.setImageDrawable(createTopicDrawable(forumTopic, false)); } } public static Drawable createGeneralTopicDrawable(Context context, float scale, Theme.ResourcesProvider resourcesProvider) { - return createGeneralTopicDrawable(context, scale, Theme.getColor(Theme.key_chat_inMenu, resourcesProvider)); + return createGeneralTopicDrawable(context, scale, Theme.getColor(Theme.key_chat_inMenu, resourcesProvider), false); } - public static GeneralTopicDrawable createGeneralTopicDrawable(Context context, float scale, int color) { + public static GeneralTopicDrawable createGeneralTopicDrawable(Context context, float scale, int color, boolean isDialog) { if (context == null) { return null; } - return new GeneralTopicDrawable(context, scale, color); + return new GeneralTopicDrawable(context, scale, color, isDialog); + } + + public static void filterMessagesByTopic(int threadMessageId, ArrayList messageObjects) { + if (messageObjects == null) { + return; + } + for (int i = 0; i < messageObjects.size(); i++) { + if (threadMessageId != MessageObject.getTopicId(messageObjects.get(i).messageOwner, true)) { + messageObjects.remove(i); + i--; + } + } } public static class GeneralTopicDrawable extends Drawable { @@ -96,8 +114,15 @@ public class ForumUtilities { this.scale = scale; } - public GeneralTopicDrawable(Context context, float scale, int color) { - this.icon = context.getResources().getDrawable(R.drawable.msg_filled_general).mutate(); + public GeneralTopicDrawable(Context context, float scale, int color, boolean isDialog) { + if (isDialog) { + if (dialogGeneralIcon == null) { + dialogGeneralIcon = context.getResources().getDrawable(R.drawable.msg_filled_general).mutate(); + } + this.icon = dialogGeneralIcon; + } else { + this.icon = context.getResources().getDrawable(R.drawable.msg_filled_general).mutate(); + } this.scale = scale; setColor(color); } @@ -140,19 +165,29 @@ public class ForumUtilities { } } - public static Drawable createTopicDrawable(TLRPC.TL_forumTopic topic) { - return topic == null ? null : createTopicDrawable(topic.title, topic.icon_color); + public static Drawable createTopicDrawable(TLRPC.TL_forumTopic topic, boolean isDialog) { + return topic == null ? null : createTopicDrawable(topic.title, topic.icon_color, isDialog); } public static Drawable createTopicDrawable(String text) { - return createTopicDrawable(text, 0); + return createTopicDrawable(text, 0, false); } - public static Drawable createTopicDrawable(String text, int color) { - Drawable forumBubbleDrawable = new ForumBubbleDrawable(color); + public static Drawable createTopicDrawable(String text, int color, boolean isDialog) { + Drawable forumBubbleDrawable; + if (isDialog) { + forumBubbleDrawable = dialogForumDrawables.get(color); + if (forumBubbleDrawable == null) { + forumBubbleDrawable = new ForumBubbleDrawable(color); + dialogForumDrawables.put(color, forumBubbleDrawable); + } + } else { + forumBubbleDrawable = new ForumBubbleDrawable(color); + } + LetterDrawable letterDrawable = new LetterDrawable(null, LetterDrawable.STYLE_TOPIC_DRAWABLE); - String title = text.trim().toUpperCase(); - letterDrawable.setTitle(title.length() >= 1 ? title.substring(0, 1) : ""); + String title = text.trim(); + letterDrawable.setTitle(title.length() >= 1 ? title.substring(0, 1).toUpperCase() : ""); CombinedDrawable combinedDrawable = new CombinedDrawable(forumBubbleDrawable, letterDrawable, 0, 0); combinedDrawable.setFullsize(true); return combinedDrawable; @@ -205,17 +240,17 @@ public class ForumUtilities { baseFragment.presentFragment(chatActivity); } - public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint) { - return getTopicSpannedName(topic, paint, null); + public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint, boolean isDialog) { + return getTopicSpannedName(topic, paint, null, isDialog); } - public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint, Drawable[] drawableToSet) { + public static CharSequence getTopicSpannedName(TLRPC.ForumTopic topic, Paint paint, Drawable[] drawableToSet, boolean isDialog) { SpannableStringBuilder sb = new SpannableStringBuilder(); if (topic instanceof TLRPC.TL_forumTopic) { TLRPC.TL_forumTopic forumTopic = (TLRPC.TL_forumTopic) topic; if (forumTopic.id == 1) { try { - Drawable drawable = createGeneralTopicDrawable(ApplicationLoader.applicationContext, 1f, paint == null ? Theme.getColor(Theme.key_chat_inMenu) : paint.getColor()); + Drawable drawable = createGeneralTopicDrawable(ApplicationLoader.applicationContext, 1f, paint == null ? Theme.getColor(Theme.key_chat_inMenu) : paint.getColor(), isDialog); drawable.setBounds(0, 0, paint == null ? AndroidUtilities.dp(14) : (int) (paint.getTextSize()), paint == null ? AndroidUtilities.dp(14) : (int) (paint.getTextSize())); sb.append(" "); if (drawableToSet != null) { @@ -231,7 +266,7 @@ public class ForumUtilities { span.cacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC; } else { sb.append(" "); - Drawable drawable = ForumUtilities.createTopicDrawable(forumTopic); + Drawable drawable = ForumUtilities.createTopicDrawable(forumTopic, isDialog); if (drawableToSet != null) { drawableToSet[0] = ((CombinedDrawable) drawable).getBackgroundDrawable(); } @@ -276,7 +311,7 @@ public class ForumUtilities { return null; } if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicCreate) { - return AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.TopicWasCreatedAction), ForumUtilities.getTopicSpannedName(topic, null)); + return AndroidUtilities.replaceCharSequence("%s", LocaleController.getString(R.string.TopicWasCreatedAction), ForumUtilities.getTopicSpannedName(topic, null, false)); } if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionTopicEdit) { TLRPC.TL_messageActionTopicEdit topicEdit = (TLRPC.TL_messageActionTopicEdit) messageObject.messageOwner.action; @@ -299,14 +334,14 @@ public class ForumUtilities { return AndroidUtilities.replaceCharSequence("%s", topicEdit.hidden ? LocaleController.getString(R.string.TopicHidden2) : LocaleController.getString(R.string.TopicShown2), name); } if ((topicEdit.flags & 4) != 0) { - CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", topicEdit.closed ? LocaleController.getString(R.string.TopicWasClosedAction) : LocaleController.getString(R.string.TopicWasReopenedAction), ForumUtilities.getTopicSpannedName(topic, null)); + CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", topicEdit.closed ? LocaleController.getString(R.string.TopicWasClosedAction) : LocaleController.getString(R.string.TopicWasReopenedAction), ForumUtilities.getTopicSpannedName(topic, null, false)); return AndroidUtilities.replaceCharSequence("%1$s", charSequence, name); } if ((topicEdit.flags & 1) != 0 && (topicEdit.flags & 2) != 0) { TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic(); forumTopic.icon_emoji_id = topicEdit.icon_emoji_id; forumTopic.title = topicEdit.title; - CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", LocaleController.getString(R.string.TopicWasRenamedToAction2), ForumUtilities.getTopicSpannedName(forumTopic, null)); + CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", LocaleController.getString(R.string.TopicWasRenamedToAction2), ForumUtilities.getTopicSpannedName(forumTopic, null, false)); return AndroidUtilities.replaceCharSequence("%1$s", charSequence, name); } if ((topicEdit.flags & 1) != 0) { @@ -317,7 +352,7 @@ public class ForumUtilities { TLRPC.TL_forumTopic forumTopic = new TLRPC.TL_forumTopic(); forumTopic.icon_emoji_id = topicEdit.icon_emoji_id; forumTopic.title = ""; - CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", LocaleController.getString(R.string.TopicWasIconChangedToAction), ForumUtilities.getTopicSpannedName(forumTopic, null)); + CharSequence charSequence = AndroidUtilities.replaceCharSequence("%2$s", LocaleController.getString(R.string.TopicWasIconChangedToAction), ForumUtilities.getTopicSpannedName(forumTopic, null, false)); return AndroidUtilities.replaceCharSequence("%1$s", charSequence, name); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/MessageTopicButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/MessageTopicButton.java index b18ae1913..466dec1cc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/MessageTopicButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/MessageTopicButton.java @@ -109,7 +109,7 @@ public class MessageTopicButton { int iconColor; if (topic.id == 1) { iconColor = getThemedColor(messageObject != null && messageObject.isOutOwner() ? Theme.key_chat_outReactionButtonText : Theme.key_chat_inReactionButtonText); - topicIconDrawable = ForumUtilities.createGeneralTopicDrawable(context, .65f, iconColor); + topicIconDrawable = ForumUtilities.createGeneralTopicDrawable(context, .65f, iconColor, false); } else if (topic.icon_emoji_id != 0) { if (!(topicIconDrawable instanceof AnimatedEmojiDrawable) || topic.icon_emoji_id != ((AnimatedEmojiDrawable) topicIconDrawable).getDocumentId()) { if (topicIconDrawable instanceof AnimatedEmojiDrawable) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java deleted file mode 100644 index 3d6d2e442..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java +++ /dev/null @@ -1,1038 +0,0 @@ -package org.telegram.ui.Components; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.ValueAnimator; -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Outline; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Build; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.ScrollView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.ChatListItemAnimator; -import androidx.recyclerview.widget.GridLayoutManagerFixed; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.BuildVars; -import org.telegram.messenger.ChatMessageSharedResources; -import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ContactsController; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.ForwardingMessagesParams; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessageObject; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.ActionBarMenuSubItem; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Cells.ChatMessageCell; - -import java.util.ArrayList; - -public class ForwardingPreviewView extends FrameLayout { - - TLRPC.Peer sendAsPeer; - public void setSendAsPeer(TLRPC.Peer defPeer) { - sendAsPeer = defPeer; - updateMessages(); - } - - public interface ResourcesDelegate extends Theme.ResourcesProvider { - - Drawable getWallpaperDrawable(); - - boolean isWallpaperMotion(); - } - - SizeNotifierFrameLayout chatPreviewContainer; - ActionBar actionBar; - RecyclerListView chatListView; - ChatListItemAnimator itemAnimator; - GridLayoutManagerFixed chatLayoutManager; - - ForwardingMessagesParams forwardingMessagesParams; - Adapter adapter; - - ScrollView menuScrollView; - LinearLayout menuContainer; - LinearLayout buttonsLayout; - LinearLayout buttonsLayout2; - - ActionBarMenuSubItem showSendersNameView; - ActionBarMenuSubItem hideSendersNameView; - - ActionBarMenuSubItem showCaptionView; - ActionBarMenuSubItem hideCaptionView; - - ActionBarMenuSubItem changeRecipientView; - ActionBarMenuSubItem sendMessagesView; - - int chatTopOffset; - float yOffset; - int currentTopOffset; - float currentYOffset; - - ArrayList actionItems = new ArrayList<>(); - - Rect rect = new Rect(); - ChatMessageSharedResources sharedResources; - - private boolean firstLayout = true; - ValueAnimator offsetsAnimator; - TLRPC.User currentUser; - TLRPC.Chat currentChat; - boolean showing; - boolean isLandscapeMode; - private final int currentAccount; - boolean returnSendersNames; - - Runnable changeBoundsRunnable = new Runnable() { - @Override - public void run() { - if (offsetsAnimator != null && !offsetsAnimator.isRunning()) { - offsetsAnimator.start(); - } - } - }; - - private final ArrayList drawingGroups = new ArrayList<>(10); - private final ResourcesDelegate resourcesProvider; - - @SuppressLint("ClickableViewAccessibility") - public ForwardingPreviewView(@NonNull Context context, ForwardingMessagesParams params, TLRPC.User user, TLRPC.Chat chat, int currentAccount, ResourcesDelegate resourcesProvider) { - super(context); - sharedResources = new ChatMessageSharedResources(context); - this.currentAccount = currentAccount; - currentUser = user; - currentChat = chat; - forwardingMessagesParams = params; - this.resourcesProvider = resourcesProvider; - - chatPreviewContainer = new SizeNotifierFrameLayout(context) { - @Override - protected Drawable getNewDrawable() { - Drawable drawable = resourcesProvider.getWallpaperDrawable(); - return drawable != null ? drawable : super.getNewDrawable(); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - if (ev.getY() < currentTopOffset) { - return false; - } - return super.dispatchTouchEvent(ev); - } - }; - chatPreviewContainer.setBackgroundImage(resourcesProvider.getWallpaperDrawable(), resourcesProvider.isWallpaperMotion()); - chatPreviewContainer.setOccupyStatusBar(false); - - if (Build.VERSION.SDK_INT >= 21) { - chatPreviewContainer.setOutlineProvider(new ViewOutlineProvider() { - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - @Override - public void getOutline(View view, Outline outline) { - outline.setRoundRect(0, (int) (currentTopOffset + 1), view.getMeasuredWidth(), view.getMeasuredHeight(), AndroidUtilities.dp(6)); - } - }); - chatPreviewContainer.setClipToOutline(true); - chatPreviewContainer.setElevation(AndroidUtilities.dp(4)); - } - - actionBar = new ActionBar(context, resourcesProvider); - actionBar.setBackgroundColor(getThemedColor(Theme.key_actionBarDefault)); - actionBar.setOccupyStatusBar(false); - - chatListView = new RecyclerListView(context, resourcesProvider) { - - @Override - public boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; - boolean r = super.drawChild(canvas, child, drawingTime); - cell.drawCheckBox(canvas); - canvas.save(); - canvas.translate(cell.getX(), cell.getY()); - cell.drawMessageText(canvas, cell.getMessageObject().textLayoutBlocks, cell.getMessageObject().textXOffset, true, 1f, false); - - if (cell.getCurrentMessagesGroup() != null || cell.getTransitionParams().animateBackgroundBoundsInner) { - cell.drawNamesLayout(canvas, 1f); - } - if ((cell.getCurrentPosition() != null && cell.getCurrentPosition().last) || cell.getTransitionParams().animateBackgroundBoundsInner) { - cell.drawTime(canvas, 1f, true); - } - if (cell.getCurrentPosition() == null || (cell.getCurrentPosition().last || cell.getCurrentMessagesGroup().isDocuments)) { - cell.drawCaptionLayout(canvas, false, 1f); - } - cell.getTransitionParams().recordDrawingStatePreview(); - canvas.restore(); - return r; - } - return true; - } - - @Override - protected void dispatchDraw(Canvas canvas) { - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; - cell.setParentViewSize(chatPreviewContainer.getMeasuredWidth(), chatPreviewContainer.getBackgroundSizeY()); - } - } - drawChatBackgroundElements(canvas); - super.dispatchDraw(canvas); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - updatePositions(); - } - - private void drawChatBackgroundElements(Canvas canvas) { - int count = getChildCount(); - MessageObject.GroupedMessages lastDrawnGroup = null; - - for (int a = 0; a < count; a++) { - View child = getChildAt(a); - if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; - MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); - if (group != null && group == lastDrawnGroup) { - continue; - } - lastDrawnGroup = group; - MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); - MessageBackgroundDrawable backgroundDrawable = cell.getBackgroundDrawable(); - } - } - MessageObject.GroupedMessages scrimGroup = null; - for (int k = 0; k < 3; k++) { - drawingGroups.clear(); - if (k == 2 && !chatListView.isFastScrollAnimationRunning()) { - continue; - } - for (int i = 0; i < count; i++) { - View child = chatListView.getChildAt(i); - if (child instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) child; - if (child.getY() > chatListView.getHeight() || child.getY() + child.getHeight() < 0) { - continue; - } - MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); - if (group == null || (k == 0 && group.messages.size() == 1) || (k == 1 && !group.transitionParams.drawBackgroundForDeletedItems)) { - continue; - } - if ((k == 0 && cell.getMessageObject().deleted) || (k == 1 && !cell.getMessageObject().deleted)) { - continue; - } - if ((k == 2 && !cell.willRemovedAfterAnimation()) || (k != 2 && cell.willRemovedAfterAnimation())) { - continue; - } - - if (!drawingGroups.contains(group)) { - group.transitionParams.left = 0; - group.transitionParams.top = 0; - group.transitionParams.right = 0; - group.transitionParams.bottom = 0; - - group.transitionParams.pinnedBotton = false; - group.transitionParams.pinnedTop = false; - group.transitionParams.cell = cell; - drawingGroups.add(group); - } - - group.transitionParams.pinnedTop = cell.isPinnedTop(); - group.transitionParams.pinnedBotton = cell.isPinnedBottom(); - - int left = (cell.getLeft() + cell.getBackgroundDrawableLeft()); - int right = (cell.getLeft() + cell.getBackgroundDrawableRight()); - int top = (cell.getTop() + cell.getBackgroundDrawableTop()); - int bottom = (cell.getTop() + cell.getBackgroundDrawableBottom()); - - if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_TOP) == 0) { - top -= AndroidUtilities.dp(10); - } - - if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { - bottom += AndroidUtilities.dp(10); - } - - if (cell.willRemovedAfterAnimation()) { - group.transitionParams.cell = cell; - } - - if (group.transitionParams.top == 0 || top < group.transitionParams.top) { - group.transitionParams.top = top; - } - if (group.transitionParams.bottom == 0 || bottom > group.transitionParams.bottom) { - group.transitionParams.bottom = bottom; - } - if (group.transitionParams.left == 0 || left < group.transitionParams.left) { - group.transitionParams.left = left; - } - if (group.transitionParams.right == 0 || right > group.transitionParams.right) { - group.transitionParams.right = right; - } - } - } - - for (int i = 0; i < drawingGroups.size(); i++) { - MessageObject.GroupedMessages group = drawingGroups.get(i); - if (group == scrimGroup) { - continue; - } - float x = group.transitionParams.cell.getNonAnimationTranslationX(true); - float l = (group.transitionParams.left + x + group.transitionParams.offsetLeft); - float t = (group.transitionParams.top + group.transitionParams.offsetTop); - float r = (group.transitionParams.right + x + group.transitionParams.offsetRight); - float b = (group.transitionParams.bottom + group.transitionParams.offsetBottom); - - if (!group.transitionParams.backgroundChangeBounds) { - t += group.transitionParams.cell.getTranslationY(); - b += group.transitionParams.cell.getTranslationY(); - } - - if (t < -AndroidUtilities.dp(20)) { - t = -AndroidUtilities.dp(20); - } - - if (b > chatListView.getMeasuredHeight() + AndroidUtilities.dp(20)) { - b = chatListView.getMeasuredHeight() + AndroidUtilities.dp(20); - } - - boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; - if (useScale) { - canvas.save(); - canvas.scale(group.transitionParams.cell.getScaleX(), group.transitionParams.cell.getScaleY(), l + (r - l) / 2, t + (b - t) / 2); - } - - group.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, group.transitionParams.pinnedTop, group.transitionParams.pinnedBotton, false, 0); - group.transitionParams.cell = null; - group.transitionParams.drawCaptionLayout = group.hasCaption; - if (useScale) { - canvas.restore(); - for (int ii = 0; ii < count; ii++) { - View child = chatListView.getChildAt(ii); - if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getCurrentMessagesGroup() == group) { - ChatMessageCell cell = ((ChatMessageCell) child); - int left = cell.getLeft(); - int top = cell.getTop(); - child.setPivotX(l - left + (r - l) / 2); - child.setPivotY(t - top + (b - t) / 2); - } - } - } - } - } - } - - }; - chatListView.setItemAnimator(itemAnimator = new ChatListItemAnimator(null, chatListView, resourcesProvider) { - - int scrollAnimationIndex = -1; - - @Override - public void onAnimationStart() { - super.onAnimationStart(); - AndroidUtilities.cancelRunOnUIThread(changeBoundsRunnable); - changeBoundsRunnable.run(); - - if (scrollAnimationIndex == -1) { - scrollAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(scrollAnimationIndex, null, false); - } - if (finishRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(finishRunnable); - finishRunnable = null; - } - } - - - Runnable finishRunnable; - - @Override - protected void onAllAnimationsDone() { - super.onAllAnimationsDone(); - if (finishRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(finishRunnable); - } - AndroidUtilities.runOnUIThread(finishRunnable = () -> { - if (scrollAnimationIndex != -1) { - NotificationCenter.getInstance(currentAccount).onAnimationFinish(scrollAnimationIndex); - scrollAnimationIndex = -1; - } - }); - - if (updateAfterAnimations) { - updateAfterAnimations = false; - AndroidUtilities.runOnUIThread(() -> updateMessages()); - } - } - - @Override - public void endAnimations() { - super.endAnimations(); - if (finishRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(finishRunnable); - } - AndroidUtilities.runOnUIThread(finishRunnable = () -> { - if (scrollAnimationIndex != -1) { - NotificationCenter.getInstance(currentAccount).onAnimationFinish(scrollAnimationIndex); - scrollAnimationIndex = -1; - } - }); - } - }); - chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - - for (int i = 0; i < chatListView.getChildCount(); i++) { - ChatMessageCell cell = (ChatMessageCell) chatListView.getChildAt(i); - cell.setParentViewSize(chatPreviewContainer.getMeasuredWidth(), chatPreviewContainer.getBackgroundSizeY()); - } - } - }); - chatListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - if (forwardingMessagesParams.previewMessages.size() <= 1) { - return; - } - int id = params.previewMessages.get(position).getId(); - boolean newSelected = !params.selectedIds.get(id, false); - if (forwardingMessagesParams.selectedIds.size() == 1 && !newSelected) { - return; - } - if (!newSelected) { - params.selectedIds.delete(id); - } else { - params.selectedIds.put(id, newSelected); - } - ChatMessageCell chatMessageCell = (ChatMessageCell) view; - chatMessageCell.setChecked(newSelected, newSelected, true); - actionBar.setTitle(LocaleController.formatPluralString("PreviewForwardMessagesCount", params.selectedIds.size())); - } - }); - - chatListView.setAdapter(adapter = new Adapter()); - chatListView.setPadding(0, AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4)); - chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, true) { - - @Override - public boolean shouldLayoutChildFromOpositeSide(View child) { - return false; - } - - @Override - protected boolean hasSiblingChild(int position) { - MessageObject message = params.previewMessages.get(position); - MessageObject.GroupedMessages group = getValidGroupedMessage(message); - if (group != null) { - MessageObject.GroupedMessagePosition pos = group.positions.get(message); - if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { - return false; - } - int count = group.posArray.size(); - for (int a = 0; a < count; a++) { - MessageObject.GroupedMessagePosition p = group.posArray.get(a); - if (p == pos) { - continue; - } - if (p.minY <= pos.minY && p.maxY >= pos.minY) { - return true; - } - } - } - return false; - } - - @Override - public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { - if (BuildVars.DEBUG_PRIVATE_VERSION) { - super.onLayoutChildren(recycler, state); - } else { - try { - super.onLayoutChildren(recycler, state); - } catch (Exception e) { - FileLog.e(e); - AndroidUtilities.runOnUIThread(() -> adapter.notifyDataSetChanged()); - } - } - } - }; - chatLayoutManager.setSpanSizeLookup(new GridLayoutManagerFixed.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - int idx = position; - if (idx >= 0 && idx < params.previewMessages.size()) { - MessageObject message = params.previewMessages.get(idx); - MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); - if (groupedMessages != null) { - return groupedMessages.positions.get(message).spanSize; - } - } - return 1000; - } - }); - chatListView.setClipToPadding(false); - chatListView.setLayoutManager(chatLayoutManager); - chatListView.addItemDecoration(new RecyclerView.ItemDecoration() { - @Override - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - outRect.bottom = 0; - if (view instanceof ChatMessageCell) { - ChatMessageCell cell = (ChatMessageCell) view; - MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); - if (group != null) { - MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); - if (position != null && position.siblingHeights != null) { - float maxHeight = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f; - int h = cell.getExtraInsetHeight(); - for (int a = 0; a < position.siblingHeights.length; a++) { - h += (int) Math.ceil(maxHeight * position.siblingHeights[a]); - } - h += (position.maxY - position.minY) * Math.round(7 * AndroidUtilities.density); - int count = group.posArray.size(); - for (int a = 0; a < count; a++) { - MessageObject.GroupedMessagePosition pos = group.posArray.get(a); - if (pos.minY != position.minY || pos.minX == position.minX && pos.maxX == position.maxX && pos.minY == position.minY && pos.maxY == position.maxY) { - continue; - } - if (pos.minY == position.minY) { - h -= (int) Math.ceil(maxHeight * pos.ph) - AndroidUtilities.dp(4); - break; - } - } - outRect.bottom = -h; - } - } - } - } - }); - - chatPreviewContainer.addView(chatListView); - addView(chatPreviewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 400, 0, 8, 0, 8, 0)); - chatPreviewContainer.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - menuScrollView = new ScrollView(context); - addView(menuScrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - - menuContainer = new LinearLayout(context); - menuContainer.setOrientation(LinearLayout.VERTICAL); - menuScrollView.addView(menuContainer); - - buttonsLayout = new LinearLayout(context); - buttonsLayout.setOrientation(LinearLayout.VERTICAL); - Drawable shadowDrawable = getContext().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - buttonsLayout.setBackground(shadowDrawable); - menuContainer.addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - showSendersNameView = new ActionBarMenuSubItem(context, true, true, false, resourcesProvider); - buttonsLayout.addView(showSendersNameView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - showSendersNameView.setTextAndIcon(forwardingMessagesParams.multiplyUsers ? LocaleController.getString("ShowSenderNames", R.string.ShowSenderNames) : LocaleController.getString("ShowSendersName", R.string.ShowSendersName), 0); - showSendersNameView.setChecked(true); - - hideSendersNameView = new ActionBarMenuSubItem(context, true, false, !params.hasCaption, resourcesProvider); - buttonsLayout.addView(hideSendersNameView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - hideSendersNameView.setTextAndIcon(forwardingMessagesParams.multiplyUsers ? LocaleController.getString("HideSenderNames", R.string.HideSenderNames) : LocaleController.getString("HideSendersName", R.string.HideSendersName), 0); - hideSendersNameView.setChecked(false); - - if (forwardingMessagesParams.hasCaption) { - View dividerView = new View(context) { - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(2, MeasureSpec.EXACTLY)); - } - }; - dividerView.setBackgroundColor(getThemedColor(Theme.key_divider)); - buttonsLayout.addView(dividerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - - - showCaptionView = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); - buttonsLayout.addView(showCaptionView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - showCaptionView.setTextAndIcon(LocaleController.getString("ShowCaption", R.string.ShowCaption), 0); - showCaptionView.setChecked(true); - - hideCaptionView = new ActionBarMenuSubItem(context, true, false, true, resourcesProvider); - buttonsLayout.addView(hideCaptionView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - hideCaptionView.setTextAndIcon(LocaleController.getString("HideCaption", R.string.HideCaption), 0); - hideCaptionView.setChecked(false); - } - - buttonsLayout2 = new LinearLayout(context); - buttonsLayout2.setOrientation(LinearLayout.VERTICAL); - shadowDrawable = getContext().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); - buttonsLayout2.setBackground(shadowDrawable); - menuContainer.addView(buttonsLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, forwardingMessagesParams.hasSenders ? -8 : 0, 0, 0)); - - changeRecipientView = new ActionBarMenuSubItem(context, true, false, resourcesProvider); - buttonsLayout2.addView(changeRecipientView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - changeRecipientView.setTextAndIcon(LocaleController.getString("ChangeRecipient", R.string.ChangeRecipient), R.drawable.msg_forward_replace); - - sendMessagesView = new ActionBarMenuSubItem(context, false, true, resourcesProvider); - buttonsLayout2.addView(sendMessagesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); - sendMessagesView.setTextAndIcon(LocaleController.getString("ForwardSendMessages", R.string.ForwardSendMessages), R.drawable.msg_send); - - if (forwardingMessagesParams.hasSenders) { - actionItems.add(showSendersNameView); - actionItems.add(hideSendersNameView); - - if (params.hasCaption) { - actionItems.add(showCaptionView); - actionItems.add(hideCaptionView); - } - } - - actionItems.add(changeRecipientView); - actionItems.add(sendMessagesView); - - showSendersNameView.setOnClickListener(view -> { - if (params.hideForwardSendersName) { - returnSendersNames = false; - showSendersNameView.setChecked(true); - hideSendersNameView.setChecked(false); - if (showCaptionView != null) { - showCaptionView.setChecked(true); - hideCaptionView.setChecked(false); - } - params.hideForwardSendersName = false; - params.hideCaption = false; - updateMessages(); - updateSubtitle(); - } - }); - - hideSendersNameView.setOnClickListener(view -> { - if (!params.hideForwardSendersName) { - returnSendersNames = false; - showSendersNameView.setChecked(false); - hideSendersNameView.setChecked(true); - params.hideForwardSendersName = true; - updateMessages(); - updateSubtitle(); - } - }); - - if (params.hasCaption) { - showCaptionView.setOnClickListener(view -> { - if (params.hideCaption) { - if (returnSendersNames) { - params.hideForwardSendersName = false; - } - returnSendersNames = false; - showCaptionView.setChecked(true); - hideCaptionView.setChecked(false); - showSendersNameView.setChecked(!params.hideForwardSendersName); - hideSendersNameView.setChecked(params.hideForwardSendersName); - params.hideCaption = false; - updateMessages(); - updateSubtitle(); - } - }); - - hideCaptionView.setOnClickListener(view -> { - if (!params.hideCaption) { - showCaptionView.setChecked(false); - hideCaptionView.setChecked(true); - showSendersNameView.setChecked(false); - hideSendersNameView.setChecked(true); - if (!params.hideForwardSendersName) { - params.hideForwardSendersName = true; - returnSendersNames = true; - } - params.hideCaption = true; - updateMessages(); - updateSubtitle(); - } - }); - } - - showSendersNameView.setChecked(!params.hideForwardSendersName); - hideSendersNameView.setChecked(params.hideForwardSendersName); - - if (params.hasCaption) { - showCaptionView.setChecked(!params.hideCaption); - hideCaptionView.setChecked(params.hideCaption); - } - - if (!params.hasSenders) { - buttonsLayout.setVisibility(View.GONE); - } - - sendMessagesView.setOnClickListener(View -> didSendPressed()); - changeRecipientView.setOnClickListener(view -> selectAnotherChat()); - - updateMessages(); - updateSubtitle(); - actionBar.setTitle(LocaleController.formatPluralString("PreviewForwardMessagesCount", params.selectedIds.size())); - - menuScrollView.setOnTouchListener((view, motionEvent) -> { - if (motionEvent.getAction() == MotionEvent.ACTION_UP) { - dismiss(true); - } - return true; - }); - setOnTouchListener((view, motionEvent) -> { - if (motionEvent.getAction() == MotionEvent.ACTION_UP) { - dismiss(true); - } - return true; - }); - showing = true; - setAlpha(0); - setScaleX(0.95f); - setScaleY(0.95f); - animate().alpha(1f).scaleX(1f).setDuration(ChatListItemAnimator.DEFAULT_DURATION).setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR).scaleY(1f); - - updateColors(); - } - - private void updateSubtitle() { - if (!forwardingMessagesParams.hasSenders) { - if (forwardingMessagesParams.willSeeSenders) { - if (currentUser != null) { - actionBar.setSubtitle(LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name))); - } else { - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameVisibleChannel", R.string.ForwardPreviewSendersNameVisibleChannel)); - } else { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameVisibleGroup", R.string.ForwardPreviewSendersNameVisibleGroup)); - } - } - } else { - if (currentUser != null) { - actionBar.setSubtitle(LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name))); - } else { - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameHiddenChannel", R.string.ForwardPreviewSendersNameHiddenChannel)); - } else { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameHiddenGroup", R.string.ForwardPreviewSendersNameHiddenGroup)); - } - } - } - } else if (!forwardingMessagesParams.hideForwardSendersName) { - if (currentUser != null) { - actionBar.setSubtitle(LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name))); - } else { - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameVisibleChannel", R.string.ForwardPreviewSendersNameVisibleChannel)); - } else { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameVisibleGroup", R.string.ForwardPreviewSendersNameVisibleGroup)); - } - } - } else { - if (currentUser != null) { - actionBar.setSubtitle(LocaleController.formatString("ForwardPreviewSendersNameHidden", R.string.ForwardPreviewSendersNameHidden, ContactsController.formatName(currentUser.first_name, currentUser.last_name))); - } else { - if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameHiddenChannel", R.string.ForwardPreviewSendersNameHiddenChannel)); - } else { - actionBar.setSubtitle(LocaleController.getString("ForwardPreviewSendersNameHiddenGroup", R.string.ForwardPreviewSendersNameHiddenGroup)); - } - } - } - } - - private void updateColors() { - - } - - public void dismiss(boolean canShowKeyboard) { - if (showing) { - showing = false; - animate().alpha(0).scaleX(0.95f).scaleY(0.95f).setDuration(ChatListItemAnimator.DEFAULT_DURATION).setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR).setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (getParent() != null) { - ViewGroup parent = (ViewGroup) getParent(); - parent.removeView(ForwardingPreviewView.this); - } - } - }); - onDismiss(canShowKeyboard); - } - } - - protected void onDismiss(boolean canShowKeyboard) { - - } - - boolean updateAfterAnimations; - - private void updateMessages() { - if (itemAnimator.isRunning()) { - updateAfterAnimations = true; - return; - } - for (int i = 0; i < forwardingMessagesParams.previewMessages.size(); i++) { - MessageObject messageObject = forwardingMessagesParams.previewMessages.get(i); - messageObject.forceUpdate = true; - messageObject.sendAsPeer = sendAsPeer; - if (!forwardingMessagesParams.hideForwardSendersName) { - messageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_FWD; - messageObject.hideSendersName = false; - } else { - messageObject.messageOwner.flags &= ~TLRPC.MESSAGE_FLAG_FWD; - messageObject.hideSendersName = true; - } - if (forwardingMessagesParams.hideCaption) { - messageObject.caption = null; - } else { - messageObject.generateCaption(); - } - - if (messageObject.isPoll()) { - ForwardingMessagesParams.PreviewMediaPoll mediaPoll = (ForwardingMessagesParams.PreviewMediaPoll) messageObject.messageOwner.media; - mediaPoll.results.total_voters = forwardingMessagesParams.hideCaption ? 0 : mediaPoll.totalVotersCached; - } - } - for (int i = 0; i < forwardingMessagesParams.pollChoosenAnswers.size(); i++) { - forwardingMessagesParams.pollChoosenAnswers.get(i).chosen = !forwardingMessagesParams.hideForwardSendersName; - } - for (int i = 0; i < forwardingMessagesParams.groupedMessagesMap.size(); i++) { - itemAnimator.groupWillChanged(forwardingMessagesParams.groupedMessagesMap.valueAt(i)); - } - adapter.notifyItemRangeChanged(0, forwardingMessagesParams.previewMessages.size()); - } - - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int maxActionWidth = 0; - isLandscapeMode = MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec); - - int width = MeasureSpec.getSize(widthMeasureSpec); - if (isLandscapeMode) { - width = (int) (MeasureSpec.getSize(widthMeasureSpec) * 0.38f); - } - for (int i = 0; i < actionItems.size(); i++) { - actionItems.get(i).measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); - if (actionItems.get(i).getMeasuredWidth() > maxActionWidth) { - maxActionWidth = actionItems.get(i).getMeasuredWidth(); - } - } - buttonsLayout.getBackground().getPadding(rect); - int buttonsWidth = maxActionWidth + rect.left + rect.right; - buttonsLayout.getLayoutParams().width = buttonsWidth; - buttonsLayout2.getLayoutParams().width = buttonsWidth; - - buttonsLayout.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); - buttonsLayout2.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); - - ((MarginLayoutParams) chatListView.getLayoutParams()).topMargin = ActionBar.getCurrentActionBarHeight(); - if (isLandscapeMode) { - chatPreviewContainer.getLayoutParams().height = LayoutHelper.MATCH_PARENT; - ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).topMargin = AndroidUtilities.dp(8); - ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).bottomMargin = AndroidUtilities.dp(8); - chatPreviewContainer.getLayoutParams().width = (int) Math.min(MeasureSpec.getSize(widthMeasureSpec), Math.max(AndroidUtilities.dp(340), MeasureSpec.getSize(widthMeasureSpec) * 0.6f)); - menuScrollView.getLayoutParams().height = LayoutHelper.MATCH_PARENT; - } else { - ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).topMargin = 0; - ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).bottomMargin = 0; - chatPreviewContainer.getLayoutParams().height = MeasureSpec.getSize(heightMeasureSpec) - AndroidUtilities.dp(16 - 10) - buttonsLayout.getMeasuredHeight() - buttonsLayout2.getMeasuredHeight(); - if (chatPreviewContainer.getLayoutParams().height < MeasureSpec.getSize(heightMeasureSpec) * 0.5f) { - chatPreviewContainer.getLayoutParams().height = (int) (MeasureSpec.getSize(heightMeasureSpec) * 0.5f); - } - chatPreviewContainer.getLayoutParams().width = LayoutHelper.MATCH_PARENT; - menuScrollView.getLayoutParams().height = MeasureSpec.getSize(heightMeasureSpec) - chatPreviewContainer.getLayoutParams().height; - } - - int size = MeasureSpec.getSize(widthMeasureSpec) + MeasureSpec.getSize(heightMeasureSpec) << 16; - if (lastSize != size) { - for (int i = 0; i < forwardingMessagesParams.previewMessages.size(); i++) { - if (isLandscapeMode) { - forwardingMessagesParams.previewMessages.get(i).parentWidth = chatPreviewContainer.getLayoutParams().width; - } else { - forwardingMessagesParams.previewMessages.get(i).parentWidth = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(16); - } - forwardingMessagesParams.previewMessages.get(i).resetLayout(); - forwardingMessagesParams.previewMessages.get(i).forceUpdate = true; - if (adapter != null) { - adapter.notifyDataSetChanged(); - } - } - firstLayout = true; - } - lastSize = size; - - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - - int lastSize; - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - updatePositions(); - firstLayout = false; - } - - - private void updatePositions() { - int lastTopOffset = chatTopOffset; - float lastYOffset = yOffset; - - if (!isLandscapeMode) { - if (chatListView.getChildCount() == 0 || chatListView.getChildCount() > forwardingMessagesParams.previewMessages.size()) { - chatTopOffset = 0; - } else { - int minTop = chatListView.getChildAt(0).getTop(); - for (int i = 1; i < chatListView.getChildCount(); i++) { - if (chatListView.getChildAt(i).getTop() < minTop) { - minTop = chatListView.getChildAt(i).getTop(); - } - } - minTop -= AndroidUtilities.dp(4); - if (minTop < 0) { - chatTopOffset = 0; - } else { - chatTopOffset = minTop; - } - } - - float totalViewsHeight = buttonsLayout.getMeasuredHeight() + buttonsLayout2.getMeasuredHeight() - AndroidUtilities.dp(8) + (chatPreviewContainer.getMeasuredHeight() - chatTopOffset); - float totalHeight = getMeasuredHeight() - AndroidUtilities.dp(16); - yOffset = AndroidUtilities.dp(8) + (totalHeight - totalViewsHeight) / 2 - chatTopOffset; - if (yOffset > AndroidUtilities.dp(8)) { - yOffset = AndroidUtilities.dp(8); - } - float buttonX = getMeasuredWidth() - menuScrollView.getMeasuredWidth(); - menuScrollView.setTranslationX(buttonX); - } else { - yOffset = 0; - chatTopOffset = 0; - menuScrollView.setTranslationX(chatListView.getMeasuredWidth() + AndroidUtilities.dp(8)); - } - - if (!firstLayout && (chatTopOffset != lastTopOffset || yOffset != lastYOffset)) { - if (offsetsAnimator != null) { - offsetsAnimator.cancel(); - } - offsetsAnimator = ValueAnimator.ofFloat(0, 1f); - offsetsAnimator.addUpdateListener(valueAnimator -> { - float p = (float) valueAnimator.getAnimatedValue(); - currentTopOffset = (int) (lastTopOffset * (1f - p) + chatTopOffset * p); - currentYOffset = lastYOffset * (1f - p) + yOffset * p; - setOffset(currentYOffset, currentTopOffset); - }); - offsetsAnimator.setDuration(ChatListItemAnimator.DEFAULT_DURATION); - offsetsAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); - offsetsAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - offsetsAnimator = null; - setOffset(yOffset, chatTopOffset); - } - }); - - AndroidUtilities.runOnUIThread(changeBoundsRunnable, 50); - - currentTopOffset = lastTopOffset; - currentYOffset = lastYOffset; - setOffset(lastYOffset, lastTopOffset); - } else if (firstLayout) { - setOffset(currentYOffset = yOffset, currentTopOffset = chatTopOffset); - } - } - - private void setOffset(float yOffset, int chatTopOffset) { - if (isLandscapeMode) { - actionBar.setTranslationY(0); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - chatPreviewContainer.invalidateOutline(); - } - chatPreviewContainer.setTranslationY(0); - menuScrollView.setTranslationY(0); - } else { - actionBar.setTranslationY(chatTopOffset); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - chatPreviewContainer.invalidateOutline(); - } - chatPreviewContainer.setTranslationY(yOffset); - menuScrollView.setTranslationY(yOffset + chatPreviewContainer.getMeasuredHeight() - AndroidUtilities.dp(2)); - } - } - - public boolean isShowing() { - return showing; - } - - private class Adapter extends RecyclerView.Adapter { - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), false, sharedResources, resourcesProvider); - return new RecyclerListView.Holder(chatMessageCell); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - ChatMessageCell cell = (ChatMessageCell) holder.itemView; - cell.setInvalidateSpoilersParent(forwardingMessagesParams.hasSpoilers); - cell.setParentViewSize(chatListView.getMeasuredWidth(), chatListView.getMeasuredHeight()); - int id = cell.getMessageObject() != null ? cell.getMessageObject().getId() : 0; - cell.setMessageObject(forwardingMessagesParams.previewMessages.get(position), forwardingMessagesParams.groupedMessagesMap.get(forwardingMessagesParams.previewMessages.get(position).getGroupId()), true, true); - cell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { - - }); - - if (forwardingMessagesParams.previewMessages.size() > 1) { - cell.setCheckBoxVisible(true, false); - boolean animated = id == forwardingMessagesParams.previewMessages.get(position).getId(); - boolean checked = forwardingMessagesParams.selectedIds.get(forwardingMessagesParams.previewMessages.get(position).getId(), false); - cell.setChecked(checked, checked, animated); - } - - } - - @Override - public int getItemCount() { - return forwardingMessagesParams.previewMessages.size(); - } - } - - protected void selectAnotherChat() { - - } - - protected void didSendPressed() { - - } - - private MessageObject.GroupedMessages getValidGroupedMessage(MessageObject message) { - MessageObject.GroupedMessages groupedMessages = null; - if (message.getGroupId() != 0) { - groupedMessages = forwardingMessagesParams.groupedMessagesMap.get(message.getGroupId()); - if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { - groupedMessages = null; - } - } - return groupedMessages; - } - - private int getThemedColor(int key) { - return Theme.getColor(key, resourcesProvider); - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java index 4e59f8b8a..6e30f5c41 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCreateSpan.java @@ -18,12 +18,16 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Layout; +import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.style.ReplacementSpan; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; @@ -60,6 +64,7 @@ public class GroupCreateSpan extends View { private int currentAccount; private Theme.ResourcesProvider resourcesProvider; private boolean small; + private boolean drawAvatarBackground = true; public GroupCreateSpan(Context context, Object object, int currentAccount) { this(context, object, null, currentAccount); @@ -175,6 +180,18 @@ public class GroupCreateSpan extends View { firstName = UserConfig.getChatTitleOverride(currentAccount, chat); imageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_SMALL, currentAccount); imageParent = chat; + } else if (object instanceof TLRPC.TL_help_country) { + TLRPC.TL_help_country country = (TLRPC.TL_help_country) object; + String flag = LocaleController.getLanguageFlag(country.iso2); + firstName = country.default_name; + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_COUNTRY); + avatarDrawable.setTextSize(AndroidUtilities.dp(24)); + avatarDrawable.setInfo(0, flag, null, null); + avatarDrawable.setColor(Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular, resourcesProvider), 0.7f)); + avatarDrawable.setDrawAvatarBackground(drawAvatarBackground = false); + uid = country.default_name.hashCode(); + imageLocation = null; + imageParent = null; } else { avatarDrawable.setInfo(0, contact.first_name, contact.last_name); uid = contact.contact_id; @@ -191,7 +208,7 @@ public class GroupCreateSpan extends View { imageReceiver = new ImageReceiver(); imageReceiver.setRoundRadius(AndroidUtilities.dp(16)); imageReceiver.setParentView(this); - imageReceiver.setImageCoords(0, 0, AndroidUtilities.dp(small ? 28 : 32), AndroidUtilities.dp(small ? 28 : 32)); + imageReceiver.setImageCoords(drawAvatarBackground ? 0 : AndroidUtilities.dp(4), 0, AndroidUtilities.dp(small ? 28 : 32), AndroidUtilities.dp(small ? 28 : 32)); int maxNameWidth; if (AndroidUtilities.isTablet()) { 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 399011433..2b42400f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -958,7 +958,6 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega if (messageObject != convertingVideo || parentFragment == null) { return; } - parentFragment.getSendMessagesHelper().stopVideoService(messageObject.messageOwner.attachPath); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.filePreparingStarted); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.fileNewChunkAvailable); @@ -1010,7 +1009,6 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.filePreparingStarted); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).removeObserver(ImageUpdater.this, NotificationCenter.fileNewChunkAvailable); - parentFragment.getSendMessagesHelper().stopVideoService(messageObject.messageOwner.attachPath); uploadingVideo = videoPath = finalPath; convertingVideo = null; } 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 30a02492b..bb99aa76d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -16,6 +16,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; +import android.app.ActivityManager; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothProfile; import android.content.Context; @@ -51,6 +52,7 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -69,7 +71,6 @@ import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import com.google.android.exoplayer2.ExoPlayer; -import com.google.android.exoplayer2.util.Log; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; @@ -237,6 +238,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter 285904780, // XIAOMI (Redmi Note 7) -1394191079 // samsung a31 }; + private boolean allowSendingWhileRecording; @SuppressLint("ClickableViewAccessibility") @@ -1906,6 +1908,9 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter public void startRecording(File outputFile, android.opengl.EGLContext sharedContext) { int resolution = MessagesController.getInstance(currentAccount).roundVideoSize; int bitrate = MessagesController.getInstance(currentAccount).roundVideoBitrate * 1024; + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + }); videoFile = outputFile; videoWidth = resolution; @@ -1947,6 +1952,9 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter public void stopRecording(int send) { handler.sendMessage(handler.obtainMessage(MSG_STOP_RECORDING, send, 0)); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); + }); } long prevTimestamp; @@ -2560,6 +2568,9 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter movie.setRotation(0); movie.setSize(videoWidth, videoHeight); mediaMuxer = new MP4Builder().createMovie(movie, isSecretChat, false); + allowSendingWhileRecording = SharedConfig.deviceIsHigh(); + + mediaMuxer.setAllowSyncFiles(allowSendingWhileRecording); AndroidUtilities.runOnUIThread(() -> { if (cancelled) { @@ -2761,13 +2772,13 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } catch (Exception e) { e.printStackTrace(); } - if (availableSize != 0 && !writingToDifferentFile) { + if (availableSize != 0 && !writingToDifferentFile && allowSendingWhileRecording) { didWriteData(videoFile, availableSize, false); } }); } else { long availableSize = mediaMuxer.writeSampleData(videoTrackIndex, encodedData, videoBufferInfo, true); - if (availableSize != 0 && !writingToDifferentFile) { + if (availableSize != 0 && !writingToDifferentFile && allowSendingWhileRecording) { didWriteData(videoFile, availableSize, false); } } @@ -2853,7 +2864,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } catch (Exception e) { e.printStackTrace(); } - if (availableSize != 0 && !writingToDifferentFile) { + if (availableSize != 0 && !writingToDifferentFile && allowSendingWhileRecording) { didWriteData(videoFile, availableSize, false); } }); @@ -2862,7 +2873,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } } else { long availableSize = mediaMuxer.writeSampleData(audioTrackIndex, encodedData, audioBufferInfo, false); - if (availableSize != 0 && !writingToDifferentFile) { + if (availableSize != 0 && !writingToDifferentFile && allowSendingWhileRecording) { didWriteData(videoFile, availableSize, false); } if (audioEncoder != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java index 6a5839a3b..2a60efd1c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java @@ -146,6 +146,9 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica searchListViewAdapter = searchAdapter = new SearchAdapter(); listView.setAdapter(listViewAdapter = new ListAdapter()); + emptyView.showProgress(false, false); + emptyView.setVisibility(View.GONE); + ArrayList arrayList = ContactsController.getInstance(account).contacts; for (int a = 0; a < arrayList.size(); a++) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(arrayList.get(a).user_id); 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 4ea5e09ae..712d3b50d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ItemOptions.java @@ -67,6 +67,8 @@ public class ItemOptions { private ActionBarPopupWindow actionBarPopupWindow; private final float[] point = new float[2]; + private Runnable dismissListener; + private float translateX, translateY; private int dimAlpha; @@ -106,7 +108,15 @@ public class ItemOptions { } private void init() { - lastLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider); + lastLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (this == layout && maxHeight > 0) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.min(maxHeight, MeasureSpec.getSize(heightMeasureSpec)), MeasureSpec.getMode(heightMeasureSpec)); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; lastLayout.setDispatchKeyEventListener(keyEvent -> { if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_BACK && keyEvent.getRepeatCount() == 0 && actionBarPopupWindow != null && actionBarPopupWindow.isShowing()) { actionBarPopupWindow.dismiss(); @@ -134,6 +144,10 @@ public class ItemOptions { return add(iconResId, text, Theme.key_actionBarDefaultSubmenuItemIcon, Theme.key_actionBarDefaultSubmenuItem, onClickListener); } + public ItemOptions add(CharSequence text, Runnable onClickListener) { + return add(0, text, false, onClickListener); + } + public ItemOptions add(int iconResId, CharSequence text, Runnable onClickListener) { return add(iconResId, text, false, onClickListener); } @@ -153,7 +167,11 @@ public class ItemOptions { ActionBarMenuSubItem subItem = new ActionBarMenuSubItem(context, false, false, resourcesProvider); subItem.setPadding(dp(18), 0, dp(18 + (LocaleController.isRTL ? 0 : 8)), 0); - subItem.setTextAndIcon(text, iconResId); + if (iconResId != 0) { + subItem.setTextAndIcon(text, iconResId); + } else { + subItem.setText(text); + } subItem.setColors(Theme.getColor(textColorKey, resourcesProvider), Theme.getColor(iconColorKey, resourcesProvider)); subItem.setSelectorColor(Theme.multAlpha(Theme.getColor(textColorKey, resourcesProvider), .12f)); @@ -320,6 +338,16 @@ public class ItemOptions { return this; } + private int maxHeight; + public ItemOptions setMaxHeight(int px) { + this.maxHeight = px; + return this; + } + + public ViewGroup getLayout() { + return layout; + } + public ItemOptions setBlurBackground(BlurringShader.BlurManager blurManager, float ox, float oy) { Drawable baseDrawable = context.getResources().getDrawable(R.drawable.popup_fixed_alert2).mutate(); if (layout instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) { @@ -430,6 +458,11 @@ public class ItemOptions { public void dismiss() { super.dismiss(); ItemOptions.this.dismissDim(container); + + if (dismissListener != null) { + dismissListener.run(); + dismissListener = null; + } } }; actionBarPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() { @@ -437,6 +470,11 @@ public class ItemOptions { public void onDismiss() { actionBarPopupWindow = null; dismissDim(container); + + if (dismissListener != null) { + dismissListener.run(); + dismissListener = null; + } } }); actionBarPopupWindow.setOutsideTouchable(true); @@ -488,6 +526,16 @@ public class ItemOptions { return this; } + public ItemOptions setBackgroundColor(int color) { + for (int j = 0; j < layout.getChildCount(); ++j) { + View child = j == layout.getChildCount() - 1 ? lastLayout : layout.getChildAt(j); + if (child instanceof ActionBarPopupWindow.ActionBarPopupWindowLayout) { + child.setBackgroundColor(color); + } + } + return this; + } + public float getOffsetX() { return offsetX; } @@ -520,6 +568,11 @@ public class ItemOptions { return actionBarPopupWindow != null && actionBarPopupWindow.isShowing(); } + public ItemOptions setOnDismiss(Runnable dismissListener) { + this.dismissListener = dismissListener; + return this; + } + public void dismiss() { if (actionBarPopupWindow != null) { actionBarPopupWindow.dismiss(); 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 dc97dfb69..98b95b95d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LayoutHelper.java @@ -73,6 +73,12 @@ public class LayoutHelper { return layoutParams; } + public static FrameLayout.LayoutParams createFrameMarginPx(int width, float height, int gravity, int leftMarginPx, int topMarginPx, int rightMarginPx, int bottomMarginPx) { + FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); + layoutParams.setMargins(leftMarginPx, topMarginPx, rightMarginPx, bottomMarginPx); + return layoutParams; + } + public static FrameLayout.LayoutParams createFrame(int width, int height, int gravity) { return new FrameLayout.LayoutParams(getSize(width), getSize(height), gravity); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java index 7c9ff7258..b9c148aac 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java @@ -10,6 +10,7 @@ package org.telegram.ui.Components; import android.graphics.CornerPathEffect; import android.graphics.Path; +import android.graphics.RectF; import android.os.Build; import android.text.Layout; @@ -93,10 +94,18 @@ public class LinkPath extends Path { baselineShift = value; } + private float insetVert, insetHoriz; + public void setInset(float insetVert, float insetHoriz) { + this.insetVert = insetVert; + this.insetHoriz = insetHoriz; + } + + private float minX = Float.MAX_VALUE, maxX, minY = Float.MAX_VALUE, maxY; + @Override public void addRect(float left, float top, float right, float bottom, Direction dir) { if (currentLayout == null) { - super.addRect(left, top, right, bottom, dir); + superAddRect(left, top, right, bottom, dir); return; } try { @@ -143,15 +152,31 @@ public class LinkPath extends Path { // int startOffset = currentLayout.getOffsetForHorizontal(currentLine, left), endOffset = currentLayout.getOffsetForHorizontal(currentLine, right) + 1; boolean startsWithWhitespace = false; // startOffset >= 0 && startOffset < text.length() && text.charAt(startOffset) == ' '; boolean endsWithWhitespace = false; // endOffset >= 0 && endOffset < text.length() && text.charAt(endOffset) == ' '; - super.addRect(left - (startsWithWhitespace ? 0 : getRadius() / 2f), y, right + (endsWithWhitespace ? 0 : getRadius() / 2f), y2, dir); + superAddRect(left - (startsWithWhitespace ? 0 : getRadius() / 2f), y, right + (endsWithWhitespace ? 0 : getRadius() / 2f), y2, dir); } else { - super.addRect(left, y, right, y2, dir); + superAddRect(left, y, right, y2, dir); } } catch (Exception e) { } } + private void superAddRect(float l, float t, float r, float b, Path.Direction d) { + l -= insetHoriz; + t -= insetVert; + r += insetHoriz; + b += insetVert; + minX = Math.min(minX, Math.min(l, r)); + minY = Math.min(minY, Math.min(t, b)); + maxX = Math.max(maxX, Math.max(l, r)); + maxY = Math.max(maxY, Math.max(t, b)); + super.addRect(l, t, r, b, d); + } + + public void getBounds(RectF bounds) { + bounds.set(minX, minY, maxX, maxY); + } + @Override public void reset() { if (!allowReset) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LoginOrView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LoginOrView.java index 9112bd40c..6a888c6af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LoginOrView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LoginOrView.java @@ -13,7 +13,7 @@ import org.telegram.messenger.R; import org.telegram.ui.ActionBar.Theme; public class LoginOrView extends View { - private final static int LINE_SIZE_DP = 48; + private final static int LINE_SIZE_DP = 64; private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java index 7d18f8de7..4a9db3bf0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -1,51 +1,37 @@ package org.telegram.ui.Components; import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.messenger.AndroidUtilities.dpf2; import static org.telegram.messenger.AndroidUtilities.lerp; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.animation.StateListAnimator; import android.animation.ValueAnimator; -import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.content.res.Configuration; import android.graphics.Canvas; -import android.graphics.Outline; import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.graphics.drawable.RippleDrawable; import android.os.Build; import android.os.Bundle; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; import android.text.TextUtils; import android.util.SparseArray; -import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; -import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.TextView; -import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; -import org.checkerframework.checker.units.qual.Angle; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.ContactsController; @@ -59,9 +45,9 @@ 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.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -196,7 +182,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha finishFragment(); } else if (id == 2) { if (actionModeMessageObjects != null) { - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); for (int i = 0; i < actionModeMessageObjects.size(); ++i) { MessageObject messageObject = actionModeMessageObjects.valueAt(i); if (messageObject.storyItem != null) { @@ -211,7 +197,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { - getMessagesController().getStoriesController().deleteStories(storyItems); + getMessagesController().getStoriesController().deleteStories(dialogId, storyItems); sharedMediaLayout.closeActionMode(false); } }); @@ -441,7 +427,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha Bulletin.hideVisible(); boolean pin = sharedMediaLayout.getClosestTab() == SharedMediaLayout.TAB_ARCHIVED_STORIES; int count = 0; - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); if (actionModeMessageObjects != null) { for (int i = 0; i < actionModeMessageObjects.size(); ++i) { MessageObject messageObject = actionModeMessageObjects.valueAt(i); @@ -461,7 +447,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha } boolean[] pastValues = new boolean[storyItems.size()]; for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); + TL_stories.StoryItem storyItem = storyItems.get(i); pastValues[i] = storyItem.pinned; storyItem.pinned = pin; } @@ -474,7 +460,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha undone[0] = true; AndroidUtilities.cancelRunOnUIThread(applyBulletin); for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); + TL_stories.StoryItem storyItem = storyItems.get(i); storyItem.pinned = pastValues[i]; } getMessagesController().getStoriesController().updateStoriesInLists(dialogId, storyItems); @@ -591,6 +577,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha }, SharedMediaLayout.VIEW_TYPE_MEDIA_ACTIVITY, getResourceProvider()) { @Override protected void onSelectedTabChanged() { + super.onSelectedTabChanged(); updateMediaCount(); } @@ -887,6 +874,9 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha private int lastTab; private void updateMediaCount() { + if (sharedMediaLayout == null) { + return; + } int id = sharedMediaLayout.getClosestTab(); int[] mediaCount = sharedMediaPreloader.getLastMediaCount(); final boolean animated = !LocaleController.isRTL; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java index 6023ee22d..8610b8c86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MemberRequestsBottomSheet.java @@ -38,7 +38,7 @@ public class MemberRequestsBottomSheet extends UsersAlertBase { if (membersEmptyView.getVisibility() != View.INVISIBLE) { membersEmptyView.setVisibility(View.INVISIBLE); } - dismiss(); +// dismiss(); } else if (fromHide) { searchView.searchEditText.setText(""); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MenuToItemOptions.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MenuToItemOptions.java new file mode 100644 index 000000000..fa892ea4e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MenuToItemOptions.java @@ -0,0 +1,158 @@ +package org.telegram.ui.Components; + +import android.content.ComponentName; +import android.content.Intent; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuItem; +import android.view.SubMenu; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.FloatingToolbar; + +public class MenuToItemOptions implements Menu { + + private final ItemOptions itemOptions; + private final Utilities.Callback onMenuClicked; + private final Runnable premiumLock; + + public MenuToItemOptions(@NonNull ItemOptions itemOptions, @NonNull Utilities.Callback onMenuClicked, @Nullable Runnable premiumLock) { + this.itemOptions = itemOptions; + this.onMenuClicked = onMenuClicked; + this.premiumLock = premiumLock; + } + + @Override + public MenuItem add(int groupId, int itemId, int order, CharSequence title) { + if (premiumLock != null && FloatingToolbar.premiumOptions.contains(itemId) && MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked) { + return null; + } + itemOptions.add(title, () -> onMenuClicked.run(itemId)); + if (premiumLock != null && FloatingToolbar.premiumOptions.contains(itemId)) { + itemOptions.putPremiumLock(premiumLock); + } + return null; + } + + @Override + public MenuItem add(int groupId, int itemId, int order, int titleRes) { + return this.add(groupId, itemId, order, LocaleController.getString(titleRes)); + } + + + @Override + public MenuItem add(CharSequence title) { + return null; + } + + @Override + public MenuItem add(int titleRes) { + return null; + } + + @Override + public SubMenu addSubMenu(CharSequence title) { + return null; + } + + @Override + public SubMenu addSubMenu(int titleRes) { + return null; + } + + @Override + public SubMenu addSubMenu(int groupId, int itemId, int order, CharSequence title) { + return null; + } + + @Override + public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) { + return null; + } + + @Override + public int addIntentOptions(int groupId, int itemId, int order, ComponentName caller, Intent[] specifics, Intent intent, int flags, MenuItem[] outSpecificItems) { + return 0; + } + + @Override + public void removeItem(int id) { + + } + + @Override + public void removeGroup(int groupId) { + + } + + @Override + public void clear() { + + } + + @Override + public void setGroupCheckable(int group, boolean checkable, boolean exclusive) { + + } + + @Override + public void setGroupVisible(int group, boolean visible) { + + } + + @Override + public void setGroupEnabled(int group, boolean enabled) { + + } + + @Override + public boolean hasVisibleItems() { + return false; + } + + @Override + public MenuItem findItem(int id) { + return null; + } + + @Override + public int size() { + return 0; + } + + @Override + public MenuItem getItem(int index) { + return null; + } + + @Override + public void close() { + + } + + @Override + public boolean performShortcut(int keyCode, KeyEvent event, int flags) { + return false; + } + + @Override + public boolean isShortcutKey(int keyCode, KeyEvent event) { + return false; + } + + @Override + public boolean performIdentifierAction(int id, int flags) { + return false; + } + + @Override + public void setQwertyMode(boolean isQwerty) { + + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java new file mode 100644 index 000000000..6af5bf86f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MessagePreviewView.java @@ -0,0 +1,2348 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.icu.util.Measure; +import android.os.Build; +import android.text.Spanned; +import android.text.StaticLayout; +import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.text.style.URLSpan; +import android.util.Log; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewOutlineProvider; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ScrollView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.ChatListItemAnimator; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.GridLayoutManagerFixed; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ChatMessageSharedResources; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MessagePreviewParams; +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.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; +import org.telegram.ui.ActionBar.EmojiThemes; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Cells.TextSelectionHelper; +import org.telegram.ui.ChatActivity; + +import java.util.ArrayList; + +public class MessagePreviewView extends FrameLayout { + + TLRPC.Peer sendAsPeer; + public void setSendAsPeer(TLRPC.Peer defPeer) { + sendAsPeer = defPeer; + for (int i = 0; i < viewPager.viewPages.length; ++i) { + if (viewPager.viewPages[i] != null && ((Page) viewPager.viewPages[i]).currentTab == TAB_FORWARD) { + ((Page) viewPager.viewPages[i]).updateMessages(); + } + } + } + + public interface ResourcesDelegate extends Theme.ResourcesProvider { + + Drawable getWallpaperDrawable(); + + boolean isWallpaperMotion(); + } + + public static final int TAB_REPLY = 0; + public static final int TAB_FORWARD = 1; + public static final int TAB_LINK = 2; + + final boolean showOutdatedQuote; + final ChatActivity chatActivity; + final MessagePreviewParams messagePreviewParams; + + private class Page extends FrameLayout { + public int currentTab; + + SizeNotifierFrameLayout chatPreviewContainer; + MessagePreviewView.ActionBar actionBar; + View textSelectionOverlay; + TextSelectionHelper.ChatListTextSelectionHelper textSelectionHelper; + RecyclerListView chatListView; + ChatListItemAnimator itemAnimator; + GridLayoutManagerFixed chatLayoutManager; + Adapter adapter; + + MessagePreviewParams.Messages messages; + + ActionBarPopupWindow.ActionBarPopupWindowLayout menu; + ActionBarMenuSubItem quoteButton, clearQuoteButton; + ActionBarMenuSubItem replyAnotherChatButton, quoteAnotherChatButton; + ActionBarMenuSubItem deleteReplyButton; + ToggleButton changePositionBtn; + ToggleButton changeSizeBtn; + boolean shownBackMenu; + int menuBack; + ChatMessageSharedResources sharedResources; + private boolean firstLayout = true; + + int scrollToOffset = -1; + + + boolean toQuote; + private AnimatorSet quoteSwitcher; + private void switchToQuote(boolean _quote, boolean animated) { + if (showOutdatedQuote) { + _quote = false; + } + final boolean quote = _quote; + if (animated && toQuote == quote) { + return; + } + toQuote = quote; + + if (quoteSwitcher != null) { + quoteSwitcher.cancel(); + quoteSwitcher = null; + } + + if (animated) { + quoteSwitcher = new AnimatorSet(); + final ArrayList animators = new ArrayList<>(); + if (quoteButton != null) { + quoteButton.setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(quoteButton, View.ALPHA, !quote ? 1f : 0f)); + } + if (clearQuoteButton != null) { + clearQuoteButton.setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(clearQuoteButton, View.ALPHA, quote ? 1f : 0f)); + } + if (replyAnotherChatButton != null) { + replyAnotherChatButton.setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(replyAnotherChatButton, View.ALPHA, !quote ? 1f : 0f)); + } + if (quoteAnotherChatButton != null) { + quoteAnotherChatButton.setVisibility(View.VISIBLE); + animators.add(ObjectAnimator.ofFloat(quoteAnotherChatButton, View.ALPHA, quote ? 1f : 0f)); + } + quoteSwitcher.playTogether(animators); + quoteSwitcher.setDuration(360); + quoteSwitcher.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + quoteSwitcher.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + quoteSwitcher = null; + switchToQuote(quote, false); + } + }); + quoteSwitcher.start(); + } else { + if (quoteButton != null) { + quoteButton.setAlpha(!quote ? 1f : 0f); + quoteButton.setVisibility(!quote ? View.VISIBLE : View.INVISIBLE); + } + if (clearQuoteButton != null) { + clearQuoteButton.setAlpha(quote ? 1f : 0f); + clearQuoteButton.setVisibility(quote ? View.VISIBLE : View.INVISIBLE); + } + if (replyAnotherChatButton != null) { + replyAnotherChatButton.setAlpha(!quote ? 1f : 0f); + replyAnotherChatButton.setVisibility(!quote ? View.VISIBLE : View.INVISIBLE); + } + if (quoteAnotherChatButton != null) { + quoteAnotherChatButton.setAlpha(quote ? 1f : 0f); + quoteAnotherChatButton.setVisibility(quote ? View.VISIBLE : View.INVISIBLE); + } + } + } + + public boolean isReplyMessageCell(ChatMessageCell cell) { + if (cell == null || cell.getMessageObject() == null) return false; + MessageObject replyMessage = getReplyMessage(); + if (replyMessage == null) return false; + return (cell.getMessageObject() == replyMessage || cell.getMessageObject().getId() == replyMessage.getId()); + } + + public ChatMessageCell getReplyMessageCell() { + MessageObject replyMessage = getReplyMessage(); + if (replyMessage == null) { + return null; + } + for (int i = 0; i < chatListView.getChildCount(); ++i) { + ChatMessageCell cell = (ChatMessageCell) chatListView.getChildAt(i); + if (cell.getMessageObject() == null) continue; + if (cell.getMessageObject() == replyMessage || cell.getMessageObject().getId() == replyMessage.getId()) { + return cell; + } + } + return null; + } + + public MessageObject getReplyMessage() { + if (messagePreviewParams.replyMessage != null) { + if (messagePreviewParams.replyMessage.groupedMessagesMap != null && messagePreviewParams.replyMessage.groupedMessagesMap.size() > 0) { + MessageObject.GroupedMessages group = messagePreviewParams.replyMessage.groupedMessagesMap.valueAt(0); + if (group != null) { + return group.captionMessage; + } + } + return messagePreviewParams.replyMessage.messages.get(0); + } + return null; + } + + Rect rect = new Rect(); + + int chatTopOffset; + float yOffset; + int currentTopOffset; + float currentYOffset; + + public Page(Context context, int tab) { + super(context); + sharedResources = new ChatMessageSharedResources(context); + + currentTab = tab; + + setOnTouchListener((view, motionEvent) -> { + if (motionEvent.getAction() == MotionEvent.ACTION_UP) { + dismiss(true); + } + return true; + }); + + chatPreviewContainer = new SizeNotifierFrameLayout(context) { + @Override + protected Drawable getNewDrawable() { + Drawable drawable = resourcesProvider.getWallpaperDrawable(); + return drawable != null ? drawable : super.getNewDrawable(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + if (ev.getY() < currentTopOffset) { + return false; + } + return super.dispatchTouchEvent(ev); + } + }; + chatPreviewContainer.setBackgroundImage(resourcesProvider.getWallpaperDrawable(), resourcesProvider.isWallpaperMotion()); + chatPreviewContainer.setOccupyStatusBar(false); + + if (Build.VERSION.SDK_INT >= 21) { + chatPreviewContainer.setOutlineProvider(new ViewOutlineProvider() { + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @Override + public void getOutline(View view, Outline outline) { + outline.setRoundRect(0, (int) (currentTopOffset + 1), view.getMeasuredWidth(), view.getMeasuredHeight(), dp(8)); + } + }); + chatPreviewContainer.setClipToOutline(true); + chatPreviewContainer.setElevation(dp(4)); + } + + actionBar = new MessagePreviewView.ActionBar(context, resourcesProvider); + actionBar.setBackgroundColor(getThemedColor(Theme.key_actionBarDefault)); + + textSelectionHelper = new TextSelectionHelper.ChatListTextSelectionHelper() { + { + resourcesProvider = MessagePreviewView.this.resourcesProvider; + } + + @Override + protected Theme.ResourcesProvider getResourcesProvider() { + return resourcesProvider; + } + + @Override + public void invalidate() { + super.invalidate(); + if (chatListView != null) { + chatListView.invalidate(); + } + } + + @Override + protected boolean canShowQuote() { + return currentTab == TAB_REPLY && !messagePreviewParams.secret; + } + + @Override + protected void onQuoteClick(MessageObject messageObject, int start, int end, CharSequence text) { + if (textSelectionHelper.selectionEnd - textSelectionHelper.selectionStart > MessagesController.getInstance(currentAccount).quoteLengthMax) { + showQuoteLengthError(); + return; + } + messagePreviewParams.quoteStart = textSelectionHelper.selectionStart; + messagePreviewParams.quoteEnd = textSelectionHelper.selectionEnd; + if (messagePreviewParams.quote == null) { + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(getReplyMessage(), start, end); + } + onQuoteSelectedPart(); + dismiss(true); + } + + @Override + public boolean isSelected(MessageObject messageObject) { + return currentTab == TAB_REPLY && !messagePreviewParams.secret && isInSelectionMode(); + } + }; + textSelectionHelper.setCallback(new TextSelectionHelper.Callback() { + @Override + public void onStateChanged(boolean isSelected) { + if (!showing) { + return; + } + if (!isSelected && menu.getSwipeBack().isForegroundOpen()) { + menu.getSwipeBack().closeForeground(true); + } else if (isSelected && messagePreviewParams.quote == null) { + if (textSelectionHelper.selectionEnd - textSelectionHelper.selectionStart > MessagesController.getInstance(currentAccount).quoteLengthMax) { + showQuoteLengthError(); + return; + } + messagePreviewParams.quoteStart = textSelectionHelper.selectionStart; + messagePreviewParams.quoteEnd = textSelectionHelper.selectionEnd; + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(getReplyMessage(), messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + menu.getSwipeBack().openForeground(menuBack); + } + } + }); + + chatListView = new RecyclerListView(context, resourcesProvider) { + + @Override + public boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + boolean r = super.drawChild(canvas, child, drawingTime); + cell.drawCheckBox(canvas); + canvas.save(); + canvas.translate(cell.getX(), cell.getY()); + + canvas.save(); + canvas.scale(cell.getScaleX(), cell.getScaleY(), cell.getPivotX(), cell.getPivotY()); + cell.drawContent(canvas, true); + cell.layoutTextXY(true); + cell.drawMessageText(canvas); + if ((cell.getCurrentMessagesGroup() == null || cell.getCurrentPosition() != null && cell.getCurrentPosition().last) || cell.getTransitionParams().animateBackgroundBoundsInner) { + cell.drawCaptionLayout(canvas, false, cell.getAlpha()); + } + if (cell.getCurrentMessagesGroup() != null || cell.getTransitionParams().animateBackgroundBoundsInner) { + cell.drawNamesLayout(canvas, cell.getAlpha()); + } + if ((cell.getCurrentPosition() != null && cell.getCurrentPosition().last) || cell.getTransitionParams().animateBackgroundBoundsInner) { + cell.drawTime(canvas, cell.getAlpha(), true); + } + cell.drawOverlays(canvas); + canvas.restore(); + cell.getTransitionParams().recordDrawingStatePreview(); + canvas.restore(); + return r; + } + return true; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + cell.setParentViewSize(chatPreviewContainer.getMeasuredWidth(), chatPreviewContainer.getBackgroundSizeY()); + } + } + drawChatBackgroundElements(canvas); + super.dispatchDraw(canvas); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + if (firstLayout) { + if (currentTab != TAB_REPLY) { + scrollToPosition(0); + } + firstLayout = false; + } + super.onLayout(changed, l, t, r, b); + updatePositions(); + checkScroll(); +// if (scrollToOffset != -1) { +// final int offset = scrollToOffset; +// post(() -> chatLayoutManager.scrollToPositionWithOffset(0, offset, false)); +// scrollToOffset = -1; +// } + } + + private void drawChatBackgroundElements(Canvas canvas) { + int count = getChildCount(); + MessageObject.GroupedMessages lastDrawnGroup = null; + + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); + if (group != null && group == lastDrawnGroup) { + continue; + } + lastDrawnGroup = group; + MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); + MessageBackgroundDrawable backgroundDrawable = cell.getBackgroundDrawable(); + } + } + MessageObject.GroupedMessages scrimGroup = null; + for (int k = 0; k < 3; k++) { + drawingGroups.clear(); + if (k == 2 && !chatListView.isFastScrollAnimationRunning()) { + continue; + } + for (int i = 0; i < count; i++) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) child; + if (child.getY() > chatListView.getHeight() || child.getY() + child.getHeight() < 0) { + continue; + } + MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); + if (group == null || (k == 0 && group.messages.size() == 1) || (k == 1 && !group.transitionParams.drawBackgroundForDeletedItems)) { + continue; + } + if ((k == 0 && cell.getMessageObject().deleted) || (k == 1 && !cell.getMessageObject().deleted)) { + continue; + } + if ((k == 2 && !cell.willRemovedAfterAnimation()) || (k != 2 && cell.willRemovedAfterAnimation())) { + continue; + } + + if (!drawingGroups.contains(group)) { + group.transitionParams.left = 0; + group.transitionParams.top = 0; + group.transitionParams.right = 0; + group.transitionParams.bottom = 0; + + group.transitionParams.pinnedBotton = false; + group.transitionParams.pinnedTop = false; + group.transitionParams.cell = cell; + drawingGroups.add(group); + } + + group.transitionParams.pinnedTop = cell.isPinnedTop(); + group.transitionParams.pinnedBotton = cell.isPinnedBottom(); + + int left = (cell.getLeft() + cell.getBackgroundDrawableLeft()); + int right = (cell.getLeft() + cell.getBackgroundDrawableRight()); + int top = (cell.getTop() + cell.getBackgroundDrawableTop()); + int bottom = (cell.getTop() + cell.getBackgroundDrawableBottom()); + + if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_TOP) == 0) { + top -= dp(10); + } + + if ((cell.getCurrentPosition().flags & MessageObject.POSITION_FLAG_BOTTOM) == 0) { + bottom += dp(10); + } + + if (cell.willRemovedAfterAnimation()) { + group.transitionParams.cell = cell; + } + + if (group.transitionParams.top == 0 || top < group.transitionParams.top) { + group.transitionParams.top = top; + } + if (group.transitionParams.bottom == 0 || bottom > group.transitionParams.bottom) { + group.transitionParams.bottom = bottom; + } + if (group.transitionParams.left == 0 || left < group.transitionParams.left) { + group.transitionParams.left = left; + } + if (group.transitionParams.right == 0 || right > group.transitionParams.right) { + group.transitionParams.right = right; + } + } + } + + for (int i = 0; i < drawingGroups.size(); i++) { + MessageObject.GroupedMessages group = drawingGroups.get(i); + if (group == scrimGroup) { + continue; + } + float x = group.transitionParams.cell.getNonAnimationTranslationX(true); + float l = (group.transitionParams.left + x + group.transitionParams.offsetLeft); + float t = (group.transitionParams.top + group.transitionParams.offsetTop); + float r = (group.transitionParams.right + x + group.transitionParams.offsetRight); + float b = (group.transitionParams.bottom + group.transitionParams.offsetBottom); + + if (!group.transitionParams.backgroundChangeBounds) { + t += group.transitionParams.cell.getTranslationY(); + b += group.transitionParams.cell.getTranslationY(); + } + + if (t < -dp(20)) { + t = -dp(20); + } + + if (b > chatListView.getMeasuredHeight() + dp(20)) { + b = chatListView.getMeasuredHeight() + dp(20); + } + + boolean useScale = group.transitionParams.cell.getScaleX() != 1f || group.transitionParams.cell.getScaleY() != 1f; + if (useScale) { + canvas.save(); + canvas.scale(group.transitionParams.cell.getScaleX(), group.transitionParams.cell.getScaleY(), l + (r - l) / 2, t + (b - t) / 2); + } + + group.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, group.transitionParams.pinnedTop, group.transitionParams.pinnedBotton, false, 0); + group.transitionParams.cell = null; + group.transitionParams.drawCaptionLayout = group.hasCaption; + if (useScale) { + canvas.restore(); + for (int ii = 0; ii < count; ii++) { + View child = chatListView.getChildAt(ii); + if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getCurrentMessagesGroup() == group) { + ChatMessageCell cell = ((ChatMessageCell) child); + int left = cell.getLeft(); + int top = cell.getTop(); + child.setPivotX(l - left + (r - l) / 2); + child.setPivotY(t - top + (b - t) / 2); + } + } + } + } + } + } + + @Override + public void onScrollStateChanged(int newState) { + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + textSelectionHelper.stopScrolling(); + } + super.onScrollStateChanged(newState); + } + + @Override + public void onScrolled(int dx, int dy) { + super.onScrolled(dx, dy); + textSelectionHelper.onParentScrolled(); + } + }; + chatListView.setItemAnimator(itemAnimator = new ChatListItemAnimator(null, chatListView, resourcesProvider) { + + int scrollAnimationIndex = -1; + + @Override + public void onAnimationStart() { + super.onAnimationStart(); + AndroidUtilities.cancelRunOnUIThread(changeBoundsRunnable); + changeBoundsRunnable.run(); + + if (scrollAnimationIndex == -1) { + scrollAnimationIndex = NotificationCenter.getInstance(currentAccount).setAnimationInProgress(scrollAnimationIndex, null, false); + } + if (finishRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(finishRunnable); + finishRunnable = null; + } + } + + + Runnable finishRunnable; + + @Override + protected void onAllAnimationsDone() { + super.onAllAnimationsDone(); + if (finishRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(finishRunnable); + } + AndroidUtilities.runOnUIThread(finishRunnable = () -> { + if (scrollAnimationIndex != -1) { + NotificationCenter.getInstance(currentAccount).onAnimationFinish(scrollAnimationIndex); + scrollAnimationIndex = -1; + } + }); + + if (updateAfterAnimations) { + updateAfterAnimations = false; + AndroidUtilities.runOnUIThread(() -> updateMessages()); + } + } + + @Override + public void endAnimations() { + super.endAnimations(); + if (finishRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(finishRunnable); + } + AndroidUtilities.runOnUIThread(finishRunnable = () -> { + if (scrollAnimationIndex != -1) { + NotificationCenter.getInstance(currentAccount).onAnimationFinish(scrollAnimationIndex); + scrollAnimationIndex = -1; + } + }); + } + }); + chatListView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + for (int i = 0; i < chatListView.getChildCount(); i++) { + ChatMessageCell cell = (ChatMessageCell) chatListView.getChildAt(i); + cell.setParentViewSize(chatPreviewContainer.getMeasuredWidth(), chatPreviewContainer.getBackgroundSizeY()); + } + + if (textSelectionHelper != null) { + textSelectionHelper.invalidate(); + } + } + }); + chatListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + if (currentTab != TAB_FORWARD || messages.previewMessages.size() <= 1) { + return; + } + int id = messages.previewMessages.get(position).getId(); + boolean newSelected = !messages.selectedIds.get(id, false); + if (messages.selectedIds.size() == 1 && !newSelected) { + return; + } + if (!newSelected) { + messages.selectedIds.delete(id); + } else { + messages.selectedIds.put(id, newSelected); + } + ChatMessageCell chatMessageCell = (ChatMessageCell) view; + chatMessageCell.setChecked(newSelected, newSelected, true); + updateSubtitle(true); + } + }); + + chatListView.setAdapter(adapter = new Adapter()); + chatListView.setPadding(0, dp(4), 0, dp(4)); + chatLayoutManager = new GridLayoutManagerFixed(context, 1000, LinearLayoutManager.VERTICAL, true) { + + @Override + public boolean shouldLayoutChildFromOpositeSide(View child) { + return false; + } + + @Override + protected boolean hasSiblingChild(int position) { + MessageObject message = messages.previewMessages.get(position); + MessageObject.GroupedMessages group = getValidGroupedMessage(message); + if (group != null) { + MessageObject.GroupedMessagePosition pos = group.positions.get(message); + if (pos.minX == pos.maxX || pos.minY != pos.maxY || pos.minY == 0) { + return false; + } + int count = group.posArray.size(); + for (int a = 0; a < count; a++) { + MessageObject.GroupedMessagePosition p = group.posArray.get(a); + if (p == pos) { + continue; + } + if (p.minY <= pos.minY && p.maxY >= pos.minY) { + return true; + } + } + } + return false; + } + + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + if (BuildVars.DEBUG_PRIVATE_VERSION) { + super.onLayoutChildren(recycler, state); + } else { + try { + super.onLayoutChildren(recycler, state); + } catch (Exception e) { + FileLog.e(e); + AndroidUtilities.runOnUIThread(() -> adapter.notifyDataSetChanged()); + } + } + } + }; + chatLayoutManager.setSpanSizeLookup(new GridLayoutManagerFixed.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + int idx = position; + if (idx >= 0 && idx < messages.previewMessages.size()) { + MessageObject message = messages.previewMessages.get(idx); + MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(message); + if (groupedMessages != null) { + return groupedMessages.positions.get(message).spanSize; + } + } + return 1000; + } + }); + chatListView.setClipToPadding(false); + chatListView.setLayoutManager(chatLayoutManager); + chatListView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.bottom = 0; + if (view instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) view; + MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); + if (group != null) { + MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); + if (position != null && position.siblingHeights != null) { + float maxHeight = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.5f; + int h = cell.getExtraInsetHeight(); + for (int a = 0; a < position.siblingHeights.length; a++) { + h += (int) Math.ceil(maxHeight * position.siblingHeights[a]); + } + h += (position.maxY - position.minY) * Math.round(7 * AndroidUtilities.density); + int count = group.posArray.size(); + for (int a = 0; a < count; a++) { + MessageObject.GroupedMessagePosition pos = group.posArray.get(a); + if (pos.minY != position.minY || pos.minX == position.minX && pos.maxX == position.maxX && pos.minY == position.minY && pos.maxY == position.maxY) { + continue; + } + if (pos.minY == position.minY) { + h -= (int) Math.ceil(maxHeight * pos.ph) - dp(4); + break; + } + } + outRect.bottom = -h; + } + } + } + } + }); + + chatPreviewContainer.addView(chatListView); + addView(chatPreviewContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 400, 0, 8, 0, 8, 0)); + chatPreviewContainer.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + menu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext(), R.drawable.popup_fixed_alert2, resourcesProvider, ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_USE_SWIPEBACK); + menu.getSwipeBack().setOnForegroundOpenFinished(() -> { + switchToQuote(true, false); + }); + addView(menu, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + if (tab == TAB_REPLY && messagePreviewParams.replyMessage != null) { + if (messagePreviewParams.replyMessage.hasText) { + LinearLayout swipeback = new LinearLayout(context); + swipeback.setOrientation(LinearLayout.VERTICAL); + + if (!showOutdatedQuote) { + ActionBarMenuSubItem backButton = new ActionBarMenuSubItem(context, false, true, false, resourcesProvider); + backButton.setTextAndIcon(LocaleController.getString(R.string.Back), R.drawable.msg_arrow_back); + backButton.setOnClickListener(v -> { + messagePreviewParams.quote = null; + textSelectionHelper.clear(); + switchToQuote(false, false); + menu.getSwipeBack().closeForeground(); + }); + swipeback.addView(backButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(context, resourcesProvider); + gap.setTag(R.id.fit_width_tag, 1); + swipeback.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + + ActionBarMenuSubItem selectQuoteButton = new ActionBarMenuSubItem(context, false, false, true, resourcesProvider); + selectQuoteButton.setTextAndIcon(LocaleController.getString(R.string.QuoteSelectedPart), R.drawable.menu_quote_specific); + selectQuoteButton.setOnClickListener(v -> { + MessageObject replyMessage = getReplyMessage(); + if (replyMessage != null) { + if (textSelectionHelper.selectionEnd - textSelectionHelper.selectionStart > MessagesController.getInstance(currentAccount).quoteLengthMax) { + showQuoteLengthError(); + return; + } + messagePreviewParams.quoteStart = textSelectionHelper.selectionStart; + messagePreviewParams.quoteEnd = textSelectionHelper.selectionEnd; + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(replyMessage, messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + onQuoteSelectedPart(); + dismiss(true); + } + }); + swipeback.addView(selectQuoteButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + } + + menuBack = menu.addViewToSwipeBack(swipeback); + menu.getSwipeBack().setStickToRight(true); + + FrameLayout btn1 = new FrameLayout(context); + quoteButton = new ActionBarMenuSubItem(context, true, true, false, resourcesProvider) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (getVisibility() != View.VISIBLE || getAlpha() < .5f) { + return false; + } + return super.onTouchEvent(event); + } + + @Override + public void updateBackground() { + setBackground(null); + } + }; + quoteButton.setTextAndIcon(LocaleController.getString(showOutdatedQuote ? R.string.QuoteSelectedPart : R.string.SelectSpecificQuote), R.drawable.menu_select_quote); + clearQuoteButton = new ActionBarMenuSubItem(context, true, true, false, resourcesProvider) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (getVisibility() != View.VISIBLE || getAlpha() < .5f) { + return false; + } + return super.onTouchEvent(event); + } + + @Override + public void updateBackground() { + setBackground(null); + } + }; + clearQuoteButton.setTextAndIcon(LocaleController.getString(R.string.ClearQuote), R.drawable.menu_quote_delete); + btn1.setBackground(Theme.createRadSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 6, 0)); + btn1.setOnClickListener(v -> { + if (messagePreviewParams.quote != null && !showOutdatedQuote) { + // clear + messagePreviewParams.quote = null; + textSelectionHelper.clear(); + switchToQuote(false, true); + updateSubtitle(true); + } else { + // switch to select + if (textSelectionHelper.selectionEnd - textSelectionHelper.selectionStart > MessagesController.getInstance(currentAccount).quoteLengthMax) { + showQuoteLengthError(); + return; + } + MessageObject replyMessage = getReplyMessage(); + if (replyMessage != null) { + if (textSelectionHelper.isInSelectionMode()) { + messagePreviewParams.quoteStart = textSelectionHelper.selectionStart; + messagePreviewParams.quoteEnd = textSelectionHelper.selectionEnd; + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(replyMessage, messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + onQuoteSelectedPart(); + dismiss(true); + return; + } else { + messagePreviewParams.quoteStart = 0; + messagePreviewParams.quoteEnd = Math.min(MessagesController.getInstance(currentAccount).quoteLengthMax, replyMessage.messageOwner.message.length()); + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(replyMessage, messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + textSelectionHelper.select(getReplyMessageCell(), messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + } + if (!showOutdatedQuote) { + menu.getSwipeBack().openForeground(menuBack); + } + switchToQuote(true, true); + } + } + }); + + btn1.addView(quoteButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + btn1.addView(clearQuoteButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + menu.addView(btn1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + } + + if (!messagePreviewParams.noforwards) { + FrameLayout btn2 = new FrameLayout(context); + replyAnotherChatButton = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); + replyAnotherChatButton.setTextAndIcon(LocaleController.getString(R.string.ReplyToAnotherChat), R.drawable.msg_forward_replace); + replyAnotherChatButton.setOnClickListener(v -> selectAnotherChat(false)); + quoteAnotherChatButton = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); + quoteAnotherChatButton.setTextAndIcon(LocaleController.getString(R.string.QuoteToAnotherChat), R.drawable.msg_forward_replace); + quoteAnotherChatButton.setOnClickListener(v -> selectAnotherChat(false)); + btn2.addView(quoteAnotherChatButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + btn2.addView(replyAnotherChatButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + menu.addView(btn2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + } + + ActionBarPopupWindow.GapView gap2 = new ActionBarPopupWindow.GapView(context, resourcesProvider); + gap2.setTag(R.id.fit_width_tag, 1); + menu.addView(gap2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + + switchToQuote(messagePreviewParams.quote != null, false); + + ActionBarMenuSubItem applyChanges = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); + applyChanges.setTextAndIcon(LocaleController.getString(R.string.ApplyChanges), R.drawable.msg_select); + applyChanges.setOnClickListener(v -> dismiss(true)); + menu.addView(applyChanges, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + deleteReplyButton = new ActionBarMenuSubItem(context, true, false, true, resourcesProvider); + deleteReplyButton.setTextAndIcon(LocaleController.getString(showOutdatedQuote ? R.string.DoNotQuote : R.string.DoNotReply), R.drawable.msg_delete); + deleteReplyButton.setColors(getThemedColor(Theme.key_text_RedBold), getThemedColor(Theme.key_text_RedRegular)); + deleteReplyButton.setSelectorColor(Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular), .12f)); + deleteReplyButton.setOnClickListener(v -> { + if (showOutdatedQuote) { + removeQuote(); + } else { + removeReply(); + } + }); + menu.addView(deleteReplyButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + } else if (tab == TAB_FORWARD && messagePreviewParams.forwardMessages != null) { + + ToggleButton sendersNameButton = new ToggleButton( + context, + R.raw.name_hide, messagePreviewParams.multipleUsers ? LocaleController.getString(R.string.ShowSenderNames) : LocaleController.getString(R.string.ShowSendersName), + R.raw.name_show, messagePreviewParams.multipleUsers ? LocaleController.getString(R.string.HideSenderNames) : LocaleController.getString(R.string.HideSendersName) + ); + menu.addView(sendersNameButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + final ToggleButton captionButton; + if (messagePreviewParams.hasCaption) { + captionButton = new ToggleButton( + context, + R.raw.caption_hide, LocaleController.getString(R.string.ShowCaption), + R.raw.caption_show, LocaleController.getString(R.string.HideCaption) + ); + captionButton.setState(messagePreviewParams.hideCaption, false); + menu.addView(captionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + } else { + captionButton = null; + } + + ActionBarMenuSubItem changeRecipientView = new ActionBarMenuSubItem(context, true, false, resourcesProvider); + changeRecipientView.setOnClickListener(view -> selectAnotherChat(true)); + changeRecipientView.setTextAndIcon(LocaleController.getString(R.string.ChangeRecipient), R.drawable.msg_forward_replace); + menu.addView(changeRecipientView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(context, resourcesProvider); + gap.setTag(R.id.fit_width_tag, 1); + menu.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + + ActionBarMenuSubItem applyChanges = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); + applyChanges.setTextAndIcon(LocaleController.getString(R.string.ApplyChanges), R.drawable.msg_select); + applyChanges.setOnClickListener(v -> dismiss(true)); + menu.addView(applyChanges, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + ActionBarMenuSubItem deleteLink = new ActionBarMenuSubItem(context, true, false, true, resourcesProvider); + deleteLink.setTextAndIcon(LocaleController.getString(R.string.DoNotForward), R.drawable.msg_delete); + deleteLink.setColors(getThemedColor(Theme.key_text_RedBold), getThemedColor(Theme.key_text_RedRegular)); + deleteLink.setOnClickListener(v -> removeForward()); + deleteLink.setSelectorColor(Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular), .12f)); + menu.addView(deleteLink, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + +// ActionBarMenuSubItem sendMessagesView = new ActionBarMenuSubItem(context, false, true, resourcesProvider); +// sendMessagesView.setTextAndIcon(LocaleController.getString("ForwardSendMessages", R.string.ForwardSendMessages), R.drawable.msg_send); +// menu.addView(sendMessagesView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); +// sendMessagesView.setOnClickListener(View -> didSendPressed()); + + sendersNameButton.setState(messagePreviewParams.hideForwardSendersName, false); + sendersNameButton.setOnClickListener(view -> { + messagePreviewParams.hideForwardSendersName = !messagePreviewParams.hideForwardSendersName; + returnSendersNames = false; + if (!messagePreviewParams.hideForwardSendersName) { + messagePreviewParams.hideCaption = false; + if (captionButton != null) { + captionButton.setState(messagePreviewParams.hideCaption, true); + } + } + sendersNameButton.setState(messagePreviewParams.hideForwardSendersName, true); + updateMessages(); + updateSubtitle(true); + }); + + if (captionButton != null) { + captionButton.setOnClickListener(view -> { + messagePreviewParams.hideCaption = !messagePreviewParams.hideCaption; + if (messagePreviewParams.hideCaption) { + if (!messagePreviewParams.hideForwardSendersName) { + messagePreviewParams.hideForwardSendersName = true; + returnSendersNames = true; + } + } else { + if (returnSendersNames) { + messagePreviewParams.hideForwardSendersName = false; + } + returnSendersNames = false; + } + captionButton.setState(messagePreviewParams.hideCaption, true); + sendersNameButton.setState(messagePreviewParams.hideForwardSendersName, true); + updateMessages(); + updateSubtitle(true); + }); + } + + } else if (tab == TAB_LINK && messagePreviewParams.linkMessage != null) { + + changePositionBtn = new ToggleButton( + context, + R.raw.position_below, LocaleController.getString(R.string.LinkAbove), + R.raw.position_above, LocaleController.getString(R.string.LinkBelow) + ); + changePositionBtn.setState(!messagePreviewParams.webpageTop, false); + menu.addView(changePositionBtn, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + changeSizeBtn = new ToggleButton( + context, + R.raw.media_shrink, LocaleController.getString(R.string.LinkMediaLarger), + R.raw.media_enlarge, LocaleController.getString(R.string.LinkMediaSmaller) + ); + changeSizeBtn.setState(messagePreviewParams.webpageSmall, false); + changeSizeBtn.setVisibility(messagePreviewParams.singleLink && !messagePreviewParams.hasMedia ? View.GONE : View.VISIBLE); + changeSizeBtn.setAlpha(messagePreviewParams.hasMedia ? 1f : .5f); + menu.addView(changeSizeBtn, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(context, resourcesProvider); + gap.setTag(R.id.fit_width_tag, 1); + menu.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + + ActionBarMenuSubItem applyChanges = new ActionBarMenuSubItem(context, true, false, false, resourcesProvider); + applyChanges.setTextAndIcon(LocaleController.getString(R.string.ApplyChanges), R.drawable.msg_select); + applyChanges.setOnClickListener(v -> dismiss(true)); + menu.addView(applyChanges, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + ActionBarMenuSubItem deleteLink = new ActionBarMenuSubItem(context, true, false, true, resourcesProvider); + deleteLink.setTextAndIcon(LocaleController.getString(R.string.DoNotLinkPreview), R.drawable.msg_delete); + deleteLink.setColors(getThemedColor(Theme.key_text_RedBold), getThemedColor(Theme.key_text_RedRegular)); + deleteLink.setOnClickListener(v -> removeLink()); + deleteLink.setSelectorColor(Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular), .12f)); + menu.addView(deleteLink, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); + + changeSizeBtn.setOnClickListener(view -> { + if (!messagePreviewParams.hasMedia) { + return; + } + messagePreviewParams.webpageSmall = !messagePreviewParams.webpageSmall; + changeSizeBtn.setState(messagePreviewParams.webpageSmall, true); + if (messages.messages.size() > 0) { + TLRPC.Message msg = messages.messages.get(0).messageOwner; + if (msg != null && msg.media != null) { + msg.media.force_small_media = messagePreviewParams.webpageSmall; + msg.media.force_large_media = !messagePreviewParams.webpageSmall; + } + } + if (messages.previewMessages.size() > 0) { + TLRPC.Message msg = messages.previewMessages.get(0).messageOwner; + if (msg != null && msg.media != null) { + msg.media.force_small_media = messagePreviewParams.webpageSmall; + msg.media.force_large_media = !messagePreviewParams.webpageSmall; + } + } + updateMessages(); + updateScroll = true; + }); + + changePositionBtn.setOnClickListener(view -> { + messagePreviewParams.webpageTop = !messagePreviewParams.webpageTop; + changePositionBtn.setState(!messagePreviewParams.webpageTop, true); + if (messages.messages.size() > 0) { + TLRPC.Message msg = messages.messages.get(0).messageOwner; + if (msg != null) { + msg.invert_media = messagePreviewParams.webpageTop; + } + } + if (messages.previewMessages.size() > 0) { + TLRPC.Message msg = messages.previewMessages.get(0).messageOwner; + if (msg != null) { + msg.invert_media = messagePreviewParams.webpageTop; + } + } + updateMessages(); + updateScroll = true; + }); + } + + if (currentTab == TAB_FORWARD) { + messages = messagePreviewParams.forwardMessages; + } else if (currentTab == TAB_REPLY) { + messages = messagePreviewParams.replyMessage; + } else if (currentTab == TAB_LINK) { + messages = messagePreviewParams.linkMessage; + } + + + textSelectionOverlay = textSelectionHelper.getOverlayView(context); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + textSelectionOverlay.setElevation(dp(8)); + textSelectionOverlay.setOutlineProvider(null); + } + if (textSelectionOverlay != null) { + if (textSelectionOverlay.getParent() instanceof ViewGroup) { + ((ViewGroup) textSelectionOverlay.getParent()).removeView(textSelectionOverlay); + } + addView(textSelectionOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, org.telegram.ui.ActionBar.ActionBar.getCurrentActionBarHeight() / AndroidUtilities.density, 0, 0)); + } + textSelectionHelper.setParentView(chatListView); + + } + + private boolean updateScroll = false; + private void checkScroll() { + if (!updateScroll) return; + if (chatListView.computeVerticalScrollRange() > chatListView.computeVerticalScrollExtent()) { + postDelayed(() -> { + if (messagePreviewParams.webpageTop) { + chatListView.smoothScrollBy(0, - chatListView.computeVerticalScrollOffset(), (int) (ChatListItemAnimator.DEFAULT_DURATION), ChatListItemAnimator.DEFAULT_INTERPOLATOR); + } else { + chatListView.smoothScrollBy(0, chatListView.computeVerticalScrollRange() - (chatListView.computeVerticalScrollOffset() + chatListView.computeVerticalScrollExtent()), (int) (ChatListItemAnimator.DEFAULT_DURATION), ChatListItemAnimator.DEFAULT_INTERPOLATOR); + } + }, 0); + } + updateScroll = false; + } + + private void showQuoteLengthError() { + BulletinFactory.of(MessagePreviewView.this, resourcesProvider).createSimpleBulletin(R.raw.error, LocaleController.getString(R.string.QuoteMaxError), LocaleController.getString(R.string.QuoteMaxErrorMessage)).show(); + } + + public void bind() { + updateMessages(); + updateSubtitle(false); + } + + private void updateSubtitle(boolean animated) { + if (currentTab == TAB_FORWARD) { + actionBar.setTitle(LocaleController.formatPluralString("PreviewForwardMessagesCount", messagePreviewParams.forwardMessages == null ? 0 : messagePreviewParams.forwardMessages.selectedIds.size()), animated); + CharSequence subtitle = ""; + if (!messagePreviewParams.hasSenders) { + if (messagePreviewParams.willSeeSenders) { + if (currentUser != null) { + subtitle = LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name)); + } else { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + subtitle = LocaleController.getString("ForwardPreviewSendersNameVisibleChannel", R.string.ForwardPreviewSendersNameVisibleChannel); + } else { + subtitle = LocaleController.getString("ForwardPreviewSendersNameVisibleGroup", R.string.ForwardPreviewSendersNameVisibleGroup); + } + } + } else { + if (currentUser != null) { + subtitle = LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name)); + } else { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameHiddenChannel); + } else { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameHiddenGroup); + } + } + } + } else if (!messagePreviewParams.hideForwardSendersName) { + if (currentUser != null) { + subtitle = LocaleController.formatString("ForwardPreviewSendersNameVisible", R.string.ForwardPreviewSendersNameVisible, ContactsController.formatName(currentUser.first_name, currentUser.last_name)); + } else { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameVisibleChannel); + } else { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameVisibleGroup); + } + } + } else { + if (currentUser != null) { + subtitle = LocaleController.formatString("ForwardPreviewSendersNameHidden", R.string.ForwardPreviewSendersNameHidden, ContactsController.formatName(currentUser.first_name, currentUser.last_name)); + } else { + if (ChatObject.isChannel(currentChat) && !currentChat.megagroup) { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameHiddenChannel); + } else { + subtitle = LocaleController.getString(R.string.ForwardPreviewSendersNameHiddenGroup); + } + } + } + actionBar.setSubtitle(subtitle, animated); + } else if (currentTab == TAB_REPLY) { + if (messagePreviewParams.quote != null && messagePreviewParams.replyMessage.hasText) { + actionBar.setTitle(LocaleController.getString(R.string.PreviewQuoteUpdate), animated); + actionBar.setSubtitle(LocaleController.getString(R.string.PreviewQuoteUpdateSubtitle), animated); + } else { + actionBar.setTitle(LocaleController.getString(R.string.MessageOptionsReplyTitle), animated); + actionBar.setSubtitle(messagePreviewParams.replyMessage.hasText ? LocaleController.getString(R.string.MessageOptionsReplySubtitle) : "", animated); + } + } else if (currentTab == TAB_LINK) { + actionBar.setTitle(LocaleController.getString(R.string.MessageOptionsLinkTitle), animated); + actionBar.setSubtitle(LocaleController.getString(R.string.MessageOptionsLinkSubtitle), animated); + } + } + + boolean updateAfterAnimations; + private void updateMessages() { + if (itemAnimator.isRunning()) { + updateAfterAnimations = true; + return; + } + for (int i = 0; i < messages.previewMessages.size(); i++) { + MessageObject messageObject = messages.previewMessages.get(i); + messageObject.forceUpdate = true; + messageObject.sendAsPeer = sendAsPeer; + if (!messagePreviewParams.hideForwardSendersName) { + messageObject.messageOwner.flags |= TLRPC.MESSAGE_FLAG_FWD; + messageObject.hideSendersName = false; + } else { + messageObject.messageOwner.flags &= ~TLRPC.MESSAGE_FLAG_FWD; + messageObject.hideSendersName = true; + } + if (currentTab == TAB_LINK) { + if (messagePreviewParams.webpage != null && (messageObject.messageOwner.media == null || messageObject.messageOwner.media.webpage != messagePreviewParams.webpage)) { + messageObject.messageOwner.flags |= 512; + messageObject.messageOwner.media = new TLRPC.TL_messageMediaWebPage(); + messageObject.messageOwner.media.webpage = messagePreviewParams.webpage; + messageObject.messageOwner.media.force_large_media = !messagePreviewParams.webpageSmall; + messageObject.messageOwner.media.force_small_media = messagePreviewParams.webpageSmall; + messageObject.messageOwner.media.manual = true; + messageObject.linkDescription = null; + messageObject.generateLinkDescription(); + messageObject.photoThumbs = null; + messageObject.photoThumbs2 = null; + messageObject.photoThumbsObject = null; + messageObject.photoThumbsObject2 = null; + messageObject.generateThumbs(true); + messageObject.checkMediaExistance(); + } else if (messagePreviewParams.webpage == null) { + messageObject.messageOwner.flags &=~ 512; + messageObject.messageOwner.media = null; + } + } + if (messagePreviewParams.hideCaption) { + messageObject.caption = null; + } else { + messageObject.generateCaption(); + } + + if (messageObject.isPoll()) { + MessagePreviewParams.PreviewMediaPoll mediaPoll = (MessagePreviewParams.PreviewMediaPoll) messageObject.messageOwner.media; + mediaPoll.results.total_voters = messagePreviewParams.hideCaption ? 0 : mediaPoll.totalVotersCached; + } + } + for (int i = 0; i < messages.pollChosenAnswers.size(); i++) { + messages.pollChosenAnswers.get(i).chosen = !messagePreviewParams.hideForwardSendersName; + } + for (int i = 0; i < messages.groupedMessagesMap.size(); i++) { + itemAnimator.groupWillChanged(messages.groupedMessagesMap.valueAt(i)); + } + adapter.notifyItemRangeChanged(0, messages.previewMessages.size()); + } + + + private int buttonsHeight; + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + isLandscapeMode = MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec); + + buttonsHeight = 0; + menu.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED)); + buttonsHeight = Math.max(buttonsHeight, menu.getMeasuredHeight() + rect.top + rect.bottom); + + ((MarginLayoutParams) chatListView.getLayoutParams()).topMargin = org.telegram.ui.ActionBar.ActionBar.getCurrentActionBarHeight(); + if (isLandscapeMode) { + chatPreviewContainer.getLayoutParams().height = LayoutHelper.MATCH_PARENT; + ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).topMargin = dp(8); + ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).bottomMargin = dp(8); + chatPreviewContainer.getLayoutParams().width = (int) Math.min(MeasureSpec.getSize(widthMeasureSpec), Math.max(dp(340), MeasureSpec.getSize(widthMeasureSpec) * 0.6f)); + menu.getLayoutParams().height = LayoutHelper.MATCH_PARENT; + } else { + ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).topMargin = 0; + ((MarginLayoutParams) chatPreviewContainer.getLayoutParams()).bottomMargin = 0; + chatPreviewContainer.getLayoutParams().height = MeasureSpec.getSize(heightMeasureSpec) - dp(16 - 10) - buttonsHeight; + if (chatPreviewContainer.getLayoutParams().height < MeasureSpec.getSize(heightMeasureSpec) * 0.5f) { + chatPreviewContainer.getLayoutParams().height = (int) (MeasureSpec.getSize(heightMeasureSpec) * 0.5f); + } + chatPreviewContainer.getLayoutParams().width = LayoutHelper.MATCH_PARENT; + menu.getLayoutParams().height = MeasureSpec.getSize(heightMeasureSpec) - chatPreviewContainer.getLayoutParams().height; + } + + int size = MeasureSpec.getSize(widthMeasureSpec) + MeasureSpec.getSize(heightMeasureSpec) << 16; + if (lastSize != size) { + for (int i = 0; i < messages.previewMessages.size(); i++) { + if (isLandscapeMode) { + messages.previewMessages.get(i).parentWidth = chatPreviewContainer.getLayoutParams().width; + } else { + messages.previewMessages.get(i).parentWidth = MeasureSpec.getSize(widthMeasureSpec) - dp(16); + } + messages.previewMessages.get(i).resetLayout(); + messages.previewMessages.get(i).forceUpdate = true; + if (adapter != null) { + adapter.notifyDataSetChanged(); + } + } + firstLayout = true; + } + lastSize = size; + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + int lastSize; + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + updatePositions(); + firstLayout = false; + } + + private boolean firstAttach = true; + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + updateSelection(); + firstAttach = true; + firstLayout = true; + } + + public void updateSelection() { + if (currentTab == TAB_REPLY) { + if (textSelectionHelper.selectionEnd - textSelectionHelper.selectionStart > MessagesController.getInstance(currentAccount).quoteLengthMax) { + return; + } + if (messagePreviewParams.quote != null && textSelectionHelper.isInSelectionMode()) { + messagePreviewParams.quoteStart = textSelectionHelper.selectionStart; + messagePreviewParams.quoteEnd = textSelectionHelper.selectionEnd; + } + textSelectionHelper.clear(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (currentTab == TAB_REPLY) { + AndroidUtilities.forEachViews(chatListView, child -> { + adapter.onViewAttachedToWindow(chatListView.getChildViewHolder(child)); + }); + } + } + + private void updatePositions() { + int lastTopOffset = chatTopOffset; + float lastYOffset = yOffset; + + if (!isLandscapeMode) { + int childCount = 0; + int minTop = chatListView.getMeasuredHeight(); + for (int i = 0; i < chatListView.getChildCount(); i++) { + View child = chatListView.getChildAt(i); + if (chatListView.getChildAdapterPosition(child) != RecyclerView.NO_POSITION) { + minTop = Math.min(minTop, child.getTop()); + childCount++; + } + } + if (messages == null || childCount == 0 || childCount > messages.previewMessages.size()) { + chatTopOffset = 0; + } else { + minTop -= dp(4); + chatTopOffset = Math.max(0, minTop); + chatTopOffset = Math.min((chatTopOffset + (chatListView.getMeasuredHeight() - chatTopOffset)) - (int) (AndroidUtilities.displaySize.y * .8f - buttonsHeight - dp(8)), chatTopOffset); + } + + float totalViewsHeight = buttonsHeight - dp(8) + (chatPreviewContainer.getMeasuredHeight() - chatTopOffset); + float totalHeight = getMeasuredHeight() - dp(16); + yOffset = dp(8) + (totalHeight - totalViewsHeight) / 2 - chatTopOffset; + if (yOffset > dp(8)) { + yOffset = dp(8); + } + float buttonX = getMeasuredWidth() - menu.getMeasuredWidth(); + menu.setTranslationX(buttonX); + } else { + yOffset = 0; + chatTopOffset = 0; + menu.setTranslationX(chatListView.getMeasuredWidth() + dp(8)); + } + + if (!firstLayout && (chatTopOffset != lastTopOffset || yOffset != lastYOffset)) { + if (offsetsAnimator != null) { + offsetsAnimator.cancel(); + } + offsetsAnimator = ValueAnimator.ofFloat(0, 1f); + offsetsAnimator.addUpdateListener(valueAnimator -> { + float p = (float) valueAnimator.getAnimatedValue(); + currentTopOffset = (int) (lastTopOffset * (1f - p) + chatTopOffset * p); + currentYOffset = lastYOffset * (1f - p) + yOffset * p; + setOffset(currentYOffset, currentTopOffset); + }); + offsetsAnimator.setDuration(ChatListItemAnimator.DEFAULT_DURATION); + offsetsAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); + offsetsAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + offsetsAnimator = null; + setOffset(yOffset, chatTopOffset); + } + }); + + AndroidUtilities.runOnUIThread(changeBoundsRunnable, 50); + + currentTopOffset = lastTopOffset; + currentYOffset = lastYOffset; + setOffset(lastYOffset, lastTopOffset); + } else if (firstLayout) { + setOffset(currentYOffset = yOffset, currentTopOffset = chatTopOffset); + } + } + + private void setOffset(float yOffset, int chatTopOffset) { + if (isLandscapeMode) { + actionBar.setTranslationY(0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + chatPreviewContainer.invalidateOutline(); + } + chatPreviewContainer.setTranslationY(0); + menu.setTranslationY(0); + } else { + actionBar.setTranslationY(chatTopOffset); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + chatPreviewContainer.invalidateOutline(); + } + chatPreviewContainer.setTranslationY(yOffset); + menu.setTranslationY(yOffset + chatPreviewContainer.getMeasuredHeight() - dp(2)); + } + + textSelectionOverlay.setTranslationX(chatPreviewContainer.getX()); + textSelectionOverlay.setTranslationY(chatPreviewContainer.getY()); + } + + private void updateLinkHighlight(ChatMessageCell cell) { + if (currentTab == TAB_LINK && !messagePreviewParams.singleLink && messagePreviewParams.currentLink != null && !(messagePreviewParams.webpage == null || messagePreviewParams.webpage instanceof TLRPC.TL_webPagePending)) { + cell.setHighlightedSpan(messagePreviewParams.currentLink); + } else { + cell.setHighlightedSpan(null); + } + } + + private class Adapter extends RecyclerView.Adapter { + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + ChatMessageCell chatMessageCell = new ChatMessageCell(parent.getContext(), false, sharedResources, resourcesProvider) { + @Override + public void invalidate() { + super.invalidate(); + chatListView.invalidate(); + } + + @Override + public void invalidate(int l, int t, int r, int b) { + super.invalidate(l, t, r, b); + chatListView.invalidate(); + } + + @Override + public void setMessageObject(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) { + super.setMessageObject(messageObject, groupedMessages, bottomNear, topNear); + updateLinkHighlight(this); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + updateLinkHighlight(this); + } + }; + chatMessageCell.setClipChildren(false); + chatMessageCell.setClipToPadding(false); + chatMessageCell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + @Override + public TextSelectionHelper.ChatListTextSelectionHelper getTextSelectionHelper() { + return textSelectionHelper; + } + + @Override + public boolean hasSelectedMessages() { + return true; + } + + @Override + public boolean canPerformActions() { + return currentTab == TAB_LINK && !messagePreviewParams.singleLink; + } + + @Override + public void didPressUrl(ChatMessageCell cell, CharacterStyle url, boolean longPress) { + if (currentTab != TAB_LINK || messagePreviewParams.currentLink == url) { + return; + } + MessageObject msg = cell.getMessageObject(); + if (msg == null) { + return; + } + if (!(url instanceof URLSpan)) { + return; + } + String urlText = ((URLSpan) url).getURL(); + + messagePreviewParams.currentLink = url; + messagePreviewParams.webpage = null; + + if (chatActivity != null && urlText != null) { + chatActivity.searchLinks(urlText, true); + } + updateLinkHighlight(cell); + } + + @Override + public CharacterStyle getProgressLoadingLink(ChatMessageCell cell) { + if (currentTab != TAB_LINK || messagePreviewParams.singleLink) { + return null; + } + return messagePreviewParams.currentLink; + } + + @Override + public boolean isProgressLoading(ChatMessageCell cell, int type) { + if (currentTab != TAB_LINK || type != ChatActivity.PROGRESS_LINK || messagePreviewParams.singleLink) { + return false; + } + return messagePreviewParams.webpage == null || messagePreviewParams.webpage instanceof TLRPC.TL_webPagePending; + } + }); + return new RecyclerListView.Holder(chatMessageCell); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (messages == null) { + return; + } + + ChatMessageCell cell = (ChatMessageCell) holder.itemView; + cell.setInvalidateSpoilersParent(messages.hasSpoilers); + cell.setParentViewSize(chatListView.getMeasuredWidth(), chatListView.getMeasuredHeight()); + int id = cell.getMessageObject() != null ? cell.getMessageObject().getId() : 0; + if (currentTab == TAB_LINK) { + messagePreviewParams.checkCurrentLink(messages.previewMessages.get(position)); + } + cell.setMessageObject(messages.previewMessages.get(position), messages.groupedMessagesMap.get(messages.previewMessages.get(position).getGroupId()), true, true); + if (currentTab == TAB_FORWARD) { + cell.setDelegate(new ChatMessageCell.ChatMessageCellDelegate() { + + }); + } + + if (messages.previewMessages.size() > 1) { + cell.setCheckBoxVisible(currentTab == TAB_FORWARD, false); + boolean animated = id == messages.previewMessages.get(position).getId(); + boolean checked = messages.selectedIds.get(messages.previewMessages.get(position).getId(), false); + cell.setChecked(checked, checked, animated); + } + } + + @Override + public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) { + if (messages == null || currentTab == TAB_FORWARD) { + return; + } + ChatMessageCell messageCell = (ChatMessageCell) holder.itemView; + if (currentTab == TAB_REPLY) { + MessageObject.GroupedMessages groupedMessages = getValidGroupedMessage(messageCell.getMessageObject()); + messageCell.setDrawSelectionBackground(groupedMessages == null); + messageCell.setChecked(true, groupedMessages == null, false); + + if (messagePreviewParams.quote != null && isReplyMessageCell(messageCell) && !textSelectionHelper.isInSelectionMode()) { + textSelectionHelper.select(messageCell, messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + if (firstAttach) { + scrollToOffset = offset(messageCell, messagePreviewParams.quoteStart); + firstAttach = false; + } + } + } else { + messageCell.setDrawSelectionBackground(false); + } + } + + private int offset(ChatMessageCell cell, int index) { + if (cell == null) { + return 0; + } + MessageObject object = cell.getMessageObject(); + if (object == null) { + return 0; + } + int offsetY; + CharSequence text; + ArrayList textLayoutBlocks; + if (object.getGroupId() != 0) { + return 0; + } else if (!TextUtils.isEmpty(object.caption) && cell.captionLayout != null) { + offsetY = (int) cell.captionY; + text = object.caption; + textLayoutBlocks = cell.captionLayout.textLayoutBlocks; + } else { + cell.layoutTextXY(true); + offsetY = cell.textY; + text = object.messageText; + textLayoutBlocks = object.textLayoutBlocks; + if (cell != null && cell.linkPreviewAbove) { + offsetY += cell.linkPreviewHeight + AndroidUtilities.dp(10); + } + } + if (textLayoutBlocks == null || text == null) { + return 0; + } + for (int i = 0; i < textLayoutBlocks.size(); ++i) { + MessageObject.TextLayoutBlock block = textLayoutBlocks.get(i); + StaticLayout layout = block.textLayout; + String layoutText = layout.getText().toString(); + if (index > block.charactersOffset) { + final float y; + if (index - block.charactersOffset > layoutText.length() - 1) { + y = offsetY + (int) (block.textYOffset + block.padTop + block.height); + } else { + y = offsetY + block.textYOffset + block.padTop + layout.getLineTop(layout.getLineForOffset(index - block.charactersOffset)); + } + return (int) y; + } + } + return 0; + } + + @Override + public int getItemCount() { + if (messages == null) { + return 0; + } + return messages.previewMessages.size(); + } + } + + private MessageObject.GroupedMessages getValidGroupedMessage(MessageObject message) { + MessageObject.GroupedMessages groupedMessages = null; + if (message.getGroupId() != 0) { + groupedMessages = messages.groupedMessagesMap.get(message.getGroupId()); + if (groupedMessages != null && (groupedMessages.messages.size() <= 1 || groupedMessages.positions.get(message) == null)) { + groupedMessages = null; + } + } + return groupedMessages; + } + } + +// ValueAnimator tabsAnimator; + TabsView tabsView; + ViewPagerFixed viewPager; + + ValueAnimator offsetsAnimator; + TLRPC.User currentUser; + TLRPC.Chat currentChat; + boolean showing; + boolean isLandscapeMode; + private final int currentAccount; + boolean returnSendersNames; + + Runnable changeBoundsRunnable = new Runnable() { + @Override + public void run() { + if (offsetsAnimator != null && !offsetsAnimator.isRunning()) { + offsetsAnimator.start(); + } + } + }; + + private final ArrayList drawingGroups = new ArrayList<>(10); + private final ResourcesDelegate resourcesProvider; + + @SuppressLint("ClickableViewAccessibility") + public MessagePreviewView(@NonNull Context context, ChatActivity chatActivity, MessagePreviewParams params, TLRPC.User user, TLRPC.Chat chat, int currentAccount, ResourcesDelegate resourcesProvider, int startTab, boolean showOutdatedQuote) { + super(context); + this.showOutdatedQuote = showOutdatedQuote; + this.chatActivity = chatActivity; + this.currentAccount = currentAccount; + currentUser = user; + currentChat = chat; + messagePreviewParams = params; + this.resourcesProvider = resourcesProvider; + + viewPager = new ViewPagerFixed(context, resourcesProvider) { + @Override + protected void onTabAnimationUpdate(boolean manual) { + MessagePreviewView.this.tabsView.setSelectedTab(viewPager.getPositionAnimated()); + + if (viewPages[0] instanceof Page) { + ((Page) viewPages[0]).textSelectionHelper.onParentScrolled(); + } + if (viewPages[1] instanceof Page) { + ((Page) viewPages[1]).textSelectionHelper.onParentScrolled(); + } + } + + @Override + protected void onScrollEnd() { + if (viewPages[0] instanceof Page) { + ((Page) viewPages[0]).textSelectionHelper.stopScrolling(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (isTouchedHandle()) { + return false; + } + return super.onTouchEvent(ev); + } + }; + + tabsView = new TabsView(context, resourcesProvider); + int p = 0; + for (int i = 0; i < 3; ++i) { + if (i == TAB_REPLY && params.replyMessage != null) { + tabsView.addTab(TAB_REPLY, LocaleController.getString(R.string.MessageOptionsReply)); + } else if (i == TAB_FORWARD && params.forwardMessages != null && !showOutdatedQuote) { + tabsView.addTab(TAB_FORWARD, LocaleController.getString(R.string.MessageOptionsForward)); + } else if (i == TAB_LINK && params.linkMessage != null && !showOutdatedQuote) { + tabsView.addTab(TAB_LINK, LocaleController.getString(R.string.MessageOptionsLink)); + } else { + continue; + } + if (i == startTab) { + p = tabsView.tabs.size() - 1; + } + } + + viewPager.setAdapter(new ViewPagerFixed.Adapter() { + @Override + public int getItemCount() { + return tabsView.tabs.size(); + } + + @Override + public int getItemViewType(int position) { + return tabsView.tabs.get(position).id; + } + + @Override + public View createView(int viewType) { + return new Page(context, viewType); + } + + @Override + public void bindView(View view, int position, int viewType) { + ((Page) view).bind(); + } + }); + viewPager.setPosition(p); + tabsView.setSelectedTab(p); + +// if (tabsView.tabs.size() > 1) { + addView(tabsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 66)); +// } else { +// addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL)); +// } + + tabsView.setOnTabClick(id -> { + if (tabsView.tabs.get(viewPager.getCurrentPosition()).id == id) { + return; + } + + int pos = 0; + for (int i = 0; i < tabsView.tabs.size(); ++i) { + if (tabsView.tabs.get(i).id == id) { + pos = i; + break; + } + } + + if (viewPager.getCurrentPosition() == pos) { + return; + } + + viewPager.scrollToPosition(pos); + }); + + setOnTouchListener((view, motionEvent) -> { + if (motionEvent.getAction() == MotionEvent.ACTION_UP && !showOutdatedQuote) { + dismiss(true); + } + return true; + }); + showing = true; + setAlpha(0); + setScaleX(0.95f); + setScaleY(0.95f); + animate().alpha(1f).scaleX(1f).setDuration(ChatListItemAnimator.DEFAULT_DURATION).setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR).scaleY(1f); + + updateColors(); + } + + private void updateColors() { + + } + + public void dismiss(boolean canShowKeyboard) { + if (showing) { + showing = false; + animate().alpha(0).scaleX(0.95f).scaleY(0.95f).setDuration(ChatListItemAnimator.DEFAULT_DURATION).setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (getParent() != null) { + ViewGroup parent = (ViewGroup) getParent(); + parent.removeView(MessagePreviewView.this); + } + onFullDismiss(canShowKeyboard); + } + }); + for (int i = 0; i < viewPager.viewPages.length; ++i) { + if (viewPager.viewPages[i] instanceof Page) { + Page page = (Page) viewPager.viewPages[i]; + if (page.currentTab == TAB_REPLY) { + page.updateSelection(); + break; + } + } + } + onDismiss(canShowKeyboard); + } + } + + protected void onQuoteSelectedPart() { + + } + + protected void onDismiss(boolean canShowKeyboard) { + + } + + protected void onFullDismiss(boolean canShowKeyboard) { + + } + + public boolean isShowing() { + return showing; + } + + protected void removeLink() { + + } + + protected void removeReply() { + + } + + protected void removeQuote() { + + } + + protected void removeForward() { + + } + + protected void selectAnotherChat(boolean forward) { + + } + + protected void didSendPressed() { + + } + + private static class TabsView extends View { + private static class Tab { + final int id; + final Text text; + final RectF bounds = new RectF(); + final RectF clickBounds = new RectF(); + + public Tab(int id, String name) { + this.id = id; + text = new Text(name, 14, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + } + } + + public final ArrayList tabs = new ArrayList<>(); +// private final AnimatedFloat tab = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + private float selectedTab; + private final Theme.ResourcesProvider resourcesProvider; + + private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private int color; + private int selectedColor; + + public TabsView(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + if (Theme.isCurrentThemeDark()) { + color = 0x90ffffff; + selectedColor = 0xb0ffffff; + bgPaint.setColor(0x10ffffff); + } else { + int wallpaperColor = Theme.getColor(Theme.key_chat_wallpaper, resourcesProvider); + if (resourcesProvider instanceof ChatActivity.ThemeDelegate && ((ChatActivity.ThemeDelegate) resourcesProvider).getWallpaperDrawable() instanceof MotionBackgroundDrawable) { + MotionBackgroundDrawable background = (MotionBackgroundDrawable) ((ChatActivity.ThemeDelegate) resourcesProvider).getWallpaperDrawable(); + int[] colors = background.getColors(); + if (colors != null) { + wallpaperColor = AndroidUtilities.getAverageColor( + AndroidUtilities.getAverageColor(colors[0], colors[1]), + AndroidUtilities.getAverageColor(colors[2], colors[3]) + ); + } + } + color = Theme.adaptHue(0xa0434e3b, wallpaperColor); + selectedColor = Theme.adaptHue(0xe5434e3b, wallpaperColor); + bgPaint.setColor(Theme.adaptHue(0x30939C78, wallpaperColor)); + } + } + + public boolean containsTab(int id) { + for (int i = 0; i < tabs.size(); ++i) { + if (tabs.get(i).id == id) { + return true; + } + } + return false; + } + + public void addTab(int id, String text) { + tabs.add(new Tab(id, text)); + } + + public void setSelectedTab(float position) { + selectedTab = position; + invalidate(); + } + + private float tabInnerPadding = dp(12); + private float marginBetween = dp(13); + private RectF selectRect = new RectF(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + tabInnerPadding = dp(12); + marginBetween = dp(13); + float W = 0; + for (int i = 0; i < tabs.size(); ++i) { + if (i > 0) { + W += marginBetween; + } + W += tabInnerPadding + tabs.get(i).text.getWidth() + tabInnerPadding; + } + + int fullWidth = getMeasuredWidth(); + int fullHeight = getMeasuredHeight(); + float top = (fullHeight - dp(26)) / 2f, + bottom = (fullHeight + dp(26)) / 2f; + float x = (fullWidth - W) / 2f; + for (int i = 0; i < tabs.size(); ++i) { + float w = tabInnerPadding + tabs.get(i).text.getWidth() + tabInnerPadding; + tabs.get(i).bounds.set(x, top, x + w, bottom); + tabs.get(i).clickBounds.set(tabs.get(i).bounds); + tabs.get(i).clickBounds.inset(-marginBetween / 2f, -top); + x += w + marginBetween; + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (tabs.size() <= 1) { + return; + } + + float tabT = selectedTab; + int lower = (int) Math.floor(tabT); + boolean lowerInRange = lower >= 0 && lower < tabs.size(); + int higher = (int) Math.ceil(tabT); + boolean higherInRange = higher >= 0 && higher < tabs.size(); + + if (lowerInRange && higherInRange) { + AndroidUtilities.lerp( + tabs.get(lower).bounds, + tabs.get(higher).bounds, + tabT - lower, + selectRect + ); + } else if (lowerInRange) { + selectRect.set(tabs.get(lower).bounds); + } else if (higherInRange) { + selectRect.set(tabs.get(higher).bounds); + } + if (lowerInRange || higherInRange) { + canvas.drawRoundRect(selectRect, dp(13), dp(13), bgPaint); + } + + for (int i = 0; i < tabs.size(); ++i) { + Tab tab = tabs.get(i); + tab.text.draw(canvas, tab.bounds.left + tabInnerPadding, getMeasuredHeight() / 2f, ColorUtils.blendARGB(color, selectedColor, 1f - Math.abs(tabT - i)), 1f); + } + } + + private Utilities.Callback onTabClick; + public void setOnTabClick(Utilities.Callback onTabClick) { + this.onTabClick = onTabClick; + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (tabs.size() <= 1) { + return false; + } + int tab = getHitTab(event.getX(), event.getY()); + if (event.getAction() == MotionEvent.ACTION_DOWN) { + return tab != -1; + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (tab != -1 && onTabClick != null) { + onTabClick.run(tab); + } + } + return false; + } + + private int getHitTab(float x, float y) { + for (int i = 0; i < tabs.size(); ++i) { + if (tabs.get(i).clickBounds.contains(x, y)) { + return tabs.get(i).id; + } + } + return -1; + } + } + + private int getThemedColor(int key) { + return Theme.getColor(key, resourcesProvider); + } + + private class ActionBar extends FrameLayout { + private Theme.ResourcesProvider resourcesProvider; + + private boolean forward; + private final AnimatedTextView.AnimatedTextDrawable title; + private final AnimatedTextView.AnimatedTextDrawable subtitle; + + public ActionBar(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + title = new AnimatedTextView.AnimatedTextDrawable(true, true, true); + title.setAnimationProperties(.3f, 0, 430, CubicBezierInterpolator.EASE_OUT_QUINT); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + title.setTextColor(Theme.getColor(Theme.key_actionBarDefaultTitle, resourcesProvider)); + title.setTextSize(dp(18)); + title.setEllipsizeByGradient(!LocaleController.isRTL); + title.setCallback(this); + title.setOverrideFullWidth(AndroidUtilities.displaySize.x); + + subtitle = new AnimatedTextView.AnimatedTextDrawable(true, true, true); + subtitle.setAnimationProperties(.3f, 0, 430, CubicBezierInterpolator.EASE_OUT_QUINT); + subtitle.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubtitle, resourcesProvider)); + subtitle.setTextSize(dp(14)); + subtitle.setEllipsizeByGradient(!LocaleController.isRTL); + subtitle.setCallback(this); + subtitle.setOverrideFullWidth(AndroidUtilities.displaySize.x); + } + + public void setAnimationForward(boolean forward) { + this.forward = forward; + invalidate(); + } + + public void setTitle(CharSequence text, boolean animated) { + title.setText(text, animated && !LocaleController.isRTL); + } + + public void setSubtitle(CharSequence text, boolean animated) { + subtitle.setText(text, animated && !LocaleController.isRTL); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(56), MeasureSpec.EXACTLY)); + setPadding(dp(18), 0, dp(18), 0); + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return title == who || subtitle == who || super.verifyDrawable(who); + } + + private void setBounds(Drawable drawable, float cy) { + drawable.setBounds( + getPaddingLeft(), + (int) cy - dp(32), + getMeasuredWidth() - getPaddingRight(), + (int) cy + dp(32) + ); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + setBounds(title, AndroidUtilities.lerp(dp(29), dp(18.83f), subtitle.isNotEmpty())); + title.draw(canvas); + + setBounds(subtitle, dp(39.5f)); + subtitle.draw(canvas); + } + } + + public void updateLink() { + for (int i = 0; i < viewPager.viewPages.length; ++i) { + if (viewPager.viewPages[i] != null && ((Page) viewPager.viewPages[i]).currentTab == TAB_LINK) { + Page page = (Page) viewPager.viewPages[i]; + page.changeSizeBtn.setVisibility(messagePreviewParams.singleLink && !messagePreviewParams.hasMedia ? View.GONE : View.VISIBLE); + page.changeSizeBtn.animate().alpha(messagePreviewParams.hasMedia ? 1f : .5f).start(); + page.changeSizeBtn.setState(messagePreviewParams.webpageSmall, true); + page.changePositionBtn.setState(!messagePreviewParams.webpageTop, true); + page.updateMessages(); + } + } + } + + public void updateAll() { + for (int i = 0; i < viewPager.viewPages.length; ++i) { + if (viewPager.viewPages[i] instanceof Page) { + Page page = (Page) viewPager.viewPages[i]; + if (page.currentTab == TAB_FORWARD) { + page.messages = messagePreviewParams.forwardMessages; + } else if (page.currentTab == TAB_REPLY) { + page.messages = messagePreviewParams.replyMessage; + } else if (page.currentTab == TAB_LINK) { + page.messages = messagePreviewParams.linkMessage; + } + page.updateMessages(); + if (page.currentTab == TAB_REPLY) { + if (showOutdatedQuote) { + MessageObject replyMessage = page.getReplyMessage(); + if (replyMessage != null) { + messagePreviewParams.quoteStart = 0; + messagePreviewParams.quoteEnd = Math.min(MessagesController.getInstance(currentAccount).quoteLengthMax, replyMessage.messageOwner.message.length()); + messagePreviewParams.quote = ChatActivity.ReplyQuote.from(replyMessage, messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + page.textSelectionHelper.select(page.getReplyMessageCell(), messagePreviewParams.quoteStart, messagePreviewParams.quoteEnd); + } + } else { + messagePreviewParams.quote = null; + page.textSelectionHelper.clear(); + page.switchToQuote(false, true); + } + page.updateSubtitle(true); + } + if (page.changeSizeBtn != null) { + page.changeSizeBtn.animate().alpha(messagePreviewParams.hasMedia ? 1f : .5f).start(); + } + } + } + } + + public boolean isTouchedHandle() { + for (int i = 0; i < viewPager.viewPages.length; ++i) { + if (viewPager.viewPages[i] != null && ((Page) viewPager.viewPages[i]).currentTab == TAB_REPLY) { + return ((Page) viewPager.viewPages[i]).textSelectionHelper.isTouched(); + } + } + return false; + } + + private class ToggleButton extends View { + AnimatedTextView.AnimatedTextDrawable textDrawable; + RLottieToggleDrawable iconDrawable; + + private boolean first = true; + private boolean isState1; + final String text1, text2; + final int minWidth; + + public ToggleButton( + Context context, + int iconRes1, String text1, + int iconRes2, String text2 + ) { + super(context); + + this.text1 = text1; + this.text2 = text2; + + setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); + + textDrawable = new AnimatedTextView.AnimatedTextDrawable(true, true, true); + textDrawable.setAnimationProperties(.35f, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); + textDrawable.setTextSize(dp(16)); + textDrawable.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); + textDrawable.setCallback(this); + textDrawable.setEllipsizeByGradient(!LocaleController.isRTL); + if (LocaleController.isRTL) { + textDrawable.setGravity(Gravity.RIGHT); + } + minWidth = (int) (dp(59 + 18) + Math.max(textDrawable.getPaint().measureText(text1), textDrawable.getPaint().measureText(text2))); + textDrawable.setOverrideFullWidth(minWidth); + + iconDrawable = new RLottieToggleDrawable(this, iconRes1, iconRes2); + iconDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); + } + + public void setState(boolean state1, boolean animated) { + if (!first && state1 == isState1) { + return; + } + isState1 = state1; + textDrawable.setText(state1 ? text1 : text2, animated && !LocaleController.isRTL); + iconDrawable.setState(state1, animated); + first = false; + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == textDrawable || super.verifyDrawable(who); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (LocaleController.isRTL) { + iconDrawable.setBounds( + getMeasuredWidth() - dp(17 + 24), + (getMeasuredHeight() - dp(24)) / 2, + getMeasuredWidth() - dp(17), + (getMeasuredHeight() + dp(24)) / 2 + ); + textDrawable.setBounds( + 0, + 0, + getMeasuredWidth() - dp(59), + getMeasuredHeight() + ); + } else { + iconDrawable.setBounds( + dp(17), + (getMeasuredHeight() - dp(24)) / 2, + dp(17 + 24), + (getMeasuredHeight() + dp(24)) / 2 + ); + textDrawable.setBounds( + dp(59), + 0, + getMeasuredWidth(), + getMeasuredHeight() + ); + } + + textDrawable.draw(canvas); + iconDrawable.draw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int widthMode = MeasureSpec.getMode(widthMeasureSpec); + super.onMeasure( + MeasureSpec.makeMeasureSpec( + widthMode == MeasureSpec.EXACTLY ? + Math.max(MeasureSpec.getSize(widthMeasureSpec), minWidth) : + Math.min(MeasureSpec.getSize(widthMeasureSpec), minWidth), + widthMode + ), + MeasureSpec.makeMeasureSpec(dp(48), MeasureSpec.EXACTLY) + ); + } + } + + private class RLottieToggleDrawable extends Drawable { + + private RLottieDrawable state1, state2; + private RLottieDrawable currentState; + + // R.raw.media_shrink, R.raw.media_enlarge + public RLottieToggleDrawable(View view, int state1Res, int state2Res) { + state1 = new RLottieDrawable(state1Res, "" + state1Res, dp(24), dp(24)); + state1.setMasterParent(view); + state1.setAllowDecodeSingleFrame(true); + state1.setPlayInDirectionOfCustomEndFrame(true); + state1.setAutoRepeat(0); + + state2 = new RLottieDrawable(state2Res, "" + state2Res, dp(24), dp(24)); + state2.setMasterParent(view); + state2.setAllowDecodeSingleFrame(true); + state2.setPlayInDirectionOfCustomEndFrame(true); + state2.setAutoRepeat(0); + + currentState = state1; + } + + private boolean detached; + public void detach() { + detached = true; + state1.recycle(true); + state2.recycle(true); + } + + private boolean isState1; + public void setState(boolean isState1, boolean animated) { + this.isState1 = isState1; + if (animated) { + currentState = isState1 ? state1 : state2; + state1.setCurrentFrame(0); + state2.setCurrentFrame(0); + currentState.start(); + } else { + currentState = isState1 ? state1 : state2; + currentState.setCurrentFrame(currentState.getFramesCount() - 1); + } + } + + @Override + public void draw(@NonNull Canvas canvas) { + if (detached) { + return; + } + AndroidUtilities.rectTmp2.set( + getBounds().centerX() - dp(12), + getBounds().centerY() - dp(12), + getBounds().centerX() + dp(12), + getBounds().centerY() + dp(12) + ); + if (currentState.isLastFrame() && currentState != (isState1 ? state1 : state2)) { + currentState = isState1 ? state1 : state2; + currentState.setCurrentFrame(currentState.getFramesCount() - 1); + } + currentState.setBounds(AndroidUtilities.rectTmp2); + currentState.draw(canvas); + } + + @Override + public void setAlpha(int alpha) { + state1.setAlpha(alpha); + state2.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + state1.setColorFilter(colorFilter); + state2.setColorFilter(colorFilter); + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicWidth() { + return dp(24); + } + + @Override + public int getIntrinsicHeight() { + return dp(24); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java new file mode 100644 index 000000000..75251d5c0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NoClipCanvas.java @@ -0,0 +1,247 @@ +package org.telegram.ui.Components; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.fonts.Font; +import android.graphics.text.MeasuredText; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; + +public class NoClipCanvas extends Canvas { + + public Canvas canvas; + + @Override + public boolean clipRect(float left, float top, float right, float bottom) { + // nop + return false; + } + + @Override + public int save() { + return canvas.save(); + } + + @Override + public void translate(float dx, float dy) { + canvas.translate(dx, dy); + } + + @Override + public void scale(float sx, float sy) { + canvas.scale(sx, sy); + } + + @Override + public void rotate(float degrees) { + canvas.rotate(degrees); + } + + @Override + public void restore() { + canvas.restore(); + } + + @Override + public void restoreToCount(int saveCount) { + canvas.restoreToCount(saveCount); + } + + @Override + public int getSaveCount() { + return canvas.getSaveCount(); + } + + @Override + public void drawPath(@NonNull Path path, @NonNull Paint paint) { + canvas.drawPath(path, paint); + } + + @Override + public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { + canvas.drawText(text, x, y, paint); + } + + @Override + public void drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint) { + canvas.drawText(text, start, end, x, y, paint); + } + + @Override + public void drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint) { + canvas.drawText(text, index, count, x, y, paint); + } + + @Override + public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { + canvas.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); + } + + @Override + public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint) { + canvas.drawText(text, start, end, x, y, paint); + } + + @Override + public void drawRect(@NonNull Rect r, @NonNull Paint paint) { + canvas.drawRect(r, paint); + } + + @Override + public void drawRect(@NonNull RectF rect, @NonNull Paint paint) { + canvas.drawRect(rect, paint); + } + + @Override + public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) { + canvas.drawCircle(cx, cy, radius, paint); + } + + @Override + public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) { + canvas.drawRect(left, top, right, bottom, paint); + } + + @Override + public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) { + canvas.drawRoundRect(rect, rx, ry, paint); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, @NonNull Paint paint) { + canvas.drawRoundRect(left, top, right, bottom, rx, ry, paint); + } + + @RequiresApi(api = Build.VERSION_CODES.M) + @Override + public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) { + canvas.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint); + } + + @RequiresApi(api = Build.VERSION_CODES.Q) + @Override + public void drawTextRun(@NonNull MeasuredText text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { + canvas.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); + } + + @RequiresApi(api = Build.VERSION_CODES.M) + @Override + public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { + canvas.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); + } + + @Override + public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { + canvas.drawTextOnPath(text, path, hOffset, vOffset, paint); + } + + @Override + public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { + canvas.drawBitmap(bitmap, matrix, paint); + } + + @Override + public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst, @Nullable Paint paint) { + canvas.drawBitmap(bitmap, src, dst, paint); + } + + @Override + public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y, int width, int height, boolean hasAlpha, @Nullable Paint paint) { + canvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); + } + + @Override + public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y, int width, int height, boolean hasAlpha, @Nullable Paint paint) { + canvas.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint); + } + + @Override + public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter, @NonNull Paint paint) { + canvas.drawArc(oval, startAngle, sweepAngle, useCenter, paint); + } + + @Override + public void drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) { + canvas.drawLine(startX, startY, stopX, stopY, paint); + } + + @Override + public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount, @NonNull Paint paint) { + canvas.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset, colors, colorOffset, indices, indexOffset, indexCount, paint); + } + + @Override + public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst, @Nullable Paint paint) { + canvas.drawBitmap(bitmap, src, dst, paint); + } + + @Override + public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { + canvas.drawBitmap(bitmap, left, top, paint); + } + + @Override + public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight, @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset, @Nullable Paint paint) { + canvas.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint); + } + + @RequiresApi(api = Build.VERSION_CODES.S) + @Override + public void drawGlyphs(@NonNull int[] glyphIds, int glyphIdOffset, @NonNull float[] positions, int positionOffset, int glyphCount, @NonNull Font font, @NonNull Paint paint) { + canvas.drawGlyphs(glyphIds, glyphIdOffset, positions, positionOffset, glyphCount, font, paint); + } + + @Override + public void setBitmap(@Nullable Bitmap bitmap) { + canvas.setBitmap(bitmap); + } + + @Override + public int getMaximumBitmapWidth() { + return canvas.getMaximumBitmapWidth(); + } + + @Override + public void setMatrix(@Nullable Matrix matrix) { + canvas.setMatrix(matrix); + } + + @Override + public int getMaximumBitmapHeight() { + return canvas.getMaximumBitmapHeight(); + } + + @Override + public boolean getClipBounds(@NonNull Rect bounds) { + return canvas.getClipBounds(bounds); + } + + @Override + public void getMatrix(@NonNull Matrix ctm) { + canvas.getMatrix(ctm); + } + + @Override + public int getWidth() { + return canvas.getWidth(); + } + + @Override + public int getHeight() { + return canvas.getHeight(); + } + + @Override + public boolean quickReject(float left, float top, float right, float bottom, @NonNull EdgeType type) { + return canvas.quickReject(left, top, right, bottom, type); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java index 86a9f8452..e199a6433 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -150,7 +150,7 @@ public class NumberPicker extends LinearLayout { private void init() { mSolidColor = 0; mSelectionDivider = new Paint(); - mSelectionDivider.setColor(getThemedColor(Theme.key_dialogButton)); + mSelectionDivider.setColor(getThemedColor(Theme.key_featuredStickers_addButton)); mSelectionDividerHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDER_HEIGHT, getResources().getDisplayMetrics()); mSelectionDividersDistance = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE, getResources().getDisplayMetrics()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java index 2a43868fe..666c3b103 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Painting.java @@ -741,7 +741,7 @@ public class Painting { } private void renderBlur() { - if (blurManager == null || bitmapBlurTexture == null) { + if (blurManager == null || bitmapBlurTexture == null || !hasBlur) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java index cef38cfc4..0b5ca4890 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/EditTextOutline.java @@ -254,4 +254,9 @@ public class EditTextOutline extends EditTextBoldCursor { } super.onDraw(canvas); } + + @Override + public boolean onTextContextMenuItem(int id) { + return super.onTextContextMenuItem(id); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java index 326860c0a..564526e7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LPhotoPaintView.java @@ -967,6 +967,11 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh Size paintingSize = getPaintingSize(); Point position = startPositionRelativeToEntity(null); TextPaintView view = new TextPaintView(getContext(), position, (int) (paintingSize.width / 9), "", colorSwatch, selectedTextType); + view.setMinMaxFontSize((int) (0.5f * (paintingSize.width / 9f)), (int) (2f * (paintingSize.width / 9f)), () -> { + if (weightChooserView != null) { + weightChooserView.invalidate(); + } + }); if (position.x == entitiesView.getMeasuredWidth() / 2f) { view.setStickyX(EntityView.STICKY_CENTER); } @@ -1104,6 +1109,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh if (currentEntityView instanceof TextPaintView) { TextPaintView textPaintView = (TextPaintView) currentEntityView; + textPaintView.disableAutoresize(false); textPaintView.getSwatch().brushWeight = colorSwatch.brushWeight; setCurrentSwatch(textPaintView.getSwatch(), true); @@ -1116,6 +1122,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh @Override public void set(float val) { + textPaintView.disableAutoresize(true); textPaintView.setBaseFontSize((int) (base * val)); } }); @@ -3262,7 +3269,7 @@ public class LPhotoPaintView extends SizeNotifierFrameLayoutPhoto implements IPh if (emojiView != null) { return; } - emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider); + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider, false); emojiView.allowEmojisForNonPremium(true); emojiView.setVisibility(GONE); if (AndroidUtilities.isTablet()) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LocationView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LocationView.java index 1ba9b4e53..e58a66dfd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LocationView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/LocationView.java @@ -2,49 +2,17 @@ package org.telegram.ui.Components.Paint.Views; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; -import android.graphics.Typeface; -import android.graphics.Xfermode; -import android.graphics.drawable.Drawable; -import android.graphics.text.LineBreaker; -import android.os.Build; -import android.text.Editable; -import android.text.Layout; -import android.text.SpannableString; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.TextPaint; -import android.text.TextWatcher; -import android.text.style.DynamicDrawableSpan; -import android.text.style.ImageSpan; -import android.util.TypedValue; import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; - -import androidx.core.graphics.ColorUtils; - -import com.googlecode.mp4parser.authoring.Edit; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.Emoji; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; -import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Components.AnimatedEmojiSpan; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.Paint.PaintTypeface; -import org.telegram.ui.Components.Paint.Swatch; import org.telegram.ui.Components.Point; import org.telegram.ui.Components.Rect; @@ -55,7 +23,7 @@ public class LocationView extends EntityView { private int currentType; public TLRPC.MessageMedia location; - public TLRPC.MediaArea mediaArea; + public TL_stories.MediaArea mediaArea; @Override protected float getStickyPaddingLeft() { @@ -100,7 +68,7 @@ public class LocationView extends EntityView { return deg(Lat) + (Lat > 0 ? "N" : "S") + " " + deg(Long) + (Long > 0 ? "E" : "W"); } - public LocationView(Context context, Point position, int currentAccount, TLRPC.MessageMedia location, TLRPC.MediaArea mediaArea, float density, int maxWidth, int type, int color) { + public LocationView(Context context, Point position, int currentAccount, TLRPC.MessageMedia location, TL_stories.MediaArea mediaArea, float density, int maxWidth, int type, int color) { super(context, position); marker = new LocationMarker(context, density); @@ -115,7 +83,7 @@ public class LocationView extends EntityView { updatePosition(); } - public void setLocation(int currentAccount, TLRPC.MessageMedia location, TLRPC.MediaArea area) { + public void setLocation(int currentAccount, TLRPC.MessageMedia location, TL_stories.MediaArea area) { this.location = location; this.mediaArea = area; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java index b3ea8ed9d..25a7decd0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/TextPaintView.java @@ -26,6 +26,7 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedEmojiSpan; import org.telegram.ui.Components.LayoutHelper; @@ -106,32 +107,30 @@ public class TextPaintView extends EntityView { updatePosition(); editText.addTextChangedListener(new TextWatcher() { - private String text; - private int beforeCursorPosition = 0; - + boolean pasted; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { - text = s.toString(); - beforeCursorPosition = start; + pasted = after > 3; } - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - + public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { - editText.removeTextChangedListener(this); - - if (editText.getLineCount() > 9) { - editText.setText(text); - editText.setSelection(beforeCursorPosition); + if (pasted && minFontSize > 0 && maxFontSize > 0 && !disableAutoresize && editText.getLayout() != null) { + int newHeight = editText.getLayout().getHeight(); + float maxHeight = AndroidUtilities.displaySize.y / 3f; + if (newHeight > maxHeight) { + float scale = maxHeight / newHeight; + int newFontSize = Utilities.clamp((int) (scale * getBaseFontSize()), maxFontSize, minFontSize); + if (newFontSize != getBaseFontSize()) { + setBaseFontSize(newFontSize); + if (onFontChange != null) { + onFontChange.run(); + } + } + } } - updateHint(); - - editText.addTextChangedListener(this); } }); } @@ -209,6 +208,19 @@ public class TextPaintView extends EntityView { return baseFontSize; } + private int minFontSize, maxFontSize; + private Runnable onFontChange; + public void setMinMaxFontSize(int min, int max, Runnable onFontChange) { + minFontSize = min; + maxFontSize = max; + this.onFontChange = onFontChange; + } + + private boolean disableAutoresize; + public void disableAutoresize(boolean disable) { + disableAutoresize = disable; + } + public void setBaseFontSize(int baseFontSize) { this.baseFontSize = baseFontSize; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java index 96b90672f..df2e23f75 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -725,6 +725,7 @@ public class PhotoFilterView extends FrameLayout implements FilterShaders.Filter blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); blurLinearButton.setTextColor(getThemedColor(Theme.key_dialogFloatingButton)); } + updateFiltersEmpty(); } public MediaController.SavedFilterState getSavedFilterState() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java index 6bdd698eb..622359224 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -638,7 +638,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica if (emojiView != null) { return; } - emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider); + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider, false); emojiView.emojiCacheType = AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW; emojiView.setDelegate(new EmojiView.EmojiViewDelegate() { @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java index 44da634b7..c806a759d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java @@ -314,11 +314,20 @@ public class PopupSwipeBackLayout extends FrameLayout { } invalidateTransforms(); isAnimationInProgress = false; + + if (onForegroundOpen != null && Math.abs(f - 1f) < .01f) { + onForegroundOpen.run(); + } } }); val.start(); } + private Runnable onForegroundOpen; + public void setOnForegroundOpenFinished(Runnable listener) { + onForegroundOpen = listener; + } + /** * Clears touch flags */ @@ -357,15 +366,28 @@ public class PopupSwipeBackLayout extends FrameLayout { } } + public boolean stickToRight; + public void setStickToRight(boolean right) { + stickToRight = right; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { for (int i = 0; i < getChildCount(); i++) { View ch = getChildAt(i); boolean shownFromBottom = ch.getLayoutParams() instanceof FrameLayout.LayoutParams && ((LayoutParams) ch.getLayoutParams()).gravity == Gravity.BOTTOM; if (shownFromBottom) { - ch.layout(0, bottom - top - ch.getMeasuredHeight(), ch.getMeasuredWidth(), bottom - top); + if (stickToRight) { + ch.layout((right - left) - ch.getMeasuredWidth(), bottom - top - ch.getMeasuredHeight(), right - left, bottom - top); + } else { + ch.layout(0, bottom - top - ch.getMeasuredHeight(), ch.getMeasuredWidth(), bottom - top); + } } else { - ch.layout(0, 0, ch.getMeasuredWidth(), ch.getMeasuredHeight()); + if (stickToRight) { + ch.layout((right - left) - ch.getMeasuredWidth(), 0, right - left, ch.getMeasuredHeight()); + } else { + ch.layout(0, 0, ch.getMeasuredWidth(), ch.getMeasuredHeight()); + } } } } @@ -407,7 +429,11 @@ public class PopupSwipeBackLayout extends FrameLayout { int s = canvas.save(); mPath.rewind(); int rad = AndroidUtilities.dp(6); - mRect.set(0, y, w, y + h); + if (stickToRight) { + mRect.set(getWidth() - w, y, getWidth(), y + h); + } else { + mRect.set(0, y, w, y + h); + } mPath.addRoundRect(mRect, rad, rad, Path.Direction.CW); canvas.clipPath(mPath); super.dispatchDraw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitPreviewView.java index a7546d2ee..3be324633 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitPreviewView.java @@ -34,7 +34,7 @@ import org.telegram.messenger.LocaleController; 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_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -77,7 +77,7 @@ public class LimitPreviewView extends LinearLayout { private int animateIncreaseWidth; float limitIconRotation; public boolean isStatistic; - + public boolean invalidationEnabled = true; public LimitPreviewView(@NonNull Context context, int icon, int currentValue, int premiumLimit, Theme.ResourcesProvider resourcesProvider) { this(context, icon, currentValue, premiumLimit, .5f, resourcesProvider); @@ -194,7 +194,7 @@ public class LimitPreviewView extends LinearLayout { } canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(6), dp(6), paint); canvas.restore(); - if (staticGradient == null) { + if (staticGradient == null && invalidationEnabled) { invalidate(); } super.dispatchDraw(canvas); @@ -451,7 +451,7 @@ public class LimitPreviewView extends LinearLayout { premiumLocked = true; } - public void setBoosts(TLRPC.TL_stories_boostsStatus boosts, boolean boosted) { + public void setBoosts(TL_stories.TL_premium_boostsStatus boosts, boolean boosted) { int k = boosts.current_level_boosts; boolean isZeroLevelBoosts = boosts.current_level_boosts == boosts.boosts; if ((isZeroLevelBoosts && boosted) || boosts.next_level_boosts == 0) { @@ -471,18 +471,16 @@ public class LimitPreviewView extends LinearLayout { premiumCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); defaultText.setTextColor(Color.WHITE); - setIconValue(boosts.boosts, false); isBoostsStyle = true; } - public void increaseCurrentValue(int value, int maxValue) { + public void increaseCurrentValue(int boosts, int value, int maxValue) { currentValue++; percent = MathUtils.clamp(value / (float) maxValue, 0f, 1f); animateIncrease = true; animateIncreaseWidth = width1; - - setIconValue(currentValue, true); + setIconValue(boosts, true); limitsContainer.requestLayout(); requestLayout(); } @@ -559,7 +557,9 @@ public class LimitPreviewView extends LinearLayout { PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(pathEffect); canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint()); PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(null); - invalidate(); + if (invalidationEnabled) { + invalidate(); + } } float x = (getMeasuredWidth() - textLayout.getWidth()) / 2f; @@ -679,6 +679,9 @@ public class LimitPreviewView extends LinearLayout { void createAnimationLayoutsDiff(CharSequence oldText) { + if (textLayout == null) { + return; + } animatedLayouts.clear(); SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text); int directionCount = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java index 6d4da8d80..8176a8e23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java @@ -1,18 +1,26 @@ package org.telegram.ui.Components.Premium; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorSet; +import android.animation.LayoutTransition; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; +import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; import android.text.TextUtils; +import android.text.style.ClickableSpan; import android.transition.TransitionManager; import android.transition.TransitionSet; import android.transition.TransitionValues; @@ -33,18 +41,19 @@ import androidx.core.graphics.ColorUtils; 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.ChannelBoostsController; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -56,24 +65,33 @@ import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FireworksOverlay; import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; +import org.telegram.ui.Components.LoginOrView; +import org.telegram.ui.Components.Premium.boosts.BoostCounterView; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.Premium.boosts.BoostPagerBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.ReassignBoostBottomSheet; import org.telegram.ui.Components.RecyclerItemsEnterAnimator; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.Stories.ChannelBoostUtilities; +import org.telegram.ui.Stories.recorder.StoryRecorder; import java.util.ArrayList; import java.util.HashSet; +import java.util.List; -public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { - +public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView implements NotificationCenter.NotificationCenterDelegate { public static final int TYPE_PIN_DIALOGS = 0; public static final int TYPE_PUBLIC_LINKS = 2; public static final int TYPE_FOLDERS = 3; @@ -96,14 +114,16 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { public static final int TYPE_BOOSTS = 17; public static final int TYPE_BOOSTS_FOR_POSTING = 18; public static final int TYPE_BOOSTS_FOR_USERS = 19; + public static final int TYPE_BOOSTS_FOR_COLOR = 20; private boolean canSendLink; private int linkRow = -1; private long dialogId; - private TLRPC.TL_stories_boostsStatus boostsStatus; + private TL_stories.TL_premium_boostsStatus boostsStatus; private ChannelBoostsController.CanApplyBoost canApplyBoost; private HeaderView headerView; private boolean isCurrentChat; + private boolean lockInvalidation = false; public static String limitTypeToServerString(int type) { switch (type) { @@ -144,6 +164,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { int chatEndRow = -1; int loadingRow = -1; int emptyViewDividerRow = -1; + int bottomRow = -1; public boolean parentIsChannel; private int currentValue = -1; @@ -155,6 +176,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { private ArrayList restrictedUsers = new ArrayList<>(); PremiumButtonView premiumButtonView; + TextView actionBtn; public Runnable onSuccessRunnable; public Runnable onShowPremiumScreenRunnable; private boolean loading = false; @@ -185,6 +207,23 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { fireworksOverlay = new FireworksOverlay(getContext()); container.addView(fireworksOverlay, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } + if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR) { + ((ViewGroup) premiumButtonView.getParent()).removeView(premiumButtonView); + recyclerListView.setPadding(0, 0, 0, 0); + actionBtn = new TextView(context); + actionBtn.setGravity(Gravity.CENTER); + actionBtn.setEllipsize(TextUtils.TruncateAt.END); + actionBtn.setSingleLine(true); + actionBtn.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + actionBtn.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + actionBtn.setText(premiumButtonView.getTextView().getText()); + actionBtn.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); + actionBtn.setOnClickListener(v -> { + AndroidUtilities.addToClipboard(getBoostLink()); + dismiss(); + }); + actionBtn.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider), 120))); + } } @Override @@ -192,7 +231,15 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { super.onViewCreated(containerView); Context context = containerView.getContext(); - premiumButtonView = new PremiumButtonView(context, true, resourcesProvider); + premiumButtonView = new PremiumButtonView(context, true, resourcesProvider) { + @Override + public void invalidate() { + if (lockInvalidation) { + return; + } + super.invalidate(); + } + }; if (!hasFixedSize) { divider = new View(context) { @@ -237,7 +284,9 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { }); recyclerListView.setOnItemLongClickListener((view, position) -> { recyclerListView.getOnItemClickListener().onItemClick(view, position); - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (type != TYPE_BOOSTS_FOR_USERS) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + } return false; }); premiumButtonView.buttonLayout.setOnClickListener(v -> { @@ -245,29 +294,35 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { return; } if (type == TYPE_BOOSTS_FOR_USERS) { - canApplyBoost.checkTime(); - if (!UserConfig.getInstance(currentAccount).isPremium()) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(LocaleController.getString("PremiumNeeded", R.string.PremiumNeeded)); - builder.setSubtitle(AndroidUtilities.replaceTags(LocaleController.getString("PremiumNeededForBoosting", R.string.PremiumNeededForBoosting))); - builder.setPositiveButton(LocaleController.getString("CheckPhoneNumberYes", R.string.CheckPhoneNumberYes), (dialog, which) -> { - PremiumFeatureBottomSheet featureBottomSheet = new PremiumFeatureBottomSheet(parentFragment, PremiumPreviewFragment.PREMIUM_FEATURE_STORIES, false); - parentFragment.showDialog(featureBottomSheet); - LimitReachedBottomSheet.this.dismiss(); - dialog.dismiss(); - }); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialog, which) -> dialog.dismiss()); - builder.show(); + if (canApplyBoost.empty) { + if (UserConfig.getInstance(currentAccount).isPremium() && BoostRepository.isMultiBoostsAvailable()) { + BoostDialogs.showMoreBoostsNeeded(dialogId); + } else { + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(LocaleController.getString("PremiumNeeded", R.string.PremiumNeeded)); + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.getString("PremiumNeededForBoosting", R.string.PremiumNeededForBoosting))); + builder.setPositiveButton(LocaleController.getString("CheckPhoneNumberYes", R.string.CheckPhoneNumberYes), (dialog, which) -> { + PremiumPreviewBottomSheet previewBottomSheet = new PremiumPreviewBottomSheet(getBaseFragment(), currentAccount, null, resourcesProvider); + parentFragment.showDialog(previewBottomSheet); + LimitReachedBottomSheet.this.dismiss(); + dialog.dismiss(); + }); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialog, which) -> dialog.dismiss()); + builder.show(); + } } else if (canApplyBoost.canApply && canApplyBoost.replaceDialogId == 0) { - boostChannel(); - } else if (canApplyBoost.giftedPremium) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(LocaleController.getString("CantBoostWithGiftedPremium", R.string.CantBoostWithGiftedPremium)); - builder.setSubtitle(AndroidUtilities.replaceTags(LocaleController.formatString("CantBoostWithGiftedPremiumDescription ", R.string.CantBoostWithGiftedPremiumDescription))); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { - dialog.dismiss(); - }); - builder.show(); + if (canApplyBoost.needSelector && BoostRepository.isMultiBoostsAvailable()) { + lockInvalidation = true; + limitPreviewView.invalidationEnabled = false; + ReassignBoostBottomSheet.show(getBaseFragment(), canApplyBoost.myBoosts, canApplyBoost.currentChat).setOnHideListener(dialog -> { + lockInvalidation = false; + limitPreviewView.invalidationEnabled = true; + premiumButtonView.invalidate(); + limitPreviewView.invalidate(); + }); + } else { + boostChannel(); + } } else if (canApplyBoost.canApply) { FrameLayout frameLayout = new FrameLayout(getContext()); BackupImageView fromAvatar = new BackupImageView(getContext()); @@ -329,7 +384,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setView(containerLayout); - textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ReplaceBoostChannelDescription", R.string.ReplaceBoostChannelDescription,fromChat.title, chat.title))); + textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("ReplaceBoostChannelDescription", R.string.ReplaceBoostChannelDescription, fromChat.title, chat.title))); builder.setPositiveButton(LocaleController.getString("Replace", R.string.Replace), (dialog, which) -> { dialog.dismiss(); boostChannel(); @@ -341,7 +396,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { int time = canApplyBoost.floodWait; if (time < 60) { timeString = LocaleController.formatPluralString("Seconds", time); - } else if (time < 60 * 60){ + } else if (time < 60 * 60) { timeString = LocaleController.formatPluralString("Minutes", time / 60); } else if (time / 60 / 60 > 2) { timeString = LocaleController.formatPluralString("Hours", time / 60 / 60); @@ -358,7 +413,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } return; } - if (type == TYPE_BOOSTS_FOR_POSTING) { + if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR) { AndroidUtilities.addToClipboard(getBoostLink()); dismiss(); return; @@ -381,7 +436,42 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { }); premiumButtonView.overlayTextView.setOnClickListener(v -> { if (type == TYPE_BOOSTS_FOR_USERS) { - dismiss(); + if (canApplyBoost.canApply) { + premiumButtonView.buttonLayout.callOnClick(); + if (canApplyBoost.alreadyActive && canApplyBoost.boostedNow) { + ChannelBoostsController boostsController = MessagesController.getInstance(currentAccount).getBoostsController(); + boostsController.getBoostsStats(dialogId, tlPremiumBoostsStatus -> { + setBoostsStats(tlPremiumBoostsStatus, isCurrentChat); + int defaultLimit = limitParams.defaultLimit; + int premiumLimit = limitParams.premiumLimit; + float percent = defaultLimit / (float) premiumLimit; + int icon = limitParams.icon; + + int titleIndex = headerView.indexOfChild(limitPreviewView); + headerView.removeView(limitPreviewView); + headerView.setLayoutTransition(new LayoutTransition()); + limitPreviewView = new LimitPreviewView(context, icon, 0, premiumLimit, percent, resourcesProvider) { + @Override + public void invalidate() { + if (lockInvalidation) { + return; + } + super.invalidate(); + } + }; + limitPreviewView.wasHaptic = true; + headerView.addView(limitPreviewView, titleIndex, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0, 0)); + + limitPreviewView.setBoosts(boostsStatus, false); + }); + } + } else { + if (canApplyBoost.alreadyActive && BoostRepository.isMultiBoostsAvailable() && !canApplyBoost.isMaxLvl) { + BoostDialogs.showMoreBoostsNeeded(dialogId); + } else { + dismiss(); + } + } return; } if (type == TYPE_ADD_MEMBERS_RESTRICTED) { @@ -405,6 +495,23 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } private void boostChannel() { + if (premiumButtonView.isLoading()) { + return; + } + premiumButtonView.setLoading(true); + MessagesController.getInstance(currentAccount).getBoostsController().applyBoost(dialogId, canApplyBoost.slot, arg -> { + if (canApplyBoost != null) { + canApplyBoost.boostedNow = true; + canApplyBoost.setMyBoosts(arg); + } + premiumButtonView.setLoading(false); + onBoostSuccess(1); + }, arg -> { + premiumButtonView.setLoading(false); + }); + } + + private void onBoostSuccess(int upgradeCount) { TransitionSet transitionSet = new TransitionSet(); transitionSet.addTransition(new Visibility() { @Override @@ -431,20 +538,22 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { }); transitionSet.setOrdering(TransitionSet.ORDERING_TOGETHER); TransitionManager.beginDelayedTransition(headerView, transitionSet); - MessagesController.getInstance(currentAccount).getBoostsController().applyBoost(dialogId); - limitPreviewView.increaseCurrentValue((boostsStatus.boosts + 1) - boostsStatus.next_level_boosts * boostsStatus.level, boostsStatus.next_level_boosts - boostsStatus.next_level_boosts * boostsStatus.level); - boostsStatus.boosts++; - if (boostsStatus.next_level_boosts == boostsStatus.boosts) { + + int k = boostsStatus.current_level_boosts; + boostsStatus.boosts += upgradeCount; + limitPreviewView.increaseCurrentValue(boostsStatus.boosts, (boostsStatus.boosts - k), (boostsStatus.next_level_boosts - k)); + + if (boostsStatus.next_level_boosts <= boostsStatus.boosts) { boostsStatus.level += 1; boostsStatus.current_level_boosts = boostsStatus.boosts; } - canApplyBoost.alreadyActive = true; headerView.recreateTitleAndDescription(); headerView.title.setText(getBoostsTitleString()); headerView.description.setText(AndroidUtilities.replaceTags(getBoostsDescriptionString())); updateButton(); fireworksOverlay.start(); fireworksOverlay.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + headerView.boostCounterView.setCount(canApplyBoost.boostCount, true); } private void sendInviteMessages() { @@ -486,8 +595,17 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { public void updatePremiumButtonText() { if (type == TYPE_BOOSTS_FOR_USERS) { - premiumButtonView.buttonTextView.setText(LocaleController.getString("BoostChannel", R.string.BoostChannel)); - } else if (type == TYPE_BOOSTS_FOR_POSTING) { + if (BoostRepository.isMultiBoostsAvailable()) { + premiumButtonView.buttonTextView.setText(canApplyBoost != null && canApplyBoost.alreadyActive ? + LocaleController.getString("BoostingBoostAgain", R.string.BoostingBoostAgain) + : LocaleController.getString("BoostChannel", R.string.BoostChannel)); + if (canApplyBoost != null && canApplyBoost.isMaxLvl) { + premiumButtonView.buttonTextView.setText(LocaleController.getString("OK", R.string.OK)); + } + } else { + premiumButtonView.buttonTextView.setText(LocaleController.getString("BoostChannel", R.string.BoostChannel)); + } + } else if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR) { SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("d "); spannableStringBuilder.setSpan(new ColoredImageSpan(R.drawable.msg_copy_filled), 0, 1, 0); spannableStringBuilder.append(LocaleController.getString("CopyLink", R.string.CopyLink)); @@ -548,8 +666,24 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { private void updateButton() { if (type == TYPE_BOOSTS_FOR_USERS) { - if (canApplyBoost.alreadyActive) { - premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), true, true); + if (!canApplyBoost.canApply && !canApplyBoost.empty || canApplyBoost.boostedNow || canApplyBoost.alreadyActive) { + if (canApplyBoost.canApply) { + if (BoostRepository.isMultiBoostsAvailable()) { + premiumButtonView.setOverlayText(LocaleController.getString("BoostingBoostAgain", R.string.BoostingBoostAgain), true, true); + } else { + premiumButtonView.setOverlayText(LocaleController.getString("BoostChannel", R.string.BoostChannel), true, true); + } + } else { + if (canApplyBoost.isMaxLvl) { + premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), true, true); + } else { + if (BoostRepository.isMultiBoostsAvailable()) { + premiumButtonView.setOverlayText(LocaleController.getString("BoostingBoostAgain", R.string.BoostingBoostAgain), true, true); + } else { + premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), true, true); + } + } + } } else { premiumButtonView.clearOverlayText(); } @@ -583,7 +717,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { if (type == TYPE_PIN_DIALOGS || type == TYPE_FOLDERS || type == TYPE_CHATS_IN_FOLDER || type == TYPE_LARGE_FILE || type == TYPE_ACCOUNTS || type == TYPE_FOLDER_INVITES || type == TYPE_SHARED_FOLDERS || type == TYPE_STORIES_COUNT || type == TYPE_STORIES_WEEK || - type == TYPE_STORIES_MONTH || type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) { + type == TYPE_STORIES_MONTH || type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR || type == TYPE_BOOSTS_FOR_USERS) { return true; } return false; @@ -597,6 +731,62 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { return LocaleController.getString("LimitReached", R.string.LimitReached); } + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.boostByChannelCreated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.boostedChannelByUser); + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.boostByChannelCreated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.boostedChannelByUser); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.boostByChannelCreated) { + TLRPC.Chat chat = (TLRPC.Chat) args[0]; + boolean isGiveaway = (boolean) args[1]; + if (isGiveaway) { + if (StoryRecorder.isVisible()) { + ChatActivity chatFragment = ChatActivity.of(-chat.id); + LaunchActivity.getLastFragment().presentFragment(chatFragment, false, false); + StoryRecorder.destroyInstance(); + dismiss(); + BoostDialogs.showBulletin(chatFragment, chat, true); + } else { + List fragmentStack = getBaseFragment().getParentLayout().getFragmentStack(); + BaseFragment chatFragment = fragmentStack.size() >= 2 ? fragmentStack.get(fragmentStack.size() - 2) : null; + getBaseFragment().finishFragment(); + dismiss(); + if (chatFragment instanceof ChatActivity) { + BoostDialogs.showBulletin(chatFragment, chat, true); + } + } + } else { + BoostDialogs.showBulletin(container, resourcesProvider, chat, false); + } + } else if (id == NotificationCenter.boostedChannelByUser) { + TL_stories.TL_premium_myBoosts myBoosts = (TL_stories.TL_premium_myBoosts) args[0]; + int size = (int) args[1]; + int channels = (int) args[2]; + if (canApplyBoost != null) { + canApplyBoost.boostedNow = true; + canApplyBoost.setMyBoosts(myBoosts); + onBoostSuccess(size); + } + + String str = LocaleController.formatString("BoostingReassignedFrom", R.string.BoostingReassignedFrom, + LocaleController.formatPluralString("BoostingSubscriptionsCount", size), + LocaleController.formatPluralString("BoostingFromOtherChannel", channels)); + BulletinFactory bulletinFactory = BulletinFactory.of(container, resourcesProvider); + bulletinFactory.createSimpleBulletinWithIconSize(R.raw.forward, str, 30).setDuration(4000).show(true); + } + } + @Override public RecyclerListView.SelectionAdapter createAdapter() { return new RecyclerListView.SelectionAdapter() { @@ -614,6 +804,47 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { View view; Context context = parent.getContext(); switch (viewType) { + case 8: + LinearLayout wrapperLayout = new LinearLayout(context); + wrapperLayout.setOrientation(LinearLayout.VERTICAL); + + LoginOrView orDividerView = new LoginOrView(context); + + TextView textView = new LinkSpanDrawable.LinksTextView(context); + SpannableStringBuilder text = AndroidUtilities.replaceTags(LocaleController.getString(R.string.BoostingStoriesByGifting)); + SpannableStringBuilder link = new SpannableStringBuilder(LocaleController.getString(R.string.BoostingStoriesByGiftingLink)); + link.setSpan(new ClickableSpan() { + @Override + public void updateDrawState(@NonNull TextPaint ds) { + super.updateDrawState(ds); + ds.setUnderlineText(false); + ds.setColor(Theme.getColor(Theme.key_chat_messageLinkIn, resourcesProvider)); + } + @Override + public void onClick(@NonNull View view) { + BoostPagerBottomSheet.show(getBaseFragment(), dialogId, resourcesProvider); + } + }, 0, link.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + SpannableString arrow = new SpannableString(">"); + Drawable imageDrawable = getContext().getResources().getDrawable(R.drawable.msg_arrowright).mutate(); + imageDrawable.setColorFilter(new PorterDuffColorFilter(Theme.key_chat_messageLinkIn, PorterDuff.Mode.SRC_IN)); + ColoredImageSpan span = new ColoredImageSpan(imageDrawable); + span.setColorKey(Theme.key_chat_messageLinkIn); + span.setSize(dp(18)); + span.setWidth(dp(11)); + span.setTranslateX(-dp(5)); + arrow.setSpan(span, 0, arrow.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + textView.setText(TextUtils.concat(text, " ", AndroidUtilities.replaceCharSequence(">", link, arrow))); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider)); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + + wrapperLayout.addView(actionBtn, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 12, 12, 12, 8)); + wrapperLayout.addView(orDividerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 0, 0, 0)); + wrapperLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 12, 0, 12, 4)); + + view = wrapperLayout; + break; case 7: FrameLayout frameLayout = new FrameLayout(getContext()); TextView linkView = new TextView(context); @@ -633,7 +864,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { imageView.setColorFilter(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); imageView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); imageView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(20), 0, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector, resourcesProvider), (int) (255 * 0.3f)))); - frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40 ,Gravity.RIGHT | Gravity.CENTER_VERTICAL, 15, 0, 15, 0)); + frameLayout.addView(imageView, LayoutHelper.createFrame(40, 40, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 15, 0, 15, 0)); imageView.setOnClickListener(v -> { statisticClickRunnable.run(); dismiss(); @@ -727,6 +958,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } else { headerCell.setText(LocaleController.getString("LastActiveCommunities", R.string.LastActiveCommunities)); } + } else if (holder.getItemViewType() == 8) { + } } @@ -744,6 +977,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { return 6; } else if (linkRow == position) { return 7; + } else if (bottomRow == position) { + return 8; } if (type == TYPE_TO0_MANY_COMMUNITIES || type == TYPE_ADD_MEMBERS_RESTRICTED) { return 4; @@ -788,7 +1023,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { this.dialogId = dialogId; } - public void setBoostsStats(TLRPC.TL_stories_boostsStatus boostsStatus, boolean isCurrentChat) { + public void setBoostsStats(TL_stories.TL_premium_boostsStatus boostsStatus, boolean isCurrentChat) { this.boostsStatus = boostsStatus; this.isCurrentChat = isCurrentChat; } @@ -796,6 +1031,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { public void setCanApplyBoost(ChannelBoostsController.CanApplyBoost canApplyBoost) { this.canApplyBoost = canApplyBoost; updateButton(); + updatePremiumButtonText(); } public void showStatisticButtonInLink(Runnable runnable) { @@ -806,6 +1042,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { TextView title; TextView description; + BoostCounterView boostCounterView; + LinearLayout titleLinearLayout; @SuppressLint("SetTextI18n") public HeaderView(Context context) { @@ -829,9 +1067,14 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { descriptionStr = LocaleController.formatString( "ChannelNeedBoostsDescriptionNextLevel", R.string.ChannelNeedBoostsDescriptionNextLevel, LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts, boostsStatus.next_level_boosts), - LocaleController.formatPluralString("BoostStories", boostsStatus.level) + LocaleController.formatPluralString("BoostStories", boostsStatus.level + 1) ); } + } else if (type == TYPE_BOOSTS_FOR_COLOR) { + descriptionStr = LocaleController.formatString( + "ChannelNeedBoostsForColorDescription", R.string.ChannelNeedBoostsForColorDescription, + MessagesController.getInstance(currentAccount).channelColorLevelMin + ); } else if (type == TYPE_ADD_MEMBERS_RESTRICTED) { premiumLocked = true; if (!canSendLink) { @@ -913,14 +1156,22 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { percent = defaultLimit / (float) premiumLimit; - if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) { + if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR || type == TYPE_BOOSTS_FOR_USERS) { currentValue = 0; } - limitPreviewView = new LimitPreviewView(context, icon, currentValue, premiumLimit, percent, resourcesProvider); - if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) { + limitPreviewView = new LimitPreviewView(context, icon, currentValue, premiumLimit, percent, resourcesProvider) { + @Override + public void invalidate() { + if (lockInvalidation) { + return; + } + super.invalidate(); + } + }; + if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR || type == TYPE_BOOSTS_FOR_USERS) { if (boostsStatus != null) { - limitPreviewView.setBoosts(boostsStatus, canApplyBoost != null && canApplyBoost.alreadyActive); + limitPreviewView.setBoosts(boostsStatus, canApplyBoost != null && canApplyBoost.boostedNow); } } else { limitPreviewView.setBagePosition(position); @@ -957,6 +1208,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } else { title.setText(LocaleController.getString("BoostingIncreaseLevel", R.string.BoostingIncreaseLevel)); } + } else if (type == TYPE_BOOSTS_FOR_COLOR) { + title.setText(LocaleController.getString(R.string.BoostingEnableColor)); } else if (type == TYPE_ADD_MEMBERS_RESTRICTED) { if (canSendLink) { title.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink)); @@ -971,32 +1224,56 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); title.setGravity(Gravity.CENTER); - addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, premiumLocked ? 8 : 22, 0, 10)); - if (type == TYPE_BOOSTS_FOR_USERS && !isCurrentChat) { - FrameLayout frameLayout = new FrameLayout(getContext()); - frameLayout.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(14), Theme.getColor(Theme.key_windowBackgroundGray))); - BackupImageView backupImageView = new BackupImageView(getContext()); - backupImageView.setRoundRadius(AndroidUtilities.dp(14)); - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); - AvatarDrawable avatarDrawable = new AvatarDrawable(); - avatarDrawable.setInfo(chat); - backupImageView.setForUserOrChat(chat, avatarDrawable); - frameLayout.addView(backupImageView, LayoutHelper.createFrame(28, 28)); - TextView textView = new TextView(getContext()); - textView.setText(chat.title); - textView.setSingleLine(true); - textView.setMaxLines(1); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 36, 0, 8, 0)); + if (type == TYPE_BOOSTS_FOR_USERS) { + boostCounterView = new BoostCounterView(context, resourcesProvider); + boostCounterView.setCount(canApplyBoost.boostCount, false); + if (isCurrentChat) { + titleLinearLayout = new LinearLayout(context); + titleLinearLayout.setOrientation(HORIZONTAL); + titleLinearLayout.setWeightSum(1f); + titleLinearLayout.addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 1, 0)); + titleLinearLayout.addView(boostCounterView); + addView(titleLinearLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12 + 13, premiumLocked ? 8 : 22, 12, 10)); + } else { + addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, premiumLocked ? 8 : 22, 0, 0)); - addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 28, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 12)); - ScaleStateListAnimator.apply(frameLayout); - frameLayout.setOnClickListener(v -> { - getBaseFragment().presentFragment(ChatActivity.of(dialogId)); - dismiss(); - }); + LinearLayout rootLayout = new LinearLayout(getContext()); + rootLayout.setOrientation(HORIZONTAL); + rootLayout.setClipChildren(false); + + FrameLayout frameLayout = new FrameLayout(getContext()); + frameLayout.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(14), Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider))); + BackupImageView backupImageView = new BackupImageView(getContext()); + backupImageView.setRoundRadius(AndroidUtilities.dp(14)); + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + AvatarDrawable avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(chat); + backupImageView.setForUserOrChat(chat, avatarDrawable); + frameLayout.addView(backupImageView, LayoutHelper.createFrame(28, 28)); + TextView textView = new TextView(getContext()); + if (chat != null) { + textView.setText(chat.title); + } + textView.setSingleLine(true); + textView.setMaxLines(1); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + frameLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 36, 0, 12, 0)); + + rootLayout.addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 28, Gravity.BOTTOM, 18, 0, 18, 0)); + rootLayout.addView(boostCounterView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, -30, 2, 18, 0)); + + addView(rootLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 38, Gravity.CENTER, 0, 0, 0, 12)); + ScaleStateListAnimator.apply(rootLayout); + rootLayout.setOnClickListener(v -> { + getBaseFragment().presentFragment(ChatActivity.of(dialogId)); + dismiss(); + }); + } + } else { + addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, premiumLocked ? 8 : 22, 0, 10)); } description = new TextView(context); description.setText(AndroidUtilities.replaceTags(descriptionStr)); @@ -1013,16 +1290,30 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } public void recreateTitleAndDescription() { - int titleIndex = indexOfChild(title); int descriptionIndex = indexOfChild(description); - removeView(title); - title = new TextView(getContext()); - title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); - title.setGravity(Gravity.CENTER); - addView(title, titleIndex, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 22, 0, 10)); + if (isCurrentChat) { + int titleIndex = indexOfChild(titleLinearLayout); + removeView(titleLinearLayout); + titleLinearLayout.removeView(title); + titleLinearLayout.removeView(boostCounterView); + + titleLinearLayout = new LinearLayout(getContext()); + titleLinearLayout.setOrientation(HORIZONTAL); + titleLinearLayout.setWeightSum(1f); + titleLinearLayout.addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 1, 0)); + titleLinearLayout.addView(boostCounterView); + addView(titleLinearLayout, titleIndex, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 12 + 13, 22, 12, 10)); + } else { + int titleIndex = indexOfChild(title); + removeView(title); + title = new TextView(getContext()); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + title.setGravity(Gravity.CENTER); + addView(title, titleIndex, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 22, 0, 10)); + } removeView(description); description = new TextView(getContext()); @@ -1034,10 +1325,10 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } private String getBoostsTitleString() { - if (boostsStatus.level > 0 && !canApplyBoost.alreadyActive) { - return LocaleController.getString("HelpUpgradeChannel", R.string.HelpUpgradeChannel); - } else if (boostsStatus.next_level_boosts == 0) { + if (boostsStatus.next_level_boosts == 0) { return LocaleController.formatString("BoostsMaxLevelReached", R.string.BoostsMaxLevelReached); + } else if (boostsStatus.level > 0 && !canApplyBoost.alreadyActive) { + return LocaleController.getString("HelpUpgradeChannel", R.string.HelpUpgradeChannel); } else if (isCurrentChat) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); if (canApplyBoost.alreadyActive) { @@ -1069,25 +1360,37 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { if (boostsStatus.level == 0) { return LocaleController.formatString( "ChannelNeedBoostsAlreadyBoostedDescriptionLevel1", R.string.ChannelNeedBoostsAlreadyBoostedDescriptionLevel1, - LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts) + LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts) ); } else { - return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext, - LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts), - LocaleController.formatPluralString("BoostStories", boostsStatus.level) - ); + if (boostsStatus.next_level_boosts == 0) { + return LocaleController.formatString("ChannelBoostsJustReachedLevelNext", R.string.ChannelBoostsJustReachedLevelNext, + boostsStatus.level, + LocaleController.formatPluralString("BoostStories", boostsStatus.level + 1)); + } else { + return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext, + LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts), + LocaleController.formatPluralString("BoostStories", boostsStatus.level + 1) + ); + } } } else { if (boostsStatus.level == 0) { return LocaleController.formatString( "ChannelNeedBoostsDescriptionLevel1", R.string.ChannelNeedBoostsDescriptionLevel1, - LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts) + LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts) ); } else { - return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext, - LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts), - LocaleController.formatPluralString("BoostStories", boostsStatus.level) - ); + if (boostsStatus.next_level_boosts == 0) { + return LocaleController.formatString("ChannelBoostsJustReachedLevelNext", R.string.ChannelBoostsJustReachedLevelNext, + boostsStatus.level, + LocaleController.formatPluralString("BoostStories", boostsStatus.level + 1)); + } else { + return LocaleController.formatString("ChannelNeedBoostsDescriptionLevelNext", R.string.ChannelNeedBoostsDescriptionLevelNext, + LocaleController.formatPluralString("MoreBoosts", boostsStatus.next_level_boosts - boostsStatus.boosts, boostsStatus.next_level_boosts - boostsStatus.boosts), + LocaleController.formatPluralString("BoostStories", boostsStatus.level + 1) + ); + } } } } @@ -1186,7 +1489,7 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { limitParams.descriptionStr = LocaleController.formatString("LimitReachedStoriesMonthly", R.string.LimitReachedStoriesMonthly, limitParams.defaultLimit, limitParams.premiumLimit); limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.premiumLimit); limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedStoriesMonthlyPremium", R.string.LimitReachedStoriesMonthlyPremium, limitParams.defaultLimit); - } else if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_USERS) { + } else if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR || type == TYPE_BOOSTS_FOR_USERS) { limitParams.defaultLimit = MessagesController.getInstance(currentAccount).storiesSentMonthlyLimitDefault; limitParams.premiumLimit = MessagesController.getInstance(currentAccount).storiesSentMonthlyLimitPremium; limitParams.icon = R.drawable.filled_limit_boost; @@ -1261,8 +1564,11 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { } } } - if (type == TYPE_BOOSTS_FOR_POSTING) { + if (type == TYPE_BOOSTS_FOR_POSTING || type == TYPE_BOOSTS_FOR_COLOR) { linkRow = rowCount++; + if (MessagesController.getInstance(currentAccount).giveawayGiftsPurchaseAvailable) { + bottomRow = rowCount++; + } } notifyDataSetChanged(); } @@ -1324,7 +1630,8 @@ public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { if (error == null) { final TLRPC.TL_messages_inactiveChats chats = (TLRPC.TL_messages_inactiveChats) response; final ArrayList signatures = new ArrayList<>(); - for (int i = 0; i < chats.chats.size(); i++) { + final int count = Math.min(chats.chats.size(), chats.dates.size()); + for (int i = 0; i < count; i++) { TLRPC.Chat chat = chats.chats.get(i); int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); int date = chats.dates.get(i); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java index 67456404b..6a9e3f480 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java @@ -1,5 +1,7 @@ package org.telegram.ui.Components.Premium; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; @@ -8,12 +10,10 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; -import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.widget.FrameLayout; import android.widget.LinearLayout; -import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; @@ -23,6 +23,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CounterView; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; @@ -70,7 +71,33 @@ public class PremiumButtonView extends FrameLayout { flickerDrawable.repeatProgress = 4f; LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.HORIZONTAL); - buttonTextView = new AnimatedTextView(context); + buttonTextView = new AnimatedTextView(context) { + @Override + protected void onDraw(Canvas canvas) { + if (loadingT > 0) { + if (loadingDrawable == null) { + loadingDrawable = new CircularProgressDrawable(buttonTextView.getTextColor()); + } + int y = (int) ((1f - loadingT) * dp(24)); + loadingDrawable.setBounds(0, y, getWidth(), y + getHeight()); + loadingDrawable.setAlpha((int) (0xFF * loadingT)); + loadingDrawable.draw(canvas); + invalidate(); + } + + if (loadingT < 1) { + if (loadingT != 0) { + canvas.save(); + canvas.translate(0, (int) (loadingT * dp(-24))); + canvas.scale(1, 1f - .4f * loadingT); + super.onDraw(canvas); + canvas.restore(); + return; + } + super.onDraw(canvas); + } + } + }; buttonTextView.setAnimationProperties(.35f, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); buttonTextView.setGravity(Gravity.CENTER); buttonTextView.setTextColor(Color.WHITE); @@ -90,7 +117,33 @@ public class PremiumButtonView extends FrameLayout { addView(buttonLayout); if (createOverlayTextView) { - overlayTextView = new AnimatedTextView(context, true, true, true); + overlayTextView = new AnimatedTextView(context, true, true, true) { + @Override + protected void onDraw(Canvas canvas) { + if (loadingT > 0) { + if (loadingDrawable == null) { + loadingDrawable = new CircularProgressDrawable(buttonTextView.getTextColor()); + } + int y = (int) ((1f - loadingT) * dp(24)); + loadingDrawable.setBounds(0, y, getWidth(), y + getHeight()); + loadingDrawable.setAlpha((int) (0xFF * loadingT)); + loadingDrawable.draw(canvas); + invalidate(); + } + + if (loadingT < 1) { + if (loadingT != 0) { + canvas.save(); + canvas.translate(0, (int) (loadingT * dp(-24))); + canvas.scale(1, 1f - .4f * loadingT); + super.onDraw(canvas); + canvas.restore(); + return; + } + super.onDraw(canvas); + } + } + }; overlayTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); overlayTextView.setGravity(Gravity.CENTER); overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); @@ -108,6 +161,7 @@ public class PremiumButtonView extends FrameLayout { public RLottieImageView getIconView() { return iconView; } + public AnimatedTextView getTextView() { return buttonTextView; } @@ -120,6 +174,45 @@ public class PremiumButtonView extends FrameLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + private CircularProgressDrawable loadingDrawable; + private float loadingT = 0; + private boolean loading; + private ValueAnimator loadingAnimator; + + public void setLoading(boolean loading) { + if (this.loading != loading) { + if (loadingAnimator != null) { + loadingAnimator.cancel(); + loadingAnimator = null; + } + loadingAnimator = ValueAnimator.ofFloat(loadingT, (this.loading = loading) ? 1 : 0); + loadingAnimator.addUpdateListener(anm -> { + loadingT = (float) anm.getAnimatedValue(); + buttonTextView.invalidate(); + if (overlayTextView != null) { + overlayTextView.invalidate(); + } + }); + loadingAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + loadingT = loading ? 1 : 0; + buttonTextView.invalidate(); + if (overlayTextView != null) { + overlayTextView.invalidate(); + } + } + }); + loadingAnimator.setDuration(320); + loadingAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + loadingAnimator.start(); + } + } + + public boolean isLoading() { + return loading; + } + @Override protected void dispatchDraw(Canvas canvas) { if (counterView != null) { @@ -185,7 +278,6 @@ public class PremiumButtonView extends FrameLayout { updateOverlay(animated); } - private void updateOverlay(boolean animated) { if (overlayAnimator != null) { overlayAnimator.removeAllListeners(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java index 35664bff4..0abf142d2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java @@ -455,6 +455,10 @@ public class PremiumFeatureBottomSheet extends BottomSheet implements Notificati return type == PremiumPreviewFragment.PREMIUM_FEATURE_LIMITS || type == PremiumPreviewFragment.PREMIUM_FEATURE_STORIES; } + public void hideButton() { + buttonContainer.setVisibility(View.GONE); + } + public PremiumFeatureBottomSheet setForceAbout() { this.forceAbout = true; premiumButtonView.clearOverlayText(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java index d920164cc..67f436e03 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java @@ -366,8 +366,13 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle))); } } else { - titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserDialogTitle, ContactsController.formatName(user.first_name, user.last_name)), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); - subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserDialogSubtitle))); + if(user == null) { + titleView[0].setText(LocaleController.getString(R.string.TelegramPremium)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumSubscribedSubtitle))); + } else { + titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserDialogTitle, ContactsController.formatName(user.first_name, user.last_name)), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserDialogSubtitle))); + } } } @@ -434,7 +439,7 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i titleViewContainer = new FrameLayout(context); titleViewContainer.setClipChildren(false); - final ColorFilter colorFilter = new PorterDuffColorFilter(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundWhiteLinkText), 178), PorterDuff.Mode.MULTIPLY); + final ColorFilter colorFilter = new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN); titleView = new LinkSpanDrawable.LinksTextView[2]; for (int a = 0; a < 2; ++a) { titleView[a] = new LinkSpanDrawable.LinksTextView(context, resourcesProvider) { @@ -528,7 +533,7 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i break; default: case 1: - view = new PremiumFeatureCell(context) { + view = new PremiumFeatureCell(context, resourcesProvider) { @Override protected void dispatchDraw(Canvas canvas) { AndroidUtilities.rectTmp.set(imageView.getLeft(), imageView.getTop(), imageView.getRight(), imageView.getBottom()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java new file mode 100644 index 000000000..16f93e85c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostCounterView.java @@ -0,0 +1,119 @@ +package org.telegram.ui.Components.Premium.boosts; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.view.Gravity; +import android.view.View; +import android.view.animation.OvershootInterpolator; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; + +@SuppressLint("ViewConstructor") +public class BoostCounterView extends View { + + private final AnimatedTextView.AnimatedTextDrawable countText; + private float countScale = 1; + private ValueAnimator countAnimator; + private int lastCount; + private final Paint bgPaint; + + public BoostCounterView(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + countText = new AnimatedTextView.AnimatedTextDrawable(false, false, true); + countText.setAnimationProperties(.3f, 0, 250, CubicBezierInterpolator.EASE_OUT_QUINT); + countText.setCallback(this); + countText.setTextSize(dp(11)); + countText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + countText.setTextColor(Color.WHITE); + countText.setText(""); + countText.setGravity(Gravity.CENTER_HORIZONTAL); + + bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + bgPaint.setColor(0xFF967bff); + setVisibility(GONE); + } + + private void animateCount() { + if (countAnimator != null) { + countAnimator.cancel(); + countAnimator = null; + } + + countAnimator = ValueAnimator.ofFloat(0, 1); + countAnimator.addUpdateListener(anm -> { + countScale = Math.max(1, (float) anm.getAnimatedValue()); + invalidate(); + }); + countAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + countScale = 1; + invalidate(); + } + }); + countAnimator.setInterpolator(new OvershootInterpolator(2.0f)); + countAnimator.setDuration(200); + countAnimator.start(); + } + + public void setCount(int count, boolean animated) { + if (!BoostRepository.isMultiBoostsAvailable()) { + count = 0; + } + if (count > 0) { + setVisibility(VISIBLE); + } + if (animated) { + countText.cancelAnimation(); + } + if (animated && count != lastCount && count > 0) { + animateCount(); + } + lastCount = count; + countText.setText("x" + count, animated); + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(26), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(26), MeasureSpec.EXACTLY) + ); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.save(); + canvas.translate(AndroidUtilities.dp(3), AndroidUtilities.dp(3)); + AndroidUtilities.rectTmp2.set(0, 0, AndroidUtilities.dp(20), AndroidUtilities.dp(20)); + AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); + + if (countScale != 1) { + canvas.save(); + canvas.scale(countScale, countScale, AndroidUtilities.rectTmp2.centerX(), AndroidUtilities.rectTmp2.centerY()); + } + + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(10), dp(10), bgPaint); + countText.setBounds(AndroidUtilities.rectTmp2); + countText.draw(canvas); + if (countScale != 1) { + canvas.restore(); + } + canvas.restore(); + } +} 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 new file mode 100644 index 000000000..60290845e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostDialogs.java @@ -0,0 +1,691 @@ +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 static org.telegram.ui.Components.Premium.boosts.SelectorBottomSheet.TYPE_CHANNEL; +import static org.telegram.ui.Components.Premium.boosts.SelectorBottomSheet.TYPE_COUNTRY; +import static org.telegram.ui.Components.Premium.boosts.SelectorBottomSheet.TYPE_USER; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +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.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.messenger.browser.Browser; +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.Components.AlertsCreator; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.NumberPicker; +import org.telegram.ui.LaunchActivity; +import org.telegram.ui.StatisticActivity; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class BoostDialogs { + private final static long ONE_DAY = 1000 * 60 * 60 * 24; + + public static long getThreeDaysAfterToday() { + return BoostDialogs.roundByFiveMinutes(new Date().getTime() + (ONE_DAY * 3)); + } + + public static void showToastError(Context context, TLRPC.TL_error error) { + if (error != null && error.text != null && !TextUtils.isEmpty(error.text)) { + Toast.makeText(context, error.text, Toast.LENGTH_LONG).show(); + } + } + + private static void showBulletin(final BulletinFactory bulletinFactory, Theme.ResourcesProvider resourcesProvider, final TLRPC.Chat chat, final boolean isGiveaway) { + AndroidUtilities.runOnUIThread(() -> bulletinFactory.createSimpleBulletin(R.raw.star_premium_2, + isGiveaway ? getString("BoostingGiveawayCreated", R.string.BoostingGiveawayCreated) + : getString("BoostingAwardsCreated", R.string.BoostingAwardsCreated), + AndroidUtilities.replaceSingleTag( + isGiveaway ? getString("BoostingCheckStatistic", R.string.BoostingCheckStatistic) : + getString("BoostingCheckGiftsStatistic", R.string.BoostingCheckGiftsStatistic), + Theme.key_undo_cancelColor, 0, () -> { + if (chat != null) { + Bundle args = new Bundle(); + args.putLong("chat_id", chat.id); + args.putBoolean("is_megagroup", chat.megagroup); + args.putBoolean("start_from_boosts", true); + args.putBoolean("only_boosts", true); + StatisticActivity fragment = new StatisticActivity(args); + BaseFragment.BottomSheetParams params = new BaseFragment.BottomSheetParams(); + params.transitionFromLeft = true; + LaunchActivity.getLastFragment().showAsSheet(fragment, params); + } + }, resourcesProvider) + ).setDuration(Bulletin.DURATION_PROLONG).show(), 300); + } + + public static void showGiftLinkForwardedBulletin(long did) { + CharSequence text; + if (did == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { + text = AndroidUtilities.replaceTags(LocaleController.getString("BoostingGiftLinkForwardedToSavedMsg", R.string.BoostingGiftLinkForwardedToSavedMsg)); + } else { + if (DialogObject.isChatDialog(did)) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-did); + text = AndroidUtilities.replaceTags(LocaleController.formatString("BoostingGiftLinkForwardedTo", R.string.BoostingGiftLinkForwardedTo, chat.title)); + } else { + TLRPC.User user = MessagesController.getInstance(UserConfig.selectedAccount).getUser(did); + text = AndroidUtilities.replaceTags(LocaleController.formatString("BoostingGiftLinkForwardedTo", R.string.BoostingGiftLinkForwardedTo, UserObject.getFirstName(user))); + } + } + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory bulletinFactory = BulletinFactory.global(); + if (bulletinFactory != null) { + bulletinFactory.createSimpleBulletinWithIconSize(R.raw.forward, text, 30).show(); + } + }, 450); + } + + public static void showBulletinError(TLRPC.TL_error error) { + BulletinFactory bulletinFactory = BulletinFactory.global(); + if (bulletinFactory == null || error == null || error.text == null) { + return; + } + bulletinFactory.createErrorBulletin(error.text).show(); + } + + public static void showBulletin(FrameLayout container, Theme.ResourcesProvider resourcesProvider, final TLRPC.Chat chat, final boolean isGiveaway) { + BulletinFactory bulletinFactory = BulletinFactory.of(container, resourcesProvider); + showBulletin(bulletinFactory, resourcesProvider, chat, isGiveaway); + } + + public static void showBulletin(final BaseFragment baseFragment, final TLRPC.Chat chat, final boolean isGiveaway) { + BulletinFactory bulletinFactory = BulletinFactory.of(baseFragment); + showBulletin(bulletinFactory, baseFragment.getResourceProvider(), chat, isGiveaway); + } + + private static long roundByFiveMinutes(long dateMs) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(dateMs); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.SECOND, 0); + + int minute = calendar.get(Calendar.MINUTE); + while (minute % 5 != 0) { + minute++; + } + calendar.set(Calendar.MINUTE, minute); + return calendar.getTimeInMillis(); + } + + public static void showDatePicker(Context context, long currentDate, final AlertsCreator.ScheduleDatePickerDelegate datePickerDelegate, Theme.ResourcesProvider resourcesProvider) { + final AlertsCreator.ScheduleDatePickerColors datePickerColors = new AlertsCreator.ScheduleDatePickerColors(resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(context, false, resourcesProvider); + builder.setApplyBottomPadding(false); + + final NumberPicker dayPicker = new NumberPicker(context, resourcesProvider); + dayPicker.setTextColor(datePickerColors.textColor); + dayPicker.setTextOffset(dp(10)); + dayPicker.setItemCount(5); + final NumberPicker hourPicker = new NumberPicker(context, resourcesProvider) { + @Override + protected CharSequence getContentDescription(int value) { + return formatPluralString("Hours", value); + } + }; + hourPicker.setWrapSelectorWheel(true); + hourPicker.setAllItemsCount(24); + hourPicker.setItemCount(5); + hourPicker.setTextColor(datePickerColors.textColor); + hourPicker.setTextOffset(-dp(10)); + final NumberPicker minutePicker = new NumberPicker(context, resourcesProvider) { + @Override + protected CharSequence getContentDescription(int value) { + return formatPluralString("Minutes", value); + } + }; + minutePicker.setWrapSelectorWheel(true); + minutePicker.setAllItemsCount(60); + minutePicker.setItemCount(5); + minutePicker.setTextColor(datePickerColors.textColor); + minutePicker.setTextOffset(-dp(34)); + + LinearLayout container = new LinearLayout(context) { + + boolean ignoreLayout = false; + final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + { + setWillNotDraw(false); + paint.setTextSize(dp(20)); + paint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + paint.setColor(datePickerColors.textColor); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + ignoreLayout = true; + int count; + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + count = 3; + } else { + count = 5; + } + dayPicker.setItemCount(count); + hourPicker.setItemCount(count); + minutePicker.setItemCount(count); + dayPicker.getLayoutParams().height = dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count; + hourPicker.getLayoutParams().height = dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count; + minutePicker.getLayoutParams().height = dp(NumberPicker.DEFAULT_SIZE_PER_COUNT) * count; + ignoreLayout = false; + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawText(":", hourPicker.getRight() - dp(12), (getHeight() / 2f) - dp(11), paint); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + }; + container.setOrientation(LinearLayout.VERTICAL); + + FrameLayout titleLayout = new FrameLayout(context); + container.addView(titleLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 22, 0, 0, 4)); + + TextView titleView = new TextView(context); + titleView.setText(getString("BoostingSelectDateTime", R.string.BoostingSelectDateTime)); + titleView.setTextColor(datePickerColors.textColor); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 12, 0, 0)); + titleView.setOnTouchListener((v, event) -> true); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + linearLayout.setWeightSum(1.0f); + container.addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f, 0, 0, 12, 0, 12)); + + long currentTime = System.currentTimeMillis(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(currentTime); + int currentYear = calendar.get(Calendar.YEAR); + + TextView buttonTextView = new TextView(context) { + @Override + public CharSequence getAccessibilityClassName() { + return Button.class.getName(); + } + }; + + long maxPeriodMs = BoostRepository.giveawayPeriodMax() * 1000L; + Calendar calendarMaxPeriod = Calendar.getInstance(); + calendarMaxPeriod.setTimeInMillis(maxPeriodMs); + int maxDay = calendarMaxPeriod.get(Calendar.DAY_OF_YEAR); + calendarMaxPeriod.setTimeInMillis(System.currentTimeMillis()); + calendarMaxPeriod.add(Calendar.MILLISECOND, (int) maxPeriodMs); + + int maxHour = calendarMaxPeriod.get(Calendar.HOUR_OF_DAY); + int maxMinute = calendar.get(Calendar.MINUTE); + + linearLayout.addView(dayPicker, LayoutHelper.createLinear(0, 54 * 5, 0.5f)); + dayPicker.setMinValue(0); //0 for today + dayPicker.setMaxValue(maxDay - 1); + dayPicker.setWrapSelectorWheel(false); + dayPicker.setTag("YEAR"); + dayPicker.setFormatter(value -> { + if (value == 0) { + return getString("MessageScheduleToday", R.string.MessageScheduleToday); + } else { + long date = currentTime + (long) value * 86400000L; + calendar.setTimeInMillis(date); + int year = calendar.get(Calendar.YEAR); + if (year == currentYear) { + return LocaleController.getInstance().formatterScheduleDay.format(date); + } else { + return LocaleController.getInstance().formatterScheduleYear.format(date); + } + } + }); + final NumberPicker.OnValueChangeListener onValueChangeListener = (picker, oldVal, newVal) -> { + try { + container.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignore) { + + } + if (picker.getTag() != null && picker.getTag().equals("YEAR")) { + if (picker.getValue() == picker.getMinValue()) { + Calendar calendarCurrent = Calendar.getInstance(); + calendarCurrent.setTimeInMillis(System.currentTimeMillis()); + int minHour = calendar.get(Calendar.HOUR_OF_DAY); + int minMinute = calendar.get(Calendar.MINUTE); + hourPicker.setMinValue(minHour); + minutePicker.setMinValue(Math.min((minMinute / 5) + 1, 11)); + } else if (picker.getValue() == picker.getMaxValue()) { + hourPicker.setMaxValue(maxHour); + minutePicker.setMaxValue(Math.min((maxMinute / 5), 11)); + } else { + hourPicker.setMinValue(0); + minutePicker.setMinValue(0); + hourPicker.setMaxValue(23); + minutePicker.setMaxValue(11); + } + } + }; + dayPicker.setOnValueChangedListener(onValueChangeListener); + + hourPicker.setMinValue(0); + hourPicker.setMaxValue(23); + linearLayout.addView(hourPicker, LayoutHelper.createLinear(0, 54 * 5, 0.2f)); + hourPicker.setFormatter(value -> String.valueOf(value)); + hourPicker.setOnValueChangedListener(onValueChangeListener); + + minutePicker.setMinValue(0); + minutePicker.setMaxValue(11); + minutePicker.setValue(0); + minutePicker.setFormatter(value -> String.format("%02d", value * 5)); + linearLayout.addView(minutePicker, LayoutHelper.createLinear(0, 54 * 5, 0.3f)); + minutePicker.setOnValueChangedListener(onValueChangeListener); + + if (currentDate > 0) { + calendar.setTimeInMillis(System.currentTimeMillis()); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + calendar.set(Calendar.HOUR_OF_DAY, 0); + int days = (int) ((currentDate - calendar.getTimeInMillis()) / (24 * 60 * 60 * 1000)); + calendar.setTimeInMillis(currentDate); + if (days >= 0) { + minutePicker.setValue(calendar.get(Calendar.MINUTE) / 5); + hourPicker.setValue(calendar.get(Calendar.HOUR_OF_DAY)); + dayPicker.setValue(days); + } + } + + buttonTextView.setPadding(dp(34), 0, dp(34), 0); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(datePickerColors.buttonTextColor); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(datePickerColors.buttonBackgroundColor, 8)); + buttonTextView.setText(getString("BoostingConfirm", R.string.BoostingConfirm)); + container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16)); + buttonTextView.setOnClickListener(v -> { + calendar.setTimeInMillis(System.currentTimeMillis() + (long) dayPicker.getValue() * 24 * 3600 * 1000); + calendar.set(Calendar.HOUR_OF_DAY, hourPicker.getValue()); + calendar.set(Calendar.MINUTE, minutePicker.getValue() * 5); + datePickerDelegate.didSelectDate(true, (int) (calendar.getTimeInMillis() / 1000)); + builder.getDismissRunnable().run(); + }); + + builder.setCustomView(container); + BottomSheet bottomSheet = builder.show(); + bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); + AndroidUtilities.setLightStatusBar(bottomSheet.getWindow(), ColorUtils.calculateLuminance(datePickerColors.backgroundColor) > 0.7f); + } + + public static void showUnsavedChanges(int type, Context context, Theme.ResourcesProvider resourcesProvider, Runnable onApply, Runnable onDiscard) { + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("UnsavedChanges", R.string.UnsavedChanges)); + String text; + switch (type) { + case TYPE_USER: + text = getString("BoostingApplyChangesUsers", R.string.BoostingApplyChangesUsers); + break; + case TYPE_CHANNEL: + text = getString("BoostingApplyChangesChannels", R.string.BoostingApplyChangesChannels); + break; + case TYPE_COUNTRY: + text = getString("BoostingApplyChangesCountries", R.string.BoostingApplyChangesCountries); + break; + default: + text = ""; + } + builder.setMessage(text); + builder.setPositiveButton(getString("ApplyTheme", R.string.ApplyTheme), (dialogInterface, i) -> { + onApply.run(); + }); + builder.setNegativeButton(getString("Discard", R.string.Discard), (dialogInterface, i) -> { + onDiscard.run(); + }); + builder.show(); + } + + public static boolean checkReduceUsers(Context context, Theme.ResourcesProvider resourcesProvider, List list, TLRPC.TL_premiumGiftCodeOption selected) { + if (selected.store_product == null) { + List result = new ArrayList<>(); + for (TLRPC.TL_premiumGiftCodeOption item : list) { + if (item.months == selected.months && item.store_product != null) { + result.add(item.users); + } + } + + String downTo = TextUtils.join(", ", result); + int current = selected.users; + + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("BoostingReduceQuantity", R.string.BoostingReduceQuantity)); + builder.setMessage(replaceTags(formatString("BoostingReduceUsersText", R.string.BoostingReduceUsersText, current, downTo))); + builder.setPositiveButton(getString("OK", R.string.OK), (dialogInterface, i) -> { + + }); + builder.show(); + return true; + } + return false; + } + + public static boolean checkReduceQuantity(Context context, Theme.ResourcesProvider resourcesProvider, List list, TLRPC.TL_premiumGiftCodeOption selected, Utilities.Callback onSuccess) { + if (selected.store_product == null) { + List result = new ArrayList<>(); + for (TLRPC.TL_premiumGiftCodeOption item : list) { + if (item.months == selected.months && item.store_product != null) { + result.add(item); + } + } + TLRPC.TL_premiumGiftCodeOption suggestion = result.get(0); + + for (TLRPC.TL_premiumGiftCodeOption option : result) { + if (selected.users > option.users && option.users > suggestion.users) { + suggestion = option; + } + } + + final TLRPC.TL_premiumGiftCodeOption finalSuggestion = suggestion; + + String months = LocaleController.formatPluralString("GiftMonths", suggestion.months); + int current = selected.users; + int downTo = suggestion.users; + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("BoostingReduceQuantity", R.string.BoostingReduceQuantity)); + builder.setMessage(replaceTags(formatString("BoostingReduceQuantityText", R.string.BoostingReduceQuantityText, current, months, downTo))); + builder.setPositiveButton(getString("Reduce", R.string.Reduce), (dialogInterface, i) -> onSuccess.run(finalSuggestion)); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), (dialogInterface, i) -> { + + }); + builder.show(); + return true; + } + return false; + } + + public static void showAbout(long chatId, long msgDate, TLRPC.TL_payments_giveawayInfo giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId); + String from = chat != null ? chat.title : ""; + int quantity = giveaway.quantity; + String months = formatPluralString("BoldMonths", giveaway.months); + String endDate = LocaleController.getInstance().formatterGiveawayMonthDay.format(new Date(giveaway.until_date * 1000L)); + + String fromTime = LocaleController.getInstance().formatterDay.format(new Date(giveawayInfo.start_date * 1000L)); + String fromDate = LocaleController.getInstance().formatterGiveawayMonthDayYear.format(new Date(giveawayInfo.start_date * 1000L)); + boolean isSeveralChats = giveaway.channels.size() > 1; + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("BoostingGiveAwayAbout", R.string.BoostingGiveAwayAbout)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); + + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksText", quantity, from, quantity, months))); + stringBuilder.append("\n\n"); + + if (giveaway.only_new_subscribers) { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1, fromTime, fromDate))); + } else { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDate", quantity, endDate, quantity, from, fromTime, fromDate))); + } + } else { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1))); + } else { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubText", quantity, endDate, quantity, from))); + } + } + + stringBuilder.append("\n\n"); + + if (giveawayInfo.participating) { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatString("BoostingGiveawayParticipantMulti", R.string.BoostingGiveawayParticipantMulti, from, giveaway.channels.size() - 1))); + } else { + stringBuilder.append(replaceTags(formatString("BoostingGiveawayParticipant", R.string.BoostingGiveawayParticipant, from))); + } + } else if (giveawayInfo.disallowed_country != null && !giveawayInfo.disallowed_country.isEmpty()) { + stringBuilder.append(replaceTags(getString("BoostingGiveawayNotEligibleCountry", R.string.BoostingGiveawayNotEligibleCountry))); + } else if (giveawayInfo.admin_disallowed_chat_id != 0) { + TLRPC.Chat badChat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(giveawayInfo.admin_disallowed_chat_id); + String title = badChat != null ? badChat.title : ""; + stringBuilder.append(replaceTags(formatString("BoostingGiveawayNotEligibleAdmin", R.string.BoostingGiveawayNotEligibleAdmin, title))); + } else if (giveawayInfo.joined_too_early_date != 0) { + String date = LocaleController.getInstance().formatterGiveawayMonthDayYear.format(new Date(giveawayInfo.joined_too_early_date * 1000L)); + stringBuilder.append(replaceTags(formatString("BoostingGiveawayNotEligible", R.string.BoostingGiveawayNotEligible, date))); + } else { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatString("BoostingGiveawayTakePartMulti", R.string.BoostingGiveawayTakePartMulti, from, giveaway.channels.size() - 1, endDate))); + } else { + stringBuilder.append(replaceTags(formatString("BoostingGiveawayTakePart", R.string.BoostingGiveawayTakePart, from, endDate))); + } + } + + builder.setMessage(stringBuilder); + builder.setPositiveButton(getString("OK", R.string.OK), (dialogInterface, i) -> { + + }); + builder.show(); + } + + public static void showAboutEnd(long chatId, long msgDate, TLRPC.TL_payments_giveawayInfoResults giveawayInfo, TLRPC.TL_messageMediaGiveaway giveaway, Context context, Theme.ResourcesProvider resourcesProvider) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-chatId); + String from = chat != null ? chat.title : ""; + int quantity = giveaway.quantity; + String months = formatPluralString("BoldMonths", giveaway.months); + String endDate = LocaleController.getInstance().formatterGiveawayMonthDay.format(new Date(giveaway.until_date * 1000L)); + + String fromTime = LocaleController.getInstance().formatterDay.format(new Date(giveawayInfo.start_date * 1000L)); + String fromDate = LocaleController.getInstance().formatterGiveawayMonthDayYear.format(new Date(giveawayInfo.start_date * 1000L)); + boolean isSeveralChats = giveaway.channels.size() > 1; + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("BoostingGiveawayEnd", R.string.BoostingGiveawayEnd)); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); + + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksText", quantity, from, quantity, months))); + stringBuilder.append("\n\n"); + + if (giveaway.only_new_subscribers) { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDateSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1, fromTime, fromDate))); + } else { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextDate", quantity, endDate, quantity, from, fromTime, fromDate))); + } + } else { + if (isSeveralChats) { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubTextSeveral", quantity, endDate, quantity, from, giveaway.channels.size() - 1))); + } else { + stringBuilder.append(replaceTags(formatPluralString("BoostingGiveawayHowItWorksSubText", quantity, endDate, quantity, from))); + } + } + + stringBuilder.append(" "); + stringBuilder.append(replaceTags(formatString("BoostingGiveawayUsedLinks", R.string.BoostingGiveawayUsedLinks, giveawayInfo.activated_count))); + stringBuilder.append("\n\n"); + + if (giveawayInfo.refunded) { + String str = getString("BoostingGiveawayCanceledByPayment", R.string.BoostingGiveawayCanceledByPayment); + TextView bottomTextView = new TextView(context); + bottomTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + bottomTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + bottomTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + bottomTextView.setGravity(Gravity.CENTER); + bottomTextView.setText(str); + bottomTextView.setTextColor(Theme.getColor(Theme.key_text_RedRegular, resourcesProvider)); + bottomTextView.setBackground(Theme.createRoundRectDrawable(dp(10), dp(10), Theme.multAlpha(Theme.getColor(Theme.key_text_RedRegular, resourcesProvider), 0.1f))); + bottomTextView.setPadding(0, dp(12), 0, dp(12)); + builder.addBottomView(bottomTextView); + builder.setMessage(stringBuilder); + builder.setPositiveButton(getString("Close", R.string.Close), (dialogInterface, i) -> { + + }); + } else { + if (giveawayInfo.winner) { + stringBuilder.append(getString("BoostingGiveawayYouWon", R.string.BoostingGiveawayYouWon)); + builder.setMessage(stringBuilder); + builder.setPositiveButton(getString("BoostingGiveawayViewPrize", R.string.BoostingGiveawayViewPrize), (dialogInterface, i) -> { + //todo + }); + builder.setNegativeButton(getString("Close", R.string.Close), (dialogInterface, i) -> { + + }); + } else { + stringBuilder.append(getString("BoostingGiveawayYouNotWon", R.string.BoostingGiveawayYouNotWon)); + builder.setMessage(stringBuilder); + builder.setPositiveButton(getString("Close", R.string.Close), (dialogInterface, i) -> { + + }); + } + } + + builder.show(); + } + + public static void showPrivateChannelAlert(Context context, Theme.ResourcesProvider resourcesProvider, Runnable onCanceled) { + final AtomicBoolean isAddButtonClicked = new AtomicBoolean(false); + AlertDialog.Builder builder = new AlertDialog.Builder(context, resourcesProvider); + builder.setTitle(getString("BoostingGiveawayPrivateChannel", R.string.BoostingGiveawayPrivateChannel)); + builder.setMessage(getString("BoostingGiveawayPrivateChannelWarning", R.string.BoostingGiveawayPrivateChannelWarning)); + builder.setPositiveButton(getString("Add", R.string.Add), (dialogInterface, i) -> { + isAddButtonClicked.set(true); + }); + builder.setNegativeButton(getString("Cancel", R.string.Cancel), (dialogInterface, i) -> { + + }); + builder.setOnDismissListener(dialog -> { + if (!isAddButtonClicked.get()) { + onCanceled.run(); + } + }); + builder.show(); + } + + public static void openGiveAwayStatusDialog(MessageObject messageObject, Browser.Progress progress, Context context, Theme.ResourcesProvider resourcesProvider) { + final AtomicBoolean isCanceled = new AtomicBoolean(false); + progress.init(); + progress.onCancel(() -> isCanceled.set(true)); + final TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; + final long chatId = messageObject.getFromChatId(); + final long msgDate = messageObject.messageOwner.date * 1000L; + BoostRepository.getGiveawayInfo(messageObject, result -> { + if (isCanceled.get()) { + return; + } + progress.end(); + if (result instanceof TLRPC.TL_payments_giveawayInfo) { + TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result; + showAbout(chatId, msgDate, giveawayInfo, giveaway, context, resourcesProvider); + } else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) { + TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result; + showAboutEnd(chatId, msgDate, giveawayInfoResults, giveaway, context, resourcesProvider); + } + }, error -> { + if (isCanceled.get()) { + return; + } + progress.end(); + }); + } + + public static void showBulletinAbout(MessageObject messageObject) { + if (messageObject == null) { + return; + } + BoostRepository.getGiveawayInfo(messageObject, result -> { + final TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; + final long chatId = messageObject.getFromChatId(); + final long msgDate = messageObject.messageOwner.date * 1000L; + BaseFragment fragment = LaunchActivity.getLastFragment(); + if (fragment == null) { + return; + } + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); + + if (result instanceof TLRPC.TL_payments_giveawayInfoResults) { + layout.setAnimation(R.raw.chats_infotip, 30, 30); + layout.textView.setText(LocaleController.getString("BoostingGiveawayShortStatusEnded", R.string.BoostingGiveawayShortStatusEnded)); + } else if (result instanceof TLRPC.TL_payments_giveawayInfo) { + TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result; + if (giveawayInfo.participating) { + layout.setAnimation(R.raw.forward, 30, 30); + layout.textView.setText(LocaleController.getString("BoostingGiveawayShortStatusParticipating", R.string.BoostingGiveawayShortStatusParticipating)); + } else { + layout.setAnimation(R.raw.chats_infotip, 30, 30); + layout.textView.setText(LocaleController.getString("BoostingGiveawayShortStatusNotParticipating", R.string.BoostingGiveawayShortStatusNotParticipating)); + } + } + + layout.textView.setSingleLine(false); + layout.textView.setMaxLines(2); + + layout.setButton(new Bulletin.UndoButton(fragment.getParentActivity(), true, fragment.getResourceProvider()) + .setText(LocaleController.getString("LearnMore", R.string.LearnMore)) + .setUndoAction(() -> { + if (result instanceof TLRPC.TL_payments_giveawayInfo) { + TLRPC.TL_payments_giveawayInfo giveawayInfo = (TLRPC.TL_payments_giveawayInfo) result; + showAbout(chatId, msgDate, giveawayInfo, giveaway, fragment.getParentActivity(), fragment.getResourceProvider()); + } else if (result instanceof TLRPC.TL_payments_giveawayInfoResults) { + TLRPC.TL_payments_giveawayInfoResults giveawayInfoResults = (TLRPC.TL_payments_giveawayInfoResults) result; + showAboutEnd(chatId, msgDate, giveawayInfoResults, giveaway, fragment.getParentActivity(), fragment.getResourceProvider()); + } + })); + Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); + }, error -> { + + }); + } + + public static void showMoreBoostsNeeded(long dialogId) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-dialogId); + BaseFragment baseFragment = LaunchActivity.getLastFragment(); + if (baseFragment == null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(baseFragment.getContext(), baseFragment.getResourceProvider()); + builder.setTitle(LocaleController.getString("BoostingMoreBoostsNeeded", R.string.BoostingMoreBoostsNeeded)); + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingGetMoreBoostByGifting", R.string.BoostingGetMoreBoostByGifting, chat.title))); + builder.setPositiveButton(getString("OK", R.string.OK), (dialogInterface, i) -> { + + }); + builder.show(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java new file mode 100644 index 000000000..c8549c460 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostPagerBottomSheet.java @@ -0,0 +1,273 @@ +package org.telegram.ui.Components.Premium.boosts; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.view.MotionEvent; +import android.view.View; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ViewPagerFixed; +import org.telegram.ui.Stories.DarkThemeResourceProvider; + +import java.util.List; + +public class BoostPagerBottomSheet extends BottomSheet { + + private static BoostPagerBottomSheet instance; + private final ViewPagerFixed viewPager; + private final SelectorBottomSheet rightSheet; + + public static void show(BaseFragment fragment, long dialogId, Theme.ResourcesProvider resourcesProvider) { + show(fragment, resourcesProvider, dialogId, null); + } + + public static void show(BaseFragment fragment, Theme.ResourcesProvider resourcesProvider, long dialogId, TL_stories.TL_prepaidGiveaway prepaidGiveaway) { + if (instance != null) { + return; + } + boolean forceDark = resourcesProvider instanceof DarkThemeResourceProvider; + BaseFragment fragmentWrapper = forceDark ? new DarkFragmentWrapper(fragment) : fragment; + resourcesProvider = fragmentWrapper.getResourceProvider(); + BoostPagerBottomSheet alert = new BoostPagerBottomSheet(fragment.getParentActivity(), true, + new BoostViaGiftsBottomSheet(fragmentWrapper, false, false, dialogId, prepaidGiveaway), + new SelectorBottomSheet(fragmentWrapper, false, dialogId), + resourcesProvider, forceDark); + alert.show(); + instance = alert; + } + + public static BoostPagerBottomSheet getInstance() { + return instance; + } + + public BoostPagerBottomSheet(Context context, boolean needFocus, BoostViaGiftsBottomSheet leftSheet, SelectorBottomSheet rightSheet, Theme.ResourcesProvider resourcesProvider, boolean forceDark) { + super(context, needFocus, resourcesProvider); + this.rightSheet = rightSheet; + setApplyBottomPadding(false); + setApplyTopPadding(false); + useBackgroundTopPadding = false; + setBackgroundColor(Color.TRANSPARENT); + fixNavigationBar(); + AndroidUtilities.setLightStatusBar(getWindow(), isLightStatusBar()); + + viewPager = new ViewPagerFixed(getContext()) { + + private final Path path = new Path(); + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private boolean isScrolling; + private boolean isKeyboardVisible; + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (isKeyboardVisible != isKeyboardVisible()) { + isKeyboardVisible = isKeyboardVisible(); + if (isKeyboardVisible) { + rightSheet.scrollToTop(true); + } + } + } + + @Override + protected void onTabAnimationUpdate(boolean manual) { + float percent = viewPager.getPositionAnimated(); + if (percent > 0f && percent < 1f) { + if (!isScrolling) { + isScrolling = true; + hideKeyboardIfVisible(); + } + } else { + isScrolling = false; + } + viewPager.invalidate(); + } + + @Override + protected void onScrollEnd() { + isScrolling = false; + viewPager.invalidate(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + if (isScrolling) { + int top1 = leftSheet.getTop() + AndroidUtilities.dp(10); + int top2 = rightSheet.getTop(); + int diffTop = Math.abs(top1 - top2); + int currentTop; + if (viewPager.getCurrentPosition() == 0) { + float diffFloat = diffTop * viewPager.getPositionAnimated(); + currentTop = top1 < top2 ? (int) (top1 + diffFloat) : (int) (top1 - diffFloat); + } else { + float diffFloat = diffTop * (1 - viewPager.getPositionAnimated()); + currentTop = top2 < top1 ? (int) (top2 + diffFloat) : (int) (top2 - diffFloat); + } + final float r = dp(14); + AndroidUtilities.rectTmp.set(0, currentTop, getWidth(), getHeight() + dp(8)); + 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(); + } else { + super.dispatchDraw(canvas); + } + } + + @Override + protected boolean canScroll(MotionEvent e) { + return viewPager.getCurrentPosition() == 1; + } + }; + viewPager.setOverScrollMode(View.OVER_SCROLL_NEVER); + viewPager.setClipToPadding(false); + + ViewPagerFixed.Adapter adapter = new ViewPagerFixed.Adapter() { + @Override + public int getItemCount() { + return 2; + } + + @Override + public View createView(int viewType) { + if (viewType == 0) { + return leftSheet.getContainerView(); + } else { + return rightSheet.getContainerView(); + } + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public void bindView(View view, int position, int viewType) { + + } + }; + viewPager.setAdapter(adapter); + viewPager.setPosition(0); + setCustomView(viewPager); + leftSheet.setOnCloseClick(this::dismiss); + leftSheet.setActionListener(new BoostViaGiftsBottomSheet.ActionListener() { + @Override + public void onAddChat(List chats) { + rightSheet.prepare(chats, SelectorBottomSheet.TYPE_CHANNEL); + viewPager.scrollToPosition(1); + } + + @Override + public void onSelectUser(List users) { + rightSheet.prepare(users, SelectorBottomSheet.TYPE_USER); + viewPager.scrollToPosition(1); + } + + @Override + public void onSelectCountries(List countries) { + rightSheet.prepare(countries, SelectorBottomSheet.TYPE_COUNTRY); + viewPager.scrollToPosition(1); + } + }); + rightSheet.setSelectedObjectsListener(new SelectorBottomSheet.SelectedObjectsListener() { + @Override + public void onChatsSelected(List chats) { + viewPager.scrollToPosition(0); + leftSheet.onChatsSelected(chats); + } + + @Override + public void onUsersSelected(List users) { + viewPager.scrollToPosition(0); + leftSheet.onUsersSelected(users); + } + + @Override + public void onCountrySelected(List countries) { + viewPager.scrollToPosition(0); + leftSheet.onCountrySelected(countries); + } + + @Override + public void onShowToast(String text) { + BulletinFactory.of(container, resourcesProvider).createSimpleBulletin(R.raw.chats_infotip, text).show(true); + } + }); + rightSheet.setOnCloseClick(this::onBackPressed); + loadData(forceDark); + Bulletin.addDelegate(container, new Bulletin.Delegate() { + @Override + public int getTopOffset(int tag) { + return AndroidUtilities.statusBarHeight; + } + }); + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + instance = null; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + rightSheet.onConfigurationChanged(newConfig); + super.onConfigurationChanged(newConfig); + } + + private void loadData(boolean forceDark) { + if (!forceDark) { + MessagesController.getInstance(currentAccount).getStoriesController().loadSendAs(); + } + } + + private void hideKeyboardIfVisible() { + if (isKeyboardVisible()) { + AndroidUtilities.hideKeyboard(rightSheet.getContainerView()); + } + } + + @Override + public void onBackPressed() { + if (viewPager.getCurrentPosition() > 0) { + if (rightSheet.hasChanges()) { + return; + } + hideKeyboardIfVisible(); + viewPager.scrollToPosition(0); + return; + } + super.onBackPressed(); + } + + private boolean isLightStatusBar() { + return ColorUtils.calculateLuminance(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)) > 0.7f; + } + + @Override + protected boolean canDismissWithSwipe() { + return false; + } +} 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 new file mode 100644 index 000000000..5e2aecd28 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostRepository.java @@ -0,0 +1,635 @@ +package org.telegram.ui.Components.Premium.boosts; + +import android.os.Build; +import android.util.Pair; + +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.BillingController; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +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.BaseFragment; +import org.telegram.ui.Components.BotWebViewSheet; +import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PaymentFormActivity; + +import java.text.Collator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; + +public class BoostRepository { + + public static int prepareServerDate(long date) { + long twoMinutes = 1000L * 60 * 2; + if (date < System.currentTimeMillis() + twoMinutes) { + date = System.currentTimeMillis() + twoMinutes; + } + return (int) (date / 1000L); + } + + public static long giveawayAddPeersMax() { + return MessagesController.getInstance(UserConfig.selectedAccount).giveawayAddPeersMax; + } + + public static long giveawayPeriodMax() { + return MessagesController.getInstance(UserConfig.selectedAccount).giveawayPeriodMax; + } + + public static long giveawayCountriesMax() { + return MessagesController.getInstance(UserConfig.selectedAccount).giveawayCountriesMax; + } + + public static int giveawayBoostsPerPremium() { + return (int) MessagesController.getInstance(UserConfig.selectedAccount).giveawayBoostsPerPremium; + } + + public static boolean isMultiBoostsAvailable() { + return MessagesController.getInstance(UserConfig.selectedAccount).boostsPerSentGift > 0; + } + + public static int boostsPerSentGift() { + return (int) MessagesController.getInstance(UserConfig.selectedAccount).boostsPerSentGift; + } + + public static ArrayList getMyChannels(long chatId) { + ArrayList sendAs = MessagesController.getInstance(UserConfig.selectedAccount).getStoriesController().sendAs; + ArrayList peers = new ArrayList<>(sendAs); + for (int i = 0; i < peers.size(); i++) { + if (peers.get(i) instanceof TLRPC.TL_inputPeerSelf) { + peers.remove(i); + break; + } + } + for (int i = 0; i < peers.size(); i++) { + if (peers.get(i).channel_id == chatId) { + peers.remove(i); + break; + } + } + return peers; + } + + public static void payGiftCode(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + if (!isGoogleBillingAvailable()) { + payGiftCodeByInvoice(users, option, chat, baseFragment, onSuccess, onError); + } else { + payGiftCodeByGoogle(users, option, chat, baseFragment, onSuccess, onError); + } + } + + public static boolean isGoogleBillingAvailable() { + if (BuildVars.useInvoiceBilling()) { + return false; + } + 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) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); + TLRPC.TL_inputInvoicePremiumGiftCode invoice = new TLRPC.TL_inputInvoicePremiumGiftCode(); + TLRPC.TL_inputStorePaymentPremiumGiftCode payload = new TLRPC.TL_inputStorePaymentPremiumGiftCode(); + + payload.flags = 1; + payload.users = new ArrayList<>(); + for (TLObject user : users) { + if (user instanceof TLRPC.User) { + payload.users.add(controller.getInputUser((TLRPC.User) user)); + } + } + payload.boost_peer = controller.getInputPeer(-chat.id); + payload.currency = option.currency; + payload.amount = option.amount; + + invoice.purpose = payload; + invoice.option = option; + + final JSONObject themeParams = BotWebViewSheet.makeThemeParams(baseFragment.getResourceProvider()); + if (themeParams != null) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams.toString(); + req.flags |= 1; + } + req.invoice = invoice; + + int requestId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + PaymentFormActivity paymentFormActivity = null; + if (response instanceof TLRPC.TL_payments_paymentForm) { + TLRPC.TL_payments_paymentForm form = (TLRPC.TL_payments_paymentForm) response; + form.invoice.recurring = true; + controller.putUsers(form.users, false); + paymentFormActivity = new PaymentFormActivity(form, invoice, baseFragment); + } else if (response instanceof TLRPC.TL_payments_paymentReceipt) { + paymentFormActivity = new PaymentFormActivity((TLRPC.TL_payments_paymentReceipt) response); + } + if (paymentFormActivity != null) { + paymentFormActivity.setPaymentFormCallback(status -> { + if (status == PaymentFormActivity.InvoiceStatus.PAID) { + onSuccess.run(null); + } else if (status != PaymentFormActivity.InvoiceStatus.PENDING) { + onError.run(null); + } + }); + LaunchActivity.getLastFragment().showAsSheet(paymentFormActivity, new BaseFragment.BottomSheetParams()); + } else { + onError.run(null); + } + })); + } + + public static void payGiftCodeByGoogle(List users, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, 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(); + + payload.flags = 1; + payload.users = new ArrayList<>(); + for (TLObject user : users) { + if (user instanceof TLRPC.User) { + payload.users.add(controller.getInputUser((TLRPC.User) user)); + } + } + payload.boost_peer = controller.getInputPeer(-chat.id); + + QueryProductDetailsParams.Product product = QueryProductDetailsParams.Product.newBuilder() + .setProductType(BillingClient.ProductType.INAPP) + .setProductId(option.store_product) + .build(); + BillingController.getInstance().queryProductDetails(Arrays.asList(product), (billingResult, list) -> { + ProductDetails.OneTimePurchaseOfferDetails offerDetails = list.get(0).getOneTimePurchaseOfferDetails(); + payload.currency = offerDetails.getPriceCurrencyCode(); + payload.amount = (long) ((offerDetails.getPriceAmountMicros() / Math.pow(10, 6)) * Math.pow(10, BillingController.getInstance().getCurrencyExp(option.currency))); + + TLRPC.TL_payments_canPurchasePremium req = new TLRPC.TL_payments_canPurchasePremium(); + req.purpose = payload; + connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + if (response != null) { + BillingController.getInstance().addResultListener(list.get(0).getProductId(), billingResult1 -> { + if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { + AndroidUtilities.runOnUIThread(() -> onSuccess.run(null)); + } + }); + BillingController.getInstance().setOnCanceled(() -> { + AndroidUtilities.runOnUIThread(() -> onError.run(null)); + }); + BillingController.getInstance().launchBillingFlow( + baseFragment.getParentActivity(), AccountInstance.getInstance(UserConfig.selectedAccount), payload, + Collections.singletonList(BillingFlowParams.ProductDetailsParams.newBuilder() + .setProductDetails(list.get(0)) + .build()) + ); + } + })); + }); + } + + public static void launchPreparedGiveaway(TL_stories.TL_prepaidGiveaway prepaidGiveaway, List chats, List selectedCountries, TLRPC.Chat chat, int date, boolean onlyNewSubscribers, Utilities.Callback onSuccess, Utilities.Callback onError) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_inputStorePaymentPremiumGiveaway purpose = new TLRPC.TL_inputStorePaymentPremiumGiveaway(); + purpose.only_new_subscribers = onlyNewSubscribers; + purpose.until_date = date; + purpose.flags |= 2; + purpose.flags |= 4; + purpose.random_id = System.currentTimeMillis(); + purpose.additional_peers = new ArrayList<>(); + purpose.boost_peer = controller.getInputPeer(-chat.id); + purpose.currency = ""; + + for (TLObject object : selectedCountries) { + TLRPC.TL_help_country country = (TLRPC.TL_help_country) object; + purpose.countries_iso2.add(country.iso2); + } + + for (TLObject o : chats) { + if (o instanceof TLRPC.Chat) { + purpose.additional_peers.add(controller.getInputPeer(-((TLRPC.Chat) o).id)); + } + } + TLRPC.TL_payments_launchPrepaidGiveaway req = new TLRPC.TL_payments_launchPrepaidGiveaway(); + req.giveaway_id = prepaidGiveaway.id; + req.peer = controller.getInputPeer(-chat.id); + req.purpose = purpose; + connection.sendRequest(req, (response, error) -> { + if (error != null) { + AndroidUtilities.runOnUIThread(() -> onError.run(error)); + return; + } + if (response != null) { + controller.processUpdates((TLRPC.Updates) response, false); + AndroidUtilities.runOnUIThread(() -> onSuccess.run(null)); + } + }); + } + + public static void payGiveAway(List chats, List selectedCountries, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, int date, boolean onlyNewSubscribers, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + if (!isGoogleBillingAvailable()) { + payGiveAwayByInvoice(chats, selectedCountries, option, chat, date, onlyNewSubscribers, baseFragment, onSuccess, onError); + } else { + payGiveAwayByGoogle(chats, selectedCountries, option, chat, date, onlyNewSubscribers, baseFragment, onSuccess, onError); + } + } + + public static void payGiveAwayByInvoice(List chats, List selectedCountries, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, int date, boolean onlyNewSubscribers, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); + TLRPC.TL_inputInvoicePremiumGiftCode invoice = new TLRPC.TL_inputInvoicePremiumGiftCode(); + TLRPC.TL_inputStorePaymentPremiumGiveaway payload = new TLRPC.TL_inputStorePaymentPremiumGiveaway(); + + payload.only_new_subscribers = onlyNewSubscribers; + payload.until_date = date; + payload.flags |= 2; + payload.flags |= 4; + payload.random_id = System.currentTimeMillis(); + payload.additional_peers = new ArrayList<>(); + for (TLObject o : chats) { + if (o instanceof TLRPC.Chat) { + payload.additional_peers.add(controller.getInputPeer(-((TLRPC.Chat) o).id)); + } + } + payload.boost_peer = controller.getInputPeer(-chat.id); + payload.boost_peer = controller.getInputPeer(-chat.id); + payload.currency = option.currency; + payload.amount = option.amount; + + for (TLObject object : selectedCountries) { + TLRPC.TL_help_country country = (TLRPC.TL_help_country) object; + payload.countries_iso2.add(country.iso2); + } + + invoice.purpose = payload; + invoice.option = option; + + final JSONObject themeParams = BotWebViewSheet.makeThemeParams(baseFragment.getResourceProvider()); + if (themeParams != null) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams.toString(); + req.flags |= 1; + } + req.invoice = invoice; + + int requestId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + PaymentFormActivity paymentFormActivity = null; + if (response instanceof TLRPC.TL_payments_paymentForm) { + TLRPC.TL_payments_paymentForm form = (TLRPC.TL_payments_paymentForm) response; + form.invoice.recurring = true; + controller.putUsers(form.users, false); + paymentFormActivity = new PaymentFormActivity(form, invoice, baseFragment); + } else if (response instanceof TLRPC.TL_payments_paymentReceipt) { + paymentFormActivity = new PaymentFormActivity((TLRPC.TL_payments_paymentReceipt) response); + } + if (paymentFormActivity != null) { + paymentFormActivity.setPaymentFormCallback(status -> { + if (status == PaymentFormActivity.InvoiceStatus.PAID) { + onSuccess.run(null); + } else if (status != PaymentFormActivity.InvoiceStatus.PENDING) { + onError.run(null); + } + }); + LaunchActivity.getLastFragment().showAsSheet(paymentFormActivity, new BaseFragment.BottomSheetParams()); + } else { + onError.run(null); + } + })); + } + + public static void payGiveAwayByGoogle(List chats, List selectedCountries, TLRPC.TL_premiumGiftCodeOption option, TLRPC.Chat chat, int date, boolean onlyNewSubscribers, BaseFragment baseFragment, Utilities.Callback onSuccess, Utilities.Callback onError) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + TLRPC.TL_inputStorePaymentPremiumGiveaway payload = new TLRPC.TL_inputStorePaymentPremiumGiveaway(); + + payload.only_new_subscribers = onlyNewSubscribers; + payload.until_date = date; + payload.flags |= 2; + payload.flags |= 4; + payload.random_id = System.currentTimeMillis(); + payload.additional_peers = new ArrayList<>(); + for (TLObject o : chats) { + if (o instanceof TLRPC.Chat) { + payload.additional_peers.add(controller.getInputPeer(-((TLRPC.Chat) o).id)); + } + } + payload.boost_peer = controller.getInputPeer(-chat.id); + for (TLObject object : selectedCountries) { + TLRPC.TL_help_country country = (TLRPC.TL_help_country) object; + payload.countries_iso2.add(country.iso2); + } + + QueryProductDetailsParams.Product product = QueryProductDetailsParams.Product.newBuilder() + .setProductType(BillingClient.ProductType.INAPP) + .setProductId(option.store_product) + .build(); + BillingController.getInstance().queryProductDetails(Arrays.asList(product), (billingResult, list) -> { + ProductDetails.OneTimePurchaseOfferDetails offerDetails = list.get(0).getOneTimePurchaseOfferDetails(); + payload.currency = offerDetails.getPriceCurrencyCode(); + payload.amount = (long) ((offerDetails.getPriceAmountMicros() / Math.pow(10, 6)) * Math.pow(10, BillingController.getInstance().getCurrencyExp(option.currency))); + + TLRPC.TL_payments_canPurchasePremium req = new TLRPC.TL_payments_canPurchasePremium(); + req.purpose = payload; + connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + if (response != null) { + BillingController.getInstance().addResultListener(list.get(0).getProductId(), billingResult1 -> { + if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { + AndroidUtilities.runOnUIThread(() -> onSuccess.run(null)); + } + }); + BillingController.getInstance().setOnCanceled(() -> { + AndroidUtilities.runOnUIThread(() -> onError.run(null)); + }); + BillingController.getInstance().launchBillingFlow( + baseFragment.getParentActivity(), AccountInstance.getInstance(UserConfig.selectedAccount), payload, + Collections.singletonList(BillingFlowParams.ProductDetailsParams.newBuilder() + .setProductDetails(list.get(0)) + .build()) + ); + } + })); + }); + } + + public static List filterGiftOptions(List list, int selected) { + List result = new ArrayList<>(); + for (TLRPC.TL_premiumGiftCodeOption item : list) { + boolean isAvailableInGoogleStore = item.store_product != null; + if (item.users == selected) { + result.add(item); + } + } + if (result.isEmpty()) { + for (TLRPC.TL_premiumGiftCodeOption item : list) { + if (item.users == 1) { + result.add(item); + } + } + } + return result; + } + + public static void loadCountries(Utilities.Callback>, List>> onDone) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_help_getCountriesList req = new TLRPC.TL_help_getCountriesList(); + req.lang_code = LocaleController.getInstance().getCurrentLocaleInfo() != null ? LocaleController.getInstance().getCurrentLocaleInfo().getLangCode() : Locale.getDefault().getCountry(); + int reqId = connection.sendRequest(req, (response, error) -> { + if (response != null) { + TLRPC.TL_help_countriesList help_countriesList = (TLRPC.TL_help_countriesList) response; + Map> countriesMap = new HashMap<>(); + List sortedLetters = new ArrayList<>(); + + for (int i = 0; i < help_countriesList.countries.size(); i++) { + TLRPC.TL_help_country country = help_countriesList.countries.get(i); + if (country.iso2.equalsIgnoreCase("FT")) { + continue; + } + String letter = country.default_name.substring(0, 1).toUpperCase(); + List arr = countriesMap.get(letter); + if (arr == null) { + arr = new ArrayList<>(); + countriesMap.put(letter, arr); + sortedLetters.add(letter); + } + arr.add(country); + } + + Comparator comparator; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + Collator collator = Collator.getInstance(LocaleController.getInstance().getCurrentLocale() != null ? LocaleController.getInstance().getCurrentLocale() : Locale.getDefault()); + comparator = collator::compare; + } else { + comparator = String::compareTo; + } + Collections.sort(sortedLetters, comparator); + for (List arr : countriesMap.values()) { + Collections.sort(arr, (country, country2) -> comparator.compare(country.default_name, country2.default_name)); + } + AndroidUtilities.runOnUIThread(() -> onDone.run(new Pair<>(countriesMap, sortedLetters))); + } + }); + } + + public static void loadGiftOptions(TLRPC.Chat chat, Utilities.Callback> onDone) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + TLRPC.TL_payments_getPremiumGiftCodeOptions req = new TLRPC.TL_payments_getPremiumGiftCodeOptions(); + req.flags = 1; + req.boost_peer = controller.getInputPeer(-chat.id); + + int reqId = connection.sendRequest(req, (response, error) -> { + if (response != null) { + TLRPC.Vector vector = (TLRPC.Vector) response; + List result = new ArrayList<>(); + List products = new ArrayList<>(); + for (int i = 0; i < vector.objects.size(); i++) { + final TLRPC.TL_premiumGiftCodeOption object = (TLRPC.TL_premiumGiftCodeOption) vector.objects.get(i); + result.add(object); + if (object.store_product != null) { + products.add(QueryProductDetailsParams.Product.newBuilder() + .setProductType(BillingClient.ProductType.INAPP) + .setProductId(object.store_product) + .build()); + } + } + if (products.isEmpty() || !isGoogleBillingAvailable()) { + AndroidUtilities.runOnUIThread(() -> onDone.run(result)); + return; + } + BillingController.getInstance().queryProductDetails(products, (billingResult, list) -> { + for (ProductDetails productDetails : list) { + ProductDetails.OneTimePurchaseOfferDetails offerDetails = productDetails.getOneTimePurchaseOfferDetails(); + for (TLRPC.TL_premiumGiftCodeOption option : result) { + if (option.store_product != null && option.store_product.equals(productDetails.getProductId())) { + option.amount = (long) ((offerDetails.getPriceAmountMicros() / Math.pow(10, 6)) * Math.pow(10, BillingController.getInstance().getCurrencyExp(option.currency))); + option.currency = offerDetails.getPriceCurrencyCode(); + break; + } + } + } + AndroidUtilities.runOnUIThread(() -> onDone.run(result)); + }); + } + }); + } + + public static void searchChats(long currentChatId, int guid, String query, int count, Utilities.Callback> onDone) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_contacts_search req = new TLRPC.TL_contacts_search(); + req.q = query; + req.limit = 50; + + int reqId = connection.sendRequest(req, (response, error) -> { + if (response instanceof TLRPC.TL_contacts_found) { + TLRPC.TL_contacts_found res = (TLRPC.TL_contacts_found) response; + controller.putChats(res.chats, false); + List result = new ArrayList<>(); + for (int a = 0; a < res.chats.size(); a++) { + TLRPC.Chat chat = res.chats.get(a); + TLRPC.InputPeer inputPeer = MessagesController.getInputPeer(chat); + if (chat.id != currentChatId && ChatObject.isChannel(chat)) { + result.add(inputPeer); + } + } + AndroidUtilities.runOnUIThread(() -> onDone.run(result)); + } + }); + } + + public static void loadChatParticipants(long chatId, int guid, String query, int offset, int count, Utilities.Callback> onDone) { + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + + TLRPC.TL_channels_getParticipants req = new TLRPC.TL_channels_getParticipants(); + req.channel = controller.getInputChannel(chatId); + req.filter = query == null ? new TLRPC.TL_channelParticipantsRecent() : new TLRPC.TL_channelParticipantsSearch(); + req.filter.q = query == null ? "" : query; + req.offset = offset; + req.limit = count; + + int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_channels_channelParticipants) { + TLRPC.TL_channels_channelParticipants res = ((TLRPC.TL_channels_channelParticipants) response); + controller.putUsers(res.users, false); + controller.putChats(res.chats, false); + long selfId = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + List result = new ArrayList<>(); + for (int a = 0; a < res.participants.size(); a++) { + TLRPC.Peer peer = res.participants.get(a).peer; + if (MessageObject.getPeerId(peer) != selfId) { + result.add(controller.getInputPeer(peer)); + } + } + onDone.run(result); + } + })); + } + + public static void checkGiftCode(String slug, Utilities.Callback onDone, Utilities.Callback onError) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + TLRPC.TL_payments_checkGiftCode req = new TLRPC.TL_payments_checkGiftCode(); + req.slug = slug; + int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_payments_checkedGiftCode) { + TLRPC.TL_payments_checkedGiftCode checkedGiftCode = (TLRPC.TL_payments_checkedGiftCode) response; + controller.putChats(checkedGiftCode.chats, false); + controller.putUsers(checkedGiftCode.users, false); + onDone.run((TLRPC.TL_payments_checkedGiftCode) response); + } + onError.run(error); + })); + } + + public static void applyGiftCode(String slug, Utilities.Callback onDone, Utilities.Callback onError) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + TLRPC.TL_payments_applyGiftCode req = new TLRPC.TL_payments_applyGiftCode(); + req.slug = slug; + int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + onDone.run(null); + })); + } + + public static void getGiveawayInfo(MessageObject messageObject, Utilities.Callback onDone, Utilities.Callback onError) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + TLRPC.TL_payments_getGiveawayInfo req = new TLRPC.TL_payments_getGiveawayInfo(); + long selfId = UserConfig.getInstance(UserConfig.selectedAccount).getClientUserId(); + req.msg_id = messageObject.getId(); + req.peer = controller.getInputPeer(messageObject.getFromChatId()); + int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + if (response instanceof TLRPC.payments_GiveawayInfo) { + onDone.run((TLRPC.payments_GiveawayInfo) response); + } + })); + } + + public static void getMyBoosts(Utilities.Callback onDone, Utilities.Callback onError) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + TL_stories.TL_premium_getMyBoosts req = new TL_stories.TL_premium_getMyBoosts(); + int reqId = connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + if (response instanceof TL_stories.TL_premium_myBoosts) { + TL_stories.TL_premium_myBoosts myBoosts = (TL_stories.TL_premium_myBoosts) response; + controller.putUsers(myBoosts.users, false); + controller.putChats(myBoosts.chats, false); + onDone.run(myBoosts); + } + })); + } + + public static void applyBoost(long dialogId, List slots, Utilities.Callback onDone, Utilities.Callback onError) { + ConnectionsManager connection = ConnectionsManager.getInstance(UserConfig.selectedAccount); + MessagesController controller = MessagesController.getInstance(UserConfig.selectedAccount); + TL_stories.TL_premium_applyBoost req = new TL_stories.TL_premium_applyBoost(); + req.peer = controller.getInputPeer(-dialogId); + req.flags |= 1; + req.slots.addAll(slots); + connection.sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onError.run(error); + return; + } + if (response instanceof TL_stories.TL_premium_myBoosts) { + TL_stories.TL_premium_myBoosts myBoosts = (TL_stories.TL_premium_myBoosts) response; + controller.putUsers(myBoosts.users, false); + controller.putChats(myBoosts.chats, false); + onDone.run(myBoosts); + } + })); + } +} 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 new file mode 100644 index 000000000..909084fde --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/BoostViaGiftsBottomSheet.java @@ -0,0 +1,396 @@ +package org.telegram.ui.Components.Premium.boosts; + +import android.annotation.SuppressLint; +import android.graphics.Canvas; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import androidx.recyclerview.widget.DefaultItemAnimator; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; +import org.telegram.ui.Components.Premium.boosts.adapters.BoostAdapter; +import org.telegram.ui.Components.Premium.boosts.cells.ActionBtnCell; +import org.telegram.ui.Components.Premium.boosts.cells.AddChannelCell; +import org.telegram.ui.Components.Premium.boosts.cells.BaseCell; +import org.telegram.ui.Components.Premium.boosts.cells.DateEndCell; +import org.telegram.ui.Components.Premium.boosts.cells.ParticipantsTypeCell; +import org.telegram.ui.Components.Premium.boosts.cells.BoostTypeCell; +import org.telegram.ui.Components.Premium.boosts.cells.DurationCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.Premium.boosts.adapters.BoostAdapter.Item; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class BoostViaGiftsBottomSheet extends BottomSheetWithRecyclerListView implements SelectorBottomSheet.SelectedObjectsListener { + + private static final int BOTTOM_HEIGHT_DP = 68; + + public interface ActionListener { + void onAddChat(List chats); + + void onSelectUser(List users); + + void onSelectCountries(List countries); + } + + private final ArrayList items = new ArrayList<>(); + private final List sliderValues = BoostRepository.isGoogleBillingAvailable() ? Arrays.asList(1, 3, 5, 7, 10, 25, 50) : Arrays.asList(1, 3, 5, 7, 10, 25, 50, 100); + private final TLRPC.Chat currentChat; + private final List selectedChats = new ArrayList<>(); + private final List selectedUsers = new ArrayList<>(); + private final List selectedCountries = new ArrayList<>(); + private final List giftCodeOptions = new ArrayList<>(); + private BoostAdapter adapter; + private int selectedBoostType = BoostTypeCell.TYPE_GIVEAWAY; + private int selectedParticipantsType = ParticipantsTypeCell.TYPE_ALL; + private int selectedMonths = 3; + private long selectedEndDate = BoostDialogs.getThreeDaysAfterToday(); + private int selectedSliderIndex = 0; + private ActionBtnCell actionBtn; + private ActionListener actionListener; + private int top; + private Runnable onCloseClick; + private final TL_stories.TL_prepaidGiveaway prepaidGiveaway; + + public BoostViaGiftsBottomSheet(BaseFragment fragment, boolean needFocus, boolean hasFixedSize, long dialogId, TL_stories.TL_prepaidGiveaway prepaidGiveaway) { + super(fragment, needFocus, hasFixedSize); + this.prepaidGiveaway = prepaidGiveaway; + this.topPadding = 0.3f; + setApplyTopPadding(false); + setApplyBottomPadding(false); + useBackgroundTopPadding = false; + backgroundPaddingLeft = 0; + updateTitle(); + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + ((ViewGroup.MarginLayoutParams) actionBar.getLayoutParams()).leftMargin = 0; + ((ViewGroup.MarginLayoutParams) actionBar.getLayoutParams()).rightMargin = 0; + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, AndroidUtilities.dp(BOTTOM_HEIGHT_DP)); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.setOnItemClickListener((view, position) -> { + if (view instanceof BaseCell) { + if (view instanceof BoostTypeCell) { + int boostType = ((BoostTypeCell) view).getSelectedType(); + if (boostType == BoostTypeCell.TYPE_SPECIFIC_USERS) { + if (actionListener != null) { + actionListener.onSelectUser(selectedUsers); + } + } else { + ((BaseCell) view).markChecked(recyclerListView); + selectedBoostType = boostType; + updateRows(true, true); + updateActionButton(true); + updateTitle(); + } + } else { + ((BaseCell) view).markChecked(recyclerListView); + } + } + if (view instanceof ParticipantsTypeCell) { + int tmpParticipantsType = ((ParticipantsTypeCell) view).getSelectedType(); + if (selectedParticipantsType == tmpParticipantsType) { + if (actionListener != null) { + actionListener.onSelectCountries(selectedCountries); + } + } + selectedParticipantsType = tmpParticipantsType; + } else if (view instanceof DurationCell) { + selectedMonths = ((TLRPC.TL_premiumGiftCodeOption) ((DurationCell) view).getGifCode()).months; + } else if (view instanceof DateEndCell) { + BoostDialogs.showDatePicker(fragment.getContext(), selectedEndDate, (notify, timeSec) -> { + selectedEndDate = timeSec * 1000L; + updateRows(false, true); + }, resourcesProvider); + } else if (view instanceof AddChannelCell) { + if (actionListener != null) { + actionListener.onAddChat(selectedChats); + } + } + }); + this.currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + this.adapter.setItems(items, recyclerListView, sliderIndex -> { + selectedSliderIndex = sliderIndex; + int counter = getSelectedSliderValue(); + actionBtn.updateCounter(counter); + updateRows(false, false); + adapter.updateBoostCounter(getSelectedSliderValueWithBoosts()); + }, deletedChat -> { + selectedChats.remove(deletedChat); + updateRows(true, true); + }); + updateRows(false, false); + actionBtn = new ActionBtnCell(getContext(), resourcesProvider); + actionBtn.setOnClickListener(v -> { + if (actionBtn.isLoading()) { + return; + } + + if (selectedBoostType == BoostTypeCell.TYPE_SPECIFIC_USERS) { + List options = BoostRepository.filterGiftOptions(giftCodeOptions, selectedUsers.size()); + for (int i = 0; i < options.size(); i++) { + TLRPC.TL_premiumGiftCodeOption option = options.get(i); + if (option.months == selectedMonths && selectedUsers.size() > 0) { + if (BoostRepository.isGoogleBillingAvailable() && BoostDialogs.checkReduceUsers(getContext(), resourcesProvider, giftCodeOptions, option)) { + return; + } + actionBtn.updateLoading(true); + BoostRepository.payGiftCode(selectedUsers, option, currentChat, fragment, result -> { + dismiss(); + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.boostByChannelCreated, currentChat, false); + }, error -> { + actionBtn.updateLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + break; + } + } + } else { + List options = BoostRepository.filterGiftOptions(giftCodeOptions, getSelectedSliderValue()); + if (isPreparedGiveaway()) { + int dateInt = BoostRepository.prepareServerDate(selectedEndDate); + boolean onlyNewSubscribers = selectedParticipantsType == ParticipantsTypeCell.TYPE_NEW; + actionBtn.updateLoading(true); + BoostRepository.launchPreparedGiveaway(prepaidGiveaway, selectedChats, selectedCountries, currentChat, dateInt, onlyNewSubscribers, + result -> { + dismiss(); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.boostByChannelCreated, currentChat, true, prepaidGiveaway), 220); + }, error -> { + actionBtn.updateLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + } else { + for (int i = 0; i < options.size(); i++) { + TLRPC.TL_premiumGiftCodeOption option = options.get(i); + if (option.months == selectedMonths) { + if (BoostRepository.isGoogleBillingAvailable() && BoostDialogs.checkReduceQuantity(getContext(), resourcesProvider, giftCodeOptions, option, arg -> { + selectedSliderIndex = sliderValues.indexOf(arg.users); + updateRows(true, true); + updateActionButton(true); + })) { + return; + } + boolean onlyNewSubscribers = selectedParticipantsType == ParticipantsTypeCell.TYPE_NEW; + int dateInt = BoostRepository.prepareServerDate(selectedEndDate); + actionBtn.updateLoading(true); + BoostRepository.payGiveAway(selectedChats, selectedCountries, option, currentChat, dateInt, onlyNewSubscribers, fragment, result -> { + dismiss(); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.boostByChannelCreated, currentChat, true), 220); + }, error -> { + actionBtn.updateLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + break; + } + } + } + } + }); + updateActionButton(false); + containerView.addView(actionBtn, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, BOTTOM_HEIGHT_DP, Gravity.BOTTOM, 0, 0, 0, 0)); + loadOptions(); + } + + @Override + protected boolean needPaddingShadow() { + return false; + } + + public void setOnCloseClick(Runnable onCloseClick) { + this.onCloseClick = onCloseClick; + } + + @Override + public void dismiss() { + if (onCloseClick != null) { + onCloseClick.run(); + } + } + + private void loadOptions() { + BoostRepository.loadGiftOptions(currentChat, arg -> { + giftCodeOptions.clear(); + giftCodeOptions.addAll(arg); + updateRows(true, true); + }); + } + + private void updateActionButton(boolean animated) { + if (isPreparedGiveaway()) { + actionBtn.setStartGiveAwayStyle(prepaidGiveaway.quantity, animated); + } else { + if (selectedBoostType == BoostTypeCell.TYPE_GIVEAWAY) { + actionBtn.setStartGiveAwayStyle(getSelectedSliderValue(), animated); + } else { + actionBtn.setGiftPremiumStyle(selectedUsers.size(), animated, selectedUsers.size() > 0); + } + } + } + + private boolean isGiveaway() { + return selectedBoostType == BoostTypeCell.TYPE_GIVEAWAY; + } + + public void setActionListener(ActionListener actionListener) { + this.actionListener = actionListener; + } + + @Override + protected void onPreDraw(Canvas canvas, int top, float progressToFullView) { + this.top = top; + } + + public int getTop() { + return Math.max(-AndroidUtilities.dp(16), top - (actionBar.getVisibility() == View.VISIBLE ? (AndroidUtilities.statusBarHeight + AndroidUtilities.dp(16)) : 0)); + } + + private int getSelectedSliderValue() { + return sliderValues.get(selectedSliderIndex); + } + + private int getSelectedSliderValueWithBoosts() { + return sliderValues.get(selectedSliderIndex) * BoostRepository.giveawayBoostsPerPremium(); + } + + private boolean isPreparedGiveaway() { + return prepaidGiveaway != null; + } + + @SuppressLint("NotifyDataSetChanged") + private void updateRows(boolean animated, boolean notify) { + ArrayList oldItems = new ArrayList<>(items); + items.clear(); + items.add(Item.asHeader()); + if (isPreparedGiveaway()) { + items.add(Item.asSingleBoost(prepaidGiveaway)); + } else { + items.add(Item.asBoost(BoostTypeCell.TYPE_GIVEAWAY, selectedUsers.size(), null, selectedBoostType)); + items.add(Item.asBoost(BoostTypeCell.TYPE_SPECIFIC_USERS, selectedUsers.size(), selectedUsers.size() > 0 ? selectedUsers.get(0) : null, selectedBoostType)); + } + items.add(Item.asDivider()); + if (selectedBoostType == BoostTypeCell.TYPE_GIVEAWAY) { + if (!isPreparedGiveaway()) { + items.add(Item.asSubTitleWithCounter(LocaleController.getString("BoostingQuantityPrizes", R.string.BoostingQuantityPrizes), getSelectedSliderValueWithBoosts())); + items.add(Item.asSlider(sliderValues, selectedSliderIndex)); + items.add(Item.asDivider(LocaleController.getString("BoostingChooseHowMany", R.string.BoostingChooseHowMany), false)); + } + items.add(Item.asSubTitle(LocaleController.getString("BoostingChannelsIncludedGiveaway", R.string.BoostingChannelsIncludedGiveaway))); + items.add(Item.asChat(currentChat, false, getSelectedSliderValueWithBoosts())); + for (TLObject selectedChat : selectedChats) { + if (selectedChat instanceof TLRPC.Chat) { + items.add(Item.asChat((TLRPC.Chat) selectedChat, true, getSelectedSliderValueWithBoosts())); + } + if (selectedChat instanceof TLRPC.InputPeer) { + items.add(Item.asPeer((TLRPC.InputPeer) selectedChat, true, getSelectedSliderValueWithBoosts())); + } + } + if (selectedChats.size() < BoostRepository.giveawayAddPeersMax()) { + items.add(Item.asAddChannel()); + } + items.add(Item.asDivider(LocaleController.getString("BoostingChooseChannelsNeedToJoin", R.string.BoostingChooseChannelsNeedToJoin), false)); + items.add(Item.asSubTitle(LocaleController.getString("BoostingEligibleUsers", R.string.BoostingEligibleUsers))); + items.add(Item.asParticipants(ParticipantsTypeCell.TYPE_ALL, selectedParticipantsType, true, selectedCountries)); + items.add(Item.asParticipants(ParticipantsTypeCell.TYPE_NEW, selectedParticipantsType, false, selectedCountries)); + items.add(Item.asDivider(LocaleController.getString("BoostingChooseLimitGiveaway", R.string.BoostingChooseLimitGiveaway), false)); + items.add(Item.asSubTitle(LocaleController.getString("BoostingDateWhenGiveawayEnds", R.string.BoostingDateWhenGiveawayEnds))); + items.add(Item.asDateEnd(selectedEndDate)); + if (!isPreparedGiveaway()) { + items.add(Item.asDivider(LocaleController.formatPluralString("BoostingChooseRandom", getSelectedSliderValue()), false)); + } + } + + if (!isPreparedGiveaway()) { + items.add(Item.asSubTitle(LocaleController.getString("BoostingDurationOfPremium", R.string.BoostingDurationOfPremium))); + List options = BoostRepository.filterGiftOptions(giftCodeOptions, isGiveaway() ? getSelectedSliderValue() : selectedUsers.size()); + for (int i = 0; i < options.size(); i++) { + TLRPC.TL_premiumGiftCodeOption option = options.get(i); + items.add(Item.asDuration(option, option.months, isGiveaway() ? getSelectedSliderValue() : selectedUsers.size(), option.amount, selectedMonths, option.currency, i != options.size() - 1)); + } + } + String textDivider = !isPreparedGiveaway() ? LocaleController.getString("BoostingStoriesFeaturesAndTerms", R.string.BoostingStoriesFeaturesAndTerms) + : LocaleController.formatPluralString("BoostingChooseRandom", prepaidGiveaway.quantity) + "\n\n" + LocaleController.getString("BoostingStoriesFeaturesAndTerms", R.string.BoostingStoriesFeaturesAndTerms); + items.add(Item.asDivider(AndroidUtilities.replaceSingleTag( + textDivider, + Theme.key_chat_messageLinkIn, 0, () -> { + PremiumPreviewBottomSheet previewBottomSheet = new PremiumPreviewBottomSheet(getBaseFragment(), currentAccount, null, resourcesProvider); + previewBottomSheet.setOnDismissListener(dialog -> adapter.setPausedStars(false)); + previewBottomSheet.setOnShowListener(dialog -> adapter.setPausedStars(true)); + previewBottomSheet.show(); + }, + resourcesProvider), true)); + if (adapter == null) { + return; + } + if (!notify) { + return; + } + if (animated) { + adapter.setItems(oldItems, items); + } else { + adapter.notifyDataSetChanged(); + } + } + + @Override + protected CharSequence getTitle() { + return selectedBoostType == BoostTypeCell.TYPE_SPECIFIC_USERS ? + LocaleController.getString("GiftPremium", R.string.GiftPremium) + : LocaleController.formatString("BoostingStartGiveaway", R.string.BoostingStartGiveaway); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return adapter = new BoostAdapter(resourcesProvider); + } + + @Override + public void onChatsSelected(List chats) { + selectedChats.clear(); + selectedChats.addAll(chats); + updateRows(true, true); + } + + @Override + public void onUsersSelected(List users) { + selectedUsers.clear(); + selectedUsers.addAll(users); + if (users.isEmpty()) { + selectedBoostType = BoostTypeCell.TYPE_GIVEAWAY; + } else { + selectedBoostType = BoostTypeCell.TYPE_SPECIFIC_USERS; + } + selectedSliderIndex = 0; + updateRows(true, true); + updateActionButton(true); + updateTitle(); + } + + @Override + public void onCountrySelected(List countries) { + selectedCountries.clear(); + selectedCountries.addAll(countries); + updateRows(false, true); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/DarkFragmentWrapper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/DarkFragmentWrapper.java new file mode 100644 index 000000000..7c0d1e5df --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/DarkFragmentWrapper.java @@ -0,0 +1,37 @@ +package org.telegram.ui.Components.Premium.boosts; + +import android.app.Activity; + +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Stories.DarkThemeResourceProvider; +import org.telegram.ui.WrappedResourceProvider; + +public class DarkFragmentWrapper extends BaseFragment { + + private final BaseFragment parentFragment; + + DarkFragmentWrapper(BaseFragment parentFragment) { + this.parentFragment = parentFragment; + } + + @Override + public boolean isLightStatusBar() { + return false; + } + + @Override + public Activity getParentActivity() { + return parentFragment.getParentActivity(); + } + + @Override + public Theme.ResourcesProvider getResourceProvider() { + return new WrappedResourceProvider(new DarkThemeResourceProvider()); + } + + @Override + public boolean presentFragment(BaseFragment fragment) { + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java new file mode 100644 index 000000000..921fe6327 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/GiftInfoBottomSheet.java @@ -0,0 +1,172 @@ +package org.telegram.ui.Components.Premium.boosts; + +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.browser.Browser; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; +import org.telegram.ui.Components.Premium.boosts.adapters.GiftInfoAdapter; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.UndoView; +import org.telegram.ui.LaunchActivity; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class GiftInfoBottomSheet extends BottomSheetWithRecyclerListView { + + public static void show(BaseFragment fragment, String slug, Browser.Progress progress) { + final AtomicBoolean isCanceled = new AtomicBoolean(false); + if (progress != null) { + progress.init(); + progress.onCancel(() -> isCanceled.set(true)); + } + BoostRepository.checkGiftCode(slug, giftCode -> { + if (isCanceled.get()) { + return; + } + GiftInfoBottomSheet alert = new GiftInfoBottomSheet(fragment, false, true, giftCode, slug); + if (fragment != null && fragment.getParentActivity() != null) { + fragment.showDialog(alert); + } else { + alert.show(); + } + if (progress != null) { + progress.end(); + } + }, error -> { + if (isCanceled.get()) { + return; + } + if (progress != null) { + progress.end(); + } + }); + } + + public static void show(BaseFragment fragment, String slug) { + show(fragment, slug, null); + } + + public static boolean handleIntent(Intent intent, Browser.Progress progress) { + Uri data = intent.getData(); + if (data != null) { + String scheme = data.getScheme(); + if (scheme != null) { + if ((scheme.equals("http") || scheme.equals("https"))) { + String host = data.getHost().toLowerCase(); + if (host.equals("telegram.me") || host.equals("t.me") || host.equals("telegram.dog")) { + String path = data.getPath(); + if (path != null) { + String lastPathSegment = data.getLastPathSegment(); + if (path.startsWith("/giftcode") && lastPathSegment != null) { + show(LaunchActivity.getLastFragment(), lastPathSegment, progress); + return true; + } + } + } + } else if (scheme.equals("tg")) { + String url = data.toString(); + String lastPathSegment = data.getLastPathSegment(); + if (url.startsWith("tg:giftcode") || url.startsWith("tg://giftcode")) { + if (lastPathSegment != null) { + show(LaunchActivity.getLastFragment(), lastPathSegment, progress); + return true; + } + + } + } + } + } + return false; + } + + private final TLRPC.TL_payments_checkedGiftCode giftCode; + private final boolean isUnused; + private GiftInfoAdapter adapter; + + public GiftInfoBottomSheet(BaseFragment fragment, boolean needFocus, boolean hasFixedSize, TLRPC.TL_payments_checkedGiftCode giftCode, String slug) { + super(fragment, needFocus, hasFixedSize); + this.isUnused = giftCode.used_date == 0; + this.giftCode = giftCode; + setApplyTopPadding(false); + setApplyBottomPadding(true); + fixNavigationBar(); + updateTitle(); + adapter.init(fragment, giftCode, slug); + } + + @Override + public void onViewCreated(FrameLayout containerView) { + super.onViewCreated(containerView); + Bulletin.addDelegate(container, new Bulletin.Delegate() { + @Override + public int getTopOffset(int tag) { + return AndroidUtilities.statusBarHeight; + } + }); + } + + @Override + protected CharSequence getTitle() { + return isUnused ? LocaleController.getString("BoostingGiftLink", R.string.BoostingGiftLink) + : LocaleController.getString("BoostingUsedGiftLink", R.string.BoostingUsedGiftLink); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return adapter = new GiftInfoAdapter(resourcesProvider) { + @Override + protected void dismiss() { + GiftInfoBottomSheet.this.dismiss(); + } + + @Override + protected void afterCodeApplied() { + AndroidUtilities.runOnUIThread(() -> { + PremiumPreviewBottomSheet previewBottomSheet = new PremiumPreviewBottomSheet(getBaseFragment(), currentAccount, null, null, resourcesProvider) + .setAnimateConfetti(true) + .setOutboundGift(true); + getBaseFragment().showDialog(previewBottomSheet); + }, 200); + } + + @Override + protected void onObjectClicked(TLObject object) { + dismiss(); + if (object instanceof TLRPC.Chat) { + getBaseFragment().presentFragment(ChatActivity.of(-((TLRPC.Chat) object).id)); + } else if (object instanceof TLRPC.User) { + getBaseFragment().presentFragment(ChatActivity.of(((TLRPC.User) object).id)); + } else { + Bundle bundle = new Bundle(); + bundle.putLong("chat_id", -DialogObject.getPeerDialogId(giftCode.from_id)); + bundle.putInt("message_id", giftCode.giveaway_msg_id); + ChatActivity chatFragment = new ChatActivity(bundle); + getBaseFragment().presentFragment(chatFragment); + } + } + + @Override + protected void onHiddenLinkClicked() { + String text = LocaleController.getString("BoostingOnlyRecipientCode", R.string.BoostingOnlyRecipientCode); + BulletinFactory.of(container, resourcesProvider).createSimpleBulletin(R.raw.chats_infotip, text).show(true); + } + }; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java new file mode 100644 index 000000000..384188be8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/ReassignBoostBottomSheet.java @@ -0,0 +1,559 @@ +package org.telegram.ui.Components.Premium.boosts; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.CountDownTimer; +import android.text.SpannableStringBuilder; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +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.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Premium.PremiumGradient; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorUserCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.UndoView; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +public class ReassignBoostBottomSheet extends BottomSheetWithRecyclerListView { + private static final int + HOLDER_TYPE_HEADER = 0, + HOLDER_TYPE_DIVIDER = 1, + HOLDER_TYPE_SUBTITLE = 2, + HOLDER_TYPE_USER = 3; + + private static final int CONTENT_VIEWS_COUNT = 3; + private static final int CONTAINER_HEIGHT_DP = 64; + + public static ReassignBoostBottomSheet show(BaseFragment fragment, TL_stories.TL_premium_myBoosts myBoosts, TLRPC.Chat currentChat) { + ReassignBoostBottomSheet bottomSheet = new ReassignBoostBottomSheet(fragment, myBoosts, currentChat); + bottomSheet.show(); + return bottomSheet; + } + + private final List selectedBoosts = new ArrayList<>(); + private final List allUsedBoosts = new ArrayList<>(); + private final TL_stories.TL_premium_myBoosts myBoosts; + private final TLRPC.Chat currentChat; + + private final SelectorBtnCell buttonContainer; + private final ButtonWithCounterView actionButton; + private TopCell topCell; + private CountDownTimer timer; + + public ReassignBoostBottomSheet(BaseFragment fragment, TL_stories.TL_premium_myBoosts myBoosts, TLRPC.Chat currentChat) { + super(fragment, false, false); + this.topPadding = 0.3f; + this.myBoosts = myBoosts; + this.currentChat = currentChat; + + for (TL_stories.TL_myBoost myBoost : myBoosts.my_boosts) { + if (myBoost.peer != null && DialogObject.getPeerDialogId(myBoost.peer) != -currentChat.id) { + allUsedBoosts.add(myBoost); + } + } + + 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)); + actionButton = new ButtonWithCounterView(getContext(), true, resourcesProvider) { + + private final RectF rect = new RectF(); + private boolean incGradient; + private float progress; + + @Override + protected void onDraw(Canvas canvas) { + if (incGradient) { + progress += 16f / 1000f; + if (progress > 3) { + incGradient = false; + } + } else { + progress -= 16f / 1000f; + if (progress < 1) { + incGradient = true; + } + } + rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0); + canvas.drawRoundRect(rect, dp(8), dp(8), PremiumGradient.getInstance().getMainGradientPaint()); + invalidate(); + super.onDraw(canvas); + } + }; + actionButton.withCounterIcon(); + actionButton.setCounterColor(0xFF9874fc); + actionButton.setOnClickListener(view -> { + if (selectedBoosts.isEmpty()) { + return; + } + if (actionButton.isLoading()) { + return; + } + actionButton.setLoading(true); + List slots = new ArrayList<>(); + HashSet uniqueChannelIds = new HashSet<>(); + for (TL_stories.TL_myBoost selectedBoost : selectedBoosts) { + slots.add(selectedBoost.slot); + uniqueChannelIds.add(DialogObject.getPeerDialogId(selectedBoost.peer)); + } + BoostRepository.applyBoost(currentChat.id, slots, result -> { + dismiss(); + NotificationCenter.getInstance(UserConfig.selectedAccount).postNotificationName(NotificationCenter.boostedChannelByUser, result, slots.size(), uniqueChannelIds.size()); + }, error -> { + actionButton.setLoading(false); + BoostDialogs.showToastError(getContext(), error); + }); + }); + + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, AndroidUtilities.dp(CONTAINER_HEIGHT_DP)); + recyclerListView.setOnItemClickListener((view, position) -> { + if (view instanceof SelectorUserCell) { + SelectorUserCell cell = ((SelectorUserCell) view); + if (cell.getBoost().cooldown_until_date > 0) { + SpannableStringBuilder text = AndroidUtilities.replaceTags(LocaleController.formatString("BoostingWaitWarning", R.string.BoostingWaitWarning, BoostRepository.boostsPerSentGift())); + BulletinFactory.of(container, resourcesProvider).createSimpleBulletin(R.raw.chats_infotip, text, 5).show(true); + return; + } + if (selectedBoosts.contains(cell.getBoost())) { + selectedBoosts.remove(cell.getBoost()); + } else { + selectedBoosts.add(cell.getBoost()); + } + cell.setChecked(selectedBoosts.contains(cell.getBoost()), true); + updateActionButton(true); + topCell.showBoosts(selectedBoosts, currentChat); + } + }); + + fixNavigationBar(); + updateTitle(); + updateActionButton(false); + Bulletin.addDelegate(container, new Bulletin.Delegate() { + @Override + public int getTopOffset(int tag) { + return AndroidUtilities.statusBarHeight; + } + }); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + timer = new CountDownTimer(Long.MAX_VALUE, 1000) { + public void onTick(long millisUntilFinished) { + List updates = new ArrayList<>(allUsedBoosts.size()); + for (TL_stories.TL_myBoost boost : allUsedBoosts) { + if (boost.cooldown_until_date > 0) { + updates.add(boost); + } + if (boost.cooldown_until_date * 1000L < System.currentTimeMillis()) { + boost.cooldown_until_date = 0; + } + } + if (updates.isEmpty()) { + return; + } + for (int i = 0; i < recyclerListView.getChildCount(); ++i) { + View child = recyclerListView.getChildAt(i); + if (child instanceof SelectorUserCell) { + SelectorUserCell cell = (SelectorUserCell) child; + if (updates.contains(cell.getBoost())) { + cell.updateTimer(); + } + } + } + } + + public void onFinish() { + + } + }; + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + timer.cancel(); + } + + @Override + public void onOpenAnimationEnd() { + timer.start(); + } + + private void updateActionButton(boolean animated) { + actionButton.setShowZero(false); + if (selectedBoosts.size() > 1) { + actionButton.setText(LocaleController.getString("BoostingReassignBoosts", R.string.BoostingReassignBoosts), animated); + } else { + actionButton.setText(LocaleController.getString("BoostingReassignBoost", R.string.BoostingReassignBoost), animated); + } + actionButton.setCount(selectedBoosts.size(), animated); + actionButton.setEnabled(selectedBoosts.size() > 0); + } + + @Override + protected CharSequence getTitle() { + return LocaleController.getString("BoostingReassignBoost", R.string.BoostingReassignBoost); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return new RecyclerListView.SelectionAdapter() { + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == HOLDER_TYPE_USER; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + case HOLDER_TYPE_HEADER: + TopCell cell = new TopCell(context); + cell.showBoosts(selectedBoosts, currentChat); + view = cell; + 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 SelectorUserCell(context, resourcesProvider, true); + break; + default: + view = new View(context); + } + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (holder.getItemViewType() == HOLDER_TYPE_USER) { + TL_stories.TL_myBoost boost = allUsedBoosts.get(position - CONTENT_VIEWS_COUNT); + SelectorUserCell userCell = (SelectorUserCell) holder.itemView; + userCell.setBoost(boost); + userCell.setChecked(selectedBoosts.contains(boost), false); + } else if (holder.getItemViewType() == HOLDER_TYPE_SUBTITLE) { + HeaderCell cell = (HeaderCell) holder.itemView; + cell.setTextSize(15); + cell.setPadding(0, 0, 0, AndroidUtilities.dp(2)); + cell.setText(LocaleController.getString("BoostingRemoveBoostFrom", R.string.BoostingRemoveBoostFrom)); + } else if (holder.getItemViewType() == HOLDER_TYPE_HEADER) { + topCell = (TopCell) holder.itemView; + topCell.setData(currentChat); + } + } + + @Override + public int getItemViewType(int position) { + switch (position) { + case 0: + return HOLDER_TYPE_HEADER; + case 1: + return HOLDER_TYPE_DIVIDER; + case 2: + return HOLDER_TYPE_SUBTITLE; + default: + return HOLDER_TYPE_USER; + } + } + + @Override + public int getItemCount() { + return CONTENT_VIEWS_COUNT + allUsedBoosts.size(); + } + }; + } + + private static class TopCell extends LinearLayout { + + private final List addedChats = new ArrayList<>(); + private final AvatarHolderView toAvatar; + private final ArrowView arrowView; + private final FrameLayout avatarsContainer; + private final FrameLayout avatarsWrapper; + private final TextView description; + + public TopCell(Context context) { + super(context); + setOrientation(LinearLayout.VERTICAL); + + avatarsContainer = new FrameLayout(getContext()); + + avatarsWrapper = new FrameLayout(getContext()); + avatarsContainer.addView(avatarsWrapper, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 70, 0, 0, 0, 0, 0)); + + arrowView = new ArrowView(context); + avatarsContainer.addView(arrowView, LayoutHelper.createFrame(24, 24, Gravity.CENTER)); + + toAvatar = new AvatarHolderView(context); + toAvatar.setLayerType(View.LAYER_TYPE_HARDWARE, null); + avatarsContainer.addView(toAvatar, LayoutHelper.createFrame(70, 70, Gravity.CENTER)); + + addView(avatarsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 70, 0, 15, 0, 0)); + + TextView title = new TextView(context); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + title.setText(LocaleController.getString("BoostingReassignBoost", R.string.BoostingReassignBoost)); + 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, 15, 0, 7)); + + description = new TextView(context); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + description.setGravity(Gravity.CENTER_HORIZONTAL); + description.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + + description.setLineSpacing(description.getLineSpacingExtra(), description.getLineSpacingMultiplier() * 1.1f); + addView(description, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 28, 0, 28, 18)); + } + + public void setData(TLRPC.Chat chat) { + description.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingReassignBoostText", R.string.BoostingReassignBoostText, chat == null ? "" : chat.title, BoostRepository.boostsPerSentGift()))); + } + + public void showBoosts(List selectedBoosts, TLRPC.Chat currentChat) { + List selectedChats = new ArrayList<>(selectedBoosts.size()); + for (TL_stories.TL_myBoost selectedBoost : selectedBoosts) { + selectedChats.add(MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(selectedBoost.peer))); + } + showChats(selectedChats, currentChat); + } + + public void showChats(List selectedChats, TLRPC.Chat currentChat) { + List chatsToRemove = new ArrayList<>(); + List chatsToAdd = new ArrayList<>(); + int duration = 200; + CubicBezierInterpolator interpolator = CubicBezierInterpolator.DEFAULT; + + for (TLRPC.Chat selectedChat : selectedChats) { + if (!addedChats.contains(selectedChat)) { + chatsToAdd.add(selectedChat); + } + } + + for (TLRPC.Chat addedChat : addedChats) { + if (!selectedChats.contains(addedChat)) { + chatsToRemove.add(addedChat); + } + } + + List allViews = new ArrayList<>(); + for (int i = 0; i < avatarsWrapper.getChildCount(); i++) { + AvatarHolderView child = (AvatarHolderView) avatarsWrapper.getChildAt(i); + if (child.getTag() == null) { + allViews.add(child); + } + } + + for (TLRPC.Chat chat : chatsToAdd) { + AvatarHolderView avatar = new AvatarHolderView(getContext()); + avatar.setLayerType(View.LAYER_TYPE_HARDWARE, null); + avatar.setChat(chat); + int childCount = allViews.size(); + avatarsWrapper.addView(avatar, 0, LayoutHelper.createFrame(70, 70, Gravity.CENTER)); + avatar.setTranslationX(-childCount * (52 + 18)); + avatar.setAlpha(0f); + avatar.setScaleX(0.1f); + avatar.setScaleY(0.1f); + avatar.animate().alpha(1f).scaleX(1f).scaleY(1f).setInterpolator(interpolator).setDuration(duration).start(); + if (childCount == 0) { + avatar.boostIconView.setScaleY(1f); + avatar.boostIconView.setScaleX(1f); + avatar.boostIconView.setAlpha(1f); + } + } + + for (TLRPC.Chat chat : chatsToRemove) { + AvatarHolderView removedAvatar = null; + + for (AvatarHolderView view : allViews) { + if (view.chat == chat) { + removedAvatar = view; + break; + } + } + + if (removedAvatar != null) { + final AvatarHolderView finalRemovedAvatar = removedAvatar; + finalRemovedAvatar.setTag("REMOVED"); + finalRemovedAvatar.animate() + .alpha(0f).translationXBy((52 + 18)) + .scaleX(0.1f).scaleY(0.1f) + .setInterpolator(interpolator) + .setDuration(duration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finalRemovedAvatar.setLayerType(View.LAYER_TYPE_NONE, null); + avatarsWrapper.removeView(finalRemovedAvatar); + } + }).start(); + int pos = 0; + for (AvatarHolderView view : allViews) { + int childCount = allViews.size() - 1; + if (view != finalRemovedAvatar) { + pos++; + childCount -= pos; + view.animate().translationX(-childCount * (52 + 18)) + .setInterpolator(interpolator) + .setDuration(duration).start(); + } + } + if (allViews.get(allViews.size() - 1) == finalRemovedAvatar && allViews.size() > 1) { + allViews.get(allViews.size() - 2).boostIconView.setScaleY(0.1f); + allViews.get(allViews.size() - 2).boostIconView.setScaleX(0.1f); + allViews.get(allViews.size() - 2).boostIconView.animate().alpha(1f).scaleY(1f).scaleX(1f).setDuration(duration).setInterpolator(interpolator).start(); + } + } + } + if (toAvatar.chat == null) { + toAvatar.setChat(currentChat); + } + addedChats.removeAll(chatsToRemove); + addedChats.addAll(chatsToAdd); + + avatarsContainer.animate().cancel(); + if (addedChats.isEmpty() || addedChats.size() == 1) { + avatarsContainer.animate().setInterpolator(interpolator).translationX(0).setDuration(duration).start(); + } else { + int count = addedChats.size() - 1; + avatarsContainer.animate().setInterpolator(interpolator).translationX(dp(11) * count).setDuration(duration).start(); + } + + toAvatar.animate().cancel(); + avatarsWrapper.animate().cancel(); + if (addedChats.isEmpty()) { + avatarsWrapper.animate().setInterpolator(interpolator).translationX(0).setDuration(duration).start(); + toAvatar.animate().setInterpolator(interpolator).translationX(0).setDuration(duration).start(); + } else { + avatarsWrapper.animate().setInterpolator(interpolator).translationX(-dp(30 + 18)).setDuration(duration).start(); + toAvatar.animate().setInterpolator(interpolator).translationX(dp(30 + 18)).setDuration(duration).start(); + } + } + } + + private static class ArrowView extends FrameLayout { + + public ArrowView(Context context) { + super(context); + ImageView arrowImage = new ImageView(getContext()); + arrowImage.setImageResource(R.drawable.msg_arrow_avatar); + arrowImage.setColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText7)); + addView(arrowImage); + } + } + + private static class AvatarHolderView extends FrameLayout { + private final BackupImageView imageView; + private final BoostIconView boostIconView; + private final Paint bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + public TLRPC.Chat chat; + AvatarDrawable fromAvatarDrawable = new AvatarDrawable(); + + public AvatarHolderView(Context context) { + super(context); + imageView = new BackupImageView(getContext()); + imageView.setRoundRadius(AndroidUtilities.dp(30)); + boostIconView = new BoostIconView(context); + boostIconView.setAlpha(0f); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 5, 5, 5, 5)); + addView(boostIconView, LayoutHelper.createFrame(28, 28, Gravity.BOTTOM | Gravity.RIGHT, 0, 0, 0, 3)); + bgPaint.setColor(Theme.getColor(Theme.key_dialogBackground)); + } + + public void setChat(TLRPC.Chat chat) { + this.chat = chat; + fromAvatarDrawable.setInfo(chat); + imageView.setForUserOrChat(chat, fromAvatarDrawable); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.drawCircle(getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, (getMeasuredHeight() / 2f) - dp(2f), bgPaint); + super.dispatchDraw(canvas); + } + } + + private static class BoostIconView extends View { + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + Drawable boostDrawable = ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_remove); + + public BoostIconView(Context context) { + super(context); + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + } + + @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(2), PremiumGradient.getInstance().getMainGradientPaint()); + float iconSizeHalf = AndroidUtilities.dp(18) / 2f; + boostDrawable.setBounds( + (int) (cx - iconSizeHalf), + (int) (cy - iconSizeHalf), + (int) (cx + iconSizeHalf), + (int) (cy + iconSizeHalf) + ); + boostDrawable.draw(canvas); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java new file mode 100644 index 000000000..60d88c1f4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/SelectorBottomSheet.java @@ -0,0 +1,663 @@ +package org.telegram.ui.Components.Premium.boosts; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.translitSafe; + +import android.annotation.SuppressLint; +import android.content.res.Configuration; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearSmoothScrollerCustom; +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.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.GraySectionCell; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter; +import org.telegram.ui.Components.Premium.boosts.adapters.SelectorAdapter.Item; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorBtnCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorCountryCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorSearchCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorHeaderCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorUserCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +public class SelectorBottomSheet extends BottomSheetWithRecyclerListView { + + public interface SelectedObjectsListener { + void onChatsSelected(List chats); + + void onUsersSelected(List users); + + void onCountrySelected(List countries); + + default void onShowToast(String text) { + + } + } + + private static final int BOTTOM_HEIGHT_DP = 60; + public static final int TYPE_COUNTRY = 3; + public static final int TYPE_CHANNEL = 2; + public static final int TYPE_USER = 1; + + private final ButtonWithCounterView actionButton; + private final SelectorSearchCell searchField; + private final GraySectionCell sectionCell; + private final SelectorHeaderCell headerView; + private final SelectorBtnCell buttonContainer; + + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final ArrayList oldItems = new ArrayList<>(); + private final ArrayList items = new ArrayList<>(); + private final HashSet selectedIds = new HashSet<>(); + private final HashSet openedIds = new HashSet<>(); + private final ArrayList peers = new ArrayList<>(); + private final ArrayList users = new ArrayList<>(); + private final Map> countriesMap = new HashMap<>(); + private final List countriesLetters = new ArrayList<>(); + private final List countriesList = new ArrayList<>(); + private final AnimatedFloat statusBarT; + private String query; + private SelectorAdapter selectorAdapter; + private int listPaddingTop = AndroidUtilities.dp(56 + 78); + private final TLRPC.Chat currentChat; + private int type; + private Runnable onCloseClick; + private int top; + private SelectedObjectsListener selectedObjectsListener; + private final Runnable remoteSearchRunnable = new Runnable() { + @Override + public void run() { + final String finalQuery = query; + if (finalQuery != null) { + loadData(type, false, finalQuery); + } + } + }; + + public SelectorBottomSheet(BaseFragment fragment, boolean needFocus, long dialogId) { + super(fragment, needFocus, false); + backgroundPaddingLeft = 0; + this.currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + + ((ViewGroup) actionBar.getParent()).removeView(actionBar); //we used custom action bar + + statusBarT = new AnimatedFloat(containerView, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); + + headerView = new SelectorHeaderCell(getContext(), resourcesProvider); + headerView.setOnCloseClickListener(this::dismiss); + headerView.setText(getTitle()); + headerView.setCloseImageVisible(true); + headerView.backDrawable.setRotation(0f, false); + + searchField = new SelectorSearchCell(getContext(), resourcesProvider, null) { + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + listPaddingTop = getMeasuredHeight() + AndroidUtilities.dp(78); + selectorAdapter.notifyChangedLast(); + } + }; + searchField.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + searchField.setOnSearchTextChange(this::onSearch); + + sectionCell = new GraySectionCell(getContext(), resourcesProvider); + updateSection(); + + containerView.addView(headerView, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + containerView.addView(searchField, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + containerView.addView(sectionCell, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, 32, Gravity.TOP | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + buttonContainer = new SelectorBtnCell(getContext(), resourcesProvider, null); + buttonContainer.setClickable(true); + buttonContainer.setOrientation(LinearLayout.VERTICAL); + buttonContainer.setPadding(dp(10), dp(10), dp(10), dp(10)); + buttonContainer.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + actionButton = new ButtonWithCounterView(getContext(), resourcesProvider); + actionButton.setOnClickListener(v -> save(false)); + buttonContainer.addView(actionButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + containerView.addView(buttonContainer, LayoutHelper.createFrameMarginPx(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, backgroundPaddingLeft, 0, backgroundPaddingLeft, 0)); + + selectorAdapter.setData(items, recyclerListView); + recyclerListView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, AndroidUtilities.dp(BOTTOM_HEIGHT_DP)); + recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + AndroidUtilities.hideKeyboard(searchField.getEditText()); + } + } + }); + recyclerListView.setOnItemClickListener((view, position, x, y) -> { + if (view instanceof SelectorUserCell) { + TLRPC.User user = ((SelectorUserCell) view).getUser(); + TLRPC.Chat chat = ((SelectorUserCell) view).getChat(); + long id = user != null ? user.id : -chat.id; + if (selectedIds.contains(id)) { + selectedIds.remove(id); + } else { + selectedIds.add(id); + } + if ((selectedIds.size() == 11 && type == TYPE_USER) || (selectedIds.size() == (BoostRepository.giveawayAddPeersMax() + 1) && type == TYPE_CHANNEL)) { + selectedIds.remove(id); + showMaximumUsersToast(); + return; + } + searchField.updateSpans(true, selectedIds, () -> updateList(true, false), null); + updateList(true, false); + if (chat != null && !ChatObject.isPublic(chat) && selectedIds.contains(id)) { + BoostDialogs.showPrivateChannelAlert(getBaseFragment().getContext(), resourcesProvider, () -> { + selectedIds.remove(id); + searchField.updateSpans(true, selectedIds, () -> updateList(true, false), null); + updateList(true, false); + }); + } + } + if (view instanceof SelectorCountryCell) { + SelectorCountryCell countryCell = (SelectorCountryCell) view; + long id = countryCell.getCountry().default_name.hashCode(); + if (selectedIds.contains(id)) { + selectedIds.remove(id); + } else { + selectedIds.add(id); + } + if (selectedIds.size() == (BoostRepository.giveawayCountriesMax() + 1) && type == TYPE_COUNTRY) { + selectedIds.remove(id); + showMaximumUsersToast(); + return; + } + searchField.updateSpans(true, selectedIds, () -> updateList(true, false), countriesList); + query = null; + searchField.setText(""); + updateList(false, false); + updateList(true, true); + } + }); + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + recyclerListView.setItemAnimator(itemAnimator); + recyclerListView.addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { + super.getItemOffsets(outRect, view, parent, state); + int position = parent.getChildAdapterPosition(view); + if (position == items.size()) { + outRect.bottom = listPaddingTop; + } + } + }); + + updateList(false, true); + loadData(TYPE_USER, true, null); + loadData(TYPE_COUNTRY, true, null); + } + + private void save(boolean force) { + if (selectedIds.size() == 0 && !force) { + return; + } + switch (type) { + case TYPE_CHANNEL: + List selectedChats = new ArrayList<>(); + for (TLRPC.InputPeer peer : peers) { + if (peer instanceof TLRPC.TL_inputPeerChat && selectedIds.contains(-peer.chat_id)) { + selectedChats.add(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.chat_id)); + } else if (peer instanceof TLRPC.TL_inputPeerChannel && selectedIds.contains(-peer.channel_id)) { + selectedChats.add(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.channel_id)); + } + } + if (selectedObjectsListener != null) { + selectedObjectsListener.onChatsSelected(selectedChats); + } + break; + case TYPE_USER: + List selectedUsers = new ArrayList<>(); + for (TLRPC.InputPeer peer : peers) { + if (peer instanceof TLRPC.TL_inputPeerUser && selectedIds.contains(peer.user_id)) { + selectedUsers.add(MessagesController.getInstance(UserConfig.selectedAccount).getUser(peer.user_id)); + } + } + if (selectedObjectsListener != null) { + selectedObjectsListener.onUsersSelected(selectedUsers); + } + break; + case TYPE_COUNTRY: + List selectedCountries = new ArrayList<>(); + for (TLRPC.TL_help_country country : countriesList) { + long id = country.default_name.hashCode(); + if (selectedIds.contains(id)) { + selectedCountries.add(country); + } + } + if (selectedObjectsListener != null) { + selectedObjectsListener.onCountrySelected(selectedCountries); + } + break; + } + } + + public void scrollToTop(boolean animate) { + if (animate) { + LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(getContext(), LinearSmoothScrollerCustom.POSITION_TOP, .6f); + linearSmoothScroller.setTargetPosition(1); + linearSmoothScroller.setOffset(AndroidUtilities.dp(38)); + recyclerListView.getLayoutManager().startSmoothScroll(linearSmoothScroller); + } else { + recyclerListView.scrollToPosition(1); + } + } + + private void loadData(int localType, boolean preCache, String query) { + switch (localType) { + case TYPE_CHANNEL: + BoostRepository.searchChats(currentChat.id, 0, query, 50, peers -> { + if (!isSearching()) { + return; + } + this.peers.clear(); + this.peers.addAll(peers); + updateList(true, true); + scrollToTop(true); + }); + break; + case TYPE_USER: + BoostRepository.loadChatParticipants(currentChat.id, 0, query, 0, 50, peers -> { + if (preCache) { + users.addAll(peers); + } + if (type == TYPE_USER) { + this.peers.clear(); + this.peers.addAll(peers); + updateList(true, true); + scrollToTop(true); + } + }); + break; + case TYPE_COUNTRY: + BoostRepository.loadCountries(arg -> { + if (preCache) { + countriesMap.putAll(arg.first); + countriesLetters.addAll(arg.second); + countriesMap.forEach((s, list) -> countriesList.addAll(list)); + } + if (type == TYPE_COUNTRY) { + updateList(true, true); + scrollToTop(true); + } + }); + break; + } + } + + public boolean hasChanges() { + if ((selectedIds.size() != openedIds.size() || !openedIds.containsAll(selectedIds) || !selectedIds.containsAll(openedIds))) { + BoostDialogs.showUnsavedChanges(type, getContext(), resourcesProvider, () -> save(true), () -> { + selectedIds.clear(); + openedIds.clear(); + dismiss(); + }); + return true; + } + return false; + } + + @Override + public void dismiss() { + if (onCloseClick != null) { + onCloseClick.run(); + } + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + AndroidUtilities.cancelRunOnUIThread(remoteSearchRunnable); + } + + public void setSelectedObjectsListener(SelectedObjectsListener selectedObjectsListener) { + this.selectedObjectsListener = selectedObjectsListener; + } + + public int getTop() { + return Math.max(0, top - (statusBarT.get() == 1 ? AndroidUtilities.statusBarHeight : 0)); + } + + public void setOnCloseClick(Runnable onCloseClick) { + this.onCloseClick = onCloseClick; + } + + public void prepare(List selectedObjects, int type) { + this.type = type; + query = null; + openedIds.clear(); + selectedIds.clear(); + peers.clear(); + + switch (type) { + case TYPE_CHANNEL: + peers.addAll(BoostRepository.getMyChannels(currentChat.id)); + break; + case TYPE_USER: + peers.addAll(users); + break; + case TYPE_COUNTRY: + + break; + } + + if (selectedObjects != null) { + for (TLObject selectedChat : selectedObjects) { + if (selectedChat instanceof TLRPC.TL_inputPeerChat) { + selectedIds.add(-((TLRPC.TL_inputPeerChat) selectedChat).chat_id); + } + if (selectedChat instanceof TLRPC.TL_inputPeerChannel) { + selectedIds.add(-((TLRPC.TL_inputPeerChannel) selectedChat).channel_id); + } + if (selectedChat instanceof TLRPC.Chat) { + selectedIds.add(-((TLRPC.Chat) selectedChat).id); + } + if (selectedChat instanceof TLRPC.User) { + selectedIds.add(((TLRPC.User) selectedChat).id); + } + if (selectedChat instanceof TLRPC.TL_help_country) { + long id = ((TLRPC.TL_help_country) selectedChat).default_name.hashCode(); + selectedIds.add(id); + } + } + } + + openedIds.addAll(selectedIds); + + searchField.setText(""); + searchField.spansContainer.removeAllSpans(false); + searchField.updateSpans(false, selectedIds, () -> updateList(true, false), countriesList); + + updateSection(); + updateList(false, true); + headerView.setText(getTitle()); + updateActionButton(false); + } + + private void updateSection() { + String text; + switch (type) { + case TYPE_CHANNEL: + text = LocaleController.formatString("BoostingSelectUpTo", R.string.BoostingSelectUpTo, BoostRepository.giveawayAddPeersMax()); + sectionCell.setLayerHeight(32); + break; + case TYPE_USER: + text = LocaleController.formatPluralStringComma("Subscribers", Math.max(0, selectorAdapter.getParticipantsCount(currentChat) - 1)); + sectionCell.setLayerHeight(32); + break; + case TYPE_COUNTRY: + text = LocaleController.formatString("BoostingSelectUpTo", R.string.BoostingSelectUpToCountries, BoostRepository.giveawayCountriesMax()); + sectionCell.setLayerHeight(1); + break; + default: + text = ""; + } + sectionCell.setText(text); + } + + private void showMaximumUsersToast() { + String text = ""; + switch (type) { + case TYPE_CHANNEL: + text = LocaleController.formatString("BoostingSelectUpToWarningChannels", R.string.BoostingSelectUpToWarningChannels, BoostRepository.giveawayAddPeersMax()); + break; + case TYPE_USER: + text = LocaleController.getString("BoostingSelectUpToWarningUsers", R.string.BoostingSelectUpToWarningUsers); + break; + case TYPE_COUNTRY: + text = LocaleController.formatString("BoostingSelectUpToWarningCountries", R.string.BoostingSelectUpToWarningCountries, BoostRepository.giveawayCountriesMax()); + break; + } + if (selectedObjectsListener != null) { + selectedObjectsListener.onShowToast(text); + } + } + + private void updateList(boolean animated, boolean notify) { + updateItems(animated, notify); + updateCheckboxes(animated); + updateActionButton(animated); + } + + private void updateCheckboxes(boolean animated) { + for (int i = 0; i < recyclerListView.getChildCount(); ++i) { + View child = recyclerListView.getChildAt(i); + if (child instanceof SelectorUserCell) { + int position = recyclerListView.getChildAdapterPosition(child); + if (position < 0) { + continue; + } + Item item = items.get(position - 1); + SelectorUserCell cell = (SelectorUserCell) child; + cell.setChecked(item.checked, animated); + if (item.chat != null) { + cell.setCheckboxAlpha(selectorAdapter.getParticipantsCount(item.chat) > 200 ? .3f : 1f, animated); + } else { + cell.setCheckboxAlpha(1f, animated); + } + } + if (child instanceof SelectorCountryCell) { + SelectorCountryCell cell = (SelectorCountryCell) child; + long id = cell.getCountry().default_name.hashCode(); + cell.setChecked(selectedIds.contains(id), true); + } + } + } + + @Override + protected void onPreDraw(Canvas canvas, int top, float progressToFullView) { + this.top = top; + float minTop = AndroidUtilities.statusBarHeight + (headerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(40)) / 2f; + float fromY = Math.max(top, minTop); + headerView.setTranslationY(fromY); + searchField.setTranslationY(headerView.getTranslationY() + headerView.getMeasuredHeight()); + sectionCell.setTranslationY(searchField.getTranslationY() + searchField.getMeasuredHeight()); + recyclerListView.setTranslationY(headerView.getMeasuredHeight() + searchField.getMeasuredHeight() + sectionCell.getMeasuredHeight() - AndroidUtilities.dp(16)); + drawFilledStatusBar(canvas, top); + } + + private void drawFilledStatusBar(Canvas canvas, int top) { + backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + top = Math.max(0, top); + top = AndroidUtilities.lerp(top, 0, statusBarT.set(top < AndroidUtilities.statusBarHeight)); + AndroidUtilities.rectTmp.set(backgroundPaddingLeft, top, containerView.getWidth() - backgroundPaddingLeft, containerView.getHeight() + dp(14)); + final float r = dp(14) * (1f - statusBarT.get()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, backgroundPaint); + } + + private void updateActionButton(boolean animated) { + actionButton.setShowZero(false); + String text; + switch (type) { + case TYPE_COUNTRY: + case TYPE_CHANNEL: + text = LocaleController.getString("Save", R.string.Save); + break; + case TYPE_USER: + text = LocaleController.getString("BoostingSaveRecipients", R.string.BoostingSaveRecipients); + break; + default: + text = ""; + } + actionButton.setText(text, animated); + actionButton.setCount(selectedIds.size(), animated); + actionButton.setEnabled(selectedIds.size() > 0); + } + + private void onSearch(String text) { + this.query = text; + switch (type) { + case TYPE_CHANNEL: + if (!isSearching()) { + AndroidUtilities.cancelRunOnUIThread(remoteSearchRunnable); + peers.clear(); + peers.addAll(BoostRepository.getMyChannels(currentChat.id)); + updateItems(false, true); + scrollToTop(true); + } else { + AndroidUtilities.cancelRunOnUIThread(remoteSearchRunnable); + AndroidUtilities.runOnUIThread(remoteSearchRunnable, 350); + } + break; + case TYPE_USER: + AndroidUtilities.cancelRunOnUIThread(remoteSearchRunnable); + AndroidUtilities.runOnUIThread(remoteSearchRunnable, 350); + break; + case TYPE_COUNTRY: + updateItems(false, true); + scrollToTop(true); + break; + } + } + + private void updateSectionCell(boolean animated) { + if (selectedIds.size() > 0 && type != TYPE_COUNTRY) { + sectionCell.setRightText(LocaleController.getString(R.string.UsersDeselectAll), true, v -> { + selectedIds.clear(); + searchField.spansContainer.removeAllSpans(true); + updateList(true, false); + }); + } else { + if (animated) { + sectionCell.setRightText(null); + } else { + sectionCell.setRightText(null, null); + } + } + } + + private boolean isSearching() { + return !TextUtils.isEmpty(query); + } + + @SuppressLint("NotifyDataSetChanged") + public void updateItems(boolean animated, boolean notify) { + oldItems.clear(); + oldItems.addAll(items); + items.clear(); + + int h = 0; + if (type == TYPE_COUNTRY) { + for (String countriesLetter : countriesLetters) { + List countryItems = new ArrayList<>(); + for (TLRPC.TL_help_country country : countriesMap.get(countriesLetter)) { + if (isSearching()) { + String q = translitSafe(query).toLowerCase(); + if (!matchLocal(country, q)) { + continue; + } + } + h += dp(44); + long id = country.default_name.hashCode(); + countryItems.add(Item.asCountry(country, selectedIds.contains(id))); + } + + if (!countryItems.isEmpty()) { + h += dp(32); + items.add(Item.asLetter(countriesLetter)); + items.addAll(countryItems); + } + } + } + + for (TLRPC.InputPeer peer : peers) { + h += dp(56); + items.add(Item.asPeer(peer, selectedIds.contains(DialogObject.getPeerDialogId(peer)))); + } + if (items.isEmpty()) { + items.add(Item.asNoUsers()); + h += dp(150); + } + int minHeight = (int) (AndroidUtilities.displaySize.y * 0.6f); + items.add(Item.asPad(Math.max(0, minHeight - h))); + + updateSectionCell(animated); + + if (notify && selectorAdapter != null) { + if (animated) { + selectorAdapter.setItems(oldItems, items); + } else { + selectorAdapter.notifyDataSetChanged(); + } + } + } + + private boolean matchLocal(TLObject obj, String q) { + if (TextUtils.isEmpty(q)) { + return true; + } + if (obj instanceof TLRPC.TL_help_country) { + TLRPC.TL_help_country chat = (TLRPC.TL_help_country) obj; + String name = translitSafe(chat.default_name).toLowerCase(); + if (name.startsWith(q) || name.contains(" " + q)) { + return true; + } + String username = translitSafe(chat.iso2).toLowerCase(); + if (username.startsWith(q) || username.contains(" " + q)) { + return true; + } + } + return false; + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + updateItems(false, true); + } + + @Override + protected CharSequence getTitle() { + switch (type) { + case TYPE_CHANNEL: + return LocaleController.getString("BoostingAddChannel", R.string.BoostingAddChannel); + case TYPE_USER: + return LocaleController.getString("GiftPremium", R.string.GiftPremium); + case TYPE_COUNTRY: + return LocaleController.getString("BoostingSelectCountry", R.string.BoostingSelectCountry); + } + return ""; + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return selectorAdapter = new SelectorAdapter(getContext(), resourcesProvider); + } +} 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 new file mode 100644 index 000000000..276c5c04e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/BoostAdapter.java @@ -0,0 +1,444 @@ +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.MessagesController; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; +import org.telegram.ui.Components.Premium.boosts.cells.AddChannelCell; +import org.telegram.ui.Components.Premium.boosts.cells.BoostTypeCell; +import org.telegram.ui.Components.Premium.boosts.cells.BoostTypeSingleCell; +import org.telegram.ui.Components.Premium.boosts.cells.ChatCell; +import org.telegram.ui.Components.Premium.boosts.cells.DateEndCell; +import org.telegram.ui.Components.Premium.boosts.cells.HeaderCell; +import org.telegram.ui.Components.Premium.boosts.cells.ParticipantsTypeCell; +import org.telegram.ui.Components.Premium.boosts.cells.DurationCell; +import org.telegram.ui.Components.Premium.boosts.cells.SliderCell; +import org.telegram.ui.Components.Premium.boosts.cells.SubtitleWithCounterCell; +import org.telegram.ui.Components.Premium.boosts.cells.TextInfoCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SlideChooseView; + +import java.util.ArrayList; +import java.util.List; + +public class BoostAdapter extends AdapterWithDiffUtils { + + public static final int + HOLDER_TYPE_HEADER = 0, + HOLDER_TYPE_BOOST_TYPE = 2, + HOLDER_TYPE_EMPTY = 3, + HOLDER_TYPE_SIMPLE_DIVIDER = 4, + HOLDER_TYPE_SLIDER = 5, + HOLDER_TYPE_SUBTITLE = 6, + HOLDER_TYPE_TEXT_DIVIDER = 7, + HOLDER_TYPE_ADD_CHANNEL = 8, + HOLDER_TYPE_CHAT = 9, + HOLDER_TYPE_DATE_END = 10, + HOLDER_TYPE_PARTICIPANTS = 11, + HOLDER_TYPE_DURATION = 12, + HOLDER_TYPE_SUBTITLE_WITH_COUNTER = 13, + HOLDER_TYPE_SINGLE_BOOST_TYPE = 14; + + private final Theme.ResourcesProvider resourcesProvider; + private List items = new ArrayList<>(); + private RecyclerListView recyclerListView; + private SlideChooseView.Callback sliderCallback; + private ChatCell.ChatDeleteListener chatDeleteListener; + private HeaderCell headerCell; + + public BoostAdapter(Theme.ResourcesProvider resourcesProvider) { + this.resourcesProvider = resourcesProvider; + } + + public void setItems(List items, RecyclerListView recyclerListView, SlideChooseView.Callback sliderCallback, ChatCell.ChatDeleteListener chatDeleteListener) { + this.items = items; + this.recyclerListView = recyclerListView; + this.sliderCallback = sliderCallback; + this.chatDeleteListener = chatDeleteListener; + } + + public void updateBoostCounter(int value) { + for (int i = 0; i < recyclerListView.getChildCount(); ++i) { + View child = recyclerListView.getChildAt(i); + if (child instanceof SubtitleWithCounterCell) { + ((SubtitleWithCounterCell) child).updateCounter(true, value); + } + if (child instanceof ChatCell) { + ((ChatCell) child).setCounter(value); + } + } + //updates all prices + notifyItemChanged(items.size() - 1); + notifyItemChanged(items.size() - 2); + notifyItemChanged(items.size() - 3); + notifyItemChanged(items.size() - 4); + notifyItemChanged(items.size() - 6); + } + + public void setPausedStars(boolean paused) { + if (headerCell != null) { + headerCell.setPaused(paused); + } + } + + private RecyclerListView.Adapter realAdapter() { + return recyclerListView.getAdapter(); + } + + @Override + public void notifyItemChanged(int position) { + realAdapter().notifyItemChanged(position + 1); + } + + @Override + public void notifyItemChanged(int position, @Nullable Object payload) { + realAdapter().notifyItemChanged(position + 1, payload); + } + + @Override + public void notifyItemInserted(int position) { + realAdapter().notifyItemInserted(position + 1); + } + + @Override + public void notifyItemMoved(int fromPosition, int toPosition) { + realAdapter().notifyItemMoved(fromPosition + 1, toPosition); + } + + @Override + public void notifyItemRangeChanged(int positionStart, int itemCount) { + realAdapter().notifyItemRangeChanged(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { + realAdapter().notifyItemRangeChanged(positionStart + 1, itemCount, payload); + } + + @Override + public void notifyItemRangeInserted(int positionStart, int itemCount) { + realAdapter().notifyItemRangeInserted(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRangeRemoved(int positionStart, int itemCount) { + realAdapter().notifyItemRangeRemoved(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRemoved(int position) { + realAdapter().notifyItemRemoved(position + 1); + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void notifyDataSetChanged() { + realAdapter().notifyDataSetChanged(); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + int itemViewType = holder.getItemViewType(); + return itemViewType == HOLDER_TYPE_BOOST_TYPE + || itemViewType == HOLDER_TYPE_PARTICIPANTS + || itemViewType == HOLDER_TYPE_ADD_CHANNEL + || itemViewType == HOLDER_TYPE_DATE_END + || itemViewType == HOLDER_TYPE_DURATION; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + default: + case HOLDER_TYPE_HEADER: + view = new HeaderCell(context, resourcesProvider); + break; + case HOLDER_TYPE_BOOST_TYPE: + view = new BoostTypeCell(context, resourcesProvider); + break; + case HOLDER_TYPE_SINGLE_BOOST_TYPE: + view = new BoostTypeSingleCell(context, resourcesProvider); + break; + case HOLDER_TYPE_EMPTY: + view = new View(context); + break; + case HOLDER_TYPE_SIMPLE_DIVIDER: + view = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + break; + case HOLDER_TYPE_TEXT_DIVIDER: + view = new TextInfoCell(context, resourcesProvider); + break; + case HOLDER_TYPE_ADD_CHANNEL: + view = new AddChannelCell(context, resourcesProvider); + break; + case HOLDER_TYPE_SLIDER: + view = new SliderCell(context, resourcesProvider); + break; + case HOLDER_TYPE_SUBTITLE: + view = new org.telegram.ui.Cells.HeaderCell(context, resourcesProvider); + view.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + break; + case HOLDER_TYPE_SUBTITLE_WITH_COUNTER: + view = new SubtitleWithCounterCell(context, resourcesProvider); + view.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + break; + case HOLDER_TYPE_CHAT: + view = new ChatCell(context, resourcesProvider); + break; + case HOLDER_TYPE_DATE_END: + view = new DateEndCell(context, resourcesProvider); + break; + case HOLDER_TYPE_PARTICIPANTS: + view = new ParticipantsTypeCell(context, resourcesProvider); + break; + case HOLDER_TYPE_DURATION: + view = new DurationCell(context, resourcesProvider); + break; + } + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + final int viewType = holder.getItemViewType(); + final BoostAdapter.Item item = items.get(position); + switch (viewType) { + case HOLDER_TYPE_HEADER: { + headerCell = (HeaderCell) holder.itemView; + headerCell.setBoostViaGifsText(); + break; + } + case HOLDER_TYPE_BOOST_TYPE: { + BoostTypeCell cell = (BoostTypeCell) holder.itemView; + cell.setType(item.subType, item.intValue, (TLRPC.User) item.user, item.selectable); + break; + } + case HOLDER_TYPE_SINGLE_BOOST_TYPE: { + BoostTypeSingleCell cell = (BoostTypeSingleCell) holder.itemView; + cell.setGiveaway((TL_stories.TL_prepaidGiveaway) item.user); + break; + } + case HOLDER_TYPE_SLIDER: { + SliderCell cell = (SliderCell) holder.itemView; + cell.setValues(item.values, item.intValue); + cell.setCallBack(sliderCallback); + break; + } + case HOLDER_TYPE_SUBTITLE_WITH_COUNTER: { + SubtitleWithCounterCell cell = (SubtitleWithCounterCell) holder.itemView; + cell.setText(item.text); + cell.updateCounter(false, item.intValue); + break; + } + case HOLDER_TYPE_SUBTITLE: { + org.telegram.ui.Cells.HeaderCell cell = (org.telegram.ui.Cells.HeaderCell) holder.itemView; + cell.setText(item.text); + break; + } + case HOLDER_TYPE_TEXT_DIVIDER: { + TextInfoCell cell = (TextInfoCell) holder.itemView; + cell.setText(item.text); + cell.setBackground(item.boolValue); + break; + } + case HOLDER_TYPE_CHAT: { + ChatCell cell = (ChatCell) holder.itemView; + if (item.peer != null) { + TLRPC.InputPeer peer = item.peer; + if (peer instanceof TLRPC.TL_inputPeerChat) { + cell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.chat_id), item.intValue, item.boolValue); + } else if (peer instanceof TLRPC.TL_inputPeerChannel) { + cell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.channel_id), item.intValue, item.boolValue); + } + } else { + cell.setChat(item.chat, item.intValue, item.boolValue); + } + cell.setChatDeleteListener(chatDeleteListener); + break; + } + case HOLDER_TYPE_PARTICIPANTS: { + ParticipantsTypeCell cell = (ParticipantsTypeCell) holder.itemView; + cell.setType(item.subType, item.selectable, item.boolValue, (List) item.user); + break; + } + case HOLDER_TYPE_DATE_END: { + DateEndCell cell = (DateEndCell) holder.itemView; + cell.setDate(item.longValue); + break; + } + case HOLDER_TYPE_DURATION: { + DurationCell cell = (DurationCell) holder.itemView; + cell.setDuration(item.object, item.intValue, item.intValue2, item.longValue, item.text, item.boolValue, item.selectable); + break; + } + case HOLDER_TYPE_SIMPLE_DIVIDER: { + break; + } + } + } + + @Override + public int getItemViewType(int position) { + return items.get(position).viewType; + } + + @Override + public int getItemCount() { + return items.size(); + } + + public static class Item extends AdapterWithDiffUtils.Item { + public CharSequence text; + public TLRPC.InputPeer peer; + public TLRPC.Chat chat; + public Object user; + public boolean boolValue; + public long longValue; + public int intValue; + public int intValue2; + public int intValue3; + public List values; + public float floatValue; + public int subType; + public Object object; + + private Item(int viewType, boolean selectable) { + super(viewType, selectable); + } + + public static Item asHeader() { + return new Item(HOLDER_TYPE_HEADER, false); + } + + public static Item asDivider() { + return new Item(HOLDER_TYPE_SIMPLE_DIVIDER, false); + } + + public static Item asDivider(CharSequence text, boolean onlyTopDivider) { + Item item = new Item(HOLDER_TYPE_TEXT_DIVIDER, false); + item.text = text; + item.boolValue = onlyTopDivider; + return item; + } + + public static Item asChat(TLRPC.Chat chat, boolean removable, int count) { + Item item = new Item(HOLDER_TYPE_CHAT, false); + item.chat = chat; + item.peer = null; + item.boolValue = removable; + item.intValue = count; + return item; + } + + public static Item asPeer(TLRPC.InputPeer peer, boolean removable, int count) { + Item item = new Item(HOLDER_TYPE_CHAT, false); + item.peer = peer; + item.chat = null; + item.boolValue = removable; + item.intValue = count; + return item; + } + + public static Item asSingleBoost(Object user) { + Item item = new Item(HOLDER_TYPE_SINGLE_BOOST_TYPE, false); + item.user = user; + return item; + } + + public static Item asBoost(int subType, int count, Object user, int selectedSubType) { + Item item = new Item(HOLDER_TYPE_BOOST_TYPE, selectedSubType == subType); + item.subType = subType; + item.intValue = count; + item.user = user; + return item; + } + + public static Item asDateEnd(long time) { + Item item = new Item(HOLDER_TYPE_DATE_END, false); + item.longValue = time; + return item; + } + + public static Item asSlider(List values, int selected) { + Item item = new Item(HOLDER_TYPE_SLIDER, false); + item.values = values; + item.intValue = selected; + return item; + } + + public static Item asAddChannel() { + return new Item(HOLDER_TYPE_ADD_CHANNEL, false); + } + + public static Item asSubTitle(CharSequence text) { + Item item = new Item(HOLDER_TYPE_SUBTITLE, false); + item.text = text; + return item; + } + + public static Item asSubTitleWithCounter(CharSequence text, int counter) { + Item item = new Item(HOLDER_TYPE_SUBTITLE_WITH_COUNTER, false); + item.text = text; + item.intValue = counter; + return item; + } + + public static Item asDuration(Object code, int months, int count, long price, int selectedMonths, String currency, boolean needDivider) { + Item item = new Item(HOLDER_TYPE_DURATION, months == selectedMonths); + item.intValue = months; + item.intValue2 = count; + item.longValue = price; + item.boolValue = needDivider; + item.text = currency; + item.object = code; + return item; + } + + public static Item asParticipants(int subType, int selectedSubType, boolean needDivider, List countries) { + Item item = new Item(HOLDER_TYPE_PARTICIPANTS, selectedSubType == subType); + item.subType = subType; + item.boolValue = needDivider; + item.user = countries; + return item; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Item i = (Item) o; + if (viewType != i.viewType) { + return false; + } + if (chat != i.chat || user != i.user || peer != i.peer || object != i.object + || boolValue != i.boolValue + || values != i.values + || intValue != i.intValue || intValue2 != i.intValue2 || intValue3 != i.intValue3 + || longValue != i.longValue + || subType != i.subType + || floatValue != i.floatValue + || !TextUtils.equals(text, i.text)) { + return false; + } + return true; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java new file mode 100644 index 000000000..1b1984574 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/GiftInfoAdapter.java @@ -0,0 +1,245 @@ +package org.telegram.ui.Components.Premium.boosts.adapters; + +import static org.telegram.tgnet.TLRPC.TL_payments_checkedGiftCode.NO_USER_ID; + +import android.content.Context; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.SendMessagesHelper; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.Premium.boosts.cells.ActionBtnCell; +import org.telegram.ui.Components.Premium.boosts.cells.HeaderCell; +import org.telegram.ui.Components.Premium.boosts.cells.LinkCell; +import org.telegram.ui.Components.Premium.boosts.cells.TableCell; +import org.telegram.ui.Components.Premium.boosts.cells.TextInfoCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.DialogsActivity; + +import java.util.Date; + +public abstract class GiftInfoAdapter extends RecyclerListView.SelectionAdapter { + + public static final int + HOLDER_TYPE_HEADER = 0, + HOLDER_TYPE_LINK = 1, + HOLDER_TYPE_TABLE = 2, + HOLDER_TYPE_TEXT = 3, + HOLDER_TYPE_BUTTON = 4, + HOLDER_TYPE_EMPTY = 5; + + private final Theme.ResourcesProvider resourcesProvider; + private boolean isUnused; + private BaseFragment baseFragment; + private TLRPC.TL_payments_checkedGiftCode giftCode; + private String slug; + + public GiftInfoAdapter(Theme.ResourcesProvider resourcesProvider) { + this.resourcesProvider = resourcesProvider; + } + + public void init(BaseFragment baseFragment, TLRPC.TL_payments_checkedGiftCode giftCode, String slug) { + this.isUnused = giftCode.used_date == 0; + this.baseFragment = baseFragment; + this.giftCode = giftCode; + this.slug = slug; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @Override + public int getItemViewType(int position) { + switch (position) { + case 0: + return HOLDER_TYPE_HEADER; + case 1: + return HOLDER_TYPE_LINK; + case 2: + return HOLDER_TYPE_TABLE; + case 3: + return HOLDER_TYPE_TEXT; + case 4: + return HOLDER_TYPE_BUTTON; + } + return HOLDER_TYPE_EMPTY; + } + + protected abstract void dismiss(); + + protected abstract void afterCodeApplied(); + + protected abstract void onObjectClicked(TLObject object); + + protected abstract void onHiddenLinkClicked(); + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + default: + case HOLDER_TYPE_HEADER: + view = new HeaderCell(context, resourcesProvider); + break; + case HOLDER_TYPE_LINK: + view = new LinkCell(context, baseFragment, resourcesProvider); + break; + case HOLDER_TYPE_TABLE: + view = new TableCell(context, resourcesProvider); + break; + case HOLDER_TYPE_TEXT: + view = new TextInfoCell(context, resourcesProvider); + break; + case HOLDER_TYPE_BUTTON: + view = new ActionBtnCell(context, resourcesProvider); + break; + case HOLDER_TYPE_EMPTY: + view = new View(context); + } + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + final int viewType = holder.getItemViewType(); + switch (viewType) { + case HOLDER_TYPE_HEADER: { + HeaderCell cell = (HeaderCell) holder.itemView; + if (isUnused) { + cell.setGiftLinkText(); + } else { + cell.setUsedGiftLinkText(); + } + if (giftCode.boost != null) { + cell.setGiftLinkToUserText(giftCode.to_id, this::onObjectClicked); + } + if (giftCode.to_id == NO_USER_ID) { + cell.setUnclaimedText(); + } + break; + } + case HOLDER_TYPE_LINK: { + LinkCell cell = (LinkCell) holder.itemView; + cell.setSlug(slug); + if (giftCode.boost != null) { + cell.hideSlug(this::onHiddenLinkClicked); + } + break; + } + case HOLDER_TYPE_TABLE: { + TableCell cell = (TableCell) holder.itemView; + cell.setData(giftCode, this::onObjectClicked); + break; + } + case HOLDER_TYPE_TEXT: { + TextInfoCell cell = (TextInfoCell) holder.itemView; + cell.setTextGravity(Gravity.CENTER); + cell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + cell.setTopPadding(14); + cell.setBottomPadding(15); + + if (giftCode.boost != null) { + if (slug == null || slug.isEmpty()) { + //not activated link + cell.setText(LocaleController.getString("BoostingLinkNotActivated", R.string.BoostingLinkNotActivated)); + } else { + //activated link + cell.setText(""); + } + return; + } + + if (isUnused) { + SpannableStringBuilder text = AndroidUtilities.replaceSingleTag( + giftCode.to_id == NO_USER_ID ? + LocaleController.getString("BoostingSendLinkToAnyone", R.string.BoostingSendLinkToAnyone) + : LocaleController.getString("BoostingSendLinkToFriends", R.string.BoostingSendLinkToFriends), + Theme.key_chat_messageLinkIn, 0, + () -> { + final String slugLink = "https://t.me/giftcode/" + slug; + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_FORWARD); + DialogsActivity dialogFragment = new DialogsActivity(args); + dialogFragment.setDelegate((fragment1, dids, message, param, topicsFragment) -> { + long did = 0; + for (int a = 0; a < dids.size(); a++) { + did = dids.get(a).dialogId; + baseFragment.getSendMessagesHelper().sendMessage(SendMessagesHelper.SendMessageParams.of(slugLink, did, null, null, null, true, null, null, null, true, 0, null, false)); + } + fragment1.finishFragment(); + BoostDialogs.showGiftLinkForwardedBulletin(did); + return true; + }); + baseFragment.presentFragment(dialogFragment); + dismiss(); + }, + resourcesProvider + ); + cell.setText(text); + } else { + Date date = new Date(giftCode.used_date * 1000L); + String monthTxt = LocaleController.getInstance().formatterYear.format(date); + String timeTxt = LocaleController.getInstance().formatterDay.format(date); + String fullDateStr = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, monthTxt, timeTxt); + cell.setText(LocaleController.formatString("BoostingUsedLinkDate", R.string.BoostingUsedLinkDate, fullDateStr)); + } + break; + } + case HOLDER_TYPE_BUTTON: { + ActionBtnCell cell = (ActionBtnCell) holder.itemView; + cell.setOkStyle(isUnused); + cell.setOnClickListener(v -> { + if (isUnused) { + if (cell.isLoading()) { + return; + } + cell.updateLoading(true); + BoostRepository.applyGiftCode(slug, result -> { + cell.updateLoading(false); + afterCodeApplied(); + dismiss(); + }, error -> { + cell.updateLoading(false); + BoostDialogs.showToastError(baseFragment.getContext(), error); + }); + } else { + dismiss(); + } + }); + if (giftCode.boost != null || giftCode.to_id == NO_USER_ID) { + cell.setCloseStyle(); + cell.setOnClickListener(v -> dismiss()); + } + break; + } + default: { + + } + } + } + + @Override + public int getItemCount() { + return 5; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java new file mode 100644 index 000000000..779097aee --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/adapters/SelectorAdapter.java @@ -0,0 +1,302 @@ +package org.telegram.ui.Components.Premium.boosts.adapters; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Color; +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.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorCountryCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorLetterCell; +import org.telegram.ui.Components.Premium.boosts.cells.selector.SelectorUserCell; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.StickerEmptyView; + +import java.util.List; + +public class SelectorAdapter extends AdapterWithDiffUtils { + + public static final int VIEW_TYPE_PAD = -1; + public static final int VIEW_TYPE_USER = 3; + public static final int VIEW_TYPE_NO_USERS = 5; + public static final int VIEW_TYPE_COUNTRY = 6; + public static final int VIEW_TYPE_LETTER = 7; + + private final Theme.ResourcesProvider resourcesProvider; + private final Context context; + private final boolean reversedLayout = false; + private RecyclerListView listView; + private List items; + + public SelectorAdapter(Context context, Theme.ResourcesProvider resourcesProvider) { + this.context = context; + this.resourcesProvider = resourcesProvider; + } + + public void setData(List items, RecyclerListView listView) { + this.items = items; + this.listView = listView; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return (holder.getItemViewType() == VIEW_TYPE_USER || holder.getItemViewType() == VIEW_TYPE_COUNTRY); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + if (viewType == VIEW_TYPE_PAD) { + view = new View(context); + } else if (viewType == VIEW_TYPE_USER) { + view = new SelectorUserCell(context, resourcesProvider, false); + } else if (viewType == VIEW_TYPE_NO_USERS) { + StickerEmptyView searchEmptyView = new StickerEmptyView(context, null, StickerEmptyView.STICKER_TYPE_SEARCH, resourcesProvider); + searchEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + searchEmptyView.subtitle.setText(LocaleController.getString("SearchEmptyViewFilteredSubtitle2", R.string.SearchEmptyViewFilteredSubtitle2)); + searchEmptyView.linearLayout.setTranslationY(AndroidUtilities.dp(24)); + view = searchEmptyView; + } else if (viewType == VIEW_TYPE_LETTER) { + view = new SelectorLetterCell(context, resourcesProvider); + } else if (viewType == VIEW_TYPE_COUNTRY) { + view = new SelectorCountryCell(context, resourcesProvider); + } else { + view = new View(context); + } + return new RecyclerListView.Holder(view); + } + + public int getParticipantsCount(TLRPC.Chat chat) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(UserConfig.selectedAccount).getChatFull(chat.id); + if (chatFull != null && chatFull.participants_count > 0) { + return chatFull.participants_count; + } + return chat.participants_count; + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (items == null || position < 0) { + return; + } + final Item item = items.get(position); + final int viewType = holder.getItemViewType(); + if (viewType == VIEW_TYPE_USER) { + SelectorUserCell userCell = (SelectorUserCell) holder.itemView; + if (item.user != null) { + userCell.setUser(item.user); + } else if (item.chat != null) { + userCell.setChat(item.chat, getParticipantsCount(item.chat)); + } else if (item.peer != null) { + TLRPC.InputPeer peer = item.peer; + if (peer instanceof TLRPC.TL_inputPeerSelf) { + userCell.setUser(UserConfig.getInstance(UserConfig.selectedAccount).getCurrentUser()); + } else if (peer instanceof TLRPC.TL_inputPeerUser) { + userCell.setUser(MessagesController.getInstance(UserConfig.selectedAccount).getUser(peer.user_id)); + } else if (peer instanceof TLRPC.TL_inputPeerChat) { + userCell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.chat_id), 0); + } else if (peer instanceof TLRPC.TL_inputPeerChannel) { + userCell.setChat(MessagesController.getInstance(UserConfig.selectedAccount).getChat(peer.channel_id), 0); + } + } + userCell.setChecked(item.checked, false); + userCell.setCheckboxAlpha(1f, false); + userCell.setDivider(position < items.size() - 2); + } else if (viewType == VIEW_TYPE_COUNTRY) { + SelectorCountryCell cell = (SelectorCountryCell) holder.itemView; + boolean needDivider = (position < items.size() - 2) && (position + 1 < items.size() - 2) && (items.get(position + 1).viewType != VIEW_TYPE_LETTER); + cell.setCountry(item.country, needDivider); + cell.setChecked(item.checked, false); + } else if (viewType == VIEW_TYPE_PAD) { + int height; + if (item.padHeight >= 0) { + height = item.padHeight; + } else { + height = (int) (AndroidUtilities.displaySize.y * .3f); + } + holder.itemView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, height)); + } else if (viewType == VIEW_TYPE_LETTER) { + SelectorLetterCell cell = (SelectorLetterCell) holder.itemView; + cell.setLetter(item.text); + } else if (viewType == VIEW_TYPE_NO_USERS) { + try { + ((StickerEmptyView) holder.itemView).stickerView.getImageReceiver().startAnimation(); + } catch (Exception ignore) { + } + } + } + + @Override + public int getItemViewType(int position) { + if (items == null || position < 0) { + return VIEW_TYPE_PAD; + } + return items.get(position).viewType; + } + + @Override + public int getItemCount() { + return items == null ? 0 : items.size(); + } + + private RecyclerListView.Adapter realAdapter() { + return listView.getAdapter(); + } + + @Override + public void notifyItemChanged(int position) { + realAdapter().notifyItemChanged(position + 1); + } + + @Override + public void notifyItemChanged(int position, @Nullable Object payload) { + realAdapter().notifyItemChanged(position + 1, payload); + } + + @Override + public void notifyItemInserted(int position) { + realAdapter().notifyItemInserted(position + 1); + } + + @Override + public void notifyItemMoved(int fromPosition, int toPosition) { + realAdapter().notifyItemMoved(fromPosition + 1, toPosition); + } + + @Override + public void notifyItemRangeChanged(int positionStart, int itemCount) { + realAdapter().notifyItemRangeChanged(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) { + realAdapter().notifyItemRangeChanged(positionStart + 1, itemCount, payload); + } + + @Override + public void notifyItemRangeInserted(int positionStart, int itemCount) { + realAdapter().notifyItemRangeInserted(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRangeRemoved(int positionStart, int itemCount) { + realAdapter().notifyItemRangeRemoved(positionStart + 1, itemCount); + } + + @Override + public void notifyItemRemoved(int position) { + realAdapter().notifyItemRemoved(position + 1); + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void notifyDataSetChanged() { + realAdapter().notifyDataSetChanged(); + } + + public void notifyChangedLast() { + if (items == null || items.isEmpty()) { + return; + } + notifyItemChanged(items.size() - 1); + } + + public static class Item extends AdapterWithDiffUtils.Item { + public TLRPC.User user; + public TLRPC.InputPeer peer; + public TLRPC.Chat chat; + public TLRPC.TL_help_country country; + public String text; + public int type; + public boolean checked; + public int padHeight = -1; + + private Item(int viewType, boolean selectable) { + super(viewType, selectable); + } + + public static Item asPad(int padHeight) { + Item item = new Item(VIEW_TYPE_PAD, false); + item.padHeight = padHeight; + return item; + } + + public static Item asUser(TLRPC.User user, boolean checked) { + Item item = new Item(VIEW_TYPE_USER, true); + item.user = user; + item.peer = null; + item.chat = null; + item.checked = checked; + return item; + } + + public static Item asLetter(String letter) { + Item item = new Item(VIEW_TYPE_LETTER, false); + item.text = letter; + return item; + } + + public static Item asCountry(TLRPC.TL_help_country tlHelpCountry, boolean checked) { + Item item = new Item(VIEW_TYPE_COUNTRY, true); + item.country = tlHelpCountry; + item.checked = checked; + return item; + } + + public static Item asPeer(TLRPC.InputPeer peer, boolean checked) { + Item item = new Item(VIEW_TYPE_USER, true); + item.peer = peer; + item.user = null; + item.chat = null; + item.checked = checked; + return item; + } + + public static Item asChat(TLRPC.Chat chat, boolean checked) { + Item item = new Item(VIEW_TYPE_USER, true); + item.chat = chat; + item.user = null; + item.peer = null; + item.checked = checked; + return item; + } + + public static Item asNoUsers() { + return new Item(VIEW_TYPE_NO_USERS, false); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Item i = (Item) o; + if (viewType != i.viewType) { + return false; + } + if (viewType == VIEW_TYPE_PAD && (padHeight != i.padHeight)) { + return false; + } else if (viewType == VIEW_TYPE_USER && (user != i.user || chat != i.chat || peer != i.peer || type != i.type || checked != i.checked)) { + return false; + } else if (viewType == VIEW_TYPE_COUNTRY && (country != i.country || checked != i.checked)) { + return false; + } else if (viewType == VIEW_TYPE_LETTER && (!TextUtils.equals(text, i.text))) { + return false; + } + return true; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ActionBtnCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ActionBtnCell.java new file mode 100644 index 000000000..d6626d363 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ActionBtnCell.java @@ -0,0 +1,102 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +@SuppressLint("ViewConstructor") +public class ActionBtnCell extends FrameLayout { + + private final ButtonWithCounterView button; + private final View backgroundView; + private final Theme.ResourcesProvider resourcesProvider; + private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private boolean drawDivider; + + public ActionBtnCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + backgroundView = new View(context); + addView(backgroundView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + button = new ButtonWithCounterView(context, resourcesProvider); + + addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER, 14, 0, 14, 0)); + } + + @Override + public void setOnClickListener(@Nullable OnClickListener l) { + button.setOnClickListener(l); + } + + public void setStartGiveAwayStyle(int counter, boolean animated) { + drawDivider = true; + button.withCounterIcon(); + button.setShowZero(true); + button.setEnabled(true); + button.setCount(counter, animated); + button.setText(LocaleController.formatString("BoostingStartGiveaway", R.string.BoostingStartGiveaway), animated); + backgroundView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + } + + public void setGiftPremiumStyle(int counter, boolean animated, boolean isEnabled) { + drawDivider = true; + button.withCounterIcon(); + button.setShowZero(true); + button.setEnabled(isEnabled); + button.setCount(counter, animated); + button.setText(LocaleController.formatString("GiftPremium", R.string.GiftPremium), animated); + backgroundView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (drawDivider) { + dividerPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + dividerPaint.setAlpha(255); + canvas.drawRect(0, 0, getWidth(), 1, dividerPaint); + } + } + + public void updateLoading(boolean isLoading) { + button.setLoading(isLoading); + } + + public boolean isLoading() { + return button.isLoading(); + } + + public void updateCounter(int count) { + button.setCount(count, true); + } + + public void setOkStyle(boolean isUsed) { + drawDivider = false; + button.setShowZero(false); + button.setEnabled(true); + String text = isUsed ? LocaleController.formatString("BoostingUseLink", R.string.BoostingUseLink) : LocaleController.formatString("OK", R.string.OK); + button.setText(text, false); + } + + public void setCloseStyle(){ + drawDivider = false; + button.setShowZero(false); + button.setEnabled(true); + button.setText(LocaleController.formatString("Close", R.string.Close), false); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/AddChannelCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/AddChannelCell.java new file mode 100644 index 000000000..29ecda88b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/AddChannelCell.java @@ -0,0 +1,76 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CombinedDrawable; + +@SuppressLint("ViewConstructor") +public class AddChannelCell extends FrameLayout { + + private final SimpleTextView textView; + private final ImageView imageView; + private final Theme.ResourcesProvider resourcesProvider; + + public AddChannelCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + textView = new SimpleTextView(context); + textView.setTextSize(16); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); + textView.setTag(Theme.key_windowBackgroundWhiteBlueHeader); + addView(textView); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + addView(imageView); + + textView.setText(LocaleController.getString("BoostingAddChannel", R.string.BoostingAddChannel)); + + Drawable drawable1 = getResources().getDrawable(R.drawable.poll_add_circle); + Drawable drawable2 = getResources().getDrawable(R.drawable.poll_add_plus); + drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked, resourcesProvider), PorterDuff.Mode.MULTIPLY)); + drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_checkboxCheck, resourcesProvider), PorterDuff.Mode.MULTIPLY)); + CombinedDrawable combinedDrawable = new CombinedDrawable(drawable1, drawable2); + imageView.setImageDrawable(combinedDrawable); + setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + 23), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(50), MeasureSpec.EXACTLY)); + setMeasuredDimension(width, AndroidUtilities.dp(50)); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int height = bottom - top; + int width = right - left; + + int viewLeft; + int viewTop = (height - textView.getTextHeight()) / 2; + if (LocaleController.isRTL) { + viewLeft = getMeasuredWidth() - textView.getMeasuredWidth() - AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 68 : 23); + } else { + viewLeft = AndroidUtilities.dp(imageView.getVisibility() == VISIBLE ? 68 : 23); + } + textView.layout(viewLeft, viewTop, viewLeft + textView.getMeasuredWidth(), viewTop + textView.getMeasuredHeight()); + + viewLeft = !LocaleController.isRTL ? AndroidUtilities.dp(24) : width - imageView.getMeasuredWidth() - AndroidUtilities.dp(24); + imageView.layout(viewLeft, 0, viewLeft + imageView.getMeasuredWidth(), imageView.getMeasuredHeight()); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BaseCell.java new file mode 100644 index 000000000..5d0b6a691 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BaseCell.java @@ -0,0 +1,194 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +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.RadioButton; +import org.telegram.ui.Components.RecyclerListView; + +@SuppressLint("ViewConstructor") +public abstract class BaseCell extends FrameLayout { + + protected final Theme.ResourcesProvider resourcesProvider; + + protected final AvatarDrawable avatarDrawable = new AvatarDrawable(); + protected final BackupImageView imageView; + + protected final SimpleTextView titleTextView; + protected final SimpleTextView subtitleTextView; + + protected final RadioButton radioButton; + + protected final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + protected boolean needDivider; + protected View backgroundView; + + public BaseCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + backgroundView = new View(context); + addView(backgroundView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + backgroundView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + + avatarDrawable.setRoundRadius(AndroidUtilities.dp(40)); + + imageView = new BackupImageView(context); + imageView.setRoundRadius(AndroidUtilities.dp(20)); + addView(imageView); + + titleTextView = new SimpleTextView(context) { + @Override + public boolean setText(CharSequence value) { + value = Emoji.replaceEmoji(value, getPaint().getFontMetricsInt(), AndroidUtilities.dp(15), false); + return super.setText(value); + } + }; + NotificationCenter.listenEmojiLoading(titleTextView); + NotificationCenter.listenEmojiLoading(imageView); + titleTextView.setTextSize(16); + titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(titleTextView); + + subtitleTextView = new SimpleTextView(context); + subtitleTextView.setTextSize(14); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + subtitleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(subtitleTextView); + + radioButton = new RadioButton(context); + radioButton.setSize(AndroidUtilities.dp(20)); + radioButton.setColor(Theme.getColor(Theme.key_checkboxDisabled, resourcesProvider), Theme.getColor(Theme.key_dialogRadioBackgroundChecked, resourcesProvider)); + addView(radioButton); + + updateLayouts(); + + if (!needCheck()) { + radioButton.setVisibility(View.GONE); + } + } + + protected abstract boolean needCheck(); + + protected void updateLayouts() { + imageView.setLayoutParams(LayoutHelper.createFrame(40, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), needCheck() ? 53 : 16, 0, needCheck() ? 53 : 16, 0)); + titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (needCheck() ? 105 : 70), 0, LocaleController.isRTL ? (needCheck() ? 105 : 70) : 20, 0)); + subtitleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (needCheck() ? 105 : 70), 0, LocaleController.isRTL ? (needCheck() ? 105 : 70) : 20, 0)); + radioButton.setLayoutParams(LayoutHelper.createFrame(22, 22, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 15 : 20, 0, LocaleController.isRTL ? 20 : 15, 0)); + } + + public void setChecked(boolean checked, boolean animated) { + if (radioButton.getVisibility() == View.VISIBLE) { + radioButton.setChecked(checked, animated); + } + } + + public void markChecked(RecyclerListView recyclerListView) { + if (!needCheck()) { + return; + } + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + View child = recyclerListView.getChildAt(i); + if (child.getClass().isInstance(this)) { + BaseCell cell = (BaseCell) child; + cell.setChecked(child == this, true); + } + } + } + + protected CharSequence withArrow(CharSequence text) { + SpannableString arrow = new SpannableString(">"); + Drawable arrowDrawable = getContext().getResources().getDrawable(R.drawable.attach_arrow_right); + ColoredImageSpan span = new ColoredImageSpan(arrowDrawable, ColoredImageSpan.ALIGN_CENTER); + arrowDrawable.setBounds(0, dp(1), dp(11), dp(1 + 11)); + arrow.setSpan(span, 0, arrow.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + SpannableStringBuilder finalText = new SpannableStringBuilder(); + finalText.append(text).append(" ").append(arrow); + return finalText; + } + + protected void setSubtitle(CharSequence text) { + if (text == null) { + titleTextView.setTranslationY(0); + subtitleTextView.setVisibility(View.GONE); + } else { + titleTextView.setTranslationY(AndroidUtilities.dp(-9)); + subtitleTextView.setTranslationY(AndroidUtilities.dp(12)); + subtitleTextView.setText(text); + subtitleTextView.setVisibility(View.VISIBLE); + } + if (imageView.getVisibility() == GONE) { + if (LocaleController.isRTL) { + titleTextView.setTranslationX(AndroidUtilities.dp(40)); + subtitleTextView.setTranslationX(AndroidUtilities.dp(40)); + } else { + titleTextView.setTranslationX(AndroidUtilities.dp(-40)); + subtitleTextView.setTranslationX(AndroidUtilities.dp(-40)); + } + } + } + + public void setDivider(boolean divider) { + needDivider = divider; + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(getFullHeight()), MeasureSpec.EXACTLY) + ); + } + + protected int getFullHeight() { + return 56; + } + + protected int dividerPadding() { + return 0; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (needDivider) { + dividerPaint.setColor(Theme.getColor(Theme.key_divider, resourcesProvider)); + int paddingDp = needCheck() ? 105 : 70; + if (imageView.getVisibility() == GONE) { + paddingDp -= 40; + } + paddingDp += dividerPadding(); + if (LocaleController.isRTL) { + canvas.drawRect(0, getHeight() - 1, getWidth() - dp(paddingDp), getHeight(), dividerPaint); + } else { + canvas.drawRect(dp(paddingDp), getHeight() - 1, getWidth(), getHeight(), dividerPaint); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeCell.java new file mode 100644 index 000000000..a57dcdb79 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeCell.java @@ -0,0 +1,80 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class BoostTypeCell extends BaseCell { + + public static int TYPE_GIVEAWAY = 0; + public static int TYPE_SPECIFIC_USERS = 1; + + private int selectedType; + + public BoostTypeCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + } + + @Override + protected void updateLayouts() { + imageView.setLayoutParams(LayoutHelper.createFrame(40, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 57, 0, 57, 0)); + titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (109), 0, LocaleController.isRTL ? (109) : 20, 0)); + subtitleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (109), 0, LocaleController.isRTL ? (109) : 20, 0)); + radioButton.setLayoutParams(LayoutHelper.createFrame(22, 22, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 16, 0, 15, 0)); + } + + public int getSelectedType() { + return selectedType; + } + + @Override + protected boolean needCheck() { + return true; + } + + public void setType(int type, int count, TLRPC.User singleUser, boolean isSelected) { + selectedType = type; + if (type == TYPE_GIVEAWAY) { + titleTextView.setText(LocaleController.formatString("BoostingCreateGiveaway", R.string.BoostingCreateGiveaway)); + setSubtitle(LocaleController.formatString("BoostingWinnersRandomly", R.string.BoostingWinnersRandomly)); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_GIFT); + avatarDrawable.setColor(0xFF16A5F2, 0xFF1180F7); + setDivider(true); + setBackground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } else if (type == TYPE_SPECIFIC_USERS) { + titleTextView.setText(LocaleController.formatString("BoostingAwardSpecificUsers", R.string.BoostingAwardSpecificUsers)); + if (count == 1 && singleUser != null) { + CharSequence text = UserObject.getUserName(singleUser); + text = Emoji.replaceEmoji(text, subtitleTextView.getPaint().getFontMetricsInt(), false); + setSubtitle(withArrow(text)); + } else if (count > 0) { + setSubtitle(withArrow(LocaleController.formatPluralString("Recipient", count))); + } else { + setSubtitle(withArrow(LocaleController.getString("BoostingSelectRecipients", R.string.BoostingSelectRecipients))); + } + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2, resourcesProvider)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_FILTER_GROUPS); + avatarDrawable.setColor(0xFFC468F2, 0xFF965CFA); + setDivider(false); + setBackground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); + } + radioButton.setChecked(isSelected, false); + imageView.setImageDrawable(avatarDrawable); + imageView.setRoundRadius(dp(20)); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java new file mode 100644 index 000000000..5bbc92f80 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/BoostTypeSingleCell.java @@ -0,0 +1,52 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class BoostTypeSingleCell extends BoostTypeCell { + + public BoostTypeSingleCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + } + + public void setGiveaway(TL_stories.TL_prepaidGiveaway prepaidGiveaway) { + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_GIFT); + titleTextView.setText(LocaleController.formatString("BoostingPreparedGiveawayOne", R.string.BoostingPreparedGiveawayOne)); + String subtitle = LocaleController.formatString("BoostingPreparedGiveawaySubscriptions", R.string.BoostingPreparedGiveawaySubscriptions, prepaidGiveaway.quantity, LocaleController.formatPluralString("Months", prepaidGiveaway.months)); + setSubtitle(subtitle); + if (prepaidGiveaway.months == 12) { + avatarDrawable.setColor(0xFFff8560, 0xFFd55246); + } else if (prepaidGiveaway.months == 6) { + avatarDrawable.setColor(0xFF5caefa, 0xFF418bd0); + } else { + avatarDrawable.setColor(0xFF9ad164, 0xFF49ba44); + } + imageView.setImageDrawable(avatarDrawable); + imageView.setRoundRadius(dp(20)); + } + + @Override + protected void updateLayouts() { + imageView.setLayoutParams(LayoutHelper.createFrame(40, 40, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 16, 0, 16, 0)); + titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (69), 0, LocaleController.isRTL ? (69) : 20, 0)); + subtitleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : (69), 0, LocaleController.isRTL ? (69) : 20, 0)); + } + + @Override + protected boolean needCheck() { + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ChatCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ChatCell.java new file mode 100644 index 000000000..1c021a341 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ChatCell.java @@ -0,0 +1,86 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.view.Gravity; +import android.widget.ImageView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class ChatCell extends BaseCell { + + public interface ChatDeleteListener { + void onChatDeleted(TLRPC.Chat chat); + } + + private final ImageView deleteImageView; + private ChatDeleteListener chatDeleteListener; + private TLRPC.Chat chat; + + public ChatCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + deleteImageView = new ImageView(context); + deleteImageView.setFocusable(false); + deleteImageView.setScaleType(ImageView.ScaleType.CENTER); + deleteImageView.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + deleteImageView.setImageResource(R.drawable.poll_remove); + deleteImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); + deleteImageView.setContentDescription(LocaleController.getString("Delete", R.string.Delete)); + addView(deleteImageView, LayoutHelper.createFrame(48, 50, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER, LocaleController.isRTL ? 3 : 0, 0, LocaleController.isRTL ? 0 : 3, 0)); + titleTextView.setPadding(AndroidUtilities.dp(LocaleController.isRTL ? 24 : 0), 0, AndroidUtilities.dp(LocaleController.isRTL ? 0 : 24), 0); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + deleteImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); + } + + @Override + protected boolean needCheck() { + return false; + } + + public void setChat(TLRPC.Chat chat, int boosts, boolean removable) { + this.chat = chat; + avatarDrawable.setInfo(chat); + imageView.setRoundRadius(AndroidUtilities.dp(20)); + imageView.setForUserOrChat(chat, avatarDrawable); + + CharSequence text = chat.title; + text = Emoji.replaceEmoji(text, titleTextView.getPaint().getFontMetricsInt(), false); + titleTextView.setText(text); + + setSubtitle(LocaleController.formatPluralString("BoostingChannelWillReceiveBoost", boosts)); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + setDivider(true); + if (removable) { + deleteImageView.setVisibility(VISIBLE); + } else { + deleteImageView.setVisibility(INVISIBLE); + } + deleteImageView.setOnClickListener(v -> { + if (chatDeleteListener != null) { + chatDeleteListener.onChatDeleted(chat); + } + }); + } + + public void setChatDeleteListener(ChatDeleteListener chatDeleteListener) { + this.chatDeleteListener = chatDeleteListener; + } + + public void setCounter(int count) { + setSubtitle(LocaleController.formatPluralString("BoostingChannelWillReceiveBoost", count)); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DateEndCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DateEndCell.java new file mode 100644 index 000000000..9921627f8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DateEndCell.java @@ -0,0 +1,68 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.Date; + +@SuppressLint("ViewConstructor") +public class DateEndCell extends FrameLayout { + + private final Theme.ResourcesProvider resourcesProvider; + private final SimpleTextView titleTextView; + private final SimpleTextView timeTextView; + private long selectedTime; + + public DateEndCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + titleTextView = new SimpleTextView(context); + titleTextView.setTextSize(16); + titleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + addView(titleTextView); + + timeTextView = new SimpleTextView(context); + timeTextView.setTextSize(16); + timeTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); + timeTextView.setGravity(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); + addView(timeTextView); + titleTextView.setText(LocaleController.formatString("BoostingDateAndTime", R.string.BoostingDateAndTime)); + + titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 21, 0, LocaleController.isRTL ? 21 : 0, 0)); + timeTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), LocaleController.isRTL ? 21 : 0, 0, LocaleController.isRTL ? 0 : 21, 0)); + setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + } + + public void setDate(long time) { + selectedTime = time; + Date date = new Date(time); + String monthTxt = LocaleController.getInstance().formatterDayMonth.format(date); + String timeTxt = LocaleController.getInstance().formatterDay.format(date); + timeTextView.setText(LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, monthTxt, timeTxt)); + } + + public long getSelectedTime() { + return selectedTime; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY) + ); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DurationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DurationCell.java new file mode 100644 index 000000000..696e41633 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/DurationCell.java @@ -0,0 +1,54 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; + +import org.telegram.messenger.BillingController; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class DurationCell extends BaseCell { + + private final SimpleTextView totalTextView; + private Object code; + + public DurationCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + imageView.setVisibility(GONE); + + subtitleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4, resourcesProvider)); + totalTextView = new SimpleTextView(context); + totalTextView.setTextSize(16); + totalTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4, resourcesProvider)); + totalTextView.setGravity(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); + addView(totalTextView); + + totalTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), LocaleController.isRTL ? 20 : 0, 0, LocaleController.isRTL ? 0 : 20, 0)); + } + + public void setDuration(Object code, int months, int count, long price, CharSequence currency, boolean needDivider, boolean selected) { + this.code = code; + if (months >= 12) { + titleTextView.setText(LocaleController.formatPluralString("Years", 1)); + } else { + titleTextView.setText(LocaleController.formatPluralString("Months", months)); + } + setSubtitle(BillingController.getInstance().formatCurrency(count > 0 ? (price / count) : price, currency.toString()) + " x " + count); + totalTextView.setText(BillingController.getInstance().formatCurrency(count > 0 ? price : 0, currency.toString())); + setDivider(needDivider); + radioButton.setChecked(selected, false); + } + + public Object getGifCode() { + return code; + } + + @Override + protected boolean needCheck() { + return true; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/HeaderCell.java new file mode 100644 index 000000000..077e20d32 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/HeaderCell.java @@ -0,0 +1,232 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Outline; +import android.os.Build; +import android.os.Bundle; +import android.text.Html; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.method.LinkMovementMethod; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.core.text.HtmlCompat; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.SendMessagesHelper; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.AvatarDrawable; +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.StarParticlesView; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.DialogsActivity; +import org.telegram.ui.LaunchActivity; + +@SuppressLint("ViewConstructor") +public class HeaderCell extends FrameLayout { + + private final GLIconTextureView iconTextureView; + private final StarParticlesView starParticlesView; + private final TextView titleView; + private final LinkSpanDrawable.LinksTextView subtitleView; + private final Theme.ResourcesProvider resourcesProvider; + private final LinearLayout linearLayout; + private LinkSpanDrawable.LinkCollector links; + + public HeaderCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + iconTextureView = new GLIconTextureView(context, GLIconRenderer.DIALOG_STYLE) { + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + setPaused(false); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + setPaused(true); + } + }; + Bitmap bitmap = Bitmap.createBitmap(50, 50, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.drawColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_premiumGradient2, resourcesProvider), Theme.getColor(Theme.key_dialogBackground, resourcesProvider), 0.5f)); + iconTextureView.setBackgroundBitmap(bitmap); + iconTextureView.mRenderer.colorKey1 = Theme.key_premiumGradient2; + iconTextureView.mRenderer.colorKey2 = Theme.key_premiumGradient1; + iconTextureView.mRenderer.updateColors(); + linearLayout.addView(iconTextureView, LayoutHelper.createLinear(160, 160, Gravity.CENTER_HORIZONTAL)); + + starParticlesView = new StarParticlesView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + drawable.rect2.set(0, 0, getMeasuredWidth(), getMeasuredHeight() - AndroidUtilities.dp(52)); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + starParticlesView.setPaused(false); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + starParticlesView.setPaused(true); + } + }; + + starParticlesView.drawable.useGradient = true; + starParticlesView.drawable.useBlur = false; + starParticlesView.drawable.forceMaxAlpha = true; + starParticlesView.drawable.checkBounds = true; + starParticlesView.drawable.init(); + iconTextureView.setStarParticlesView(starParticlesView); + + titleView = new TextView(context); + titleView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + titleView.setGravity(Gravity.CENTER_HORIZONTAL); + + linearLayout.addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 24, -8, 24, 0)); + + subtitleView = new LinkSpanDrawable.LinksTextView(context, links = new LinkSpanDrawable.LinkCollector(this), resourcesProvider); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + subtitleView.setGravity(Gravity.CENTER); + subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + subtitleView.setMovementMethod(LinkMovementMethod.getInstance()); + subtitleView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); + subtitleView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + linearLayout.addView(subtitleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 24, 8, 24, 18)); + + setClipChildren(false); + addView(starParticlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 234, Gravity.TOP)); + addView(linearLayout); + setWillNotDraw(false); + } + + public void setBoostViaGifsText() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + 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); + } + }); + setClipToOutline(true); + } + MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); + lp.topMargin = -AndroidUtilities.dp(6); + setLayoutParams(lp); + setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + titleView.setText(LocaleController.formatString("BoostingBoostsViaGifts", R.string.BoostingBoostsViaGifts)); + subtitleView.setText(LocaleController.formatString("BoostingGetMoreBoost", R.string.BoostingGetMoreBoost)); + subtitleView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + } + + public void setUsedGiftLinkText() { + titleView.setText(LocaleController.formatString("BoostingUsedGiftLink", R.string.BoostingUsedGiftLink)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingLinkUsed", R.string.BoostingLinkUsed))); + } + + public void setGiftLinkText() { + titleView.setText(LocaleController.formatString("BoostingGiftLink", R.string.BoostingGiftLink)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingLinkAllows", R.string.BoostingLinkAllows))); + } + + public void setUnclaimedText() { + titleView.setText(LocaleController.formatString("BoostingGiftLink", R.string.BoostingGiftLink)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingLinkAllowsAnyone", R.string.BoostingLinkAllowsAnyone))); + } + + public void setGiftLinkToUserText(long toUserId, Utilities.Callback onObjectClicked) { + titleView.setText(LocaleController.formatString("BoostingGiftLink", R.string.BoostingGiftLink)); + + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); + try { + String description = LocaleController.getString("BoostingLinkAllowsToUser", R.string.BoostingLinkAllowsToUser); + CharSequence descriptionStart = description.substring(0, description.indexOf("**%1s**") + 7); + CharSequence descriptionEnd = description.substring(description.indexOf("**%1s**") + 7); + + TLRPC.User toUser = MessagesController.getInstance(UserConfig.selectedAccount).getUser(toUserId); + SpannableStringBuilder userName = new SpannableStringBuilder(); + userName.append("**"); + userName.append(Emoji.replaceEmoji(UserObject.getUserName(toUser), subtitleView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(12), false)); + userName.append("**"); + + descriptionStart = AndroidUtilities.replaceSingleTag( + descriptionStart.toString().replace("**%1s**", userName), + Theme.key_chat_messageLinkIn, 0, + () -> onObjectClicked.run(toUser), + resourcesProvider + ); + descriptionEnd = AndroidUtilities.replaceTags(descriptionEnd.toString()); + stringBuilder.append(descriptionStart); + stringBuilder.append(descriptionEnd); + } catch (Exception e) { + FileLog.e(e); + } + subtitleView.setText(stringBuilder); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + float y = iconTextureView.getTop() + iconTextureView.getMeasuredHeight() / 2f; + starParticlesView.setTranslationY(y - starParticlesView.getMeasuredHeight() / 2f); + } + + public void setPaused(boolean value) { + iconTextureView.setPaused(value); + starParticlesView.setPaused(value); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (links != null) { + canvas.save(); + canvas.translate(subtitleView.getLeft(), subtitleView.getTop()); + if (links.draw(canvas)) { + invalidate(); + } + canvas.restore(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/LinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/LinkCell.java new file mode 100644 index 000000000..5ee5d736b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/LinkCell.java @@ -0,0 +1,87 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.R; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.EffectsTextView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.spoilers.SpoilerEffect2; +import org.telegram.ui.Components.spoilers.SpoilersTextView; + +@SuppressLint("ViewConstructor") +public class LinkCell extends FrameLayout { + + private SpoilersTextView linkView; + private FrameLayout linkContainer; + private String slug; + private String link; + private ImageView imageView; + + public LinkCell(@NonNull Context context, BaseFragment fragment, Theme.ResourcesProvider resourcesProvider) { + super(context); + + linkContainer = new FrameLayout(context); + linkView = new SpoilersTextView(context); + linkView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(13), AndroidUtilities.dp(50), AndroidUtilities.dp(13)); + linkView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + linkView.setEllipsize(TextUtils.TruncateAt.MIDDLE); + linkView.setSingleLine(true); + linkView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + linkView.allowClickSpoilers = false; + + linkContainer.addView(linkView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + linkContainer.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Theme.getColor(Theme.key_graySection, resourcesProvider), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector, resourcesProvider), (int) (255 * 0.3f)))); + addView(linkContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 14, 0, 14, 0)); + + linkContainer.setOnClickListener(v -> AndroidUtilities.addToClipboard(link)); + + imageView = new ImageView(getContext()); + imageView.setImageResource(R.drawable.msg_copy); + imageView.setColorFilter(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + imageView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + imageView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(20), 0, ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_listSelector, resourcesProvider), (int) (255 * 0.3f)))); + addView(imageView, LayoutHelper.createFrame(40, 40, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 15, 0, 15, 0)); + imageView.setOnClickListener(v -> AndroidUtilities.addToClipboard(link)); + } + + public void setSlug(String slug) { + this.slug = slug; + this.link = "https://t.me/giftcode/" + slug; + linkView.setText("t.me/giftcode/" + slug); + } + + public void hideSlug(Runnable onHiddenLinkClicked) { + imageView.setVisibility(INVISIBLE); + linkView.setPadding(AndroidUtilities.dp(18), AndroidUtilities.dp(14), AndroidUtilities.dp(14), AndroidUtilities.dp(18)); + TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_SPOILER; + SpannableStringBuilder builder = new SpannableStringBuilder("t.me/giftcode/" + slug); + if (slug == null) { + String stub = "1234567891011123654897566536223"; + builder.append(stub); + } + builder.setSpan(new TextStyleSpan(run), 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + linkView.setText(builder); + linkContainer.setOnClickListener(v -> onHiddenLinkClicked.run()); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ParticipantsTypeCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ParticipantsTypeCell.java new file mode 100644 index 000000000..c0f332409 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/ParticipantsTypeCell.java @@ -0,0 +1,68 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; + +import java.util.List; + +@SuppressLint("ViewConstructor") +public class ParticipantsTypeCell extends BaseCell { + public static int TYPE_ALL = 0; + public static int TYPE_NEW = 1; + + private int selectedType; + + public ParticipantsTypeCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + imageView.setVisibility(GONE); + } + + public int getSelectedType() { + return selectedType; + } + + public void setType(int type, boolean isSelected, boolean needDivider, List countries) { + selectedType = type; + if (type == TYPE_ALL) { + titleTextView.setText(LocaleController.formatString("BoostingAllSubscribers", R.string.BoostingAllSubscribers)); + } else if (type == TYPE_NEW) { + titleTextView.setText(LocaleController.formatString("BoostingNewSubscribers", R.string.BoostingNewSubscribers)); + } + radioButton.setChecked(isSelected, false); + setDivider(needDivider); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2, resourcesProvider)); + + if (countries.size() == 0) { + setSubtitle(withArrow(LocaleController.getString("BoostingFromAllCountries", R.string.BoostingFromAllCountries))); + } else if (countries.size() <= 3) { + if (countries.size() == 1) { + setSubtitle(withArrow(LocaleController.formatString("BoostingFromAllCountries1", R.string.BoostingFromAllCountries1, countries.get(0).default_name))); + } else if (countries.size() == 2) { + setSubtitle(withArrow(LocaleController.formatString("BoostingFromAllCountries2", R.string.BoostingFromAllCountries2, countries.get(0).default_name, countries.get(1).default_name))); + } else { + setSubtitle(withArrow(LocaleController.formatString("BoostingFromAllCountries3", R.string.BoostingFromAllCountries3, + countries.get(0).default_name, + countries.get(1).default_name, + countries.get(2).default_name))); + } + } else { + setSubtitle(withArrow(LocaleController.formatPluralString("BoostingFromCountriesCount", countries.size()))); + } + } + + @Override + protected boolean needCheck() { + return true; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SliderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SliderCell.java new file mode 100644 index 000000000..1b77027ec --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SliderCell.java @@ -0,0 +1,47 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; + +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; +import org.telegram.ui.Components.SlideChooseView; + +import java.util.List; + +@SuppressLint("ViewConstructor") +public class SliderCell extends FrameLayout { + + private final Theme.ResourcesProvider resourcesProvider; + private final SlideChooseView slideChooseView; + protected View backgroundView; + + public SliderCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + backgroundView = new View(context); + addView(backgroundView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + backgroundView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + this.slideChooseView = new SlideChooseView(context, resourcesProvider); + addView(slideChooseView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 0, 0, 0)); + setBackground(Theme.getThemedDrawableByKey(getContext(), R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); + } + + public void setCallBack(SlideChooseView.Callback callback) { + slideChooseView.setCallback(callback); + } + + public void setValues(List values, int selected) { + String[] valuesStr = new String[values.size()]; + for (int i = 0; i < values.size(); i++) { + Integer val = values.get(i); + valuesStr[i] = String.valueOf(val); + } + slideChooseView.setOptions(selected, valuesStr); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java new file mode 100644 index 000000000..cfc67861f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/SubtitleWithCounterCell.java @@ -0,0 +1,40 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class SubtitleWithCounterCell extends org.telegram.ui.Cells.HeaderCell { + + private final AnimatedTextView counterTextView; + + public SubtitleWithCounterCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + + counterTextView = new AnimatedTextView(context, false, true, true); + counterTextView.setAnimationProperties(.45f, 0, 240, CubicBezierInterpolator.EASE_OUT_QUINT); + counterTextView.setGravity(Gravity.CENTER_HORIZONTAL); + counterTextView.setTextSize(dp(15)); + counterTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + counterTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); + addView(counterTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 24, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, 24, 0, 24, 0)); + setBackgroundColor(Theme.getColor(Theme.key_dialogBackground, resourcesProvider)); + } + + public void updateCounter(boolean animated, int count) { + CharSequence text = LocaleController.formatPluralString("BoostingSubscriptionsCount", count, count); + counterTextView.setText(text, animated); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TableCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TableCell.java new file mode 100644 index 000000000..51fa8e580 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TableCell.java @@ -0,0 +1,304 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.tgnet.tl.TL_stories.TL_boost.NO_USER_ID; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.os.Build; +import android.text.SpannableStringBuilder; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.widget.FrameLayout; +import android.widget.TableLayout; +import android.widget.TableRow; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +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.LinkSpanDrawable; + +import java.util.Date; + +@SuppressLint("ViewConstructor") +public class TableCell extends FrameLayout { + + private final TextView fromTextView; + private final TextView toTextView; + private final TextView giftTextView; + private final TextView reasonTextView; + private final TextView dateTextView; + + private final BackupImageView fromImageView; + private final BackupImageView toImageView; + + private final TextView fromNameTextView; + private final TextView toNameTextView; + private final TextView giftNameTextView; + private final TextView reasonNameTextView; + private final TextView dateNameTextView; + + private final Theme.ResourcesProvider resourcesProvider; + private final Paint linePaint = new Paint(); + private final Path roundPath = new Path(); + private final RectF roundRect = new RectF(); + private TLRPC.TL_payments_checkedGiftCode giftCode; + private FrameLayout fromFrameLayout; + private FrameLayout toFrameLayout; + private TableRow tableRow4; + + public TableCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + linePaint.setStyle(Paint.Style.STROKE); + this.resourcesProvider = resourcesProvider; + + fromNameTextView = createTextView(LocaleController.getString("BoostingFrom", R.string.BoostingFrom), false); + toNameTextView = createTextView(LocaleController.getString("BoostingTo", R.string.BoostingTo), false); + giftNameTextView = createTextView(LocaleController.getString("BoostingGift", R.string.BoostingGift), false); + reasonNameTextView = createTextView(LocaleController.getString("BoostingReason", R.string.BoostingReason), false); + dateNameTextView = createTextView(LocaleController.getString("BoostingDate", R.string.BoostingDate), false); + + fromTextView = createTextView(true); + toTextView = createTextView(true); + giftTextView = createTextView(false); + reasonTextView = createTextView(true); + dateTextView = createTextView(false); + + fromImageView = new BackupImageView(context); + fromImageView.setRoundRadius(AndroidUtilities.dp(12)); + toImageView = new BackupImageView(context); + toImageView.setRoundRadius(AndroidUtilities.dp(12)); + + TableRow tableRow1 = new TableRow(context); + fromFrameLayout = new FrameLayout(context); + fromFrameLayout.addView(fromImageView, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 12, 0, LocaleController.isRTL ? 12 : 0, 0)); + fromFrameLayout.addView(fromTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 29, 0, LocaleController.isRTL ? 29 : 0, 0)); + TableRow.LayoutParams lpFromFrameLayout = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, LocaleController.isRTL ? 1 : 0); + lpFromFrameLayout.gravity = Gravity.CENTER_VERTICAL; + if (LocaleController.isRTL) { + tableRow1.addView(fromFrameLayout, lpFromFrameLayout); + tableRow1.addView(fromNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } else { + tableRow1.addView(fromNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + tableRow1.addView(fromFrameLayout, lpFromFrameLayout); + } + fromFrameLayout.setPadding(0, AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6)); + + TableRow tableRow2 = new TableRow(context); + toFrameLayout = new FrameLayout(context); + toFrameLayout.addView(toImageView, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 12, 0, LocaleController.isRTL ? 12 : 0, 0)); + toFrameLayout.addView(toTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 29, 0, LocaleController.isRTL ? 29 : 0, 0)); + + TableRow.LayoutParams lpToFrameLayout = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, LocaleController.isRTL ? 1 : 0); + lpToFrameLayout.gravity = Gravity.CENTER_VERTICAL; + if (LocaleController.isRTL) { + tableRow2.addView(toFrameLayout, lpToFrameLayout); + tableRow2.addView(toNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } else { + tableRow2.addView(toNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + tableRow2.addView(toFrameLayout, lpToFrameLayout); + } + toFrameLayout.setPadding(0, AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6)); + + TableRow tableRow3 = new TableRow(context); + if (LocaleController.isRTL) { + tableRow3.addView(giftTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1)); + tableRow3.addView(giftNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } else { + tableRow3.addView(giftNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + tableRow3.addView(giftTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } + + tableRow4 = new TableRow(context); + if (LocaleController.isRTL) { + tableRow4.addView(reasonTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1)); + tableRow4.addView(reasonNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } else { + tableRow4.addView(reasonNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + tableRow4.addView(reasonTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } + + TableRow tableRow5 = new TableRow(context); + if (LocaleController.isRTL) { + tableRow5.addView(dateTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT, 1)); + tableRow5.addView(dateNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } else { + tableRow5.addView(dateNameTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + tableRow5.addView(dateTextView, new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)); + } + + TableLayout tableLayout = new TableLayout(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + roundRect.set(0, 0, getWidth(), getHeight()); + roundPath.rewind(); + roundPath.addRoundRect(roundRect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), Path.Direction.CW); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + canvas.clipPath(roundPath); + } + super.dispatchDraw(canvas); + linePaint.setColor(Theme.getColor(Theme.key_divider, resourcesProvider)); + linePaint.setStrokeWidth(AndroidUtilities.dp(1)); + float oneRow = getHeight() / (tableRow4.getVisibility() == VISIBLE ? 5f : 4f); + for (int i = 1; i <= 4; i++) { + float y = oneRow * i; + canvas.drawLine(0, y, getWidth(), y, linePaint); + } + float x = LocaleController.isRTL ? dateTextView.getRight() : dateTextView.getLeft(); + canvas.drawLine(x, 0, x, getHeight(), linePaint); + + linePaint.setStrokeWidth(AndroidUtilities.dp(2)); + canvas.drawPath(roundPath, linePaint); + } + }; + tableLayout.addView(tableRow1); + tableLayout.addView(tableRow2); + tableLayout.addView(tableRow3); + tableLayout.addView(tableRow4); + tableLayout.addView(tableRow5); + if (LocaleController.isRTL) { + tableLayout.setColumnShrinkable(0, true); + } else { + tableLayout.setColumnShrinkable(1, true); + } + addView(tableLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + tableLayout.setOutlineProvider(new ViewOutlineProvider() { + @Override + public void getOutline(View view, Outline outline) { + outline.setRoundRect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight(), AndroidUtilities.dp(6)); + } + }); + tableLayout.setClipToOutline(true); + } + setPaddingRelative(AndroidUtilities.dp(14), AndroidUtilities.dp(18), AndroidUtilities.dp(14), 0); + } + + public void setData(TLRPC.TL_payments_checkedGiftCode giftCode, Utilities.Callback onObjectClicked) { + this.giftCode = giftCode; + Date date = new Date(giftCode.date * 1000L); + String monthTxt = LocaleController.getInstance().formatterYear.format(date); + String timeTxt = LocaleController.getInstance().formatterDay.format(date); + + dateTextView.setText(LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, monthTxt, timeTxt)); + reasonTextView.setTextColor(Theme.getColor(giftCode.via_giveaway ? Theme.key_dialogTextBlue : Theme.key_dialogTextBlack, resourcesProvider)); + + if (giftCode.via_giveaway) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append("**"); + builder.append(LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway)); + builder.append("**"); + builder = AndroidUtilities.replaceSingleTag(builder.toString(), Theme.key_chat_messageLinkIn, 0, () -> onObjectClicked.run(giftCode), resourcesProvider); + reasonTextView.setText(builder); + reasonTextView.setOnClickListener(v -> onObjectClicked.run(giftCode)); + } else { + reasonTextView.setText(LocaleController.getString("BoostingYouWereSelected", R.string.BoostingYouWereSelected)); + reasonTextView.setOnClickListener(null); + } + + String monthsStr = giftCode.months == 12 ? LocaleController.formatPluralString("Years", 1) : LocaleController.formatPluralString("Months", giftCode.months); + giftTextView.setText(LocaleController.formatString("BoostingTelegramPremiumFor", R.string.BoostingTelegramPremiumFor, monthsStr)); + + TLRPC.Chat fromChat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(giftCode.from_id)); + if (fromChat != null) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append("**"); + builder.append(fromChat.title); + builder.append("**"); + builder = AndroidUtilities.replaceSingleTag(builder.toString(), Theme.key_chat_messageLinkIn, 0, () -> onObjectClicked.run(fromChat), resourcesProvider); + fromTextView.setText(Emoji.replaceEmoji(builder, fromTextView.getPaint().getFontMetricsInt(), dp(12), false)); + fromImageView.setForUserOrChat(fromChat, new AvatarDrawable(fromChat)); + fromFrameLayout.setOnClickListener(v -> onObjectClicked.run(fromChat)); + } else { + TLRPC.User fromUser = MessagesController.getInstance(UserConfig.selectedAccount).getUser(giftCode.from_id.user_id); + fromTextView.setText(Emoji.replaceEmoji(UserObject.getFirstName(fromUser), fromTextView.getPaint().getFontMetricsInt(), dp(12), false)); + fromImageView.setForUserOrChat(fromUser, new AvatarDrawable(fromUser)); + fromFrameLayout.setOnClickListener(v -> onObjectClicked.run(fromUser)); + } + + if (giftCode.to_id == NO_USER_ID && giftCode.via_giveaway) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append("**"); + builder.append(LocaleController.getString("BoostingIncompleteGiveaway", R.string.BoostingIncompleteGiveaway)); + builder.append("**"); + builder = AndroidUtilities.replaceSingleTag(builder.toString(), Theme.key_chat_messageLinkIn, 0, () -> onObjectClicked.run(giftCode), resourcesProvider); + reasonTextView.setText(builder); + toTextView.setText(LocaleController.getString("BoostingNoRecipient", R.string.BoostingNoRecipient)); + toTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + ((MarginLayoutParams) toTextView.getLayoutParams()).leftMargin = 0; + ((MarginLayoutParams) toTextView.getLayoutParams()).rightMargin = 0; + toImageView.setVisibility(GONE); + } else { + TLRPC.User toUser = MessagesController.getInstance(UserConfig.selectedAccount).getUser(giftCode.to_id); + if (toUser != null) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + builder.append("**"); + builder.append(UserObject.getFirstName(toUser)); + builder.append("**"); + builder = AndroidUtilities.replaceSingleTag(builder.toString(), Theme.key_chat_messageLinkIn, 0, () -> onObjectClicked.run(toUser), resourcesProvider); + toTextView.setText(Emoji.replaceEmoji(builder, toTextView.getPaint().getFontMetricsInt(), dp(12), false)); + toImageView.setForUserOrChat(toUser, new AvatarDrawable(toUser)); + toFrameLayout.setOnClickListener(v -> onObjectClicked.run(toUser)); + } + } + + if (giftCode.boost != null) { + tableRow4.setVisibility(GONE); + } + } + + private TextView createTextView(boolean blueColor) { + return createTextView(null, blueColor); + } + + private TextView createTextView(String text, boolean blueColor) { + TextView textView; + + if (blueColor) { + textView = new LinkSpanDrawable.LinksTextView(getContext(), resourcesProvider); + textView.setMovementMethod(LinkMovementMethod.getInstance()); + textView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); + } else { + textView = new TextView(getContext()); + } + + textView.setTextColor(Theme.getColor(blueColor ? Theme.key_dialogTextBlue : Theme.key_dialogTextBlack, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + if (text != null) { + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textView.setText(text); + textView.setBackgroundColor(Theme.getColor(Theme.key_graySection, resourcesProvider)); + textView.setPadding(AndroidUtilities.dp(LocaleController.isRTL ? 32 : 12), AndroidUtilities.dp(11), AndroidUtilities.dp(LocaleController.isRTL ? 12 : 32), AndroidUtilities.dp(11)); + } else { + textView.setSingleLine(true); + textView.setEllipsize(TextUtils.TruncateAt.END); + textView.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0); + } + return textView; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TextInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TextInfoCell.java new file mode 100644 index 000000000..af9ee40c8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/TextInfoCell.java @@ -0,0 +1,29 @@ +package org.telegram.ui.Components.Premium.boosts.cells; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; + +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextInfoPrivacyCell; +import org.telegram.ui.Components.CombinedDrawable; + +@SuppressLint("ViewConstructor") +public class TextInfoCell extends TextInfoPrivacyCell { + private final Theme.ResourcesProvider resourcesProvider; + + public TextInfoCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + this.resourcesProvider = resourcesProvider; + } + + public void setBackground(boolean onlyTopDivider) { + Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), onlyTopDivider ? R.drawable.greydivider_bottom : R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); + Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + setBackground(combinedDrawable); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java new file mode 100644 index 000000000..b6c254198 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/msg/GiveawayMessageCell.java @@ -0,0 +1,580 @@ +package org.telegram.ui.Components.Premium.boosts.cells.msg; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.replaceTags; +import static org.telegram.messenger.LocaleController.formatString; +import static org.telegram.messenger.LocaleController.getString; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.text.Layout; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.RelativeSizeSpan; +import android.util.StateSet; +import android.view.MotionEvent; +import android.view.SoundEffectConstants; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; +import org.telegram.ui.Components.StaticLayoutEx; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +public class GiveawayMessageCell { + + private static final Map monthsToEmoticon = new HashMap<>(); + + static { + monthsToEmoticon.put(1, 1 + "\u20E3"); + monthsToEmoticon.put(3, 2 + "\u20E3"); + monthsToEmoticon.put(6, 3 + "\u20E3"); + monthsToEmoticon.put(12, 4 + "\u20E3"); + monthsToEmoticon.put(24, 5 + "\u20E3"); + } + + private ImageReceiver[] avatarImageReceivers; + private AvatarDrawable[] avatarDrawables; + private final ChatMessageCell parentView; + private final ImageReceiver giftReceiver; + + private final CharSequence[] chatTitles = new CharSequence[10]; + private final float[] chatTitleWidths = new float[10]; + private final boolean[] needNewRow = new boolean[10]; + private final Rect[] clickRect = new Rect[10]; + private boolean[] avatarVisible; + private int measuredHeight = 0; + private int measuredWidth = 0; + private int topHeight; + private int bottomHeight; + private int countriesHeight; + private String counterStr; + private int diffTextWidth; + private StaticLayout topLayout; + private StaticLayout bottomLayout; + private StaticLayout countriesLayout; + + private final TextPaint counterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final TextPaint chatTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final TextPaint countriesTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final Paint counterBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint chatBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private final Paint saveLayerPaint = new Paint(); + private final Paint clipRectPaint = new Paint(); + private final RectF countRect = new RectF(); + private final RectF chatRect = new RectF(); + private final Rect counterTextBounds = new Rect(); + private final Rect containerRect = new Rect(); + private final int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; + + private int selectorColor; + private Drawable selectorDrawable; + private MessageObject messageObject; + private int pressedPos = -1; + private boolean isButtonPressed = false; + private boolean isContainerPressed = false; + + public GiveawayMessageCell(ChatMessageCell parentView) { + this.parentView = parentView; + giftReceiver = new ImageReceiver(parentView); + giftReceiver.setAllowLoadingOnAttachedOnly(true); + + clipRectPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + counterTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + counterTextPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + counterTextPaint.setTextSize(dp(12)); + counterTextPaint.setTextAlign(Paint.Align.CENTER); + chatTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + chatTextPaint.setTextSize(dp(13)); + countriesTextPaint.setTextSize(dp(13)); + textPaint.setTextSize(dp(14)); + } + + public boolean checkMotionEvent(MotionEvent event) { + if (messageObject == null || !messageObject.isGiveaway()) { + return false; + } + + int x = (int) event.getX(); + int y = (int) event.getY(); + + if (event.getAction() == MotionEvent.ACTION_DOWN) { + for (int i = 0; i < clickRect.length; i++) { + Rect rect = clickRect[i]; + if (rect.contains(x, y)) { + pressedPos = i; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + selectorDrawable.setHotspot(x, y); + } + isButtonPressed = true; + setButtonPressed(true); + return true; + } + } + if (containerRect.contains(x, y)) { + isContainerPressed = true; + return true; + } + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (isButtonPressed) { + if (parentView.getDelegate() != null) { + parentView.getDelegate().didPressGiveawayChatButton(parentView, pressedPos); + } + parentView.playSoundEffect(SoundEffectConstants.CLICK); + setButtonPressed(false); + isButtonPressed = false; + } + if (isContainerPressed) { + isContainerPressed = false; + BoostDialogs.showBulletinAbout(messageObject); + } + } else if (event.getAction() == MotionEvent.ACTION_MOVE) { + + } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { + if (isButtonPressed) { + setButtonPressed(false); + } + isButtonPressed = false; + isContainerPressed = false; + } + return false; + } + + public void setButtonPressed(boolean pressed) { + if (messageObject == null || !messageObject.isGiveaway()) { + return; + } + if (pressed) { + selectorDrawable.setCallback(new Drawable.Callback() { + @Override + public void invalidateDrawable(@NonNull Drawable who) { + parentView.invalidate(); + } + + @Override + public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { + parentView.invalidate(); + } + + @Override + public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { + parentView.invalidate(); + } + }); + selectorDrawable.setState(pressedState); + parentView.invalidate(); + } else { + selectorDrawable.setState(StateSet.NOTHING); + parentView.invalidate(); + } + } + + public void setMessageContent(MessageObject messageObject, int parentWidth, int forwardedNameWidth) { + this.messageObject = null; + topLayout = null; + bottomLayout = null; + countriesLayout = null; + measuredHeight = 0; + measuredWidth = 0; + if (!messageObject.isGiveaway()) { + return; + } + this.messageObject = messageObject; + createImages(); + setGiftImage(messageObject); + TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; + + int giftSize = AndroidUtilities.dp(148); + int maxWidth; + if (AndroidUtilities.isTablet()) { + maxWidth = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(80); + } else { + maxWidth = parentWidth - AndroidUtilities.dp(80); + } + + CharSequence giveawayPrizes = replaceTags(getString("BoostingGiveawayPrizes", R.string.BoostingGiveawayPrizes)); + SpannableStringBuilder topStringBuilder = new SpannableStringBuilder(giveawayPrizes); + topStringBuilder.setSpan(new RelativeSizeSpan(1.05f), 0, giveawayPrizes.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + topStringBuilder.append("\n"); + CharSequence subTitle = replaceTags(formatString("BoostingGiveawayMsgInfo", R.string.BoostingGiveawayMsgInfo, giveaway.quantity, LocaleController.formatPluralString("BoldMonths", giveaway.months))); + topStringBuilder.append(subTitle); + topStringBuilder.append("\n\n"); + + topStringBuilder.setSpan(new RelativeSizeSpan(0.5f), topStringBuilder.length() - 1, topStringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + CharSequence participants = replaceTags(getString("BoostingGiveawayMsgParticipants", R.string.BoostingGiveawayMsgParticipants)); + topStringBuilder.append(participants); + topStringBuilder.setSpan(new RelativeSizeSpan(1.05f), giveawayPrizes.length() + subTitle.length() + 2, giveawayPrizes.length() + subTitle.length() + 3 + participants.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + topStringBuilder.append("\n"); + + if (giveaway.only_new_subscribers) { + topStringBuilder.append(getString("BoostingGiveawayMsgNewSubs", R.string.BoostingGiveawayMsgNewSubs)); + } else { + topStringBuilder.append(getString("BoostingGiveawayMsgAllSubs", R.string.BoostingGiveawayMsgAllSubs)); + } + + CharSequence dateTitle = replaceTags(getString("BoostingWinnersDate", R.string.BoostingWinnersDate)); + SpannableStringBuilder bottomStringBuilder = new SpannableStringBuilder(dateTitle); + bottomStringBuilder.setSpan(new RelativeSizeSpan(1.05f), 0, dateTitle.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + Date date = new Date(giveaway.until_date * 1000L); + String monthTxt = LocaleController.getInstance().formatterGiveawayCard.format(date); + String timeTxt = LocaleController.getInstance().formatterDay.format(date); + bottomStringBuilder.append("\n"); + bottomStringBuilder.append(formatString("formatDateAtTime", R.string.formatDateAtTime, monthTxt, timeTxt)); + + topLayout = StaticLayoutEx.createStaticLayout(topStringBuilder, textPaint, maxWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, AndroidUtilities.dp(2), false, TextUtils.TruncateAt.END, maxWidth, 10); + bottomLayout = StaticLayoutEx.createStaticLayout(bottomStringBuilder, textPaint, maxWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, AndroidUtilities.dp(2), false, TextUtils.TruncateAt.END, maxWidth, 10); + + int maxRowLength = 0; + for (int a = 0; a < topLayout.getLineCount(); ++a) { + maxRowLength = (int) Math.max(maxRowLength, Math.ceil(topLayout.getLineWidth(a))); + } + for (int a = 0; a < bottomLayout.getLineCount(); ++a) { + maxRowLength = (int) Math.max(maxRowLength, Math.ceil(bottomLayout.getLineWidth(a))); + } + + if (giveaway.countries_iso2.size() > 0) { + List countriesWithFlags = new ArrayList<>(); + for (String iso2 : giveaway.countries_iso2) { + String countryName = (new Locale("", iso2)).getDisplayCountry(Locale.getDefault()); + String flag = LocaleController.getLanguageFlag(iso2); + SpannableStringBuilder builder = new SpannableStringBuilder(); + if (flag != null) { + builder.append(flag).append(" "); + } + builder.append(countryName); + countriesWithFlags.add(builder); + } + if (!countriesWithFlags.isEmpty()) { + CharSequence txt = replaceTags(formatString("BoostingGiveAwayFromCountries", R.string.BoostingGiveAwayFromCountries, TextUtils.join(", ", countriesWithFlags))); + countriesLayout = StaticLayoutEx.createStaticLayout(txt, countriesTextPaint, maxRowLength, Layout.Alignment.ALIGN_CENTER, 1.0f, AndroidUtilities.dp(2), false, TextUtils.TruncateAt.END, maxRowLength, 10); + } + } + + int oldMaxWidth = maxWidth; + maxWidth = Math.min(maxRowLength + dp(38), maxWidth); + maxWidth = Math.max(forwardedNameWidth, maxWidth); + diffTextWidth = maxWidth - oldMaxWidth; + + giftReceiver.setImageCoords((maxWidth / 2f) - (giftSize / 2f), AndroidUtilities.dp(42) - giftSize / 2f, giftSize, giftSize); + + topHeight = topLayout.getLineBottom(topLayout.getLineCount() - 1); + bottomHeight = bottomLayout.getLineBottom(bottomLayout.getLineCount() - 1); + countriesHeight = countriesLayout != null ? (countriesLayout.getLineBottom(countriesLayout.getLineCount() - 1) + dp(4 + 8)) : 0; + + measuredHeight += topHeight; + measuredHeight += countriesHeight; + measuredHeight += bottomHeight; + measuredHeight += dp(32 + 96); //gift + measuredWidth = maxWidth; + + counterStr = "x" + giveaway.quantity; + counterTextPaint.getTextBounds(counterStr, 0, counterStr.length(), counterTextBounds); + + Arrays.fill(avatarVisible, false); + + float oneRowTotalWidth = 0; + measuredHeight += dp(24 + 6); + + List visibleChannels = new ArrayList<>(giveaway.channels.size()); + for (Long channel : giveaway.channels) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(channel); + if (chat != null) { + visibleChannels.add(channel); + } + } + + for (int i = 0; i < visibleChannels.size(); i++) { + long channelId = visibleChannels.get(i); + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(channelId); + + if (chat != null) { + avatarVisible[i] = true; + CharSequence text = Emoji.replaceEmoji(chat.title, chatTextPaint.getFontMetricsInt(), dp(14), false); + chatTitles[i] = TextUtils.ellipsize(text, chatTextPaint, maxWidth * 0.8f, TextUtils.TruncateAt.END); + chatTitleWidths[i] = chatTextPaint.measureText(chatTitles[i], 0, chatTitles[i].length()); + float oneRowWidth = chatTitleWidths[i] + dp(24 + 6 + 12); + oneRowTotalWidth += oneRowWidth; + if (i > 0) { + needNewRow[i] = oneRowTotalWidth > maxWidth * 0.9f; + if (needNewRow[i]) { + oneRowTotalWidth = oneRowWidth; + measuredHeight += dp(24 + 6); + } + } else { + needNewRow[i] = false; + } + avatarDrawables[i].setInfo(chat); + avatarImageReceivers[i].setForUserOrChat(chat, avatarDrawables[i]); + avatarImageReceivers[i].setImageCoords(0, 0, dp(24), dp(24)); + } else { + avatarVisible[i] = false; + chatTitles[i] = ""; + needNewRow[i] = false; + chatTitleWidths[i] = dp(20); + avatarDrawables[i].setInfo(channelId, "", ""); + } + } + } + + public void draw(Canvas canvas, int marginTop, int marginLeft, Theme.ResourcesProvider resourcesProvider) { + if (messageObject == null || !messageObject.isGiveaway()) { + return; + } + + if (selectorDrawable == null) { + selectorDrawable = Theme.createRadSelectorDrawable(selectorColor = Theme.getColor(Theme.key_listSelector), 12, 12); + } + + int rippleColor = Theme.multAlpha(chatTextPaint.getColor(), Theme.isCurrentThemeDark() ? 0.12f : 0.10f); + if (selectorColor != rippleColor) { + Theme.setSelectorDrawableColor(selectorDrawable, selectorColor = rippleColor, true); + } + + textPaint.setColor(Theme.chat_msgTextPaint.getColor()); + countriesTextPaint.setColor(Theme.chat_msgTextPaint.getColor()); + + if (messageObject.isOutOwner()) { + chatTextPaint.setColor(Theme.getColor(Theme.key_chat_outPreviewInstantText, resourcesProvider)); + counterBgPaint.setColor(Theme.getColor(Theme.key_chat_outPreviewInstantText, resourcesProvider)); + chatBgPaint.setColor(Theme.getColor(Theme.key_chat_outReplyLine, resourcesProvider)); + } else { + chatTextPaint.setColor(Theme.getColor(Theme.key_chat_inPreviewInstantText, resourcesProvider)); + counterBgPaint.setColor(Theme.getColor(Theme.key_chat_inPreviewInstantText, resourcesProvider)); + chatBgPaint.setColor(Theme.getColor(Theme.key_chat_inReplyLine, resourcesProvider)); + } + + chatBgPaint.setAlpha((int) (chatTextPaint.getAlpha() * 0.10f)); + + int x = 0, y = 0; + canvas.save(); + x = marginLeft - dp(4); + y = marginTop; + canvas.translate(x, y); + containerRect.set(x, y, getMeasuredWidth() + x, getMeasuredHeight() + y); + + canvas.saveLayer(0, 0, getMeasuredWidth(), getMeasuredHeight(), saveLayerPaint, Canvas.ALL_SAVE_FLAG); + giftReceiver.draw(canvas); + + float centerX = getMeasuredWidth() / 2f; + float centerY = dp(106); + int textWidth = counterTextBounds.width() + dp(12); + int textHeight = counterTextBounds.height() + dp(10); + countRect.set( + centerX - ((textWidth + dp(2)) / 2f), + centerY - ((textHeight + dp(2)) / 2f), + centerX + ((textWidth + dp(2)) / 2f), + centerY + ((textHeight + dp(2)) / 2f) + ); + canvas.drawRoundRect(countRect, dp(11), dp(11), clipRectPaint); + countRect.set( + centerX - ((textWidth) / 2f), + centerY - ((textHeight) / 2f), + centerX + ((textWidth) / 2f), + centerY + ((textHeight) / 2f) + ); + canvas.drawRoundRect(countRect, dp(10), dp(10), counterBgPaint); + canvas.drawText(counterStr, countRect.centerX(), countRect.centerY() + dp(4), counterTextPaint); + canvas.restore(); + + canvas.translate(0, dp(32 + 96)); + y += dp(32 + 96); + + canvas.save(); + canvas.translate(diffTextWidth / 2f, 0); + topLayout.draw(canvas); + canvas.restore(); + canvas.translate(0, topHeight + dp(6)); + y += topHeight + dp(6); + + int i = 0; + while (i < avatarVisible.length) { + if (avatarVisible[i]) { + canvas.save(); + int k = i; + float rowWidth = 0; + + do { + rowWidth += chatTitleWidths[k] + dp(24 + 6 + 12); + k++; + } while (k < avatarVisible.length && !needNewRow[k] && avatarVisible[k]); + + float marginItemsLeft = centerX - (rowWidth / 2f); + canvas.translate(marginItemsLeft, 0); + int xRow = x + (int) (marginItemsLeft); + + k = i; + + do { + avatarImageReceivers[k].draw(canvas); + canvas.drawText(chatTitles[k], 0, chatTitles[k].length(), dp(24 + 6), dp(16), chatTextPaint); + chatRect.set(0, 0, chatTitleWidths[k] + dp(24 + 6 + 12), dp(24)); + canvas.drawRoundRect(chatRect, dp(12), dp(12), chatBgPaint); + + clickRect[k].set(xRow, y, (int) (xRow + chatRect.width()), y + dp(24)); + + canvas.translate(chatRect.width() + dp(6), 0); + xRow += chatRect.width() + dp(6); + + k++; + } while (k < avatarVisible.length && !needNewRow[k] && avatarVisible[k]); + + i = k; + + canvas.restore(); + canvas.translate(0, dp(24 + 6)); + y += dp(24 + 6); + } else { + i++; + } + } + + if (countriesLayout != null) { + canvas.save(); + canvas.translate((measuredWidth - countriesLayout.getWidth()) / 2f, dp(4)); + countriesLayout.draw(canvas); + canvas.restore(); + canvas.translate(0, countriesHeight); + } + + canvas.translate(0, dp(6)); + canvas.save(); + canvas.translate(diffTextWidth / 2f, 0); + bottomLayout.draw(canvas); + canvas.restore(); + canvas.restore(); + if (pressedPos >= 0) { + selectorDrawable.setBounds(clickRect[pressedPos]); + selectorDrawable.draw(canvas); + } + } + + public void onDetachedFromWindow() { + giftReceiver.onDetachedFromWindow(); + if (avatarImageReceivers != null) { + for (ImageReceiver avatarImageReceiver : avatarImageReceivers) { + avatarImageReceiver.onDetachedFromWindow(); + } + } + } + + public void onAttachedToWindow() { + giftReceiver.onAttachedToWindow(); + if (avatarImageReceivers != null) { + for (ImageReceiver avatarImageReceiver : avatarImageReceivers) { + avatarImageReceiver.onAttachedToWindow(); + } + } + } + + public int getMeasuredHeight() { + return measuredHeight; + } + + public int getMeasuredWidth() { + return measuredWidth; + } + + private void createImages() { + if (avatarImageReceivers != null) { + return; + } + + avatarImageReceivers = new ImageReceiver[10]; + avatarDrawables = new AvatarDrawable[10]; + avatarVisible = new boolean[10]; + for (int a = 0; a < avatarImageReceivers.length; a++) { + avatarImageReceivers[a] = new ImageReceiver(parentView); + avatarImageReceivers[a].setAllowLoadingOnAttachedOnly(true); + avatarImageReceivers[a].setRoundRadius(AndroidUtilities.dp(12)); + avatarDrawables[a] = new AvatarDrawable(); + avatarDrawables[a].setTextSize(AndroidUtilities.dp(18)); + clickRect[a] = new Rect(); + } + } + + private void setGiftImage(MessageObject messageObject) { + TLRPC.TL_messageMediaGiveaway giveaway = (TLRPC.TL_messageMediaGiveaway) messageObject.messageOwner.media; + TLRPC.TL_messages_stickerSet set; + TLRPC.Document document = null; + + String packName = UserConfig.getInstance(UserConfig.selectedAccount).premiumGiftsStickerPack; + if (packName == null) { + MediaDataController.getInstance(UserConfig.selectedAccount).checkPremiumGiftStickers(); + return; + } + set = MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSetByName(packName); + if (set == null) { + set = MediaDataController.getInstance(UserConfig.selectedAccount).getStickerSetByEmojiOrName(packName); + } + if (set != null) { + int months = giveaway.months; + String 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 && !set.documents.isEmpty()) { + document = set.documents.get(0); + } + } + if (document != null) { + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document.thumbs, Theme.key_emptyListPlaceholder, 0.2f); + if (svgThumb != null) { + svgThumb.overrideWidthAndHeight(512, 512); + } + giftReceiver.setImage(ImageLocation.getForDocument(document), "160_160_firstframe", svgThumb, "tgs", set, 1); + } else { + MediaDataController.getInstance(UserConfig.selectedAccount).loadStickersByEmojiOrName(packName, false, set == null); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java new file mode 100644 index 000000000..01916702e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorBtnCell.java @@ -0,0 +1,38 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.widget.LinearLayout; + +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.RecyclerListView; + +@SuppressLint("ViewConstructor") +public class SelectorBtnCell extends LinearLayout { + + private final Theme.ResourcesProvider resourcesProvider; + private final RecyclerListView listView; + private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final AnimatedFloat alpha = new AnimatedFloat(this); + + public SelectorBtnCell(Context context, Theme.ResourcesProvider resourcesProvider, RecyclerListView listView) { + super(context); + this.resourcesProvider = resourcesProvider; + this.listView = listView; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + dividerPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); + if (listView != null) { + dividerPaint.setAlpha((int) (0xFF * alpha.set(listView.canScrollVertically(1) ? 1 : 0))); + } else { + dividerPaint.setAlpha((int) (0xFF * alpha.set(1))); + } + canvas.drawRect(0, 0, getWidth(), 1, dividerPaint); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java new file mode 100644 index 000000000..6ac63b97b --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorCountryCell.java @@ -0,0 +1,136 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.text.SpannableStringBuilder; +import android.text.style.ReplacementSpan; +import android.view.Gravity; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.LocaleController; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CheckBox2; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.boosts.cells.BaseCell; + +@SuppressLint("ViewConstructor") +public class SelectorCountryCell extends BaseCell { + + private final CheckBox2 checkBox; + private TLRPC.TL_help_country country; + + public SelectorCountryCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + radioButton.setVisibility(View.GONE); + imageView.setVisibility(View.GONE); + checkBox = new CheckBox2(context, 21, resourcesProvider); + checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_checkboxDisabled, Theme.key_dialogRoundCheckBoxCheck); + checkBox.setDrawUnchecked(true); + checkBox.setDrawBackgroundAsArc(10); + addView(checkBox); + checkBox.setChecked(false, false); + checkBox.setLayoutParams(LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 13, 0, 14, 0)); + } + + protected void updateLayouts() { + titleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : 52, 0, LocaleController.isRTL ? 52 : 20, 0)); + subtitleTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 20 : 52, 0, LocaleController.isRTL ? 52 : 20, 0)); + radioButton.setLayoutParams(LayoutHelper.createFrame(22, 22, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 15 : 20, 0, LocaleController.isRTL ? 20 : 15, 0)); + } + + @Override + protected int getFullHeight() { + return 44; + } + + @Override + protected int dividerPadding() { + return 22; + } + + public void setCountry(TLRPC.TL_help_country country, boolean divider) { + this.country = country; + titleTextView.setText(Emoji.replaceEmoji(getCountryNameWithFlag(country), titleTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false)); + setDivider(divider); + } + + + private CharSequence getCountryNameWithFlag(TLRPC.TL_help_country country) { + SpannableStringBuilder sb = new SpannableStringBuilder(); + String flag = LocaleController.getLanguageFlag(country.iso2); + if (!LocaleController.isRTL) { + if (flag != null) { + sb.append(flag).append(" "); + sb.setSpan(new SpaceDrawable(16), flag.length(), flag.length() + 1, 0); + } else { + sb.append(" "); + sb.setSpan(new SpaceDrawable(34), 0, 1, 0); + } + sb.append(country.default_name); + } else { + sb.append(country.default_name); + if (flag != null) { + sb.append(" ").append(flag); + sb.setSpan(new SpaceDrawable(16), country.default_name.length(), country.default_name.length() + 1, 0); + } else { + sb.append(" "); + sb.setSpan(new SpaceDrawable(34), country.default_name.length(), country.default_name.length() + 1, 0); + } + } + return sb; + } + + public TLRPC.TL_help_country getCountry() { + return country; + } + + public void setChecked(boolean checked, boolean animated) { + if (checkBox.getVisibility() == View.VISIBLE) { + checkBox.setChecked(checked, animated); + } + } + + public void setCheckboxAlpha(float alpha, boolean animated) { + if (animated) { + if (Math.abs(checkBox.getAlpha() - alpha) > .1) { + checkBox.animate().cancel(); + checkBox.animate().alpha(alpha).start(); + } + } else { + checkBox.animate().cancel(); + checkBox.setAlpha(alpha); + } + } + + @Override + protected boolean needCheck() { + return true; + } + + private static class SpaceDrawable extends ReplacementSpan { + private final int size; + + public SpaceDrawable(int size) { + this.size = size; + } + + @Override + public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) { + return AndroidUtilities.dp(size); + } + + @Override + public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { + + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorHeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorHeaderCell.java new file mode 100644 index 000000000..469f7b609 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorHeaderCell.java @@ -0,0 +1,87 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.BackDrawable; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class SelectorHeaderCell extends FrameLayout { + + private final Theme.ResourcesProvider resourcesProvider; + + private final ImageView closeView; + private final TextView textView; + private Runnable onCloseClickListener; + public BackDrawable backDrawable; + + private final Paint dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + public SelectorHeaderCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + textView = new TextView(context); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + 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, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.FILL_HORIZONTAL, LocaleController.isRTL ? 16 : 53, 0, LocaleController.isRTL ? 53 : 16, 0)); + + closeView = new ImageView(context); + closeView.setImageDrawable(backDrawable = new BackDrawable(false)); + backDrawable.setColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + backDrawable.setRotatedColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); + backDrawable.setAnimationTime(220); + addView(closeView, LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 16, 0, 16, 0)); + closeView.setOnClickListener(e -> { + if (onCloseClickListener != null) { + onCloseClickListener.run(); + } + }); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + dividerPaint.setColor(Theme.getColor(Theme.key_divider, resourcesProvider)); + canvas.drawRect(0, getHeight() - AndroidUtilities.getShadowHeight(), getWidth(), getHeight(), dividerPaint); + } + + public void setText(CharSequence text) { + textView.setText(text); + } + + public void setCloseImageVisible(boolean visible) { + closeView.setVisibility(visible ? View.VISIBLE : View.GONE); + textView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.FILL_HORIZONTAL, LocaleController.isRTL || !visible ? 22 : 53, 0, LocaleController.isRTL && visible ? 53 : 22, 0)); + } + + public void setBackImage(int resId) { + closeView.setImageResource(resId); + } + + public void setOnCloseClickListener(Runnable onCloseClickListener) { + this.onCloseClickListener = onCloseClickListener; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(56), MeasureSpec.EXACTLY) + ); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorLetterCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorLetterCell.java new file mode 100644 index 000000000..d5448547c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorLetterCell.java @@ -0,0 +1,54 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +@SuppressLint("ViewConstructor") +public class SelectorLetterCell extends FrameLayout { + + private final Theme.ResourcesProvider resourcesProvider; + private final TextView textView; + + public SelectorLetterCell(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + setBackgroundColor(getThemedColor(Theme.key_graySection)); + textView = new TextView(getContext()); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textView.setTextColor(getThemedColor(Theme.key_graySectionText)); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 16, 0, 16, 0)); + } + + public void setLetter(String letter) { + textView.setText(letter.toUpperCase()); + } + + private int getThemedColor(int key) { + return Theme.getColor(key, resourcesProvider); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(32), MeasureSpec.EXACTLY)); + } + + public void setTextColor(int key) { + int color = getThemedColor(key); + textView.setTextColor(color); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorSearchCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorSearchCell.java new file mode 100644 index 000000000..dec759408 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorSearchCell.java @@ -0,0 +1,664 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.Shader; +import android.os.Build; +import android.text.Editable; +import android.text.InputType; +import android.text.TextWatcher; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.LinearInterpolator; +import android.view.inputmethod.EditorInfo; +import android.widget.ScrollView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.GroupCreateSpan; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +@SuppressLint("ViewConstructor") +public class SelectorSearchCell extends ScrollView { + + private final Theme.ResourcesProvider resourcesProvider; + private EditTextBoldCursor editText; + private int hintTextWidth; + public SpansContainer spansContainer; + private int selectedCount; + public ArrayList allSpans = new ArrayList<>(); + private GroupCreateSpan currentDeletingSpan; + private Runnable updateHeight; + private boolean ignoreTextChange; + private Utilities.Callback onSearchTextChange; + + public EditTextBoldCursor getEditText() { + return editText; + } + + public SelectorSearchCell(Context context, Theme.ResourcesProvider resourcesProvider, Runnable updateHeight) { + super(context); + this.resourcesProvider = resourcesProvider; + this.updateHeight = updateHeight; + + setVerticalScrollBarEnabled(false); + AndroidUtilities.setScrollViewEdgeEffectColor(this, Theme.getColor(Theme.key_windowBackgroundWhite)); + + spansContainer = new SpansContainer(context); + addView(spansContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + editText = new EditTextBoldCursor(context) { + @Override + public boolean onTouchEvent(MotionEvent event) { + if (currentDeletingSpan != null) { + currentDeletingSpan.cancelDeleteAnimation(); + currentDeletingSpan = null; + } + if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (!AndroidUtilities.showKeyboard(this)) { + fullScroll(View.FOCUS_DOWN); + clearFocus(); + requestFocus(); + } + } + return super.onTouchEvent(event); + } + }; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) { + editText.setRevealOnFocusHint(false); + } + editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + editText.setHintColor(Theme.getColor(Theme.key_groupcreate_hintText, resourcesProvider)); + editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + editText.setCursorColor(Theme.getColor(Theme.key_groupcreate_cursor, resourcesProvider)); + editText.setHandlesColor(Theme.getColor(Theme.key_groupcreate_cursor, resourcesProvider)); + editText.setCursorWidth(1.5f); + editText.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS | InputType.TYPE_TEXT_FLAG_MULTI_LINE); + editText.setSingleLine(true); + editText.setBackgroundDrawable(null); + editText.setVerticalScrollBarEnabled(false); + editText.setHorizontalScrollBarEnabled(false); + editText.setTextIsSelectable(false); + editText.setPadding(0, 0, 0, 0); + editText.setImeOptions(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI); + editText.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + spansContainer.addView(editText); + editText.setHintText(LocaleController.getString("Search", R.string.Search)); + hintTextWidth = (int) editText.getPaint().measureText(LocaleController.getString("Search", R.string.Search)); + editText.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (ignoreTextChange) { + return; + } + if (onSearchTextChange != null && s != null) { + onSearchTextChange.run(s.toString()); + } + } + }); + } + + private final AnimatedFloat topGradientAlpha = new AnimatedFloat(this, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); + private final LinearGradient topGradient = new LinearGradient(0, 0, 0, dp(8), new int[]{0xff000000, 0x00000000}, new float[]{0, 1}, Shader.TileMode.CLAMP); + private final Paint topGradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Matrix topGradientMatrix = new Matrix(); + + private final AnimatedFloat bottomGradientAlpha = new AnimatedFloat(this, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); + private final LinearGradient bottomGradient = new LinearGradient(0, 0, 0, dp(8), new int[]{0x00000000, 0xff000000}, new float[]{0, 1}, Shader.TileMode.CLAMP); + private final Paint bottomGradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Matrix bottomGradientMatrix = new Matrix(); + + { + topGradientPaint.setShader(topGradient); + topGradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + bottomGradientPaint.setShader(bottomGradient); + bottomGradientPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } + + public void updateSpans(boolean animated, HashSet selectedIds, Runnable afterDelete, List countries) { + final MessagesController messagesController = MessagesController.getInstance(UserConfig.selectedAccount); + final ArrayList toDelete = new ArrayList<>(); + final ArrayList toAdd = new ArrayList<>(); + + for (int i = 0; i < allSpans.size(); ++i) { + GroupCreateSpan span = allSpans.get(i); + if (!selectedIds.contains(span.getUid())) { + toDelete.add(span); + } + } + + for (long id : selectedIds) { + boolean found = false; + for (int j = 0; j < allSpans.size(); ++j) { + GroupCreateSpan span = allSpans.get(j); + if (span.getUid() == id) { + found = true; + break; + } + } + + if (!found) { + TLObject obj; + if (id >= 0) { + obj = messagesController.getUser(id); + } else { + obj = messagesController.getChat(-id); + } + if (countries != null) { + for (TLRPC.TL_help_country country : countries) { + long countryHash = country.default_name.hashCode(); + if (countryHash == id) { + obj = country; + break; + } + } + } + if (obj == null) { + continue; + } + GroupCreateSpan span = new GroupCreateSpan(getContext(), obj, null, true, resourcesProvider); + span.setOnClickListener(v -> { + onDeleteSpanClicked(v, selectedIds, afterDelete); + }); + toAdd.add(span); + } + } + + if (!toDelete.isEmpty() || !toAdd.isEmpty()) { + spansContainer.updateSpans(toDelete, toAdd, animated); + } + + editText.setOnKeyListener(new View.OnKeyListener() { + + private boolean wasEmpty; + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_DEL) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + wasEmpty = editText.length() == 0; + } else if (event.getAction() == KeyEvent.ACTION_UP && wasEmpty && !allSpans.isEmpty()) { + GroupCreateSpan span = allSpans.get(allSpans.size() - 1); + onDeleteSpanClicked(span, selectedIds, afterDelete); + return true; + } + } + return false; + } + }); + } + + private void onDeleteSpanClicked(View view, HashSet selectedIds, Runnable afterDelete) { + if (!allSpans.contains(view)) { + return; + } + GroupCreateSpan deletingSpan = (GroupCreateSpan) view; + if (deletingSpan.isDeleting()) { + currentDeletingSpan = null; + spansContainer.removeSpan(deletingSpan); + long deletingId = deletingSpan.getUid(); + selectedIds.remove(deletingId); + afterDelete.run(); + } else { + if (currentDeletingSpan != null) { + currentDeletingSpan.cancelDeleteAnimation(); + currentDeletingSpan = null; + } + currentDeletingSpan = deletingSpan; + deletingSpan.startDeleteAnimation(); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + final int y = getScrollY(); + + canvas.saveLayerAlpha(0, y, getWidth(), y + getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + super.dispatchDraw(canvas); + + canvas.save(); + + float alpha = topGradientAlpha.set(canScrollVertically(-1)); + topGradientMatrix.reset(); + topGradientMatrix.postTranslate(0, y); + topGradient.setLocalMatrix(topGradientMatrix); + topGradientPaint.setAlpha((int) (0xFF * alpha)); + canvas.drawRect(0, y, getWidth(), y + dp(8), topGradientPaint); + + alpha = bottomGradientAlpha.set(canScrollVertically(1)); + bottomGradientMatrix.reset(); + bottomGradientMatrix.postTranslate(0, y + getHeight() - dp(8)); + bottomGradient.setLocalMatrix(bottomGradientMatrix); + bottomGradientPaint.setAlpha((int) (0xFF * alpha)); + canvas.drawRect(0, y + getHeight() - dp(8), getWidth(), y + getHeight(), bottomGradientPaint); + + canvas.restore(); + + canvas.restore(); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + return super.dispatchTouchEvent(ev); + } + + public void setText(CharSequence text) { + ignoreTextChange = true; + editText.setText(text); + ignoreTextChange = false; + } + + public void setOnSearchTextChange(Utilities.Callback listener) { + this.onSearchTextChange = listener; + } + + private boolean ignoreScrollEvent; + private int fieldY; + public float containerHeight; + public int resultContainerHeight; + private int prevResultContainerHeight; + + @Override + public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { + if (ignoreScrollEvent) { + ignoreScrollEvent = false; + return false; + } + rectangle.offset(child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY()); + rectangle.top += fieldY + AndroidUtilities.dp(20); + rectangle.bottom += fieldY + AndroidUtilities.dp(50); + return super.requestChildRectangleOnScreen(child, rectangle, immediate); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(150), MeasureSpec.AT_MOST) + ); + } + + public void setContainerHeight(float value) { + containerHeight = value; + if (spansContainer != null) { + spansContainer.requestLayout(); + } + } + + protected Animator getContainerHeightAnimator(float newHeight) { + ValueAnimator animator = ValueAnimator.ofFloat(this.containerHeight, newHeight); + animator.addUpdateListener(anm -> setContainerHeight((float) anm.getAnimatedValue())); + return animator; + } + + private boolean scroll; + + public void scrollToBottom() { + scroll = true; + } + + public class SpansContainer extends ViewGroup { + + private AnimatorSet currentAnimation; + private boolean animationStarted; + private ArrayList animAddingSpans = new ArrayList<>(); + private ArrayList animRemovingSpans = new ArrayList<>(); + private ArrayList animators = new ArrayList<>(); + private View addingSpan; + private final ArrayList removingSpans = new ArrayList<>(); + + private final int padDp = 14; + private final int padYDp = 4; + private final int padXDp = 6; + private final int heightDp = 28; // 32; + + public SpansContainer(Context context) { + super(context); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int count = getChildCount(); + int width = MeasureSpec.getSize(widthMeasureSpec); + int maxWidth = width - AndroidUtilities.dp(padDp * 2); + int currentLineWidth = 0; + int y = AndroidUtilities.dp(10); + int allCurrentLineWidth = 0; + int allY = AndroidUtilities.dp(10); + int x; + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + if (!(child instanceof GroupCreateSpan)) { + continue; + } + child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(dp(heightDp), MeasureSpec.EXACTLY)); + boolean isRemoving = removingSpans.contains(child); + if (!isRemoving && currentLineWidth + child.getMeasuredWidth() > maxWidth) { + y += child.getMeasuredHeight() + dp(padYDp); + currentLineWidth = 0; + } + if (allCurrentLineWidth + child.getMeasuredWidth() > maxWidth) { + allY += child.getMeasuredHeight() + AndroidUtilities.dp(padYDp); + allCurrentLineWidth = 0; + } + x = AndroidUtilities.dp(padDp) + currentLineWidth; + if (!animationStarted) { + if (isRemoving) { + child.setTranslationX(AndroidUtilities.dp(padDp) + allCurrentLineWidth); + child.setTranslationY(allY); + } else if (!removingSpans.isEmpty()) { + if (child.getTranslationX() != x) { + animators.add(ObjectAnimator.ofFloat(child, View.TRANSLATION_X, x)); + } + if (child.getTranslationY() != y) { + animators.add(ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, y)); + } + } else { + child.setTranslationX(x); + child.setTranslationY(y); + } + } + if (!isRemoving) { + currentLineWidth += child.getMeasuredWidth() + AndroidUtilities.dp(padXDp); + } + allCurrentLineWidth += child.getMeasuredWidth() + AndroidUtilities.dp(padXDp); + } + int minWidth; + if (AndroidUtilities.isTablet()) { + minWidth = AndroidUtilities.dp(530 - padDp * 2 - padXDp * 2 - 57 * 2) / 3; + } else { + minWidth = (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(padDp * 2 + padXDp * 2 + 57 * 2)) / 3; + } + if (maxWidth - currentLineWidth < minWidth) { + currentLineWidth = 0; + y += AndroidUtilities.dp(heightDp + 8); + } + if (maxWidth - allCurrentLineWidth < minWidth) { + allY += AndroidUtilities.dp(heightDp + 8); + } + editText.measure(MeasureSpec.makeMeasureSpec(maxWidth - currentLineWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(heightDp), MeasureSpec.EXACTLY)); + editText.setHintVisible(editText.getMeasuredWidth() > hintTextWidth, true); + if (!animationStarted) { + int currentHeight = allY + AndroidUtilities.dp(heightDp + 10); + int fieldX = currentLineWidth + AndroidUtilities.dp(16); + fieldY = y; + if (currentAnimation != null) { + int resultHeight = y + AndroidUtilities.dp(heightDp + 10); + resultContainerHeight = resultHeight; + if (containerHeight != resultHeight) { + animators.add(getContainerHeightAnimator(resultHeight)); + } + if (editText.getTranslationX() != fieldX) { + animators.add(ObjectAnimator.ofFloat(editText, View.TRANSLATION_X, fieldX)); + } + if (editText.getTranslationY() != fieldY) { + animators.add(ObjectAnimator.ofFloat(editText, View.TRANSLATION_Y, fieldY)); + } + editText.setAllowDrawCursor(false); + currentAnimation.playTogether(animators); + currentAnimation.setDuration(180); + currentAnimation.setInterpolator(new LinearInterpolator()); + currentAnimation.start(); + animationStarted = true; + if (updateHeight != null) { + updateHeight.run(); + } + } else { + containerHeight = resultContainerHeight = currentHeight; + editText.setTranslationX(fieldX); + editText.setTranslationY(fieldY); + if (updateHeight != null) { + updateHeight.run(); + } + if (scroll) { + post(() -> fullScroll(View.FOCUS_DOWN)); + scroll = false; + } + } + prevResultContainerHeight = resultContainerHeight; + } else if (currentAnimation != null) { + if (!ignoreScrollEvent && removingSpans.isEmpty()) { + editText.bringPointIntoView(editText.getSelectionStart()); + } + if (scroll) { + fullScroll(View.FOCUS_DOWN); + scroll = false; + } + } + setMeasuredDimension(width, (int) containerHeight); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + int count = getChildCount(); + for (int a = 0; a < count; a++) { + View child = getChildAt(a); + child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); + } + } + + public void removeSpan(final GroupCreateSpan span) { + ignoreScrollEvent = true; + allSpans.remove(span); + span.setOnClickListener(null); + + setupEndValues(); + animationStarted = false; + currentAnimation = new AnimatorSet(); + currentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + removeView(span); + removingSpans.clear(); + currentAnimation = null; + animationStarted = false; + editText.setAllowDrawCursor(true); + if (updateHeight != null) { + updateHeight.run(); + } + if (scroll) { + fullScroll(View.FOCUS_DOWN); + scroll = false; + } + } + }); + removingSpans.clear(); + removingSpans.add(span); + animAddingSpans.clear(); + animRemovingSpans.clear(); + animAddingSpans.add(span); + animators.clear(); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.ALPHA, 1.0f, 0.0f)); + requestLayout(); + } + + public void updateSpans(ArrayList toDelete, ArrayList toAdd, boolean animated) { + ignoreScrollEvent = true; + + allSpans.removeAll(toDelete); + allSpans.addAll(toAdd); + + removingSpans.clear(); + removingSpans.addAll(toDelete); + + for (int i = 0; i < toDelete.size(); ++i) { + toDelete.get(i).setOnClickListener(null); + } + + setupEndValues(); + if (animated) { + animationStarted = false; + currentAnimation = new AnimatorSet(); + currentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + for (int i = 0; i < toDelete.size(); ++i) { + removeView(toDelete.get(i)); + } + addingSpan = null; + removingSpans.clear(); + currentAnimation = null; + animationStarted = false; + editText.setAllowDrawCursor(true); + if (updateHeight != null) { + updateHeight.run(); + } + if (scroll) { + fullScroll(View.FOCUS_DOWN); + scroll = false; + } + } + }); + animators.clear(); + animAddingSpans.clear(); + animRemovingSpans.clear(); + for (int i = 0; i < toDelete.size(); ++i) { + GroupCreateSpan span = toDelete.get(i); + animRemovingSpans.add(span); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.ALPHA, 1.0f, 0.0f)); + } + for (int i = 0; i < toAdd.size(); ++i) { + GroupCreateSpan addingSpan = toAdd.get(i); + animAddingSpans.add(addingSpan); + animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_X, 0.01f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(addingSpan, View.SCALE_Y, 0.01f, 1.0f)); + animators.add(ObjectAnimator.ofFloat(addingSpan, View.ALPHA, 0.0f, 1.0f)); + } + } else { + for (int i = 0; i < toDelete.size(); ++i) { + removeView(toDelete.get(i)); + } + addingSpan = null; + removingSpans.clear(); + currentAnimation = null; + animationStarted = false; + editText.setAllowDrawCursor(true); + } + for (int i = 0; i < toAdd.size(); ++i) { + addView(toAdd.get(i)); + } + requestLayout(); + } + + public void removeAllSpans(boolean animated) { + ignoreScrollEvent = true; + + ArrayList spans = new ArrayList<>(allSpans); + removingSpans.clear(); + removingSpans.addAll(allSpans); + allSpans.clear(); + + for (int i = 0; i < spans.size(); ++i) { + spans.get(i).setOnClickListener(null); + } + + setupEndValues(); + if (animated) { + animationStarted = false; + currentAnimation = new AnimatorSet(); + currentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animator) { + for (int i = 0; i < spans.size(); ++i) { + removeView(spans.get(i)); + } + removingSpans.clear(); + currentAnimation = null; + animationStarted = false; + editText.setAllowDrawCursor(true); + if (updateHeight != null) { + updateHeight.run(); + } + if (scroll) { + fullScroll(View.FOCUS_DOWN); + scroll = false; + } + } + }); + animators.clear(); + animAddingSpans.clear(); + animRemovingSpans.clear(); + for (int i = 0; i < spans.size(); ++i) { + GroupCreateSpan span = spans.get(i); + animAddingSpans.add(span); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_X, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.SCALE_Y, 1.0f, 0.01f)); + animators.add(ObjectAnimator.ofFloat(span, View.ALPHA, 1.0f, 0.0f)); + } + } else { + for (int i = 0; i < spans.size(); ++i) { + removeView(spans.get(i)); + } + removingSpans.clear(); + currentAnimation = null; + animationStarted = false; + editText.setAllowDrawCursor(true); + } + requestLayout(); + } + + private void setupEndValues() { + if (currentAnimation != null) { + currentAnimation.cancel(); + } + for (int i = 0; i < animAddingSpans.size(); ++i) { + animAddingSpans.get(i).setScaleX(1f); + animAddingSpans.get(i).setScaleY(1f); + animAddingSpans.get(i).setAlpha(1f); + } + for (int i = 0; i < animRemovingSpans.size(); ++i) { + animRemovingSpans.get(i).setScaleX(0f); + animRemovingSpans.get(i).setScaleY(0f); + animRemovingSpans.get(i).setAlpha(0f); + } + animAddingSpans.clear(); + animRemovingSpans.clear(); + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java new file mode 100644 index 000000000..5fd143334 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/selector/SelectorUserCell.java @@ -0,0 +1,189 @@ +package org.telegram.ui.Components.Premium.boosts.cells.selector; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.Gravity; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CheckBox2; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.boosts.cells.BaseCell; + +import java.util.Date; + +@SuppressLint("ViewConstructor") +public class SelectorUserCell extends BaseCell { + + private final boolean[] isOnline = new boolean[1]; + private final CheckBox2 checkBox; + private TLRPC.User user; + private TLRPC.Chat chat; + private TL_stories.TL_myBoost boost; + + public SelectorUserCell(Context context, Theme.ResourcesProvider resourcesProvider, boolean isGreen) { + super(context, resourcesProvider); + titleTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + radioButton.setVisibility(View.GONE); + checkBox = new CheckBox2(context, 21, resourcesProvider); + if (isGreen) { + checkBox.setColor(Theme.key_checkbox, Theme.key_checkboxDisabled, Theme.key_dialogRoundCheckBoxCheck); + } else { + checkBox.setColor(Theme.key_dialogRoundCheckBox, Theme.key_checkboxDisabled, Theme.key_dialogRoundCheckBoxCheck); + } + checkBox.setDrawUnchecked(true); + checkBox.setDrawBackgroundAsArc(10); + addView(checkBox); + checkBox.setChecked(false, false); + checkBox.setLayoutParams(LayoutHelper.createFrame(24, 24, Gravity.CENTER_VERTICAL | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 13, 0, 14, 0)); + } + + public TLRPC.User getUser() { + return user; + } + + public TLRPC.Chat getChat() { + return chat; + } + + public TL_stories.TL_myBoost getBoost() { + return boost; + } + + public void setChecked(boolean checked, boolean animated) { + if (checkBox.getVisibility() == View.VISIBLE) { + checkBox.setChecked(checked, animated); + } + } + + public void setCheckboxAlpha(float alpha, boolean animated) { + if (animated) { + if (Math.abs(checkBox.getAlpha() - alpha) > .1) { + checkBox.animate().cancel(); + checkBox.animate().alpha(alpha).start(); + } + } else { + checkBox.animate().cancel(); + checkBox.setAlpha(alpha); + } + } + + public void setUser(TLRPC.User user) { + this.user = user; + this.chat = null; + avatarDrawable.setInfo(user); + imageView.setRoundRadius(dp(20)); + imageView.setForUserOrChat(user, avatarDrawable); + titleTextView.setText(UserObject.getUserName(user)); + isOnline[0] = false; + setSubtitle(LocaleController.formatUserStatus(UserConfig.selectedAccount, user, isOnline)); + subtitleTextView.setTextColor(Theme.getColor(isOnline[0] ? Theme.key_dialogTextBlue2 : Theme.key_dialogTextGray3, resourcesProvider)); + checkBox.setAlpha(1f); + } + + public void setChat(TLRPC.Chat chat, int participants_count) { + this.chat = chat; + this.user = null; + avatarDrawable.setInfo(chat); + imageView.setRoundRadius(dp(ChatObject.isForum(chat) ? 12 : 20)); + imageView.setForUserOrChat(chat, avatarDrawable); + + titleTextView.setText(chat.title); + + String subtitle; + if (participants_count <= 0) { + participants_count = chat.participants_count; + } + if (participants_count >= 1) { + subtitle = LocaleController.formatPluralString("Subscribers", participants_count); + } else { + subtitle = LocaleController.getString(R.string.DiscussChannel); + } + setSubtitle(subtitle); + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + setCheckboxAlpha(participants_count > 200 ? .3f : 1f, false); + } + + public void setBoost(TL_stories.TL_myBoost boost) { + this.boost = boost; + this.chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-DialogObject.getPeerDialogId(boost.peer)); + + avatarDrawable.setInfo(chat); + imageView.setRoundRadius(dp(20)); + imageView.setForUserOrChat(chat, avatarDrawable); + + titleTextView.setText(chat.title); + + subtitleTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3, resourcesProvider)); + setSubtitle(LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.getInstance().formatterBoostExpired.format(new Date(boost.expires * 1000L)))); + + if (boost.cooldown_until_date > 0) { + long diff = boost.cooldown_until_date * 1000L - System.currentTimeMillis(); + setSubtitle(LocaleController.formatString("BoostingAvailableIn", R.string.BoostingAvailableIn, buildCountDownTime(diff))); + titleTextView.setAlpha(0.65f); + subtitleTextView.setAlpha(0.65f); + setCheckboxAlpha(0.3f, false); + } else { + titleTextView.setAlpha(1f); + subtitleTextView.setAlpha(1f); + setCheckboxAlpha(1f, false); + } + } + + public void updateTimer() { + if (boost.cooldown_until_date > 0) { + long diff = boost.cooldown_until_date * 1000L - System.currentTimeMillis(); + setSubtitle(LocaleController.formatString("BoostingAvailableIn", R.string.BoostingAvailableIn, buildCountDownTime(diff))); + titleTextView.setAlpha(0.65f); + subtitleTextView.setAlpha(0.65f); + setCheckboxAlpha(0.3f, false); + } else { + setSubtitle(LocaleController.formatString("BoostExpireOn", R.string.BoostExpireOn, LocaleController.getInstance().formatterBoostExpired.format(new Date(boost.expires * 1000L)))); + if (titleTextView.getAlpha() < 1f) { + titleTextView.animate().alpha(1f).start(); + subtitleTextView.animate().alpha(1f).start(); + setCheckboxAlpha(1f, true); + } else { + titleTextView.setAlpha(1f); + subtitleTextView.setAlpha(1f); + setCheckboxAlpha(1f, false); + } + } + } + + private String buildCountDownTime(long diff) { + long oneHourMs = 3600 * 1000; + long oneMinuteMs = 60 * 1000; + long oneSecondMs = 1000; + long hours = diff / oneHourMs; + long minutes = (diff % oneHourMs) / oneMinuteMs; + long seconds = ((diff % oneHourMs) % oneMinuteMs) / oneSecondMs; + + StringBuilder stringBuilder = new StringBuilder(); + if (hours > 0) { + stringBuilder.append(String.format("%02d", hours)); + stringBuilder.append(":"); + } + stringBuilder.append(String.format("%02d", minutes)); + stringBuilder.append(":"); + stringBuilder.append(String.format("%02d", seconds)); + return stringBuilder.toString(); + } + + @Override + protected boolean needCheck() { + return true; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/CounterDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/CounterDrawable.java new file mode 100644 index 000000000..b13d4706e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/CounterDrawable.java @@ -0,0 +1,82 @@ +package org.telegram.ui.Components.Premium.boosts.cells.statistics; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.TextPaint; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.R; + +public class CounterDrawable extends Drawable { + + private final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final Paint bgPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private final RectF bgRoundRect = new RectF(); + private final Drawable icon; + private float textWith; + private String text; + + public CounterDrawable(Context context) { + textPaint.setColor(Color.WHITE); + textPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + textPaint.setTextSize(dp(12)); + bgPaint.setColor(0xFF967bff); + icon = ContextCompat.getDrawable(context, R.drawable.mini_boost_badge); + } + + public void setText(String text) { + this.text = text; + textWith = textPaint.measureText(text); + invalidateSelf(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + Rect bounds = getBounds(); + bgRoundRect.set(bounds.left, bounds.top, bounds.right, bounds.bottom); + canvas.drawRoundRect(bgRoundRect, dp(12), dp(12), bgPaint); + icon.setBounds(bounds.left + dp(2), bounds.top + dp(1), bounds.left + dp(2) + icon.getIntrinsicWidth(), getBounds().top + dp(1) + icon.getIntrinsicHeight()); + icon.draw(canvas); + if (text != null) { + canvas.drawText(text, dp(16.5f) + bounds.left, bounds.top + dp(13f), textPaint); + } + } + + @Override + public void setAlpha(int alpha) { + + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.OPAQUE; + } + + @Override + public int getIntrinsicWidth() { + return (int) (dp(23) + textWith); + } + + @Override + public int getIntrinsicHeight() { + return dp(18); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java new file mode 100644 index 000000000..25e663472 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiftedUserCell.java @@ -0,0 +1,141 @@ +package org.telegram.ui.Components.Premium.boosts.cells.statistics; + +import static org.telegram.tgnet.tl.TL_stories.TL_boost.NO_USER_ID; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.UserCell; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.Date; + +@SuppressLint("ViewConstructor") +public class GiftedUserCell extends UserCell { + + private TextView badgeTextView; + private FrameLayout badgeLayout; + private Drawable giveawayDrawable; + private Drawable giftDrawable; + private TL_stories.TL_boost boost; + private CounterDrawable counterDrawable; + + public GiftedUserCell(Context context, int padding, int checkbox, boolean admin) { + super(context, padding, checkbox, admin); + init(); + } + + public GiftedUserCell(Context context, int padding, int checkbox, boolean admin, Theme.ResourcesProvider resourcesProvider) { + super(context, padding, checkbox, admin, resourcesProvider); + init(); + } + + public GiftedUserCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton) { + super(context, padding, checkbox, admin, needAddButton); + init(); + } + + public GiftedUserCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton, Theme.ResourcesProvider resourcesProvider) { + super(context, padding, checkbox, admin, needAddButton, resourcesProvider); + init(); + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(70), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(70) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + } + + public TL_stories.TL_boost getBoost() { + return boost; + } + + private void init() { + counterDrawable = new CounterDrawable(getContext()); + badgeLayout = new FrameLayout(getContext()); + badgeTextView = new TextView(getContext()); + badgeTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + badgeTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + badgeTextView.setTextSize(12); + badgeTextView.setGravity(Gravity.CENTER); + badgeLayout.addView(badgeTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 22)); + badgeLayout.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), 0); + addView(badgeLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? 9 : 0), 9, (LocaleController.isRTL ? 0 : 9), 0)); + } + + public void setStatus(TL_stories.TL_boost boost) { + this.boost = boost; + if ((boost.gift || boost.giveaway)) { + badgeLayout.setVisibility(VISIBLE); + if (boost.unclaimed) { + nameTextView.setText(LocaleController.getString("BoostingUnclaimed", R.string.BoostingUnclaimed)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_UNCLAIMED); + avatarDrawable.setColor(0xFF9ad164, 0xFF49ba44); + avatarImageView.setForUserOrChat(null, avatarDrawable); + nameTextView.setRightDrawable(null); + } else if (boost.user_id == NO_USER_ID) { + nameTextView.setText(LocaleController.getString("BoostingToBeDistributed", R.string.BoostingToBeDistributed)); + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_TO_BE_DISTRIBUTED); + avatarDrawable.setColor(0xFF5caefa, 0xFF418bd0); + avatarImageView.setForUserOrChat(null, avatarDrawable); + nameTextView.setRightDrawable(null); + } + String date = LocaleController.getInstance().formatterScheduleDay.format(new Date(boost.date * 1000L)); + String time = LocaleController.getInstance().formatterDay.format(new Date(boost.date * 1000L)); + int months = (boost.expires - boost.date) / 30 / 86400; + statusTextView.setText(months + "m • " + LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, date, time)); + if (boost.gift) { + if (giftDrawable == null) { + giftDrawable = getResources().getDrawable(R.drawable.mini_gift); + giftDrawable.setColorFilter(new PorterDuffColorFilter(0xFFce8e1f, PorterDuff.Mode.MULTIPLY)); + } + badgeTextView.setTextColor(0xFFce8e1f); + badgeTextView.setCompoundDrawablesWithIntrinsicBounds(giftDrawable, null, null, null); + badgeTextView.setCompoundDrawablePadding(AndroidUtilities.dp(4)); + badgeTextView.setText(LocaleController.getString("BoostingGift", R.string.BoostingGift)); + badgeLayout.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(12), AndroidUtilities.dp(12), Theme.multAlpha(0xFFce8e1f, 0.2f))); + } + if (boost.giveaway) { + if (giveawayDrawable == null) { + giveawayDrawable = getResources().getDrawable(R.drawable.mini_giveaway); + giveawayDrawable.setColorFilter(new PorterDuffColorFilter(0XFF3391d4, PorterDuff.Mode.MULTIPLY)); + } + badgeTextView.setTextColor(0XFF3391d4); + badgeTextView.setCompoundDrawablesWithIntrinsicBounds(giveawayDrawable, null, null, null); + badgeTextView.setCompoundDrawablePadding(AndroidUtilities.dp(4)); + badgeTextView.setText(LocaleController.getString("BoostingGiveaway", R.string.BoostingGiveaway)); + badgeLayout.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(12), AndroidUtilities.dp(12), Theme.multAlpha(0XFF3391d4, 0.2f))); + } + } else { + badgeLayout.setVisibility(GONE); + } + + if (boost.multiplier > 0) { + counterDrawable.setText(String.valueOf(boost.multiplier)); + nameTextView.setRightDrawable(counterDrawable); + } else { + nameTextView.setRightDrawable(null); + } + + if (badgeLayout.getVisibility() == VISIBLE) { + int badgeWidth = (int) badgeTextView.getPaint().measureText(badgeTextView.getText().toString()) + AndroidUtilities.dp(22); + nameTextView.setPadding(LocaleController.isRTL ? badgeWidth : 0, nameTextView.getPaddingTop(), LocaleController.isRTL ? 0 : badgeWidth, nameTextView.getPaddingBottom()); + } else { + nameTextView.setPadding(0, nameTextView.getPaddingTop(), 0, nameTextView.getPaddingBottom()); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiveawayCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiveawayCell.java new file mode 100644 index 000000000..6cf58cd12 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/boosts/cells/statistics/GiveawayCell.java @@ -0,0 +1,84 @@ +package org.telegram.ui.Components.Premium.boosts.cells.statistics; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.text.TextPaint; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.UserCell; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; + +@SuppressLint("ViewConstructor") +public class GiveawayCell extends UserCell { + private CounterDrawable counterDrawable; + private TL_stories.TL_prepaidGiveaway prepaidGiveaway; + + public GiveawayCell(Context context, int padding, int checkbox, boolean admin) { + super(context, padding, checkbox, admin); + init(context); + } + + public GiveawayCell(Context context, int padding, int checkbox, boolean admin, Theme.ResourcesProvider resourcesProvider) { + super(context, padding, checkbox, admin, resourcesProvider); + init(context); + } + + public GiveawayCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton) { + super(context, padding, checkbox, admin, needAddButton); + init(context); + } + + public GiveawayCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton, Theme.ResourcesProvider resourcesProvider) { + super(context, padding, checkbox, admin, needAddButton, resourcesProvider); + init(context); + } + + @Override + protected void onDraw(Canvas canvas) { + if (needDivider) { + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(70), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(70) : 0), getMeasuredHeight() - 1, Theme.dividerPaint); + } + } + + private void init(Context context) { + counterDrawable = new CounterDrawable(context); + } + + public TL_stories.TL_prepaidGiveaway getPrepaidGiveaway() { + return prepaidGiveaway; + } + + public void setImage(TL_stories.TL_prepaidGiveaway prepaidGiveaway) { + this.prepaidGiveaway = prepaidGiveaway; + avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_GIFT); + if (prepaidGiveaway.months == 12) { + avatarDrawable.setColor(0xFFff8560, 0xFFd55246); + } else if (prepaidGiveaway.months == 6) { + avatarDrawable.setColor(0xFF5caefa, 0xFF418bd0); + } else { + avatarDrawable.setColor(0xFF9ad164, 0xFF49ba44); + } + String counterStr = String.valueOf(prepaidGiveaway.quantity * BoostRepository.giveawayBoostsPerPremium()); + counterDrawable.setText(counterStr); + nameTextView.setRightDrawable(counterDrawable); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java index 3e95a75a8..346bdbed8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -69,6 +69,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio private ImageLocation prevImageLocation; private ImageLocation prevThumbLocation; private VectorAvatarThumbDrawable prevVectorAvatarThumbDrawable; + + private MessagesController.DialogPhotos dialogPhotos; private ArrayList videoFileNames = new ArrayList<>(); private ArrayList thumbsFileNames = new ArrayList<>(); private ArrayList photos = new ArrayList<>(); @@ -173,26 +175,28 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio BackupImageView imageView = (BackupImageView) child; ImageReceiver imageReceiver = imageView.getImageReceiver(); boolean currentAllow = imageReceiver.getAllowStartAnimation(); - if (p == position) { - if (!currentAllow) { - imageReceiver.setAllowStartAnimation(true); - imageReceiver.startAnimation(); - } - ImageLocation location = videoLocations.get(p); - if (location != null) { - FileLoader.getInstance(currentAccount).setForceStreamLoadingFile(location.location, "mp4"); - } - } else { - if (currentAllow) { - AnimatedFileDrawable fileDrawable = imageReceiver.getAnimation(); - if (fileDrawable != null) { - ImageLocation location = videoLocations.get(p); - if (location != null) { - fileDrawable.seekTo(location.videoSeekTo, false, true); - } + if (p >= 0 && p < videoLocations.size()) { + if (p == position) { + if (!currentAllow) { + imageReceiver.setAllowStartAnimation(true); + imageReceiver.startAnimation(); + } + ImageLocation location = videoLocations.get(p); + if (location != null) { + FileLoader.getInstance(currentAccount).setForceStreamLoadingFile(location.location, "mp4"); + } + } else { + if (currentAllow) { + AnimatedFileDrawable fileDrawable = imageReceiver.getAnimation(); + if (fileDrawable != null) { + ImageLocation location = videoLocations.get(p); + if (location != null) { + fileDrawable.seekTo(location.videoSeekTo, false, true); + } + } + imageReceiver.setAllowStartAnimation(false); + imageReceiver.stopAnimation(); } - imageReceiver.setAllowStartAnimation(false); - imageReceiver.stopAnimation(); } } } @@ -201,10 +205,14 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @Override public void onPageSelected(int position) { + boolean forward = position >= selectedPage; if (position != selectedPage) { prevPage = selectedPage; selectedPage = position; } + if (dialogPhotos != null) { + dialogPhotos.loadAfter(position - (adapter != null ? adapter.getExtraCount() : 0), forward); + } } @Override @@ -219,6 +227,9 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadDialogPhotos); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogPhotosUpdate); + + dialogPhotos = null; } private void checkCustomAvatar(int position, float positionOffset) { @@ -231,9 +242,9 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } if (p == index) { progressToCustomAvatar = 1f - positionOffset; - } else if ((p - 1) % getRealCount() == index) { + } else if (getRealCount() > 0 && (p - 1) % getRealCount() == index) { progressToCustomAvatar = 1f - positionOffset - 1f; - } else if ((p + 1) % getRealCount() == index) { + } else if (getRealCount() > 0 && (p + 1) % getRealCount() == index) { progressToCustomAvatar = 1f - positionOffset + 1f; } @@ -286,26 +297,28 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio BackupImageView imageView = (BackupImageView) child; ImageReceiver imageReceiver = imageView.getImageReceiver(); boolean currentAllow = imageReceiver.getAllowStartAnimation(); - if (p == position) { - if (!currentAllow) { - imageReceiver.setAllowStartAnimation(true); - imageReceiver.startAnimation(); - } - ImageLocation location = videoLocations.get(p); - if (location != null) { - FileLoader.getInstance(currentAccount).setForceStreamLoadingFile(location.location, "mp4"); - } - } else { - if (currentAllow) { - AnimatedFileDrawable fileDrawable = imageReceiver.getAnimation(); - if (fileDrawable != null) { - ImageLocation location = videoLocations.get(p); - if (location != null) { - fileDrawable.seekTo(location.videoSeekTo, false, true); - } + if (p >= 0 && p < videoLocations.size()) { + if (p == position) { + if (!currentAllow) { + imageReceiver.setAllowStartAnimation(true); + imageReceiver.startAnimation(); + } + ImageLocation location = videoLocations.get(p); + if (location != null) { + FileLoader.getInstance(currentAccount).setForceStreamLoadingFile(location.location, "mp4"); + } + } else { + if (currentAllow) { + AnimatedFileDrawable fileDrawable = imageReceiver.getAnimation(); + if (fileDrawable != null) { + ImageLocation location = videoLocations.get(p); + if (location != null) { + fileDrawable.seekTo(location.videoSeekTo, false, true); + } + } + imageReceiver.setAllowStartAnimation(false); + imageReceiver.stopAnimation(); } - imageReceiver.setAllowStartAnimation(false); - imageReceiver.stopAnimation(); } } } @@ -315,10 +328,14 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @Override public void onPageSelected(int position) { + boolean forward = position >= selectedPage; if (position != selectedPage) { prevPage = selectedPage; selectedPage = position; } + if (dialogPhotos != null) { + dialogPhotos.loadAfter(position - (adapter != null ? adapter.getExtraCount() : 0), forward); + } } @Override @@ -331,7 +348,10 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadDialogPhotos); - MessagesController.getInstance(currentAccount).loadDialogPhotos(dialogId, 80, 0, true, parentClassGuid); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogPhotosUpdate); + + dialogPhotos = MessagesController.getInstance(currentAccount).getDialogPhotos(dialogId); + dialogPhotos.loadCache(); } public void onDestroy() { @@ -340,6 +360,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.reloadDialogPhotos); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogPhotosUpdate); + int count = getChildCount(); for (int a = 0; a < count; a++) { View child = getChildAt(a); @@ -402,8 +424,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (pinchToZoomHelper != null && getCurrentItemView() != null) { if (action != MotionEvent.ACTION_DOWN && isDownReleased && !pinchToZoomHelper.isInOverlayMode()) { - pinchToZoomHelper.checkPinchToZoom(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0), this, getCurrentItemView().getImageReceiver(), null,null); - } else if (pinchToZoomHelper.checkPinchToZoom(ev, this, getCurrentItemView().getImageReceiver(), null,null)) { + pinchToZoomHelper.checkPinchToZoom(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0), this, getCurrentItemView().getImageReceiver(), null, null, null); + } else if (pinchToZoomHelper.checkPinchToZoom(ev, this, getCurrentItemView().getImageReceiver(), null, null,null)) { if (!isDownReleased) { isDownReleased = true; callback.onRelease(); @@ -424,18 +446,21 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio isDownReleased = false; } else if (action == MotionEvent.ACTION_UP) { if (!isDownReleased) { - final int itemsCount = adapter.getCount(); + int itemsCount = dialogPhotos == null ? 0 : dialogPhotos.getCount(); + if (currentUploadingImageLocation != null) { + itemsCount++; + } int currentItem = getCurrentItem(); if (itemsCount > 1) { if (ev.getX() > getWidth() / 3f) { final int extraCount = adapter.getExtraCount(); - if (++currentItem >= itemsCount - extraCount) { + if (++currentItem >= itemsCount + extraCount) { currentItem = extraCount; } } else { final int extraCount = adapter.getExtraCount(); if (--currentItem < extraCount) { - currentItem = itemsCount - extraCount - 1; + currentItem = itemsCount + extraCount - 1; } } callback.onRelease(); @@ -495,7 +520,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio public void setChatInfo(TLRPC.ChatFull chatFull) { chatInfo = chatFull; - if (!photos.isEmpty() && photos.get(0) == null && chatInfo != null && FileLoader.isSamePhoto(imagesLocations.get(0).location, chatInfo.chat_photo)) { + if (!photos.isEmpty() && photos.get(0) == null && chatInfo != null && imagesLocations.get(0) != null && FileLoader.isSamePhoto(imagesLocations.get(0).location, chatInfo.chat_photo)) { photos.set(0, chatInfo.chat_photo); if (!chatInfo.chat_photo.video_sizes.isEmpty()) { final TLRPC.VideoSize videoSize = FileLoader.getClosestVideoSizeWithSize(chatInfo.chat_photo.video_sizes, 1000); @@ -518,13 +543,15 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (prevImageLocation == null || prevImageLocation.location.local_id != imageLocation.location.local_id) { if (!imagesLocations.isEmpty()) { prevImageLocation = imageLocation; - if (reload) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(dialogId, 80, 0, true, parentClassGuid); + if (reload && dialogPhotos != null) { + dialogPhotos.reset(); + dialogPhotos.loadAfter(getCurrentItem() - (adapter != null ? adapter.getExtraCount() : 0), true); } return true; } else { - if (reload) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(dialogId, 80, 0, true, parentClassGuid); + if (reload && dialogPhotos != null) { + dialogPhotos.reset(); + dialogPhotos.loadAfter(getCurrentItem() - (adapter != null ? adapter.getExtraCount() : 0), true); } } } @@ -567,7 +594,6 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio currentUploadingImageLocation = imageLocation; curreantUploadingThumbLocation = thumbLocation; - } public void removeUploadingImage(ImageLocation imageLocation) { @@ -645,6 +671,9 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } i--; } + if (i < 0 || i >= videoLocations.size()) { + return false; + } return videoLocations.get(i) != null; } @@ -712,10 +741,17 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } public void startMovePhotoToBegin(int index) { + if (dialogPhotos != null) { + dialogPhotos.moveToStart(index); + return; + } + if (index <= 0 || index >= photos.size()) { return; } + settingMainPhoto++; + TLRPC.Photo photo = photos.get(index); photos.remove(index); photos.add(0, photo); @@ -762,22 +798,28 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (index < 0 || index >= photos.size()) { return false; } - photos.remove(index); - thumbsFileNames.remove(index); - videoFileNames.remove(index); - videoLocations.remove(index); - imagesLocations.remove(index); - thumbsLocations.remove(index); - vectorAvatars.remove(index); - imagesLocationsSizes.remove(index); - radialProgresses.delete(index); - imagesUploadProgress.remove(index); - if (index == 0 && !imagesLocations.isEmpty()) { - prevImageLocation = imagesLocations.get(0); - prevThumbLocation = null; - prevVectorAvatarThumbDrawable = null; + TLRPC.Photo photo = photos.get(index); + if (photo != null && dialogPhotos != null) { + dialogPhotos.removePhoto(photo.id); + return true; + } else { + photos.remove(index); + thumbsFileNames.remove(index); + videoFileNames.remove(index); + videoLocations.remove(index); + imagesLocations.remove(index); + thumbsLocations.remove(index); + vectorAvatars.remove(index); + imagesLocationsSizes.remove(index); + radialProgresses.delete(index); + imagesUploadProgress.remove(index); + if (index == 0 && !imagesLocations.isEmpty()) { + prevImageLocation = imagesLocations.get(0); + prevThumbLocation = null; + prevVectorAvatarThumbDrawable = null; + } + adapter.notifyDataSetChanged(); } - adapter.notifyDataSetChanged(); return photos.isEmpty(); } @@ -805,20 +847,18 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.dialogPhotosLoaded) { - int guid = (Integer) args[3]; - long did = (Long) args[0]; - if (did == dialogId && parentClassGuid == guid && adapter != null) { - boolean fromCache = (Boolean) args[2]; - ArrayList arrayList = new ArrayList<>((ArrayList) args[4]); - if (arrayList.isEmpty() && fromCache) { + if (id == NotificationCenter.dialogPhotosUpdate) { + MessagesController.DialogPhotos dialogPhotos = (MessagesController.DialogPhotos) args[0]; + if (this.dialogPhotos == dialogPhotos) { + ArrayList arrayList = new ArrayList<>(dialogPhotos.photos); + if (arrayList.isEmpty() && dialogPhotos.fromCache) { return; } customAvatarIndex = -1; fallbackPhotoIndex = -1; - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(did); - TLRPC.UserFull fullUser = MessagesController.getInstance(currentAccount).getUserFull(did); + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + TLRPC.UserFull fullUser = MessagesController.getInstance(currentAccount).getUserFull(dialogId); if (fullUser != null && fullUser.personal_photo != null) { arrayList.add(0, fullUser.personal_photo); customAvatarIndex = 0; @@ -839,8 +879,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio imagesLocationsSizes.clear(); imagesUploadProgress.clear(); ImageLocation currentImageLocation = null; - if (DialogObject.isChatDialog(did)) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-did); + if (DialogObject.isChatDialog(dialogId)) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); currentImageLocation = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_BIG, currentAccount); if (currentImageLocation != null) { imagesLocations.add(currentImageLocation); @@ -869,6 +909,15 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio for (int a = 0; a < arrayList.size(); a++) { TLRPC.Photo photo = arrayList.get(a); if (photo == null || photo instanceof TLRPC.TL_photoEmpty || photo.sizes == null) { + photos.add(null); + imagesLocations.add(null); + thumbsLocations.add(null); + vectorAvatars.add(null); + thumbsFileNames.add(null); + videoLocations.add(null); + videoFileNames.add(null); + imagesLocationsSizes.add(-1); + imagesUploadProgress.add(null); continue; } TLRPC.PhotoSize sizeThumb = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 50); @@ -983,9 +1032,6 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio forceResetPosition = false; - if (fromCache) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(did, 80, 0, false, parentClassGuid); - } if (callback != null) { callback.onPhotosLoaded(); } @@ -1005,6 +1051,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (radialProgress != null) { radialProgress.setProgress(1f, true); } + invalidate(); } } } else if (id == NotificationCenter.fileLoadProgressChanged) { @@ -1022,13 +1069,17 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio float progress = Math.min(1f, loadedSize / (float) totalSize); radialProgress.setProgress(progress, true); } + invalidate(); } } } else if (id == NotificationCenter.reloadDialogPhotos) { if (settingMainPhoto != 0) { return; } - MessagesController.getInstance(currentAccount).loadDialogPhotos(dialogId, 80, 0, true, parentClassGuid); + if (dialogPhotos != null) { + dialogPhotos.reset(); + dialogPhotos.loadAfter(getCurrentItem() - (adapter != null ? adapter.getExtraCount() : 0), true); + } } } @@ -1110,7 +1161,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio item.imageView.setImageDrawable(drawable); animatedFileDrawable.addSecondParentView(item.imageView); animatedFileDrawable.setInvalidateParentViewWithSecond(true); - } else { + } else if (imageLocationPosition >= 0 && imageLocationPosition < videoLocations.size()) { ImageLocation videoLocation = videoLocations.get(imageLocationPosition); item.imageView.isVideo = videoLocation != null; needProgress = vectorAvatars.get(imageLocationPosition) == null; @@ -1128,11 +1179,11 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio } else if (uploadingImageLocation != null) { item.imageView.setImageMedia(vectorAvatars.get(imageLocationPosition), videoLocations.get(imageLocationPosition), filter, imagesLocations.get(imageLocationPosition), null, uploadingImageLocation, null, null, imagesLocationsSizes.get(imageLocationPosition), 1, parent); } else { - String thumbFilter = location.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null; + String thumbFilter = location != null && location.photoSize instanceof TLRPC.TL_photoStrippedSize ? "b" : null; item.imageView.setImageMedia(vectorAvatars.get(imageLocationPosition), videoLocation, null, imagesLocations.get(imageLocationPosition), null, thumbsLocations.get(imageLocationPosition), thumbFilter, null, imagesLocationsSizes.get(imageLocationPosition), 1, parent); } } - } else { + } else if (imageLocationPosition >= 0 && imageLocationPosition < videoLocations.size()) { final ImageLocation videoLocation = videoLocations.get(imageLocationPosition); item.imageView.isVideo = videoLocation != null; needProgress = vectorAvatars.get(imageLocationPosition) == null; @@ -1141,7 +1192,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio String parent = "avatar_" + dialogId; item.imageView.setImageMedia(vectorAvatars.get(imageLocationPosition), videoLocation, null, imagesLocations.get(imageLocationPosition), null, thumbsLocations.get(imageLocationPosition), filter, null, imagesLocationsSizes.get(imageLocationPosition), 1, parent); } - if (imagesUploadProgress.get(imageLocationPosition) != null) { + if (imageLocationPosition >= 0 && imageLocationPosition < imagesUploadProgress.size() && imagesUploadProgress.get(imageLocationPosition) != null) { needProgress = true; } if (needProgress) { @@ -1201,7 +1252,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio @Nullable @Override public CharSequence getPageTitle(int position) { - return (getRealPosition(position) + 1) + "/" + (getCount() - getExtraCount() * 2); + return (getRealPosition(position) + 1) + "/" + (dialogPhotos == null ? 0 : dialogPhotos.getCount()); } @Override @@ -1217,7 +1268,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio if (hasActiveVideo) { size++; } - for (int a = 0, N = size + getExtraCount() * 2; a < N; a++) { + for (int a = 0, N = Math.max((dialogPhotos == null ? 0 : dialogPhotos.getCount()), size) + getExtraCount() * 2; a < N; a++) { objects.add(new Item()); imageViews.add(null); } @@ -1250,9 +1301,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio forceResetPosition = true; reset(); this.dialogId = dialogId; -// if (dialogId != 0) { -// MessagesController.getInstance(currentAccount).loadDialogPhotos(dialogId, 80, 0, true, parentClassGuid); -// } + dialogPhotos = MessagesController.getInstance(currentAccount).getDialogPhotos(dialogId); + dialogPhotos.loadCache(); } public long getDialogId() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java new file mode 100644 index 000000000..47ab9a8a8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteHighlight.java @@ -0,0 +1,209 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.lerp; + +import android.graphics.Canvas; +import android.graphics.CornerPathEffect; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; +import android.graphics.Xfermode; +import android.text.Layout; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.ViewParent; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MessageObject; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class QuoteHighlight extends Path { + + public final int id, start, end; + public final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path path = new Path(); + + private final AnimatedFloat t; + + private static class Rect { + public float left, right; + public float top, bottom; + + public boolean first, last; + public float prevTop; + public float nextBottom; + } + private final ArrayList rectangles = new ArrayList<>(); + + private float currentOffsetX, currentOffsetY; + private float minX; + + private Rect lastRect; + + public QuoteHighlight( + View view, ViewParent parent, + int id, + ArrayList blocks, + int start, int end, + float offsetX + ) { + this.t = new AnimatedFloat(0, () -> { + if (view != null) view.invalidate(); + if (parent instanceof View) ((View) parent).invalidate(); + }, 350, 420, CubicBezierInterpolator.EASE_OUT_QUINT); + this.id = id; + this.start = start; + this.end = end; + if (blocks == null) return; + + paint.setPathEffect(new CornerPathEffect(dp(4))); + + boolean isRtl = false; + for (int i = 0; i < blocks.size(); ++i) { + final MessageObject.TextLayoutBlock block = blocks.get(i); + if (block == null) continue; + if (start > block.charactersEnd || end < block.charactersOffset) continue; + + final int blockStart = Math.max(0, start - block.charactersOffset); + final int blockEnd = Math.min(end - block.charactersOffset, block.charactersEnd - block.charactersOffset); + + currentOffsetX = -offsetX; + currentOffsetY = block.textYOffset + block.padTop; + minX = block.quote ? dp(10) : 0; + + isRtl = isRtl || AndroidUtilities.isRTL(block.textLayout.getText()); + if (isRtl) { + block.textLayout.getSelectionPath(blockStart, blockEnd, this); + } else { + getSelectionPath(block.textLayout, blockStart, blockEnd); + } + } + + if (rectangles.size() > 0) { + Rect firstRect = rectangles.get(0); + Rect lastRect = rectangles.get(rectangles.size() - 1); + + firstRect.first = true; + firstRect.top -= dp(.66f); + + lastRect.last = true; + lastRect.bottom += dp(.66f); + } + } + + private void getSelectionPath(Layout layout, int start, int end) { + if (start == end) { + return; + } + + if (end < start) { + int temp = end; + end = start; + start = temp; + } + + final int startline = layout.getLineForOffset(start); + final int endline = layout.getLineForOffset(end); + + for (int line = startline; line <= endline; ++line) { + final int lineStart = layout.getLineStart(line); + final int lineEnd = layout.getLineEnd(line); + + if (lineEnd == lineStart) + continue; + if (lineStart + 1 == lineEnd && Character.isWhitespace(layout.getText().charAt(lineStart))) + continue; + + final float left, right; + if (line == startline && start > lineStart) { + left = layout.getPrimaryHorizontal(start); + } else { + left = layout.getLineLeft(line); + } + if (line == endline && end < lineEnd) { + right = layout.getPrimaryHorizontal(end); + } else { + right = layout.getLineRight(line); + } + + addRect( + Math.min(left, right), + layout.getLineTop(line), + Math.max(left, right), + layout.getLineBottom(line) + ); + } + } + + public float getT() { + return this.t.set(1); + } + + public void draw(Canvas canvas, float textX, float textY, android.graphics.Rect bounds, float alpha) { + final float t = this.t.set(1); + + canvas.save(); + canvas.translate(textX, textY); + path.rewind(); + for (int i = 0; i < rectangles.size(); ++i) { + final Rect rect = rectangles.get(i); + path.addRect( + lerp(bounds.left - textX, rect.left, t), + lerp(rect.first ? bounds.top - textY : rect.prevTop, rect.top, t), + lerp(bounds.right - textX, rect.right, t), + lerp(rect.last ? bounds.bottom - textY : rect.nextBottom, rect.bottom, t), + Path.Direction.CW + ); + } + + int wasAlpha = paint.getAlpha(); + paint.setAlpha((int) (wasAlpha * alpha)); + canvas.drawPath(path, paint); + paint.setAlpha(wasAlpha); + canvas.restore(); + } + + @Override + public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) { + addRect(left, top, right, bottom); + } + + public void addRect(float left, float top, float right, float bottom) { + if (left >= right) { + return; + } +// if (lastRect != null && Math.abs(lastRect.top - top) < 1f) { +// lastRect.left = Math.min(lastRect.left, left); +// lastRect.right = Math.min(lastRect.right, right); +// return; +// } + + left = Math.max(minX, left); + right = Math.max(minX, right); + + left += currentOffsetX; + top += currentOffsetY; + right += currentOffsetX; + bottom += currentOffsetY; + + Rect rect = new Rect(); + rect.left = left - dp(3); + rect.right = right + dp(3); + rect.top = top; + rect.bottom = bottom; + if (lastRect != null) { + lastRect.nextBottom = (lastRect.bottom + top) / 2f; + rect.prevTop = (lastRect.bottom + top) / 2f; + } + rectangles.add(rect); + lastRect = rect; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteSpan.java new file mode 100644 index 000000000..6612fbf09 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/QuoteSpan.java @@ -0,0 +1,331 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.os.Parcel; +import android.text.Editable; +import android.text.Layout; +import android.text.ParcelableSpan; +import android.text.Spannable; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.text.style.LeadingMarginSpan; +import android.text.style.LineHeightSpan; +import android.text.style.MetricAffectingSpan; +import android.text.style.ParagraphStyle; +import android.text.style.ReplacementSpan; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.R; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class QuoteSpan implements LeadingMarginSpan { + + public final boolean edit; + public boolean adaptLineHeight = true; + public int start, end; + public boolean singleLine, first, last; + public boolean rtl; + + public final QuoteStyleSpan styleSpan; + + private final Drawable quoteDrawable; + + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final float[] backgroundPathRadii = new float[8]; + private final Path backgroundPath = new Path(); + + private final Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final float[] linePathRadii = new float[8]; + private final Path linePath = new Path(); + + private int color = Color.WHITE; + + public QuoteSpan(boolean edit, QuoteStyleSpan helperSpan) { + this.edit = edit; + this.styleSpan = helperSpan; + + quoteDrawable = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.mini_quote).mutate(); + linePaint.setColor(color); + backgroundPaint.setColor(ColorUtils.setAlphaComponent(color, 0x1e)); + } + + public void setColor(int color) { + if (this.color != color) { + quoteDrawable.setColorFilter(new PorterDuffColorFilter(this.color = color, PorterDuff.Mode.SRC_IN)); + linePaint.setColor(color); + backgroundPaint.setColor(ColorUtils.setAlphaComponent(color, 0x1e)); + } + } + + @Override + public int getLeadingMargin(boolean first) { + return AndroidUtilities.dp(adaptLineHeight ? 8 : 10); + } + + @Override + public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) { + + } + + public static class QuoteStyleSpan extends MetricAffectingSpan implements LineHeightSpan { + + @NonNull + public QuoteSpan span; + + @Override + public void updateDrawState(TextPaint tp) { + if (tp == null) { + return; + } + tp.setTextSize(AndroidUtilities.dp(span.edit ? 16 : SharedConfig.fontSize - 2)); + } + + @Override + public void updateMeasureState(@NonNull TextPaint tp) { + tp.setTextSize(AndroidUtilities.dp(span.edit ? 16 : SharedConfig.fontSize - 2)); + tp.setTextScaleX(span.edit ? 1.08f : 1f); + } + + @Override + public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) { + if (span.adaptLineHeight) { + final int dp = span.singleLine ? 7 : 2; + if (start <= span.start) { + fm.ascent -= AndroidUtilities.dp((span.last ? 2 : 0) + dp); + fm.top -= AndroidUtilities.dp((span.last ? 2 : 0) + dp); + } + if (end >= span.end) { + fm.descent += AndroidUtilities.dp(dp); + fm.bottom += AndroidUtilities.dp(dp); + } + } + } + } + + public static int putQuote(Spannable spannable, int start, int end) { + if (spannable == null) { + return -1; + } + QuoteSpan[] existingSpans = spannable.getSpans(start, end, QuoteSpan.class); + if (existingSpans != null && existingSpans.length > 0) { + return -1; + } + start = Utilities.clamp(start, spannable.length(), 0); + end = Utilities.clamp(end, spannable.length(), 0); + final QuoteStyleSpan styleSpan = new QuoteStyleSpan(); + final QuoteSpan quoteSpan = styleSpan.span = new QuoteSpan(false, styleSpan); + quoteSpan.start = start; + quoteSpan.end = end; + spannable.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(quoteSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return end; + } + + public static int putQuoteToEditable(Editable editable, int start, int end) { + if (editable == null) { + return -1; + } + start = Utilities.clamp(start, editable.length(), 0); + end = Utilities.clamp(end, editable.length(), 0); + if (start > 0 && editable.charAt(start - 1) != '\n') { + editable.insert(start, "\n"); + start++; + end++; + } + int selectEnd = end + 1; + if (end >= editable.length() || editable.charAt(end) != '\n') { + editable.insert(end, "\n"); + } + final QuoteStyleSpan styleSpan = new QuoteStyleSpan(); + final QuoteSpan quoteSpan = styleSpan.span = new QuoteSpan(true, styleSpan); + quoteSpan.start = start; + quoteSpan.end = end; + editable.setSpan(quoteSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editable.setSpan(styleSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + + editable.insert(end, "\uFEFF"); + editable.delete(end, end + 1); + + return selectEnd; + } + + public static ArrayList updateQuoteBlocks(Layout layout, ArrayList blocks) { + return updateQuoteBlocks(layout, blocks, null); + } + + public static ArrayList updateQuoteBlocks(Layout layout, ArrayList blocks, boolean[] updateLayout) { + if (layout == null) { + if (blocks != null) { + blocks.clear(); + } + return blocks; + } + CharSequence text = layout.getText(); + if (text == null || !(text instanceof Spannable)) { + if (blocks != null) { + blocks.clear(); + } + return blocks; + } + Spannable spannable = (Spannable) text; + if (blocks != null) { + blocks.clear(); + } + QuoteSpan[] spans = spannable.getSpans(0, spannable.length(), QuoteSpan.class); + for (int i = 0; i < spans.length; ++i) { + boolean wasLast = spans[i].last; + Block block = new Block(layout, spannable, spans[i]); + if (block.span.edit) { + if (!(block.span.start == 0 || text.charAt(block.span.start - 1) == '\n')) { + spannable.removeSpan(spans[i]); + spannable.removeSpan(spans[i].styleSpan); + continue; + } + if (!(block.span.end == text.length() || text.charAt(block.span.end) == '\n')) { + // new line was removed after a quote, finding a new quote end + int newEnd = block.span.end; + for (; newEnd <= text.length() && !(newEnd == text.length() || text.charAt(newEnd) == '\n'); ++newEnd); + spannable.removeSpan(spans[i]); + spannable.removeSpan(spans[i].styleSpan); + spannable.setSpan(spans[i], block.span.start, newEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + spannable.setSpan(spans[i].styleSpan, block.span.start, newEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + block = new Block(layout, spannable, spans[i]); + } + } + if (blocks == null) { + blocks = new ArrayList<>(); + } + if (spans[i].last != wasLast && updateLayout != null) { + updateLayout[0] = true; + } + blocks.add(block); + } + return blocks; + } + + public static ArrayList updateQuoteBlocksSpanned(Layout layout, ArrayList blocks) { + if (layout == null) { + if (blocks != null) { + blocks.clear(); + } + return blocks; + } + CharSequence text = layout.getText(); + if (text == null || !(text instanceof Spanned)) { + if (blocks != null) { + blocks.clear(); + } + return blocks; + } + Spanned spanned = (Spanned) text; + if (blocks != null) { + blocks.clear(); + } + QuoteSpan[] spans = spanned.getSpans(0, spanned.length(), QuoteSpan.class); + for (int i = 0; i < spans.length; ++i) { + boolean wasLast = spans[i].last; + Block block = new Block(layout, spanned, spans[i]); + if (blocks == null) { + blocks = new ArrayList<>(); + } + blocks.add(block); + } + return blocks; + } + + public static class Block { + public final int top, bottom, width; + public final @NonNull QuoteSpan span; + + public Block(Layout layout, Spanned spanned, @NonNull QuoteSpan span) { + this.span = span; + span.start = spanned.getSpanStart(span); + span.end = spanned.getSpanEnd(span); + final int lineStart = layout.getLineForOffset(span.start); + final int lineEnd = layout.getLineForOffset(span.end); + span.singleLine = lineEnd - lineStart < 1; + span.first = lineStart <= 0; + span.last = lineEnd + 1 >= layout.getLineCount(); + + if (span.edit) { + this.top = layout.getLineTop(lineStart) + AndroidUtilities.dp(3 - (span.singleLine ? 0 : 3 + (span.first ? 2 : 0))); + this.bottom = layout.getLineBottom(lineEnd) - AndroidUtilities.dp(2 - (span.singleLine ? 0 : 3 + (span.last ? 2 : 0))); + } else { + this.top = layout.getLineTop(lineStart) + AndroidUtilities.dp(3 - (span.singleLine ? 1 : 2)); + this.bottom = layout.getLineBottom(lineEnd) - AndroidUtilities.dp(2 - (span.singleLine ? 1 : 2)); + } + + float width = 0; + span.rtl = false; + for (int line = lineStart; line <= lineEnd; ++line) { + width = Math.max(width, layout.getLineRight(line)); + if (layout.getLineLeft(line) > 0) + span.rtl = true; + } + this.width = (int) Math.ceil(width); + } + + public void draw(Canvas canvas, float offsetY, int maxWidth, int color, float alpha) { + span.setColor(color); + + int width = span.edit ? maxWidth : (this.width + AndroidUtilities.dp(32)); + if (width >= maxWidth * 0.95) { + width = maxWidth; + } + + canvas.save(); + canvas.translate(0, offsetY); + + AndroidUtilities.rectTmp.set(0, top, width, bottom); + span.backgroundPathRadii[0] = span.backgroundPathRadii[1] = span.backgroundPathRadii[6] = span.backgroundPathRadii[7] = 0; // left + span.backgroundPathRadii[2] = span.backgroundPathRadii[3] = span.backgroundPathRadii[4] = span.backgroundPathRadii[5] = AndroidUtilities.dp(4); // right + span.backgroundPath.rewind(); + span.backgroundPath.addRoundRect(AndroidUtilities.rectTmp, span.backgroundPathRadii, Path.Direction.CW); + canvas.drawPath(span.backgroundPath, span.backgroundPaint); + + AndroidUtilities.rectTmp.set(-AndroidUtilities.dp(3), top, 0, bottom); + span.linePathRadii[0] = span.linePathRadii[1] = span.linePathRadii[6] = span.linePathRadii[7] = AndroidUtilities.dp(4); // left + span.linePathRadii[2] = span.linePathRadii[3] = span.linePathRadii[4] = span.linePathRadii[5] = 0; // right + span.linePath.rewind(); + span.linePath.addRoundRect(AndroidUtilities.rectTmp, span.linePathRadii, Path.Direction.CW); + canvas.drawPath(span.linePath, span.linePaint); + + if (!span.rtl) { + int quoteTop = (int) ((top + bottom - span.quoteDrawable.getIntrinsicHeight()) / 2f); + if (quoteTop > top + AndroidUtilities.dp(8)) { + quoteTop = top + AndroidUtilities.dp(4); + } + span.quoteDrawable.setBounds( + width - span.quoteDrawable.getIntrinsicWidth() - AndroidUtilities.dp(4), + quoteTop, + width - AndroidUtilities.dp(4), + quoteTop + span.quoteDrawable.getIntrinsicHeight() + ); + span.quoteDrawable.setAlpha((int) (0xFF * alpha)); + span.quoteDrawable.draw(canvas); + } + + canvas.restore(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsUtils.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsUtils.java index 239e57763..1e4f6ff22 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsUtils.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsUtils.java @@ -4,6 +4,7 @@ import android.text.SpannableStringBuilder; import android.text.TextUtils; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.AnimatedEmojiSpan; public class ReactionsUtils { @@ -57,7 +58,7 @@ public class ReactionsUtils { return ""; } - public static void applyForStoryViews(TLRPC.Reaction oldReaction, TLRPC.Reaction newReaction, TLRPC.StoryViews views) { + public static void applyForStoryViews(TLRPC.Reaction oldReaction, TLRPC.Reaction newReaction, TL_stories.StoryViews views) { boolean found = false; if (views == null) { return; 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 031d0f5a7..d9e7fbcba 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -59,6 +59,7 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -1087,7 +1088,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } } - public void setStoryItem(TLRPC.StoryItem storyItem) { + public void setStoryItem(TL_stories.StoryItem storyItem) { selectedReactions.clear(); if (storyItem != null && storyItem.sent_reaction != null) { selectedReactions.add(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(storyItem.sent_reaction)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplaceableIconDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplaceableIconDrawable.java index f6199deca..e8a188db7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplaceableIconDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplaceableIconDrawable.java @@ -45,6 +45,10 @@ public class ReplaceableIconDrawable extends Drawable implements Animator.Animat currentResId = resId; } + public Drawable getIcon() { + return currentDrawable; + } + public void setIcon(Drawable drawable, boolean animated) { if (drawable == null) { currentDrawable = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java new file mode 100644 index 000000000..e372d4c4e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReplyMessageLine.java @@ -0,0 +1,559 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.dpf2; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatMessageCell; + +public class ReplyMessageLine { + + private final RectF rectF = new RectF(); + private final Path clipPath = new Path(); + private final Paint color1Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint color2Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint color3Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + public final float[] radii = new float[8]; + private final Path lineClipPath = new Path(); + private final Path backgroundPath = new Path(); + private final Paint backgroundPaint = new Paint(); + private LoadingDrawable backgroundLoadingDrawable; + + public boolean hasColor2, hasColor3; + private boolean lastHasColor3; + private float lastHeight; + private Path color2Path = new Path(); + private Path color3Path = new Path(); + + private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable emoji; + + private long emojiDocumentId; + private int backgroundColor, nameColor, color1, color2, color3; + private final View parentView; + public final AnimatedColor backgroundColorAnimated; + public final AnimatedColor color1Animated, color2Animated, color3Animated; + public final AnimatedColor nameColorAnimated; + public final AnimatedFloat color2Alpha; + public final AnimatedFloat color3Alpha; + public final AnimatedFloat emojiLoadedT; + public final AnimatedFloat loadingStateT; + + public ReplyMessageLine(View view) { + this.parentView = view; + parentView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(@NonNull View v) { + if (emoji != null) { + emoji.attach(); + } + } + @Override + public void onViewDetachedFromWindow(@NonNull View v) { + if (emoji != null) { + emoji.detach(); + } + } + }); + + backgroundColorAnimated = new AnimatedColor(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + color1Animated = new AnimatedColor(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + color2Animated = new AnimatedColor(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + color3Animated = new AnimatedColor(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + nameColorAnimated = new AnimatedColor(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + color2Alpha = new AnimatedFloat(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + color3Alpha = new AnimatedFloat(view, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + emojiLoadedT = new AnimatedFloat(view, 0, 440, CubicBezierInterpolator.EASE_OUT_QUINT); + loadingStateT = new AnimatedFloat(view, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + } + + public int getColor() { + return reversedOut ? color2 : color1; + } + + public int getBackgroundColor() { + return backgroundColor; + } + + private void resolveColor(MessageObject messageObject, int colorId, Theme.ResourcesProvider resourcesProvider) { + if (colorId < 7) { + color1 = color2 = color3 = Theme.getColor(Theme.keys_avatar_nameInMessage[colorId], resourcesProvider); + hasColor2 = hasColor3 = false; + return; + } + final int currentAccount = messageObject != null ? messageObject.currentAccount : UserConfig.selectedAccount; + final MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + final MessagesController.PeerColor peerColor = peerColors != null ? peerColors.getColor(colorId) : null; + if (peerColor == null) { + color1 = color2 = color3 = Theme.getColor(messageObject != null && messageObject.isOutOwner() ? Theme.key_chat_outReplyLine : Theme.key_chat_inReplyLine, resourcesProvider); + hasColor2 = hasColor3 = false; + return; + } + color1 = peerColor.getColor1(); + color2 = peerColor.getColor2(); + color3 = peerColor.getColor3(); + hasColor2 = color2 != color1; + hasColor3 = color3 != color1; + if (hasColor3) { + int temp = color3; + color3 = color2; + color2 = temp; + } + } + + public int check(MessageObject messageObject, TLRPC.User currentUser, TLRPC.Chat currentChat, Theme.ResourcesProvider resourcesProvider, boolean isReply) { + reversedOut = false; + emojiDocumentId = 0; + if (messageObject == null) { + hasColor2 = hasColor3 = false; + color1 = color2 = color3 = Theme.getColor(Theme.key_chat_inReplyLine, resourcesProvider); + backgroundColor = Theme.multAlpha(color1, Theme.isCurrentThemeDark() ? 0.12f : 0.10f); + return nameColorAnimated.set(nameColor = Theme.getColor(Theme.key_chat_inReplyNameText, resourcesProvider)); + } else if (!isReply && ( + messageObject.overrideLinkColor >= 0 || + messageObject.messageOwner != null && ( + messageObject.isFromUser() && currentUser != null || + messageObject.isFromChannel() && currentChat != null || + messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite || + messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null + ) + )) { + int colorId; + if (messageObject.overrideLinkColor >= 0) { + colorId = messageObject.overrideLinkColor; + } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite instanceof TLRPC.TL_chatInvite) { + colorId = messageObject.sponsoredChatInvite.color; + } else if (messageObject.isSponsored() && messageObject.sponsoredChatInvite != null && messageObject.sponsoredChatInvite.chat != null) { + if ((messageObject.sponsoredChatInvite.chat.flags2 & 64) != 0) { + colorId = messageObject.sponsoredChatInvite.chat.color; + } else { + colorId = (int) (messageObject.sponsoredChatInvite.chat.id % 7); + } + } else if (messageObject.isFromUser() && currentUser != null) { + if ((currentUser.flags2 & 128) != 0) { + colorId = currentUser.color; + } else { + colorId = (int) (currentUser.id % 7); + } + } else if (messageObject.isFromChannel() && currentChat != null) { + if ((currentChat.flags2 & 64) != 0) { + colorId = currentChat.color; + } else { + colorId = (int) (currentChat.id % 7); + } + } else { + colorId = 0; + } + resolveColor(messageObject, colorId, resourcesProvider); + backgroundColor = Theme.multAlpha(color1, 0.10f); + nameColor = color1; + } else if (isReply && ( + messageObject.overrideLinkColor >= 0 || + messageObject.messageOwner != null && + messageObject.replyMessageObject != null && + messageObject.messageOwner.reply_to != null && (messageObject.messageOwner.reply_to.reply_from == null || TextUtils.isEmpty(messageObject.messageOwner.reply_to.reply_from.from_name)) && + messageObject.replyMessageObject.messageOwner != null && + messageObject.replyMessageObject.messageOwner.from_id != null && ( + messageObject.replyMessageObject.isFromUser() || + messageObject.replyMessageObject.isFromChannel() + ))) { + int colorId; + if (messageObject.overrideLinkColor >= 0) { + colorId = messageObject.overrideLinkColor; + } else if (messageObject.replyMessageObject.isFromUser()) { + TLRPC.User user = MessagesController.getInstance(messageObject.currentAccount).getUser(messageObject.replyMessageObject.messageOwner.from_id.user_id); + if (user != null) { + colorId = (user.flags2 & 128) != 0 ? user.color : (int) (user.id % 7); + if ((user.flags2 & 64) != 0) { + emojiDocumentId = user.background_emoji_id; + } + } else { + colorId = 0; + } + } else if (messageObject.replyMessageObject.isFromChannel()) { + TLRPC.Chat chat = MessagesController.getInstance(messageObject.currentAccount).getChat(messageObject.replyMessageObject.messageOwner.from_id.channel_id); + if (chat != null) { + colorId = (chat.flags2 & 64) != 0 ? chat.color : (int) (chat.id % 7); + if ((chat.flags2 & 32) != 0) { + emojiDocumentId = chat.background_emoji_id; + } + } else { + colorId = 0; + } + } else { + colorId = 0; + } + resolveColor(messageObject.replyMessageObject, colorId, resourcesProvider); + backgroundColor = Theme.multAlpha(color1, 0.10f); + nameColor = color1; + } else { + hasColor2 = false; + hasColor3 = false; + color1 = color2 = color3 = Theme.getColor(Theme.key_chat_inReplyLine, resourcesProvider); + backgroundColor = Theme.multAlpha(color1, 0.10f); + nameColor = Theme.getColor(Theme.key_chat_inReplyNameText, resourcesProvider); + } + if (messageObject.shouldDrawWithoutBackground()) { + hasColor2 = false; + hasColor3 = false; + color1 = color2 = color3 = Color.WHITE; + backgroundColor = Color.TRANSPARENT; + nameColor = Theme.getColor(Theme.key_chat_stickerReplyNameText, resourcesProvider); + } else if (messageObject.isOutOwner()) { + color1 = color2 = color3 = Theme.getColor(hasColor2 || hasColor3 ? Theme.key_chat_outReplyLine2 : Theme.key_chat_outReplyLine, resourcesProvider); + if (hasColor3) { + reversedOut = true; + color1 = Theme.multAlpha(color1, .20f); + color2 = Theme.multAlpha(color2, .50f); // 50% over 20% = 60% + } else if (hasColor2) { + reversedOut = true; + color1 = Theme.multAlpha(color1, .35f); + } + backgroundColor = Theme.multAlpha(color3, Theme.isCurrentThemeDark() ? 0.12f : 0.10f); + nameColor = Theme.getColor(Theme.key_chat_outReplyNameText, resourcesProvider); + } + if (isReply && messageObject != null && messageObject.overrideLinkEmoji != -1) { + emojiDocumentId = messageObject.overrideLinkEmoji; + } + if (emojiDocumentId != 0 && emoji == null) { + emoji = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(parentView, false, dp(20), AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC); + if (parentView instanceof ChatMessageCell ? ((ChatMessageCell) parentView).isCellAttachedToWindow() : parentView.isAttachedToWindow()) { + emoji.attach(); + } + } + if (emoji != null) { + if (emoji.set(emojiDocumentId, true)) { + emojiLoaded = false; + } + } + return nameColorAnimated.set(nameColor); + } + + public void resetAnimation() { + color1Animated.set(color1, true); + color2Animated.set(color2, true); + color2Alpha.set(hasColor2, true); + nameColorAnimated.set(nameColor, true); + backgroundColorAnimated.set(backgroundColor, true); + if (emoji != null) { + emoji.resetAnimation(); + } + } + + private boolean reversedOut; + private boolean loading; + private float loadingT; + private float loadingTranslationT; + + public void setLoading(boolean loading) { + if (!loading && this.loading) { + loadingT = 0; + if (backgroundLoadingDrawable != null) { + backgroundLoadingDrawable.disappear(); + } + } else if (loading && !this.loading) { + if (backgroundLoadingDrawable != null) { + backgroundLoadingDrawable.resetDisappear(); + backgroundLoadingDrawable.reset(); + } + } + this.loading = loading; + } + + private long lastLoadingTTime; + private void incrementLoadingT() { + final long now = System.currentTimeMillis(); + final float loadingAlpha = loadingStateT.set(loading); + loadingT += Math.min(30, now - lastLoadingTTime) * loadingAlpha; + loadingTranslationT += Math.min(30, now - lastLoadingTTime) * loadingAlpha; + lastLoadingTTime = now; + } + + public void drawLine(Canvas canvas, RectF rect) { + drawLine(canvas, rect, 1f); + } + + public void drawLine(Canvas canvas, RectF rect, float alpha) { + canvas.save(); + + clipPath.rewind(); + final int rad = (int) Math.floor(SharedConfig.bubbleRadius / 3f); + rectF.set(rect.left, rect.top, rect.left + Math.max(dp(3), dp(2 * rad)), rect.bottom); + clipPath.addRoundRect(rectF, dp(rad), dp(rad), Path.Direction.CW); + canvas.clipPath(clipPath); + canvas.clipRect(rect.left, rect.top, rect.left + dp(3), rect.bottom); + + color1Paint.setColor(Theme.multAlpha(color1Animated.set(color1), alpha)); + color2Paint.setColor(Theme.multAlpha(color2Animated.set(color2), alpha)); + color3Paint.setColor(Theme.multAlpha(color3Animated.set(color3), alpha)); + + boolean restore = false; + final float loadingAlpha = loadingStateT.set(loading); + if (loadingAlpha > 0 && !hasColor2) { + canvas.save(); + + // under line + int wasAlpha = color1Paint.getAlpha(); + color1Paint.setAlpha((int) (wasAlpha * .3f)); + canvas.drawPaint(color1Paint); + color1Paint.setAlpha(wasAlpha); + + canvas.clipPath(lineClipPath); + + incrementLoadingT(); + + float x = (float) Math.pow(loadingT / 240f / 4f, .85f) * 4f; + final float from = MathUtils.clamp(.5f * ((Math.max(x, .5f) + 1.5f) % 3.5f), 0, 1); + final float to = MathUtils.clamp(.5f * (((x + 1.5f) % 3.5f) - 1.5f), 0, 1); + + rectF.set( + rect.left, + rect.top + rect.height() * AndroidUtilities.lerp(0, 1f - CubicBezierInterpolator.EASE_IN.getInterpolation(from), loadingAlpha), + rect.left + dp(6), + rect.top + rect.height() * AndroidUtilities.lerp(1f, 1f - CubicBezierInterpolator.EASE_OUT.getInterpolation(to), loadingAlpha) + ); + lineClipPath.rewind(); + lineClipPath.addRoundRect(rectF, dp(4), dp(4), Path.Direction.CW); + canvas.clipPath(lineClipPath); + restore = true; + + parentView.invalidate(); + } + + canvas.drawPaint(color1Paint); + final float color2Alpha = this.color2Alpha.set(hasColor2); + if (color2Alpha > 0) { + canvas.save(); + canvas.translate(rect.left, rect.top); + incrementLoadingT(); + + final float color3Alpha = this.color3Alpha.set(hasColor3); + final float fh; + if (hasColor3) { + fh = rect.height() - Math.floorMod((int) rect.height(), dp(6.33f + 6.33f + 3 + 3.33f)); + } else { + fh = rect.height() - Math.floorMod((int) rect.height(), dp(6.33f + 3 + 3.33f)); + } + canvas.translate(0, -((loadingTranslationT + (reversedOut ? 100 : 0)) / 1000f * dp(30) % fh)); + + checkColorPathes(rect.height() * 2); + int wasAlpha = color2Paint.getAlpha(); + color2Paint.setAlpha((int) (wasAlpha * color2Alpha)); + canvas.drawPath(color2Path, color2Paint); + color2Paint.setAlpha(wasAlpha); + + wasAlpha = color3Paint.getAlpha(); + color3Paint.setAlpha((int) (wasAlpha * color3Alpha)); + canvas.drawPath(color3Path, color3Paint); + color3Paint.setAlpha(wasAlpha); + + canvas.restore(); + } + + if (restore) { + canvas.restore(); + } + + canvas.restore(); + } + + public void drawBackground(Canvas canvas, RectF rect, float leftRad, float rightRad, float bottomRad, float alpha) { + drawBackground(canvas, rect, leftRad, rightRad, bottomRad, alpha, false, false); + } + + public void drawBackground(Canvas canvas, RectF rect, float leftRad, float rightRad, float bottomRad, float alpha, boolean hasQuote, boolean emojiOnly) { + radii[0] = radii[1] = Math.max(AndroidUtilities.dp((int) Math.floor(SharedConfig.bubbleRadius / 3f)), AndroidUtilities.dp(leftRad)); + radii[2] = radii[3] = AndroidUtilities.dp(rightRad); + radii[4] = radii[5] = AndroidUtilities.dp(bottomRad); + radii[6] = radii[7] = Math.max(AndroidUtilities.dp((int) Math.floor(SharedConfig.bubbleRadius / 3f)), AndroidUtilities.dp(bottomRad)); + drawBackground(canvas, rect, alpha, hasQuote, emojiOnly); + } + + private static class IconCoords { + public float x, y, s, a; + public boolean q; + public IconCoords(float x, float y, float s, float a, boolean q) { + this(x, y, s, a); + this.q = q; + } + public IconCoords(float x, float y, float s, float a) { + this.x = x; + this.y = y; + this.s = s; + this.a = a; + } + } + + private IconCoords[] iconCoords; + + public void drawBackground(Canvas canvas, RectF rect, float alpha) { + drawBackground(canvas, rect, alpha, false, false); + } + + public void drawBackground(Canvas canvas, RectF rect, float alpha, boolean hasQuote, boolean emojiOnly) { + if (!emojiOnly) { + backgroundPath.rewind(); + backgroundPath.addRoundRect(rect, radii, Path.Direction.CW); + + backgroundPaint.setColor(backgroundColorAnimated.set(backgroundColor)); + backgroundPaint.setAlpha((int) (backgroundPaint.getAlpha() * alpha)); + canvas.drawPath(backgroundPath, backgroundPaint); + } + + if (emoji != null) { + final float loadedScale = emojiLoadedT.set(isEmojiLoaded()); + + if (loadedScale > 0) { + if (iconCoords == null) { + iconCoords = new IconCoords[]{ + new IconCoords(4, -6.33f, 1f, 1f), + new IconCoords(30, 3, .78f, .9f), + new IconCoords(46, -17, .6f, .6f), + new IconCoords(69.66f, -0.666f, .87f, .7f), + new IconCoords(107, -12.6f, 1.03f, .3f), + new IconCoords(51, 24, 1f, .5f), + new IconCoords(6.33f, 20, .77f, .7f), + new IconCoords(-19, 12, .8f, .6f, true), + new IconCoords(26, 42, .78f, .9f), + new IconCoords(-22, 36, .7f, .5f, true), + new IconCoords(-1, 48, 1f, .4f), + }; + } + + canvas.save(); + canvas.clipRect(rect); + + float x0 = Math.max(rect.right - dp(15), rect.centerX()); + if (hasQuote) { + x0 -= dp(12); + } + float y0 = Math.min(rect.centerY(), rect.top + dp(42 / 2)); + + emoji.setColor(getColor()); + emoji.setAlpha((int) (0xFF * alpha * (rect.width() < dp(140) ? .27f : .5f ))); + for (int i = 0; i < iconCoords.length; ++i) { + IconCoords c = iconCoords[i]; + if (c.q && !hasQuote) { + continue; + } + emoji.setAlpha((int) (0xFF * .30f * c.a)); + final float cx = x0 - dp(c.x); + final float cy = y0 + dp(c.y); + final float sz = dp(10) * c.s * loadedScale; + emoji.setBounds((int) (cx - sz), (int) (cy - sz), (int) (cx + sz), (int) (cy + sz)); + emoji.draw(canvas); + } + + canvas.restore(); + } + } + } + + private boolean emojiLoaded; + private boolean isEmojiLoaded() { + if (emojiLoaded) { + return true; + } + if (emoji != null && emoji.getDrawable() instanceof AnimatedEmojiDrawable) { + AnimatedEmojiDrawable drawable = (AnimatedEmojiDrawable) emoji.getDrawable(); + if (drawable.getImageReceiver() != null && drawable.getImageReceiver().hasImageLoaded()) { + return emojiLoaded = true; + } + } + return false; + } + + public void drawLoadingBackground(Canvas canvas, RectF rect, float leftRad, float rightRad, float bottomRad, float alpha) { + radii[0] = radii[1] = Math.max(AndroidUtilities.dp((int) Math.floor(SharedConfig.bubbleRadius / 3f)), AndroidUtilities.dp(leftRad)); + radii[2] = radii[3] = AndroidUtilities.dp(rightRad); + radii[4] = radii[5] = AndroidUtilities.dp(bottomRad); + radii[6] = radii[7] = Math.max(AndroidUtilities.dp((int) Math.floor(SharedConfig.bubbleRadius / 3f)), AndroidUtilities.dp(bottomRad)); + + if (loading || backgroundLoadingDrawable != null && backgroundLoadingDrawable.isDisappearing()) { + if (backgroundLoadingDrawable == null) { + backgroundLoadingDrawable = new LoadingDrawable(); + backgroundLoadingDrawable.setAppearByGradient(true); + backgroundLoadingDrawable.setGradientScale(3.5f); + backgroundLoadingDrawable.setSpeed(.5f); + } + + backgroundLoadingDrawable.setColors( + Theme.multAlpha(color1, .1f), + Theme.multAlpha(color1, .3f), + Theme.multAlpha(color1, .3f), + Theme.multAlpha(color1, 1.25f) + ); + + backgroundLoadingDrawable.setBounds(rect); + backgroundLoadingDrawable.setRadii(radii); + backgroundLoadingDrawable.strokePaint.setStrokeWidth(AndroidUtilities.dp(1)); + + backgroundLoadingDrawable.setAlpha((int) (0xFF * alpha)); + backgroundLoadingDrawable.draw(canvas); + + parentView.invalidate(); + } else if (backgroundLoadingDrawable != null) { + backgroundLoadingDrawable.reset(); + } + } + + private void checkColorPathes(float height) { + if (Math.abs(lastHeight - height) > 3 || lastHasColor3 != hasColor3) { + final float w = dpf2(3); + final float h = dpf2(6.33f); + final float sk = dpf2(3); + final float margin = dpf2(3.33f); + float y = margin + sk; + + color2Path.rewind(); + while (y < height) { + color2Path.moveTo(w + 1, y - 1); + color2Path.lineTo(w + 1, y + h); + color2Path.lineTo(0, y + h + sk); + color2Path.lineTo(0, y + sk); + color2Path.close(); + + y += h + sk + margin; + if (hasColor3) { + y += h; + } + } + + if (hasColor3) { + y = margin + sk + h; + color3Path.rewind(); + while (y < height) { + color3Path.moveTo(w + 1, y - 1); + color3Path.lineTo(w + 1, y + h); + color3Path.lineTo(0, y + h + sk); + color3Path.lineTo(0, y + sk); + color3Path.close(); + + y += h + sk + margin + h; + } + } + + lastHeight = height; + lastHasColor3 = hasColor3; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchCounterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchCounterView.java index 8991f4aba..5aa2f342d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchCounterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchCounterView.java @@ -154,9 +154,9 @@ public class SearchCounterView extends View { int cutIndexNew = 0; int cutIndexOld = 0; if (countStartIndex > 0) { - oldSpannableStr.setSpan(new EmptyStubSpan(), 0, countStartIndex, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); - newSpannableStr.setSpan(new EmptyStubSpan(), 0, countStartIndex, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); - stableStr.setSpan(new EmptyStubSpan(), 0, countStartIndex, SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); + oldSpannableStr.setSpan(new EmptyStubSpan(), 0, Math.min(oldSpannableStr.length(), countStartIndex), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); + newSpannableStr.setSpan(new EmptyStubSpan(), 0, Math.min(newSpannableStr.length(), countStartIndex), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); + stableStr.setSpan(new EmptyStubSpan(), 0, Math.min(stableStr.length(), countStartIndex), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE); } for (int i = countStartIndex; i < n; i++) { if (!newEndReached && !oldEndReached) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java index 901d64110..48fe8cc71 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java @@ -73,7 +73,7 @@ public class SeekBarView extends FrameLayout { public interface SeekBarViewDelegate { void onSeekBarDrag(boolean stop, float progress); - void onSeekBarPressed(boolean pressed); + default void onSeekBarPressed(boolean pressed) {}; default CharSequence getContentDescription() { return null; } @@ -527,7 +527,7 @@ public class SeekBarView extends FrameLayout { return; } lastCaption = text; - lastDuration = duration; + lastDuration = duration * 10; if (!(text instanceof Spanned)) { timestamps = null; currentTimestamp = -1; @@ -681,10 +681,9 @@ public class SeekBarView extends FrameLayout { timestampLabel = new StaticLayout[2]; } - float left = selectorWidth / 2f; - float right = getMeasuredWidth() - selectorWidth / 2f; - float rightPadded = right - (lastDuration > 1000L * 60 * 10 ? AndroidUtilities.dp(36) : 0); - float width = Math.abs(left - rightPadded) - AndroidUtilities.dp(16 + 50); + float left = selectorWidth / 2f + (lastDuration > 1000L * 60 * 10 ? AndroidUtilities.dp(42) : 0); + float right = getMeasuredWidth() - selectorWidth / 2f - (lastDuration > 1000L * 60 * 10 ? AndroidUtilities.dp(42) : 0); + float width = Math.abs(left - right) - AndroidUtilities.dp(16 + 50); if (lastWidth > 0 && Math.abs(lastWidth - width) > 0.01f) { if (timestampLabel[0] != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java index a6b04a651..05187b975 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -70,6 +70,7 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLog; +import org.telegram.messenger.GenericProvider; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; @@ -88,6 +89,7 @@ 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_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; @@ -188,9 +190,9 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi private ArrayList recentSearchObjects = new ArrayList<>(); private LongSparseArray recentSearchObjectsById = new LongSparseArray<>(); private final Theme.ResourcesProvider resourcesProvider; - TLRPC.StoryItem storyItem; + TL_stories.StoryItem storyItem; - public void setStoryToShare(TLRPC.StoryItem storyItem) { + public void setStoryToShare(TL_stories.StoryItem storyItem) { this.storyItem = storyItem; } @@ -1006,6 +1008,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi topicsGridView.setHorizontalScrollBarEnabled(false); topicsGridView.setOverScrollMode(View.OVER_SCROLL_NEVER); topicsGridView.setSelectorDrawableColor(0); + topicsGridView.setItemSelectorColorProvider(i -> 0); topicsGridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); topicsGridView.setClipToPadding(false); topicsGridView.addItemDecoration(new RecyclerView.ItemDecoration() { @@ -1083,6 +1086,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } }; gridView.setSelectorDrawableColor(0); + gridView.setItemSelectorColorProvider(i -> 0); gridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); gridView.setClipToPadding(false); gridView.setLayoutManager(layoutManager = new GridLayoutManager(getContext(), 4)); @@ -1154,6 +1158,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } } }; + searchGridView.setItemSelectorColorProvider(i -> 0); searchGridView.setSelectorDrawableColor(0); searchGridView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); searchGridView.setClipToPadding(false); @@ -1543,7 +1548,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } private void selectDialog(ShareDialogCell cell, TLRPC.Dialog dialog) { - if (topicsGridView.getVisibility() != View.GONE) { + if (topicsGridView.getVisibility() != View.GONE || parentActivity == null) { return; } 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 6a589eb39..6051ba2ea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -60,8 +60,6 @@ import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; import org.telegram.messenger.ApplicationLoader; @@ -80,7 +78,6 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.browser.Browser; @@ -90,6 +87,7 @@ import org.telegram.messenger.fakepasscode.Utils; 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.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -124,8 +122,8 @@ import org.telegram.ui.PhotoViewer; import org.telegram.ui.ProfileActivity; import org.telegram.ui.Stories.StoriesController; import org.telegram.ui.Stories.StoriesListPlaceProvider; -import org.telegram.ui.Stories.StoriesUtilities; import org.telegram.ui.Stories.UserListPoller; +import org.telegram.ui.Stories.ViewsForPeerStoriesRequester; import java.util.ArrayList; import java.util.Collections; @@ -1309,6 +1307,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingPlayStateChanged); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidStart); profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.storiesListUpdated); + profileActivity.getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); for (int a = 0; a < 10; a++) { //cellCache.add(new SharedPhotoVideoCell(context)); @@ -2557,14 +2556,14 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter floatingDateView.setTranslationY(-AndroidUtilities.dp(48)); addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 48 + 4, 0, 0)); - addView(fragmentContextView = new FragmentContextView(context, parent, this, false, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); - fragmentContextView.setDelegate((start, show) -> { - if (!start) { - requestLayout(); - } - }); - if (!isStoriesView()) { + addView(fragmentContextView = new FragmentContextView(context, parent, this, false, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 0, 0)); + fragmentContextView.setDelegate((start, show) -> { + if (!start) { + requestLayout(); + } + }); + addView(scrollSlidingTextTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); addView(actionModeLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); } @@ -3477,7 +3476,13 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } protected void onSelectedTabChanged() { - + boolean pollerEnabled = isStoriesView() || isArchivedOnlyStoriesView(); + if (archivedStoriesAdapter.poller != null) { + archivedStoriesAdapter.poller.start(pollerEnabled && getClosestTab() == TAB_ARCHIVED_STORIES); + } + if (storiesAdapter.poller != null) { + storiesAdapter.poller.start(pollerEnabled && getClosestTab() == TAB_STORIES); + } } protected boolean canShowSearchItem() { @@ -3501,6 +3506,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingPlayStateChanged); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingDidStart); profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.storiesListUpdated); + profileActivity.getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); if (storiesAdapter != null && storiesAdapter.storiesList != null) { storiesAdapter.destroy(); @@ -3845,7 +3851,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter for (int a = 0; a < mediaPages.length; a++) { mediaPages[a].setTranslationY(topPadding - lastMeasuredTopPadding); } - fragmentContextView.setTranslationY(AndroidUtilities.dp(48) + top); + if (fragmentContextView != null) { + fragmentContextView.setTranslationY(AndroidUtilities.dp(48) + top); + } additionalFloatingTranslation = top; floatingDateView.setTranslationY((floatingDateView.getTag() == null ? -AndroidUtilities.dp(48) : 0) + additionalFloatingTranslation); } @@ -4554,6 +4562,17 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter delegate.updateSelectedMediaTabText(); } } + } else if (id == NotificationCenter.storiesUpdated) { + for (int i = 0; i < mediaPages.length; ++i) { + if (mediaPages[i] != null && mediaPages[i].listView != null && (mediaPages[i].selectedType == TAB_STORIES || mediaPages[i].selectedType == TAB_ARCHIVED_STORIES)) { + for (int j = 0; j < mediaPages[i].listView.getChildCount(); ++j) { + View child = mediaPages[i].listView.getChildAt(j); + if (child instanceof SharedPhotoVideoCell2) { + ((SharedPhotoVideoCell2) child).updateViews(); + } + } + } + } } } @@ -4999,6 +5018,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter mediaPages[0].selectedType = id; } scrollSlidingTextTabStrip.finishAddingTabs(); + onSelectedTabChanged(); } private void startStopVisibleGifs() { @@ -6845,6 +6865,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter private StoriesAdapter supportingAdapter; private int id; + private ViewsForPeerStoriesRequester poller; + public StoriesAdapter(Context context, boolean isArchive) { super(context); this.isArchive = isArchive; @@ -6855,6 +6877,36 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } if (storiesList != null) { id = storiesList.link(); + poller = new ViewsForPeerStoriesRequester(profileActivity.getMessagesController().getStoriesController(), dialog_id, storiesList.currentAccount) { + @Override + protected void getStoryIds(ArrayList ids) { + RecyclerListView listView = null; + for (int i = 0; i < mediaPages.length; ++i) { + if (mediaPages[i].listView != null && mediaPages[i].listView.getAdapter() == StoriesAdapter.this) { + listView = mediaPages[i].listView; + break; + } + } + + if (listView != null) { + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (child instanceof SharedPhotoVideoCell2) { + MessageObject msg = ((SharedPhotoVideoCell2) child).getMessageObject(); + if (msg != null && msg.isStory()) { + ids.add(msg.storyItem.id); + } + } + } + } + } + + @Override + protected boolean updateStories(ArrayList reqIds, TL_stories.TL_stories_storyViews storyViews) { + storiesList.updateStoryViews(reqIds, storyViews.views); + return true; + } + }; } checkColumns(); } @@ -7409,14 +7461,16 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextView.class}, null, null, null, Theme.key_profile_tabText)); arrayList.add(new ThemeDescription(scrollSlidingTextTabStrip.getTabsContainer(), ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{TextView.class}, null, null, null, Theme.key_profile_tabSelector)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose)); + if (fragmentContextView != null) { + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_inappPlayerBackground)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"playButton"}, null, null, null, Theme.key_inappPlayerPlayPause)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerTitle)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_FASTSCROLL, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_inappPlayerPerformer)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_IMAGECOLOR, new Class[]{FragmentContextView.class}, new String[]{"closeButton"}, null, null, null, Theme.key_inappPlayerClose)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); - arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_BACKGROUND | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"frameLayout"}, null, null, null, Theme.key_returnToCallBackground)); + arrayList.add(new ThemeDescription(fragmentContextView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{FragmentContextView.class}, new String[]{"titleTextView"}, null, null, null, Theme.key_returnToCallText)); + } for (int a = 0; a < mediaPages.length; a++) { final int num = a; 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 fd121d850..97dd775c5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SizeNotifierFrameLayout.java @@ -20,16 +20,22 @@ import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Matrix; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.Rect; +import android.graphics.Region; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; +import android.graphics.text.MeasuredText; import android.os.Build; +import android.util.Log; import android.view.View; import android.widget.FrameLayout; +import androidx.annotation.NonNull; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLog; @@ -168,7 +174,7 @@ public class SizeNotifierFrameLayout extends FrameLayout { } backgroundDrawable = newDrawable; if (attached && backgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(); + ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(this); } backgroundMotion = newMotion; themeAnimationValue = 0f; @@ -197,7 +203,6 @@ public class SizeNotifierFrameLayout extends FrameLayout { parallaxScale = 1.0f; translationX = 0; translationY = 0; - } if (drawable instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) drawable; @@ -300,6 +305,7 @@ public class SizeNotifierFrameLayout extends FrameLayout { (int) (getMeasuredWidth() * parallaxScale + x), (int) (backgroundTranslationY + getRootView().getMeasuredHeight() * parallaxScale + y) ); + drawable.draw(canvas); checkSnowflake(canvas); if (bottomClip != 0) { @@ -308,7 +314,7 @@ public class SizeNotifierFrameLayout extends FrameLayout { } if (a == 0 && oldBackgroundDrawable != null && themeAnimationValue >= 1.0f) { if (attached && oldBackgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) oldBackgroundDrawable).onDetachedFromWindow(); + ((ChatBackgroundDrawable) oldBackgroundDrawable).onDetachedFromWindow(backgroundView); } oldBackgroundDrawable = null; oldBackgroundMotion = false; @@ -335,11 +341,11 @@ public class SizeNotifierFrameLayout extends FrameLayout { motionBackgroundDrawable.setParentView(backgroundView); } if (attached && backgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) backgroundDrawable).onDetachedFromWindow(); + ((ChatBackgroundDrawable) backgroundDrawable).onDetachedFromWindow(backgroundView); } backgroundDrawable = bitmap; if (attached && backgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(); + ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(backgroundView); } checkMotion(); backgroundView.invalidate(); @@ -597,11 +603,11 @@ public class SizeNotifierFrameLayout extends FrameLayout { if (bitmap == null) { bitmap = new BlurBitmap(); bitmap.topBitmap = Bitmap.createBitmap(bitmapW, bitmapH, Bitmap.Config.ARGB_8888); - bitmap.topCanvas = new Canvas(bitmap.topBitmap); + bitmap.topCanvas = new SimplerCanvas(bitmap.topBitmap); if (needBlurBottom) { bitmap.bottomBitmap = Bitmap.createBitmap(bitmapW, bitmapH, Bitmap.Config.ARGB_8888); - bitmap.bottomCanvas = new Canvas(bitmap.bottomBitmap); + bitmap.bottomCanvas = new SimplerCanvas(bitmap.bottomBitmap); } } else { bitmap.topBitmap.eraseColor(Color.TRANSPARENT); @@ -781,10 +787,10 @@ public class SizeNotifierFrameLayout extends FrameLayout { invalidateBlur = true; } if (backgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(); + ((ChatBackgroundDrawable) backgroundDrawable).onAttachedToWindow(backgroundView); } if (oldBackgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) oldBackgroundDrawable).onAttachedToWindow(); + ((ChatBackgroundDrawable) oldBackgroundDrawable).onAttachedToWindow(backgroundView); } } @@ -812,10 +818,10 @@ public class SizeNotifierFrameLayout extends FrameLayout { blurIsRunning = false; if (backgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) backgroundDrawable).onDetachedFromWindow(); + ((ChatBackgroundDrawable) backgroundDrawable).onDetachedFromWindow(backgroundView); } if (oldBackgroundDrawable instanceof ChatBackgroundDrawable) { - ((ChatBackgroundDrawable) oldBackgroundDrawable).onDetachedFromWindow(); + ((ChatBackgroundDrawable) oldBackgroundDrawable).onDetachedFromWindow(backgroundView); } } @@ -934,4 +940,80 @@ public class SizeNotifierFrameLayout extends FrameLayout { } } + public static class SimplerCanvas extends Canvas { + public SimplerCanvas(Bitmap bitmap) { + super(bitmap); + } + + // all calls to render text for blur should be replaced with drawRect using SpoilerEffect.layoutDrawMaybe + + @Override + public void drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint) { + // NOP +// super.drawText(text, index, count, x, y, paint); + } + + @Override + public void drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint) { + // NOP +// super.drawText(text, start, end, x, y, paint); + } + + @Override + public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) { + // NOP +// super.drawText(text, x, y, paint); + } + + @Override + public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint) { + // NOP +// super.drawText(text, start, end, x, y, paint); + } + + @Override + public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { + // NOP +// super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); + } + + @Override + public void drawTextRun(@NonNull MeasuredText text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) { + // NOP +// super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint); + } + + @Override + public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) { + // NOP +// super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint); + } + + @Override + public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { + // NOP +// super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint); + } + + @Override + public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { + // NOP +// super.drawTextOnPath(text, path, hOffset, vOffset, paint); + } + + @Override + public boolean clipPath(@NonNull Path path) { + // NOP + return false; +// return super.clipPath(path); + } + + @Override + public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) { + // NOP + return false; +// return super.clipPath(path, op); + } + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java index 4e7d346a4..984f189be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java @@ -191,7 +191,7 @@ public class StickerSetBulletinLayout extends Bulletin.TwoLineLayout { case TYPE_REPLACED_TO_FAVORITES: if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium() && !MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked) { titleTextView.setText(LocaleController.formatString("LimitReachedFavoriteStickers", R.string.LimitReachedFavoriteStickers, MessagesController.getInstance(UserConfig.selectedAccount).stickersFavedLimitDefault)); - CharSequence str = AndroidUtilities.replaceSingleTag(LocaleController.formatString("LimitReachedFavoriteStickersSubtitle", R.string.LimitReachedFavoriteStickersSubtitle, MessagesController.getInstance(UserConfig.selectedAccount).stickersFavedLimitPremium), () -> { + CharSequence str = AndroidUtilities.premiumText(LocaleController.formatString("LimitReachedFavoriteStickersSubtitle", R.string.LimitReachedFavoriteStickersSubtitle, MessagesController.getInstance(UserConfig.selectedAccount).stickersFavedLimitPremium), () -> { Activity activity = AndroidUtilities.findActivity(context); if (activity instanceof LaunchActivity) { ((LaunchActivity) activity).presentFragment(new PremiumPreviewFragment(LimitReachedBottomSheet.limitTypeToServerString(LimitReachedBottomSheet.TYPE_STICKERS))); @@ -206,7 +206,7 @@ public class StickerSetBulletinLayout extends Bulletin.TwoLineLayout { case TYPE_REPLACED_TO_FAVORITES_GIFS: if (!UserConfig.getInstance(UserConfig.selectedAccount).isPremium() && !MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked) { titleTextView.setText(LocaleController.formatString("LimitReachedFavoriteGifs", R.string.LimitReachedFavoriteGifs, MessagesController.getInstance(UserConfig.selectedAccount).savedGifsLimitDefault)); - CharSequence str = AndroidUtilities.replaceSingleTag(LocaleController.formatString("LimitReachedFavoriteGifsSubtitle", R.string.LimitReachedFavoriteGifsSubtitle, MessagesController.getInstance(UserConfig.selectedAccount).savedGifsLimitPremium), () -> { + CharSequence str = AndroidUtilities.premiumText(LocaleController.formatString("LimitReachedFavoriteGifsSubtitle", R.string.LimitReachedFavoriteGifsSubtitle, MessagesController.getInstance(UserConfig.selectedAccount).savedGifsLimitPremium), () -> { Activity activity = AndroidUtilities.findActivity(context); if (activity instanceof LaunchActivity) { ((LaunchActivity) activity).presentFragment(new PremiumPreviewFragment(LimitReachedBottomSheet.limitTypeToServerString(LimitReachedBottomSheet.TYPE_GIFS))); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java index 7b67a4120..98cf9c767 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SuggestEmojiView.java @@ -467,7 +467,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. forceClose(); } } - }, true); + }, SharedConfig.suggestAnimatedEmoji && UserConfig.getInstance(currentAccount).isPremium()); }; if (keywordResults == null || keywordResults.isEmpty()) { AndroidUtilities.runOnUIThread(searchRunnable, 600); @@ -498,7 +498,7 @@ public class SuggestEmojiView extends FrameLayout implements NotificationCenter. searchRunnable = () -> { ArrayList standard = new ArrayList<>(1); standard.add(new MediaDataController.KeywordResult(emoji, null)); - MediaDataController.getInstance(currentAccount).fillWithAnimatedEmoji(standard, 15, false, false, () -> { + MediaDataController.getInstance(currentAccount).fillWithAnimatedEmoji(standard, 15, false, false, false, () -> { if (id == lastQueryId) { lastQuery = emoji; lastQueryType = 2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java new file mode 100644 index 000000000..c3f527514 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Text.java @@ -0,0 +1,131 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Shader; +import android.graphics.Typeface; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; + +public class Text { + + private final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private StaticLayout layout; + private float width, left; + + public Text(CharSequence text, int textSizeDp) { + this(text, textSizeDp, null); + } + + public Text(CharSequence text, int textSizeDp, Typeface typeface) { + paint.setTextSize(dp(textSizeDp)); + paint.setTypeface(typeface); + setText(text); + } + + public void setText(CharSequence text) { + layout = new StaticLayout(text, paint, 99999, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false); + width = layout.getLineCount() > 0 ? layout.getLineWidth(0) : 0; + left = layout.getLineCount() > 0 ? layout.getLineLeft(0) : 0; + } + + public boolean isEmpty() { + return layout == null || TextUtils.isEmpty(layout.getText()); + } + + public void setColor(int color) { + paint.setColor(color); + } + + private int ellipsizeWidth = -1; + public Text ellipsize(int width) { + ellipsizeWidth = width; + return this; + } + + public void draw(Canvas canvas, int color) { + if (layout == null) { + return; + } + draw(canvas, 0, layout.getHeight() / 2f, color, 1f); + } + + public void draw(Canvas canvas, float x, float cy, int color, float alpha) { + if (layout == null) { + return; + } + paint.setColor(color); + if (alpha != 1f) { + paint.setAlpha((int) (paint.getAlpha() * alpha)); + } + canvas.save(); + canvas.translate(x - left, cy - layout.getHeight() / 2f); + draw(canvas); + canvas.restore(); + } + + public void draw(Canvas canvas, float x, float cy) { + if (layout == null) { + return; + } + canvas.save(); + canvas.translate(x - left, cy - layout.getHeight() / 2f); + draw(canvas); + canvas.restore(); + } + + private LinearGradient ellipsizeGradient; + private Matrix ellipsizeMatrix; + private Paint ellipsizePaint; + + public void draw(Canvas canvas) { + if (layout == null) { + return; + } + if (ellipsizeWidth >= 0 && width > ellipsizeWidth) { + canvas.saveLayerAlpha(0, 0, ellipsizeWidth, layout.getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + } + layout.draw(canvas); + if (ellipsizeWidth >= 0 && width > ellipsizeWidth) { + if (ellipsizeGradient == null) { + ellipsizeGradient = new LinearGradient(0, 0, dp(8), 0, new int[] { 0x00ffffff, 0xffffffff }, new float[] {0, 1}, Shader.TileMode.CLAMP); + ellipsizeMatrix = new Matrix(); + ellipsizePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + ellipsizePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + ellipsizePaint.setShader(ellipsizeGradient); + } + canvas.save(); + ellipsizeMatrix.reset(); + ellipsizeMatrix.postTranslate(ellipsizeWidth - left - dp(8), 0); + ellipsizeGradient.setLocalMatrix(ellipsizeMatrix); + canvas.drawRect(ellipsizeWidth - left - dp(8), 0, ellipsizeWidth - left, layout.getHeight(), ellipsizePaint); + canvas.restore(); + canvas.restore(); + } + } + + public float getWidth() { + return ellipsizeWidth >= 0 ? Math.min(ellipsizeWidth, width) : width; + } + + @NonNull + public CharSequence getText() { + if (layout == null || layout.getText() == null) { + return ""; + } + return layout.getText(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextSelectionHint.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextSelectionHint.java index 0d1e81a60..a2fef99c9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextSelectionHint.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextSelectionHint.java @@ -78,7 +78,7 @@ public class TextSelectionHint extends View { a.cancel(); } - String text = LocaleController.getString("TextSelectionHit", R.string.TextSelectionHit); + String text = LocaleController.getString(R.string.TextSelectionHint); Pattern pattern = Pattern.compile("\\*\\*.*\\*\\*"); Matcher matcher = pattern.matcher(text); String word = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java index 3aa271282..670dc3260 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TextStyleSpan.java @@ -29,6 +29,7 @@ public class TextStyleSpan extends MetricAffectingSpan { public int start; public int end; public TLRPC.MessageEntity urlEntity; + public String lng; public TextStyleRun() { @@ -75,7 +76,7 @@ public class TextStyleSpan extends MetricAffectingSpan { } public Typeface getTypeface() { - if ((flags & FLAG_STYLE_MONO) != 0 || (flags & FLAG_STYLE_QUOTE) != 0) { + if ((flags & FLAG_STYLE_MONO) != 0 || (flags & FLAG_STYLE_CODE) != 0) { return Typeface.MONOSPACE; } else if ((flags & FLAG_STYLE_BOLD) != 0 && (flags & FLAG_STYLE_ITALIC) != 0) { return AndroidUtilities.getTypeface("fonts/rmediumitalic.ttf"); @@ -100,6 +101,7 @@ public class TextStyleSpan extends MetricAffectingSpan { public final static int FLAG_STYLE_SPOILER = 256; public final static int FLAG_STYLE_SPOILER_REVEALED = 512; public final static int FLAG_STYLE_TEXT_URL = 1024; + public final static int FLAG_STYLE_CODE = 2048; public TextStyleSpan(TextStyleRun run) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java index 29db2ecf2..f94327b3d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java @@ -205,16 +205,16 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe backupImageView.setImage(ImageLocation.getForDocument(document), "50_50", thumb, null); if (item.chatTheme.wallpaper != null) { if (attached && chatBackgroundDrawable != null) { - chatBackgroundDrawable.onDetachedFromWindow(); + chatBackgroundDrawable.onDetachedFromWindow(ThemeSmallPreviewView.this); } chatBackgroundDrawable = new ChatBackgroundDrawable(item.chatTheme.wallpaper, false, true); chatBackgroundDrawable.setParent(this); if (attached) { - chatBackgroundDrawable.onAttachedToWindow(); + chatBackgroundDrawable.onAttachedToWindow(ThemeSmallPreviewView.this); } } else { if (attached && chatBackgroundDrawable != null) { - chatBackgroundDrawable.onDetachedFromWindow(); + chatBackgroundDrawable.onDetachedFromWindow(ThemeSmallPreviewView.this); } chatBackgroundDrawable = null; } @@ -680,7 +680,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); attached = true; if (chatBackgroundDrawable != null) { - chatBackgroundDrawable.onAttachedToWindow(); + chatBackgroundDrawable.onAttachedToWindow(ThemeSmallPreviewView.this); } } @@ -690,7 +690,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); attached = false; if (chatBackgroundDrawable != null) { - chatBackgroundDrawable.onDetachedFromWindow(); + chatBackgroundDrawable.onDetachedFromWindow(ThemeSmallPreviewView.this); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java index 034df3572..22749d9ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -56,6 +56,7 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.boosts.BoostRepository; import org.telegram.ui.PaymentFormActivity; import java.util.ArrayList; @@ -184,6 +185,12 @@ public class UndoView extends FrameLayout { public final static int ACTION_PROXY_ADDED = 87; public final static int ACTION_SHARED_FOLDER_DELETED = 88; + public final static int ACTION_BOOSTING_SELECTOR_WARNING_CHANNEL = 90; + public final static int ACTION_BOOSTING_SELECTOR_WARNING_USERS = 91; + public final static int ACTION_BOOSTING_SELECTOR_WARNING_COUNTRY = 92; + public final static int ACTION_BOOSTING_AWAIT = 93; + public final static int ACTION_BOOSTING_ONLY_RECIPIENT_CODE = 94; + private CharSequence infoText; private int hideAnimationType = 1; Drawable backgroundDrawable; @@ -1357,6 +1364,40 @@ public class UndoView extends FrameLayout { avatarImageView.setVisibility(GONE); undoButton.setVisibility(GONE); + } else if (currentAction == ACTION_BOOSTING_SELECTOR_WARNING_CHANNEL + || currentAction == ACTION_BOOSTING_SELECTOR_WARNING_USERS + || currentAction == ACTION_BOOSTING_SELECTOR_WARNING_COUNTRY + || currentAction == ACTION_BOOSTING_AWAIT + || currentAction == ACTION_BOOSTING_ONLY_RECIPIENT_CODE + ) { + switch (currentAction) { + case ACTION_BOOSTING_ONLY_RECIPIENT_CODE: + infoTextView.setText(LocaleController.getString("BoostingOnlyRecipientCode", R.string.BoostingOnlyRecipientCode)); + break; + case ACTION_BOOSTING_SELECTOR_WARNING_USERS: + infoTextView.setText(LocaleController.getString("BoostingSelectUpToWarningUsers", R.string.BoostingSelectUpToWarningUsers)); + break; + case ACTION_BOOSTING_SELECTOR_WARNING_CHANNEL: + infoTextView.setText(LocaleController.formatString("BoostingSelectUpToWarningChannels", R.string.BoostingSelectUpToWarningChannels, BoostRepository.giveawayAddPeersMax())); + break; + case ACTION_BOOSTING_SELECTOR_WARNING_COUNTRY: + infoTextView.setText(LocaleController.formatString("BoostingSelectUpToWarningCountries", R.string.BoostingSelectUpToWarningCountries, BoostRepository.giveawayCountriesMax())); + break; + case ACTION_BOOSTING_AWAIT: + infoTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("BoostingWaitWarning", R.string.BoostingWaitWarning, BoostRepository.boostsPerSentGift()))); + break; + } + layoutParams.leftMargin = AndroidUtilities.dp(58); + layoutParams.rightMargin = AndroidUtilities.dp(8); + infoTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + undoButton.setVisibility(GONE); + infoTextView.setTypeface(Typeface.DEFAULT); + subinfoTextView.setVisibility(GONE); + + leftImageView.setVisibility(VISIBLE); + leftImageView.setAnimation(R.raw.chats_infotip, 36, 36); + leftImageView.setProgress(0); + leftImageView.playAnimation(); } else if (currentAction == ACTION_ARCHIVE || currentAction == ACTION_ARCHIVE_FEW) { if (action == ACTION_ARCHIVE) { infoTextView.setText(LocaleController.getString("ChatArchived", R.string.ChatArchived)); @@ -1613,7 +1654,7 @@ public class UndoView extends FrameLayout { if (timeLeft <= 0) { hide(true, hideAnimationType); } - + if (currentAction != ACTION_PREVIEW_MEDIA_DESELECTED) { invalidate(); } 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 567bebe80..fe9d79841 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java @@ -220,6 +220,7 @@ public class ViewPagerFixed extends FrameLayout { } manualScrolling = null; onTabAnimationUpdate(true); + onScrollEnd(); } }); manualScrolling.setDuration(540); 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 c978e7a21..36bf407a9 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 @@ -18,14 +18,17 @@ import android.graphics.Rect; 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; @@ -41,7 +44,10 @@ import org.telegram.messenger.LiteMode; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.Utilities; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.BlurredFrameLayout; import org.telegram.ui.Components.Easings; +import org.telegram.ui.Components.QuoteSpan; +import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.TextStyleSpan; import java.util.ArrayList; @@ -49,6 +55,7 @@ import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Stack; +import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicReference; public class SpoilerEffect extends Drawable { @@ -101,6 +108,8 @@ public class SpoilerEffect extends Drawable { private static Paint xRefPaint; private int bitmapSize; + public boolean insideQuote; + private static int measureParticlesPerCharacter() { switch (SharedConfig.getDevicePerformanceClass()) { default: @@ -551,7 +560,12 @@ public class SpoilerEffect extends Drawable { */ public static void addSpoilers(TextView tv, @Nullable Stack spoilersPool, List spoilers) { int width = tv.getMeasuredWidth(); - addSpoilers(tv, tv.getLayout(), 0, width > 0 ? width : -2, (Spanned) tv.getText(), spoilersPool, spoilers); + addSpoilers(tv, tv.getLayout(), 0, width > 0 ? width : -2, (Spanned) tv.getText(), spoilersPool, spoilers, null); + } + + public static void addSpoilers(TextView tv, @Nullable Stack spoilersPool, List spoilers, ArrayList quoteBlocks) { + int width = tv.getMeasuredWidth(); + addSpoilers(tv, tv.getLayout(), 0, width > 0 ? width : -2, (Spanned) tv.getText(), spoilersPool, spoilers, quoteBlocks); } /** @@ -570,7 +584,7 @@ public class SpoilerEffect extends Drawable { public static void addSpoilers(@Nullable View v, Layout textLayout, int left, int right, @Nullable Stack spoilersPool, List spoilers) { if (textLayout.getText() instanceof Spanned) { - addSpoilers(v, textLayout, left, right, (Spanned) textLayout.getText(), spoilersPool, spoilers); + addSpoilers(v, textLayout, left, right, (Spanned) textLayout.getText(), spoilersPool, spoilers, null); } } @@ -578,7 +592,7 @@ public class SpoilerEffect extends Drawable { if (textLayout == null) { return; } - addSpoilers(v, textLayout, -1, -1, spannable, spoilersPool, spoilers); + addSpoilers(v, textLayout, -1, -1, spannable, spoilersPool, spoilers, null); } /** @@ -594,15 +608,15 @@ public class SpoilerEffect extends Drawable { * @param spoilersPool Cached spoilers pool, could be null, but highly recommended * @param spoilers Spoilers list to populate */ - public static void addSpoilers(@Nullable View v, Layout textLayout, int layoutLeft, int layoutRight, Spanned spannable, @Nullable Stack spoilersPool, List spoilers) { + public static void addSpoilers(@Nullable View v, Layout textLayout, int layoutLeft, int layoutRight, Spanned spannable, @Nullable Stack spoilersPool, List spoilers, ArrayList quoteBlocks) { if (textLayout == null) { return; } TextStyleSpan[] spans = spannable.getSpans(0, textLayout.getText().length(), TextStyleSpan.class); for (int i = 0; i < spans.length; ++i) { if (spans[i].isSpoiler()) { - int start = spannable.getSpanStart(spans[i]); - int end = spannable.getSpanEnd(spans[i]); + final int start = spannable.getSpanStart(spans[i]); + final int end = spannable.getSpanEnd(spans[i]); int left = layoutLeft, right = layoutRight; if (left == -1 && right == -1) { left = Integer.MAX_VALUE; @@ -614,7 +628,7 @@ public class SpoilerEffect extends Drawable { right = Math.max(right, (int) textLayout.getLineRight(l)); } } - addSpoilerRangesInternal(v, textLayout, left, right, start, end, spoilersPool, spoilers); + addSpoilerRangesInternal(v, textLayout, left, right, start, end, spoilersPool, spoilers, quoteBlocks); } } if (v instanceof TextView && spoilersPool != null) { @@ -622,17 +636,28 @@ public class SpoilerEffect extends Drawable { } } - private static void addSpoilerRangesInternal(@Nullable View v, @NonNull Layout textLayout, int mostleft, int mostright, int start, int end, @Nullable Stack spoilersPool, List spoilers) { + private static void addSpoilerRangesInternal(@Nullable View v, @NonNull Layout textLayout, int mostleft, int mostright, int start, int end, @Nullable Stack spoilersPool, List spoilers, ArrayList quoteBlocks) { textLayout.getSelectionPath(start, end, new Path() { @Override public void addRect(float left, float top, float right, float bottom, @NonNull Direction dir) { - addSpoilerRangeInternal(v, textLayout, left, top, right, bottom, spoilersPool, spoilers, mostleft, mostright); + addSpoilerRangeInternal(v, textLayout, left, top, right, bottom, spoilersPool, spoilers, mostleft, mostright, quoteBlocks); } }); } - private static void addSpoilerRangeInternal(@Nullable View v, @NonNull Layout textLayout, float left, float top, float right, float bottom, @Nullable Stack spoilersPool, List spoilers, int mostleft, int mostright) { + private static void addSpoilerRangeInternal(@Nullable View v, @NonNull Layout textLayout, float left, float top, float right, float bottom, @Nullable Stack spoilersPool, List spoilers, int mostleft, int mostright, ArrayList quote) { SpoilerEffect spoilerEffect = spoilersPool == null || spoilersPool.isEmpty() ? new SpoilerEffect() : spoilersPool.remove(0); + spoilerEffect.insideQuote = false; + if (quote != null) { + final float cy = (top + bottom) / 2f; + for (int j = 0; j < quote.size(); ++j) { + QuoteSpan.Block block = quote.get(j); + if (cy >= block.top && cy <= block.bottom) { + spoilerEffect.insideQuote = true; + break; + } + } + } spoilerEffect.setRippleProgress(-1); spoilerEffect.setBounds((int) Math.max(left, mostleft), (int) top, (int) Math.min(right, mostright <= 0 ? Integer.MAX_VALUE : mostright), (int) bottom); spoilerEffect.setColor(textLayout.getPaint().getColor()); @@ -657,6 +682,39 @@ public class SpoilerEffect extends Drawable { canvas.clipPath(tempPath, Region.Op.DIFFERENCE); } + private static WeakHashMap> lazyLayoutLines; + public static void layoutDrawMaybe(Layout layout, Canvas canvas) { + if (canvas instanceof SizeNotifierFrameLayout.SimplerCanvas) { + final int wasAlpha = layout.getPaint().getAlpha(); + layout.getPaint().setAlpha((int) (wasAlpha * .4f)); + if (lazyLayoutLines == null) { + lazyLayoutLines = new WeakHashMap<>(); + } + ArrayList linesRect = lazyLayoutLines.get(layout); + if (linesRect == null) { + linesRect = new ArrayList<>(); + final int lineCount = layout.getLineCount(); + for (int i = 0; i < lineCount; ++i) { + linesRect.add(new RectF( + layout.getLineLeft(i), + layout.getLineTop(i), + layout.getLineRight(i), + layout.getLineBottom(i) + )); + } + lazyLayoutLines.put(layout, linesRect); + } + if (linesRect != null) { + for (int i = 0; i < linesRect.size(); ++i) { + canvas.drawRect(linesRect.get(i), layout.getPaint()); + } + } + layout.getPaint().setAlpha(wasAlpha); + } else { + layout.draw(canvas); + } + } + /** * Optimized version of text layout double-render * @param v View to use as a parent view @@ -673,15 +731,15 @@ public class SpoilerEffect extends Drawable { @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()) { - textLayout.draw(canvas); + layoutDrawMaybe(textLayout, canvas); return; } Layout pl = patchedLayoutRef.get(); if (pl == null || !textLayout.getText().toString().equals(pl.getText().toString()) || textLayout.getWidth() != pl.getWidth() || textLayout.getHeight() != pl.getHeight()) { SpannableStringBuilder sb = new SpannableStringBuilder(textLayout.getText()); - if (textLayout.getText() instanceof Spannable) { - Spannable sp = (Spannable) textLayout.getText(); + if (textLayout.getText() instanceof Spanned) { + Spanned sp = (Spanned) textLayout.getText(); for (TextStyleSpan ss : sp.getSpans(0, sp.length(), TextStyleSpan.class)) { if (ss.isSpoiler()) { int start = sp.getSpanStart(ss), end = sp.getSpanEnd(ss); @@ -699,7 +757,7 @@ public class SpoilerEffect extends Drawable { sb.removeSpan(e); } - sb.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), sp.getSpanStart(ss), sp.getSpanEnd(ss), sp.getSpanFlags(ss)); + sb.setSpan(new ForegroundColorSpan(Color.TRANSPARENT), start, end, sp.getSpanFlags(ss)); sb.removeSpan(ss); } } @@ -725,7 +783,7 @@ public class SpoilerEffect extends Drawable { pl.draw(canvas); canvas.restore(); } else { - textLayout.draw(canvas); + layoutDrawMaybe(textLayout, canvas); } if (!spoilers.isEmpty()) { @@ -743,7 +801,7 @@ public class SpoilerEffect extends Drawable { } canvas.clipPath(tempPath); canvas.translate(0, -v.getPaddingTop()); - textLayout.draw(canvas); + layoutDrawMaybe(textLayout, canvas); canvas.restore(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect2.java index f12507edc..7cd8d43e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/spoilers/SpoilerEffect2.java @@ -87,12 +87,12 @@ public class SpoilerEffect2 { private static int getSize() { switch (SharedConfig.getDevicePerformanceClass()) { case SharedConfig.PERFORMANCE_CLASS_HIGH: - return Math.min(900, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .9f)); + return Math.min(900, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 1.0f)); case SharedConfig.PERFORMANCE_CLASS_AVERAGE: - return Math.min(512, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .6f)); + return Math.min(512, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .95f)); default: case SharedConfig.PERFORMANCE_CLASS_LOW: - return Math.min(400, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .5f)); + return Math.min(400, (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * .85f)); } } @@ -541,19 +541,19 @@ public class SpoilerEffect2 { private void die() { if (particlesData != null) { - GLES31.glDeleteBuffers(2, particlesData, 0); + try { GLES31.glDeleteBuffers(2, particlesData, 0); } catch (Exception e) { FileLog.e(e); }; particlesData = null; } if (drawProgram != 0) { - GLES31.glDeleteProgram(drawProgram); + try { GLES31.glDeleteProgram(drawProgram); } catch (Exception e) { FileLog.e(e); }; drawProgram = 0; } if (egl != null) { - egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); - egl.eglDestroySurface(eglDisplay, eglSurface); - egl.eglDestroyContext(eglDisplay, eglContext); + try { egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); } catch (Exception e) { FileLog.e(e); }; + try { egl.eglDestroySurface(eglDisplay, eglSurface); } catch (Exception e) { FileLog.e(e); }; + try { egl.eglDestroyContext(eglDisplay, eglContext); } catch (Exception e) { FileLog.e(e); }; } - surfaceTexture.release(); + try { surfaceTexture.release(); } catch (Exception e) { FileLog.e(e); }; checkGlErrors(); } 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 38c288aab..9f5e1ee90 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 @@ -589,7 +589,7 @@ public class VoIPHelper { } if (includeLogs[0] && log.exists() && req.rating < 4) { AccountInstance accountInstance = AccountInstance.getInstance(UserConfig.selectedAccount); - SendMessagesHelper.prepareSendingDocument(accountInstance, log.getAbsolutePath(), log.getAbsolutePath(), null, TextUtils.join(" ", problemTags), "text/plain", VOIP_SUPPORT_ID, null, null, null, null, true, 0, null); + SendMessagesHelper.prepareSendingDocument(accountInstance, log.getAbsolutePath(), log.getAbsolutePath(), null, TextUtils.join(" ", problemTags), "text/plain", VOIP_SUPPORT_ID, null, null, null, null, null, true, 0, null); Toast.makeText(context, LocaleController.getString("CallReportSent", R.string.CallReportSent), Toast.LENGTH_LONG).show(); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPWindowView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPWindowView.java index e40acd01c..e5779637b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPWindowView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/VoIPWindowView.java @@ -20,6 +20,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.UserConfig; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.VoIPFragment; +import org.webrtc.OrientationHelper; public class VoIPWindowView extends FrameLayout { @@ -39,6 +40,7 @@ public class VoIPWindowView extends FrameLayout { orientationBefore = activity.getRequestedOrientation(); activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); + OrientationHelper.cameraRotationDisabled = true; if (!enterAnimation) { runEnterTransition = true; } @@ -153,6 +155,8 @@ public class VoIPWindowView extends FrameLayout { } catch (Exception ignore) { } + + OrientationHelper.cameraRotationDisabled = false; } } }).setDuration(animDuration).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); @@ -218,6 +222,8 @@ public class VoIPWindowView extends FrameLayout { WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE); setVisibility(View.GONE); wm.removeView(VoIPWindowView.this); + + OrientationHelper.cameraRotationDisabled = false; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index d5608a3bd..d6cfd00a8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -86,6 +86,8 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent private View avatarOverlay; private AnimatorSet avatarAnimation; + private MessagesController.DialogPhotos dialogPhotos; + private long user_id; private boolean addContact; private boolean needAddException; @@ -134,7 +136,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent @Override public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); - getNotificationCenter().addObserver(this, NotificationCenter.dialogPhotosLoaded); + getNotificationCenter().addObserver(this, NotificationCenter.dialogPhotosUpdate); user_id = getArguments().getLong("user_id", 0); phone = getArguments().getString("phone"); firstNameFromCard = getArguments().getString("first_name_card"); @@ -149,6 +151,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent imageUpdater.parentFragment = this; imageUpdater.setDelegate(this); } + dialogPhotos = MessagesController.getInstance(currentAccount).getDialogPhotos(user_id); return user != null && super.onFragmentCreate(); } @@ -157,7 +160,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent public void onFragmentDestroy() { super.onFragmentDestroy(); getNotificationCenter().removeObserver(this, NotificationCenter.updateInterfaces); - getNotificationCenter().removeObserver(this, NotificationCenter.dialogPhotosLoaded); + getNotificationCenter().removeObserver(this, NotificationCenter.dialogPhotosUpdate); if (imageUpdater != null) { imageUpdater.clear(); } @@ -491,7 +494,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent linearLayout.addView(oldPhotoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0)); - getMessagesController().loadDialogPhotos(user_id, 2, 0, true, getClassGuid()); +// getMessagesController().loadDialogPhotos(user_id, 2, 0, true, getClassGuid(), null); TLRPC.UserFull userFull = getMessagesController().getUserFull(user_id); if (userFull != null) { prevAvatar = userFull.profile_photo; @@ -599,24 +602,20 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent if ((mask & MessagesController.UPDATE_MASK_AVATAR) != 0 || (mask & MessagesController.UPDATE_MASK_STATUS) != 0) { updateAvatarLayout(); } - } else if (id == NotificationCenter.dialogPhotosLoaded) { - int guid = (Integer) args[3]; - long did = (Long) args[0]; - boolean fromCache = (Boolean) args[2]; - if (user_id == did && classGuid == guid) { - ArrayList photos = (ArrayList) args[4]; - if (photos != null) { - for (int i = 0; i < photos.size(); i++) { - if (photos.get(i) != null) { - prevAvatar = photos.get(i); - updateCustomPhotoInfo(); - break; - } + } else if (id == NotificationCenter.dialogPhotosUpdate) { + MessagesController.DialogPhotos dialogPhotos = (MessagesController.DialogPhotos) args[0]; + if (dialogPhotos == this.dialogPhotos) { + ArrayList photos = new ArrayList<>(dialogPhotos.photos); + for (int i = 0; i < photos.size(); i++) { + if (photos.get(i) == null) { + photos.remove(i); + i--; } } - - if (prevAvatar == null && fromCache) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(did, 80, 0, false, getClassGuid()); + for (int i = 0; i < photos.size(); ++i) { + prevAvatar = photos.get(i); + updateCustomPhotoInfo(); + break; } } } @@ -829,7 +828,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent ArrayList users = new ArrayList<>(); users.add(user); getMessagesStorage().putUsersAndChats(users, null, false, true); - getMessagesStorage().addDialogPhoto(user_id, photo2.photo); + getMessagesController().getDialogPhotos(user_id).addPhotoAtStart(photo2.photo); getNotificationCenter().postNotificationName(NotificationCenter.reloadDialogPhotos); getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_AVATAR); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index c00841a1b..f629761c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -475,7 +475,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter Bundle args = new Bundle(); args.putLong("user_id", user.id); if (getMessagesController().checkCanOpenChat(args, ContactsActivity.this)) { - presentFragment(new ChatActivity(args), true); + presentFragment(new ChatActivity(args), needFinishFragment); } } } @@ -588,7 +588,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter Bundle args = new Bundle(); args.putLong("user_id", user.id); if (getMessagesController().checkCanOpenChat(args, ContactsActivity.this)) { - presentFragment(new ChatActivity(args), true); + presentFragment(new ChatActivity(args), needFinishFragment); } } } @@ -950,8 +950,10 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter Activity activity = getParentActivity(); if (activity != null) { checkPermission = false; - if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { - if (activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)) { + if (activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED/* || + activity.checkSelfPermission(Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED*/) { + if (activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_CONTACTS)/* || + activity.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_CONTACTS)*/) { AlertDialog.Builder builder = AlertsCreator.createContactsPermissionDialog(activity, param -> { askAboutContacts = param != 0; if (param == 0) { @@ -1000,7 +1002,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter @TargetApi(Build.VERSION_CODES.M) private void askForPermissons(boolean alert) { Activity activity = getParentActivity(); - if (activity == null || !UserConfig.getInstance(currentAccount).syncContacts || activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) { + if (activity == null || !UserConfig.getInstance(currentAccount).syncContacts || activity.checkSelfPermission(Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED/* && activity.checkSelfPermission(Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED*/) { return; } if (alert && askAboutContacts) { @@ -1090,7 +1092,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter Bundle args2 = new Bundle(); args2.putInt("enc_id", encryptedChat.id); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - presentFragment(new ChatActivity(args2), true); + presentFragment(new ChatActivity(args2), false); } } else if (id == NotificationCenter.closeChats) { if (!creatingChat) { @@ -1196,7 +1198,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter final boolean stories = dialogsActivity.storiesEnabled; RLottieImageView previousFab = dialogsActivity.getFloatingButton(); View previousFabContainer = previousFab.getParent() != null ? (View) previousFab.getParent() : null; - if (floatingButtonContainer == null || previousFabContainer == null || previousFab.getVisibility() != View.VISIBLE || Math.abs(previousFabContainer.getTranslationY()) > AndroidUtilities.dp(4) || Math.abs(floatingButtonContainer.getTranslationY()) > AndroidUtilities.dp(4)) { + if (floatingButton != null && (floatingButtonContainer == null || previousFabContainer == null || previousFab.getVisibility() != View.VISIBLE || Math.abs(previousFabContainer.getTranslationY()) > AndroidUtilities.dp(4) || Math.abs(floatingButtonContainer.getTranslationY()) > AndroidUtilities.dp(4))) { if (stories) { floatingButton.setAnimation(R.raw.write_contacts_fab_icon_camera, 56, 56); } else { @@ -1249,20 +1251,15 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter }); animatorSet.playTogether(valueAnimator); AndroidUtilities.runOnUIThread(() -> { + if (floatingButton == null) { + return; + } animationIndex = getNotificationCenter().setAnimationInProgress(animationIndex, new int[]{NotificationCenter.diceStickersDidLoad}, false); animatorSet.start(); - if (isOpen) { - if (stories) { - floatingButton.setAnimation(R.raw.write_contacts_fab_icon_camera, 56, 56); - } else { - floatingButton.setAnimation(R.raw.write_contacts_fab_icon, 52, 52); - } + if (stories) { + floatingButton.setAnimation(isOpen ? R.raw.write_contacts_fab_icon_camera : R.raw.write_contacts_fab_icon_reverse_camera, 56, 56); } else { - if (stories) { - floatingButton.setAnimation(R.raw.write_contacts_fab_icon_reverse_camera, 56, 56); - } else { - floatingButton.setAnimation(R.raw.write_contacts_fab_icon_reverse, 52, 52); - } + floatingButton.setAnimation(isOpen ? R.raw.write_contacts_fab_icon : R.raw.write_contacts_fab_icon_reverse, 52, 52); } floatingButton.playAnimation(); if (bounceIconAnimator != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index 2a8dce968..2e31f826b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -214,8 +214,6 @@ public class ContentPreviewViewer { ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); - menuVisible = true; - containerView.invalidate(); if (delegate != null) { if (delegate.needSend(currentContentType) && !delegate.isInScheduleMode()) { items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); @@ -256,6 +254,8 @@ public class ContentPreviewViewer { if (items.isEmpty()) { return; } + menuVisible = true; + containerView.invalidate(); int[] ic = new int[icons.size()]; for (int a = 0; a < icons.size(); a++) { ic[a] = icons.get(a); @@ -354,8 +354,6 @@ public class ContentPreviewViewer { containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); } else if (currentContentType == CONTENT_TYPE_EMOJI && delegate != null) { - menuVisible = true; - containerView.invalidate(); ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); @@ -396,6 +394,8 @@ public class ContentPreviewViewer { if (items.isEmpty()) { return; } + menuVisible = true; + containerView.invalidate(); int[] ic = new int[icons.size()]; for (int a = 0; a < icons.size(); a++) { @@ -492,8 +492,6 @@ public class ContentPreviewViewer { valueAnimator.start(); } } else if (delegate != null) { - menuVisible = true; - containerView.invalidate(); ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); @@ -531,6 +529,8 @@ public class ContentPreviewViewer { if (items.isEmpty()) { return; } + menuVisible = true; + containerView.invalidate(); int[] ic = new int[icons.size()]; for (int a = 0; a < icons.size(); a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java index 3f5ff5c4c..3812954e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/ChatActivityMemberRequestsDelegate.java @@ -84,6 +84,7 @@ public class ChatActivityMemberRequestsDelegate { super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(width), MeasureSpec.EXACTLY), heightMeasureSpec); } }; + avatarsView.setAvatarsTextSize(AndroidUtilities.dp(18)); avatarsView.reset(); requestsDataLayout.addView(avatarsView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 8, 0, 10, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java index fc8d9dc93..d2d0029a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java @@ -38,6 +38,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; import androidx.core.math.MathUtils; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -64,6 +65,7 @@ import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; @@ -109,7 +111,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener private Runnable searchRunnable; private int searchRequestId; private boolean isLoading; - private boolean hasMore; + private boolean hasMore = true; private boolean isSearchExpanded; private boolean isDataLoaded; private boolean isFirstLoading = true; @@ -128,7 +130,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener public FrameLayout getRootLayout() { if (rootLayout == null) { rootLayout = new FrameLayout(fragment.getParentActivity()); - rootLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, fragment.getResourceProvider())); + rootLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, fragment.getResourceProvider())); loadingView = getLoadingView(); rootLayout.addView(loadingView, MATCH_PARENT, MATCH_PARENT); @@ -147,6 +149,13 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener recyclerView.setOnScrollListener(listScrollListener); recyclerView.setSelectorDrawableColor(Theme.getColor(Theme.key_listSelector, fragment.getResourceProvider())); rootLayout.addView(recyclerView, MATCH_PARENT, MATCH_PARENT); + + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + recyclerView.setItemAnimator(itemAnimator); } return rootLayout; } @@ -168,6 +177,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } loadingView.setColors(Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundGray, -1); loadingView.setViewType(FlickerLoadingView.MEMBER_REQUESTS_TYPE); + loadingView.setMemberRequestButton(isChannel); } return loadingView; } @@ -323,20 +333,19 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener final boolean needShowLoading = isNeedShowLoading; AndroidUtilities.runOnUIThread(() -> { final boolean isEmptyQuery = TextUtils.isEmpty(query); - final boolean isEmptyOffset = currentImporters.isEmpty() || isFirstLoading; final String lastQuery = query; isLoading = true; isFirstLoading = false; - final Runnable showLoadingRunnable = isEmptyQuery && needShowLoading ? () -> setViewVisible(loadingView, true, true) : null; + TLRPC.TL_chatInviteImporter lastInvitedUser = isEmptyQuery && !currentImporters.isEmpty() + ? currentImporters.get(currentImporters.size() - 1) + : null; + final boolean isEmptyOffset = lastInvitedUser == null; + final Runnable showLoadingRunnable = isEmptyQuery && isEmptyOffset && needShowLoading ? () -> setViewVisible(loadingView, true, true) : null; if (isEmptyQuery) { AndroidUtilities.runOnUIThread(showLoadingRunnable, 300); } - - TLRPC.TL_chatInviteImporter lastInvitedUser = !isEmptyQuery && !currentImporters.isEmpty() - ? currentImporters.get(currentImporters.size() - 1) - : null; searchRequestId = controller.getImporters(chatId, lastQuery, lastInvitedUser, users, (response, error) -> { AndroidUtilities.runOnUIThread(() -> { isLoading = false; @@ -359,6 +368,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } private void onImportersLoaded(TLRPC.TL_messages_chatInviteImporters importers, String lastQuery, boolean isEmptyOffset, boolean fromCache) { + boolean hadMore = !currentImporters.isEmpty() && hasMore; for (int i = 0; i < importers.users.size(); ++i) { TLRPC.User user = importers.users.get(i); users.put(user.id, user); @@ -366,10 +376,19 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener if (isEmptyOffset) { adapter.setItems(importers.importers); } else { + boolean moveMore = importers.importers.size() > 0 && currentImporters.size() + importers.importers.size() < importers.count; // last loading cell should be reappeared, instead of a move forward + if (moveMore) { + adapter.notifyItemRemoved((isShowLastItemDivider ? 0 : 1) + currentImporters.size()); + } adapter.appendItems(importers.importers); + if (moveMore) { + adapter.notifyItemInserted((isShowLastItemDivider ? 0 : 1) + currentImporters.size()); + } } if (TextUtils.isEmpty(lastQuery)) { - allImporters.clear(); + if (isEmptyOffset) { + allImporters.clear(); + } allImporters.addAll(importers.importers); if (showSearchMenu) { fragment.getActionBar().createMenu().getItem(MemberRequestsActivity.searchMenuItem).setVisibility(allImporters.isEmpty() ? GONE : VISIBLE); @@ -377,6 +396,13 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } onImportersChanged(lastQuery, fromCache, false); hasMore = currentImporters.size() < importers.count; + if (hadMore != (!currentImporters.isEmpty() && hasMore)) { + if (hasMore) { + adapter.notifyItemInserted(adapter.getItemCount() - 1); + } else { + adapter.notifyItemRemoved(adapter.getItemCount()); + } + } } @Override @@ -525,6 +551,8 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } } + private final Runnable loadMembersRunnable = () -> loadMembers(); + private final RecyclerView.OnScrollListener listScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { @@ -532,7 +560,8 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener if (hasMore && !isLoading && layoutManager != null) { int lastPosition = layoutManager.findLastVisibleItemPosition(); if (adapter.getItemCount() - lastPosition < 10) { - loadMembers(); + AndroidUtilities.cancelRunOnUIThread(loadMembersRunnable); + AndroidUtilities.runOnUIThread(loadMembersRunnable); } } } @@ -567,6 +596,26 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener case 3: view = new View(parent.getContext()); break; + case 4: + FlickerLoadingView loadingView = new FlickerLoadingView(fragment.getParentActivity(), fragment.getResourceProvider()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension( + MeasureSpec.getSize(widthMeasureSpec), + AndroidUtilities.dp(2 * 52) + ); + } + }; + if (isShowLastItemDivider) { + loadingView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, fragment.getResourceProvider())); + } + loadingView.setColors(Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundGray, -1); + loadingView.setViewType(FlickerLoadingView.MEMBER_REQUESTS_TYPE); + loadingView.setMemberRequestButton(isChannel); + loadingView.setIsSingleCell(true); + loadingView.setItemsCount(1); + view = loadingView; + break; } return new RecyclerListView.Holder(view); } @@ -576,7 +625,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener if (holder.getItemViewType() == 0) { MemberRequestCell cell = (MemberRequestCell) holder.itemView; position -= extraFirstHolders(); - cell.setData(users, currentImporters.get(position), position != currentImporters.size() - 1); + cell.setData(users, currentImporters.get(position), position != currentImporters.size() - 1 || hasMore); } else if (holder.getItemViewType() == 2) { holder.itemView.requestLayout(); } @@ -594,22 +643,17 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener @Override public int getItemViewType(int position) { - if (isShowLastItemDivider) { - if (position == currentImporters.size() && !currentImporters.isEmpty()) { - return 1; - } - } else { - if (position == 0) { - return 2; - } else if (position == getItemCount() - 1) { - return 3; - } + if (position == 0 && !isShowLastItemDivider) { + return 2; + } else if (position == getItemCount() - 1 && extraLastHolders() > 0) { + return 4; } return 0; } @SuppressLint("NotifyDataSetChanged") public void setItems(List newItems) { + boolean fromEmptyArray = currentImporters.isEmpty(); for (int i = 0; i < newItems.size(); ++i) { long id = newItems.get(i).user_id; for (int j = i + 1; j < newItems.size(); ++j) { @@ -623,7 +667,11 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } currentImporters.clear(); currentImporters.addAll(newItems); - notifyDataSetChanged(); + if (fromEmptyArray) { + notifyItemRangeInserted((isShowLastItemDivider ? 0 : 1), currentImporters.size()); + } else { + notifyDataSetChanged(); + } } public void appendItems(List newItems) { @@ -639,10 +687,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } } currentImporters.addAll(newItems); - if (currentImporters.size() > newItems.size()) { - notifyItemChanged(currentImporters.size() - newItems.size() - 1); - } - notifyItemRangeInserted(currentImporters.size() - newItems.size(), newItems.size()); + notifyItemRangeInserted((isShowLastItemDivider ? 0 : 1) + currentImporters.size() - newItems.size(), newItems.size()); } public void removeItem(TLRPC.TL_chatInviteImporter item) { @@ -667,7 +712,10 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener } private int extraLastHolders() { - return isShowLastItemDivider && currentImporters.isEmpty() ? 0 : 1; + if (!currentImporters.isEmpty() && hasMore) { + return 1; + } + return 0; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 6d5ed352e..484c99f98 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -84,8 +84,6 @@ import androidx.recyclerview.widget.LinearSmoothScrollerCustom; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; @@ -124,6 +122,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -208,7 +207,6 @@ import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.RecyclerAnimationScrollHelper; import org.telegram.ui.Components.RecyclerItemsEnterAnimator; import org.telegram.ui.Components.RecyclerListView; -import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.Components.SearchViewPager; import org.telegram.ui.Components.SharedMediaLayout; import org.telegram.ui.Components.SimpleThemeDescription; @@ -303,14 +301,44 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } boolean updating; + + Runnable saveScrollPositionRunnable = () -> { + if (listView != null && listView.getScrollState() == RecyclerView.SCROLL_STATE_IDLE && listView.getChildCount() > 0 && listView.getLayoutManager() != null) { + boolean hasHiddenArchive = dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() && archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN; + float tabsTranslation = scrollYOffset; + LinearLayoutManager layoutManager = ((LinearLayoutManager) listView.getLayoutManager()); + View view = null; + int position = -1; + int top = Integer.MAX_VALUE; + for (int i = 0; i < listView.getChildCount(); i++) { + int childPosition = listView.getChildAdapterPosition(listView.getChildAt(i)); + View child = listView.getChildAt(i); + if (childPosition != RecyclerListView.NO_POSITION && child != null && child.getTop() < top) { + view = child; + position = childPosition; + top = child.getTop(); + } + } + if (view != null) { + float offset = view.getTop() - listView.getPaddingTop(); + if (!hasStories) { + // offset += tabsTranslation; + } else { + tabsTranslation = 0; + } + if (listView.getScrollState() != RecyclerView.SCROLL_STATE_DRAGGING) { + if (hasHiddenArchive && position == 0 && listView.getPaddingTop() - view.getTop() - view.getMeasuredHeight() + tabsTranslation < 0) { + position = 1; + offset = tabsTranslation; + } + layoutManager.scrollToPositionWithOffset(position, (int) offset); + } + } + } + }; + Runnable updateListRunnable = () -> { - float scrollYOffset = DialogsActivity.this.scrollYOffset; - boolean hasStories = DialogsActivity.this.hasStories; -// if (hasStories && rightSlidingDialogContainer.hasFragment()) { -// hasStories = false; -// //scrollYOffset = 0; -// } - dialogsAdapter.updateList(listView, dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() && archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN, scrollYOffset, hasStories); + dialogsAdapter.updateList(saveScrollPositionRunnable); invalidateScrollY = true; listView.updateDialogsOnNextDraw = true; updating = false; @@ -392,6 +420,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow selectAnimatedEmojiDialog; + public boolean isReplyTo, isQuote; private int initialDialogsType; private boolean checkingImportDialog; @@ -2588,6 +2617,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. canSelectTopics = arguments.getBoolean("canSelectTopics", false); cantSendToChannels = arguments.getBoolean("cantSendToChannels", false); initialDialogsType = arguments.getInt("dialogsType", DIALOGS_TYPE_DEFAULT); + isQuote = arguments.getBoolean("quote", false); + isReplyTo = arguments.getBoolean("reply_to", false); selectAlertString = arguments.getString("selectAlertString"); selectAlertStringGroup = arguments.getString("selectAlertStringGroup"); addToGroupAlertString = arguments.getString("addToGroupAlertString"); @@ -3131,7 +3162,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); if (onlySelect) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); - if (initialDialogsType == DIALOGS_TYPE_FORWARD && selectAlertString == null) { + if (isReplyTo) { + actionBar.setTitle(LocaleController.getString(R.string.ReplyToDialog)); + } else if (isQuote) { + actionBar.setTitle(LocaleController.getString(R.string.QuoteTo)); + } else if (initialDialogsType == DIALOGS_TYPE_FORWARD && selectAlertString == null) { actionBar.setTitle(LocaleController.getString("ForwardTo", R.string.ForwardTo)); } else if (initialDialogsType == DIALOGS_TYPE_WIDGET) { actionBar.setTitle(LocaleController.getString("SelectChats", R.string.SelectChats)); @@ -3891,7 +3926,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. presentFragment(activity); return; } else if (view instanceof DialogsHintCell && (viewPage.dialogsType == 7 || viewPage.dialogsType == 8)) { - TLRPC.TL_chatlists_chatlistUpdates updates = viewPage.dialogsAdapter.getChatlistUpdate(); + TL_chatlists.TL_chatlists_chatlistUpdates updates = viewPage.dialogsAdapter.getChatlistUpdate(); if (updates != null) { MessagesController.DialogFilter filter = getMessagesController().selectedDialogFilter[viewPage.dialogsType - 7]; if (filter != null) { @@ -3906,7 +3941,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. dialogCell.avatarImage.getImageX2(), dialogCell.avatarImage.getImageY2() ); } - onItemClick(view, position, viewPage.dialogsAdapter); + onItemClick(view, position, viewPage.dialogsAdapter, x, y); }); viewPage.listView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListenerExtended() { @Override @@ -4346,12 +4381,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } }); - searchViewPager.searchListView.setOnItemClickListener((view, position) -> { + searchViewPager.searchListView.setOnItemClickListener((view, position, x, y) -> { if (initialDialogsType == DIALOGS_TYPE_WIDGET) { - onItemLongClick(searchViewPager.searchListView, view, position, 0, 0, -1, searchViewPager.dialogsSearchAdapter); + onItemLongClick(searchViewPager.searchListView, view, position, x, y, -1, searchViewPager.dialogsSearchAdapter); return; } - onItemClick(view, position, searchViewPager.dialogsSearchAdapter); + onItemClick(view, position, searchViewPager.dialogsSearchAdapter, x, y); }); searchViewPager.searchListView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListenerExtended() { @Override @@ -4664,7 +4699,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } @Override - public void onTextChanged(final CharSequence text, boolean bigChange) { + public void onTextChanged(final CharSequence text, boolean bigChange, boolean fromDraft) { } @@ -5621,7 +5656,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (dialogsHintCell == null || fragmentView == null || getContext() == null) { return; } - if (!getMessagesController().getUnconfirmedAuthController().auths.isEmpty() && folderId == 0 && initialDialogsType == DIALOGS_TYPE_DEFAULT) { + if (isInPreviewMode()) { + dialogsHintCellVisible = false; + dialogsHintCell.setVisibility(View.GONE); + updateAuthHintCellVisibility(false); + } else if (!getMessagesController().getUnconfirmedAuthController().auths.isEmpty() && folderId == 0 && initialDialogsType == DIALOGS_TYPE_DEFAULT) { dialogsHintCellVisible = false; dialogsHintCell.setVisibility(View.GONE); if (authHintCell == null) { @@ -5644,7 +5683,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. AndroidUtilities.replaceSingleTag( LocaleController.formatString(R.string.RestorePremiumHintTitle, MediaDataController.getInstance(currentAccount).getPremiumHintAnnualDiscount(false)), Theme.key_windowBackgroundWhiteValueText, - 0, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, null ), LocaleController.getString(R.string.RestorePremiumHintMessage) @@ -5664,7 +5703,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. AndroidUtilities.replaceSingleTag( LocaleController.formatString(isPremiumHintUpgrade ? R.string.SaveOnAnnualPremiumTitle : R.string.UpgradePremiumTitle, MediaDataController.getInstance(currentAccount).getPremiumHintAnnualDiscount(false)), Theme.key_windowBackgroundWhiteValueText, - 0, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, null ), LocaleController.getString(isPremiumHintUpgrade ? R.string.UpgradePremiumMessage : R.string.SaveOnAnnualPremiumMessage) @@ -5684,7 +5723,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. AndroidUtilities.replaceSingleTag( LocaleController.formatString(R.string.ClearStorageHintTitle, AndroidUtilities.formatFileSize(cacheSize)), Theme.key_windowBackgroundWhiteValueText, - 0, + AndroidUtilities.REPLACING_TAG_TYPE_LINKBOLD, null ), LocaleController.getString(R.string.ClearStorageHintMessage) @@ -6970,9 +7009,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } @Override - public void setInPreviewMode(boolean value) { - super.setInPreviewMode(value); - if (!value && avatarContainer != null) { + public void setInPreviewMode(boolean isInPreviewMode) { + super.setInPreviewMode(isInPreviewMode); + if (!isInPreviewMode && avatarContainer != null) { actionBar.setBackground(null); ((ViewGroup.MarginLayoutParams) actionBar.getLayoutParams()).topMargin = 0; actionBar.removeView(avatarContainer); @@ -6987,6 +7026,20 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. contentView.addView(fragmentLocationContextView); } } + if (dialogStoriesCell != null) { + if (dialogStoriesCellVisible && !isInPreviewMode) { + dialogStoriesCell.setVisibility(View.VISIBLE); + } else { + dialogStoriesCell.setVisibility(View.GONE); + } + } + if (floatingButtonContainer != null) { + floatingButtonContainer.setVisibility(onlySelect && initialDialogsType != 10 || folderId != 0 || isInPreviewMode ? View.GONE : View.VISIBLE); + } + if (floatingButton2Container != null) { + floatingButton2Container.setVisibility(onlySelect && initialDialogsType != 10 || folderId != 0 || !storiesEnabled || (searchItem != null && searchItem.isSearchFieldVisible()) || isInPreviewMode ? View.GONE : View.VISIBLE); + } + updateDialogsHint(); } public boolean addOrRemoveSelectedDialog(long did, View cell) { @@ -7309,7 +7362,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } if (dialogStoriesCell != null) { - if (dialogStoriesCellVisible && !show) { + if (dialogStoriesCellVisible && !isInPreviewMode() && !show) { dialogStoriesCell.setVisibility(View.VISIBLE); } else { dialogStoriesCell.setVisibility(View.GONE); @@ -7595,7 +7648,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } - private void onItemClick(View view, int position, RecyclerListView.Adapter adapter) { + private void onItemClick(View view, int position, RecyclerListView.Adapter adapter, float x, float y) { if (getParentActivity() == null) { return; } @@ -7747,6 +7800,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. bundle.putLong("chat_id", -dialogId); bundle.putBoolean("for_select", true); bundle.putBoolean("forward_to", true); + bundle.putBoolean("quote", isQuote); + bundle.putBoolean("reply_to", isReplyTo); TopicsFragment topicsFragment = new TopicsFragment(bundle); topicsFragment.setForwardFromDialogFragment(DialogsActivity.this); presentFragment(topicsFragment); @@ -7926,7 +7981,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. TLRPC.Dialog dialog; if (adapter == searchViewPager.dialogsSearchAdapter) { if (onlySelect) { - onItemClick(view, position, adapter); + onItemClick(view, position, adapter, x, y); return false; } long dialogId = 0; @@ -8377,7 +8432,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. final boolean storiesEnabled = getMessagesController().storiesEnabled(); if (this.storiesEnabled != storiesEnabled) { if (floatingButton2Container != null) { - floatingButton2Container.setVisibility(onlySelect && initialDialogsType != 10 || folderId != 0 || !storiesEnabled || (searchItem != null && searchItem.isSearchFieldVisible()) ? View.GONE : View.VISIBLE); + floatingButton2Container.setVisibility(onlySelect && initialDialogsType != 10 || folderId != 0 || !storiesEnabled || (searchItem != null && searchItem.isSearchFieldVisible()) || isInPreviewMode() ? View.GONE : View.VISIBLE); } updateFloatingButtonOffset(); if (!this.storiesEnabled && storiesEnabled && storyHint != null) { @@ -10441,6 +10496,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } else if (id == NotificationCenter.storiesUpdated) { updateStoriesVisibility(wasDrawn); + updateVisibleRows(0); } else if (id == NotificationCenter.storiesEnabledUpdate) { updateStoriesPosting(); } else if (id == NotificationCenter.unconfirmedAuthUpdate) { @@ -12328,7 +12384,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (storiesVisibilityAnimator2 != null) { storiesVisibilityAnimator2.cancel(); } - if (dialogStoriesCellVisible) { + if (dialogStoriesCellVisible && !isInPreviewMode()) { dialogStoriesCell.setVisibility(View.VISIBLE); } storiesVisibilityAnimator2 = ValueAnimator.ofFloat(progressToDialogStoriesCell, dialogStoriesCellVisible ? 1f : 0); @@ -12357,7 +12413,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. storiesVisibilityAnimator2.setInterpolator(CubicBezierInterpolator.DEFAULT); storiesVisibilityAnimator2.start(); } else { - dialogStoriesCell.setVisibility(dialogStoriesCellVisible ? View.VISIBLE : View.GONE); + dialogStoriesCell.setVisibility(dialogStoriesCellVisible && !isInPreviewMode() ? View.VISIBLE : View.GONE); progressToDialogStoriesCell = dialogStoriesCellVisible ? 1f : 0; if (fragmentView != null) { fragmentView.invalidate(); @@ -12372,7 +12428,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (newVisibility) { dialogStoriesCell.setProgressToCollapse(1f, false); } - if (animated) { + if (animated && !isInPreviewMode()) { dialogStoriesCell.setVisibility(View.VISIBLE); float fromScrollY = -scrollYOffset; float toScrollY; @@ -12432,7 +12488,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { progressToShowStories = newVisibility ? 1f : 0; hasStories = newVisibility; - dialogStoriesCell.setVisibility(hasStories || hasOnlySlefStories ? View.VISIBLE : View.GONE); + dialogStoriesCell.setVisibility((hasStories || hasOnlySlefStories) && !isInPreviewMode() ? View.VISIBLE : View.GONE); if (!newVisibility) { setScrollY(0); } else { @@ -12444,9 +12500,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPages[i].listView.requestLayout(); } } -// if (viewPages[0] != null) { -// viewPages[0].layoutManager.scrollToPositionWithOffset(hasHiddenArchive() ? 1 : 0, 0/*(int) -scrollYOffset*/); -// } if (fragmentView != null) { fragmentView.requestLayout(); fragmentView.invalidate(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterChatlistActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterChatlistActivity.java index 9525fad66..c913bc269 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterChatlistActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterChatlistActivity.java @@ -62,6 +62,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -97,7 +98,7 @@ public class FilterChatlistActivity extends BaseFragment { private ListAdapter adapter; MessagesController.DialogFilter filter; - TLRPC.TL_exportedChatlistInvite invite; + TL_chatlists.TL_exportedChatlistInvite invite; private static final int MAX_NAME_LENGTH = 32; @@ -111,21 +112,21 @@ public class FilterChatlistActivity extends BaseFragment { private int shiftDp = -5; private long lastClickedDialogId, lastClicked; - public FilterChatlistActivity(MessagesController.DialogFilter filter, TLRPC.TL_exportedChatlistInvite invite) { + public FilterChatlistActivity(MessagesController.DialogFilter filter, TL_chatlists.TL_exportedChatlistInvite invite) { super(); this.filter = filter; this.invite = invite; } - private Utilities.Callback onDelete; - private Utilities.Callback onEdit; + private Utilities.Callback onDelete; + private Utilities.Callback onEdit; - public void setOnDelete(Utilities.Callback onDelete) { + public void setOnDelete(Utilities.Callback onDelete) { this.onDelete = onDelete; } - public void setOnEdit(Utilities.Callback onEdit) { + public void setOnEdit(Utilities.Callback onEdit) { this.onEdit = onEdit; } @@ -329,8 +330,8 @@ public class FilterChatlistActivity extends BaseFragment { invite.peers.add(getMessagesController().getPeer(selectedPeers.get(i))); } - TLRPC.TL_chatlists_editExportedInvite req = new TLRPC.TL_chatlists_editExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_editExportedInvite req = new TL_chatlists.TL_chatlists_editExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.slug = getSlug(); req.revoked = invite.revoked; @@ -363,8 +364,8 @@ public class FilterChatlistActivity extends BaseFragment { getConnectionsManager().cancelRequest(savingTitleReqId, true); savingTitleReqId = 0; } - TLRPC.TL_chatlists_editExportedInvite req = new TLRPC.TL_chatlists_editExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_editExportedInvite req = new TL_chatlists.TL_chatlists_editExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.slug = getSlug(); req.revoked = invite.revoked; @@ -495,8 +496,8 @@ public class FilterChatlistActivity extends BaseFragment { return; } - TLRPC.TL_chatlists_editExportedInvite req = new TLRPC.TL_chatlists_editExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_editExportedInvite req = new TL_chatlists.TL_chatlists_editExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.revoked = revoke; req.slug = getSlug(); @@ -513,8 +514,8 @@ public class FilterChatlistActivity extends BaseFragment { @Override protected void deleteLink() { - TLRPC.TL_chatlists_deleteExportedInvite req = new TLRPC.TL_chatlists_deleteExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_deleteExportedInvite req = new TL_chatlists.TL_chatlists_deleteExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.slug = getSlug(); final AlertDialog progressDialog = new AlertDialog(getContext(), AlertDialog.ALERT_TYPE_SPINNER); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java index dada3b7e0..0cc262bcb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java @@ -59,6 +59,7 @@ import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -127,7 +128,7 @@ public class FilterCreateActivity extends BaseFragment { ); } - private ArrayList invites = new ArrayList<>(); + private ArrayList invites = new ArrayList<>(); private static final int MAX_NAME_LENGTH = 12; @@ -207,17 +208,17 @@ public class FilterCreateActivity extends BaseFragment { return; } loadingInvites = true; - TLRPC.TL_chatlists_getExportedInvites req = new TLRPC.TL_chatlists_getExportedInvites(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_getExportedInvites req = new TL_chatlists.TL_chatlists_getExportedInvites(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; requestingInvitesReqId = getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { loadingInvites = false; - if (res instanceof TLRPC.TL_chatlists_exportedInvites) { - TLRPC.TL_chatlists_exportedInvites invs = (TLRPC.TL_chatlists_exportedInvites) res; + if (res instanceof TL_chatlists.TL_chatlists_exportedInvites) { + TL_chatlists.TL_chatlists_exportedInvites invs = (TL_chatlists.TL_chatlists_exportedInvites) res; getMessagesController().putChats(invs.chats, false); getMessagesController().putUsers(invs.users, false); invites.clear(); - invites.addAll(((TLRPC.TL_chatlists_exportedInvites) res).invites); + invites.addAll(((TL_chatlists.TL_chatlists_exportedInvites) res).invites); updateRows(); } requestingInvitesReqId = 0; @@ -514,20 +515,20 @@ public class FilterCreateActivity extends BaseFragment { } if (!peers.isEmpty()) { - TLRPC.TL_chatlists_exportChatlistInvite req = new TLRPC.TL_chatlists_exportChatlistInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_exportChatlistInvite req = new TL_chatlists.TL_chatlists_exportChatlistInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.peers = peers; req.title = ""; getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if ( processErrors(err, FilterCreateActivity.this, BulletinFactory.of(FilterCreateActivity.this)) && - res instanceof TLRPC.TL_chatlists_exportedChatlistInvite + res instanceof TL_chatlists.TL_chatlists_exportedChatlistInvite ) { FilterCreateActivity.hideNew(0); getMessagesController().loadRemoteFilters(true); - TLRPC.TL_chatlists_exportedChatlistInvite inv = (TLRPC.TL_chatlists_exportedChatlistInvite) res; + TL_chatlists.TL_chatlists_exportedChatlistInvite inv = (TL_chatlists.TL_chatlists_exportedChatlistInvite) res; FilterChatlistActivity fragment = new FilterChatlistActivity(filter, inv.invite); fragment.setOnEdit(this::onEdit); fragment.setOnDelete(this::onDelete); @@ -575,14 +576,14 @@ public class FilterCreateActivity extends BaseFragment { return ChatObject.canUserDoAdminAction(chat, ChatObject.ACTION_INVITE) || ChatObject.isPublic(chat) && !chat.join_request; } - private void onDelete(TLRPC.TL_exportedChatlistInvite editedInvite) { + private void onDelete(TL_chatlists.TL_exportedChatlistInvite editedInvite) { if (editedInvite == null) { return; } int index = -1; for (int i = 0; i < invites.size(); ++i) { - TLRPC.TL_exportedChatlistInvite invite = invites.get(i); + TL_chatlists.TL_exportedChatlistInvite invite = invites.get(i); if (TextUtils.equals(invite.url, editedInvite.url)) { index = i; break; @@ -600,14 +601,14 @@ public class FilterCreateActivity extends BaseFragment { } } - private void onEdit(TLRPC.TL_exportedChatlistInvite editedInvite) { + private void onEdit(TL_chatlists.TL_exportedChatlistInvite editedInvite) { if (editedInvite == null) { return; } int index = -1; for (int i = 0; i < invites.size(); ++i) { - TLRPC.TL_exportedChatlistInvite invite = invites.get(i); + TL_chatlists.TL_exportedChatlistInvite invite = invites.get(i); if (TextUtils.equals(invite.url, editedInvite.url)) { index = i; break; @@ -1134,7 +1135,7 @@ public class FilterCreateActivity extends BaseFragment { private int iconResId; private boolean isRed; - private TLRPC.TL_exportedChatlistInvite link; + private TL_chatlists.TL_exportedChatlistInvite link; public ItemInner(int viewType, boolean selectable) { super(viewType, selectable); @@ -1179,7 +1180,7 @@ public class FilterCreateActivity extends BaseFragment { return item; } - public static ItemInner asLink(TLRPC.TL_exportedChatlistInvite invite) { + public static ItemInner asLink(TL_chatlists.TL_exportedChatlistInvite invite) { ItemInner item = new ItemInner(VIEW_TYPE_LINK, false); item.link = invite; return item; @@ -1333,7 +1334,7 @@ public class FilterCreateActivity extends BaseFragment { case VIEW_TYPE_LINK: view = new LinkCell(mContext, FilterCreateActivity.this, currentAccount, filter.id) { @Override - protected void onDelete(TLRPC.TL_exportedChatlistInvite invite) { + protected void onDelete(TL_chatlists.TL_exportedChatlistInvite invite) { FilterCreateActivity.this.onDelete(invite); } @@ -1796,9 +1797,9 @@ public class FilterCreateActivity extends BaseFragment { } protected String lastUrl; - private TLRPC.TL_exportedChatlistInvite lastInvite; + private TL_chatlists.TL_exportedChatlistInvite lastInvite; - public void setInvite(TLRPC.TL_exportedChatlistInvite invite, boolean divider) { + public void setInvite(TL_chatlists.TL_exportedChatlistInvite invite, boolean divider) { boolean animated = lastInvite == invite; lastInvite = invite; String url = lastUrl = invite.url; @@ -1850,8 +1851,8 @@ public class FilterCreateActivity extends BaseFragment { return; } - TLRPC.TL_chatlists_editExportedInvite req = new TLRPC.TL_chatlists_editExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_editExportedInvite req = new TL_chatlists.TL_chatlists_editExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; req.revoked = revoke; req.slug = getSlug(); @@ -1872,8 +1873,8 @@ public class FilterCreateActivity extends BaseFragment { return; } - TLRPC.TL_chatlists_deleteExportedInvite req = new TLRPC.TL_chatlists_deleteExportedInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_deleteExportedInvite req = new TL_chatlists.TL_chatlists_deleteExportedInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filterId; req.slug = slug; Runnable update = () -> onDelete(lastInvite); @@ -1887,7 +1888,7 @@ public class FilterCreateActivity extends BaseFragment { AndroidUtilities.runOnUIThread(update, 150); } - protected void onDelete(TLRPC.TL_exportedChatlistInvite invite) { + protected void onDelete(TL_chatlists.TL_exportedChatlistInvite invite) { } @@ -2092,18 +2093,18 @@ public class FilterCreateActivity extends BaseFragment { public static void show(BaseFragment fragment, MessagesController.DialogFilter filter, Runnable onLoaded) { long start = System.currentTimeMillis(); - TLRPC.TL_chatlists_getExportedInvites req = new TLRPC.TL_chatlists_getExportedInvites(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_getExportedInvites req = new TL_chatlists.TL_chatlists_getExportedInvites(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; fragment.getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (fragment == null || fragment.getContext() == null) { return; } - if (res instanceof TLRPC.TL_chatlists_exportedInvites) { - TLRPC.TL_chatlists_exportedInvites invs = (TLRPC.TL_chatlists_exportedInvites) res; + if (res instanceof TL_chatlists.TL_chatlists_exportedInvites) { + TL_chatlists.TL_chatlists_exportedInvites invs = (TL_chatlists.TL_chatlists_exportedInvites) res; fragment.getMessagesController().putChats(invs.chats, false); fragment.getMessagesController().putUsers(invs.users, false); - new FilterCreateActivity.FilterInvitesBottomSheet(fragment, filter, ((TLRPC.TL_chatlists_exportedInvites) res).invites).show(); + new FilterCreateActivity.FilterInvitesBottomSheet(fragment, filter, ((TL_chatlists.TL_chatlists_exportedInvites) res).invites).show(); } else if (err != null && "FILTER_ID_INVALID".equals(err.text) && !filter.isDefault()) { new FilterCreateActivity.FilterInvitesBottomSheet(fragment, filter, null).show(); } else { @@ -2116,7 +2117,7 @@ public class FilterCreateActivity extends BaseFragment { } private MessagesController.DialogFilter filter; - private ArrayList invites = new ArrayList<>(); + private ArrayList invites = new ArrayList<>(); private FrameLayout bulletinContainer; @@ -2124,7 +2125,7 @@ public class FilterCreateActivity extends BaseFragment { private TextView button; - public FilterInvitesBottomSheet(BaseFragment fragment, MessagesController.DialogFilter filter, ArrayList loadedInvites) { + public FilterInvitesBottomSheet(BaseFragment fragment, MessagesController.DialogFilter filter, ArrayList loadedInvites) { super(fragment, false, false); this.filter = filter; @@ -2287,7 +2288,7 @@ public class FilterCreateActivity extends BaseFragment { } @Override - protected void onDelete(TLRPC.TL_exportedChatlistInvite invite) { + protected void onDelete(TL_chatlists.TL_exportedChatlistInvite invite) { invites.remove(invite); updateCreateInviteButton(); updateRows(true); @@ -2418,21 +2419,21 @@ public class FilterCreateActivity extends BaseFragment { dismiss(); getBaseFragment().presentFragment(new FilterChatlistActivity(filter, null)); } else { - TLRPC.TL_chatlists_exportChatlistInvite req = new TLRPC.TL_chatlists_exportChatlistInvite(); - req.chatlist = new TLRPC.TL_inputChatlistDialogFilter(); + TL_chatlists.TL_chatlists_exportChatlistInvite req = new TL_chatlists.TL_chatlists_exportChatlistInvite(); + req.chatlist = new TL_chatlists.TL_inputChatlistDialogFilter(); req.chatlist.filter_id = filter.id; req.peers = peers; req.title = ""; getBaseFragment().getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if ( processErrors(err, getBaseFragment(), BulletinFactory.of(bulletinContainer, null)) && - res instanceof TLRPC.TL_chatlists_exportedChatlistInvite + res instanceof TL_chatlists.TL_chatlists_exportedChatlistInvite ) { FilterCreateActivity.hideNew(0); dismiss(); getBaseFragment().getMessagesController().loadRemoteFilters(true); - TLRPC.TL_chatlists_exportedChatlistInvite inv = (TLRPC.TL_chatlists_exportedChatlistInvite) res; + TL_chatlists.TL_chatlists_exportedChatlistInvite inv = (TL_chatlists.TL_chatlists_exportedChatlistInvite) res; getBaseFragment().presentFragment(new FilterChatlistActivity(filter, inv.invite)); } })); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index 20ff87621..613a6df5a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -477,7 +477,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente if (ChatObject.isForum(chatTo)) { TLRPC.TL_forumTopic topic = MessagesController.getInstance(UserConfig.selectedAccount).getTopicsController().findTopic(chatTo.id, MessageObject.getTopicId(messageObject.messageOwner, true)); if (topic != null) { - chatTitle = ForumUtilities.getTopicSpannedName(topic, null); + chatTitle = ForumUtilities.getTopicSpannedName(topic, null, false); } } chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false); @@ -496,7 +496,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente if (ChatObject.isForum(chatFrom)) { TLRPC.TL_forumTopic topic = MessagesController.getInstance(UserConfig.selectedAccount).getTopicsController().findTopic(chatFrom.id, MessageObject.getTopicId(messageObject.messageOwner, true)); if (topic != null) { - chatTitle = ForumUtilities.getTopicSpannedName(topic, null); + chatTitle = ForumUtilities.getTopicSpannedName(topic, null, false); } } chatTitle = Emoji.replaceEmoji(chatTitle, textPaint == null ? null : textPaint.getFontMetricsInt(), false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index 8d54b64a8..98e8570b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -8460,7 +8460,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter src.renameTo(destFile); } - accountInstance.getMessagesStorage().clearUserPhotos(user.id); + accountInstance.getMessagesController().getDialogPhotos(user.id).reset(); ArrayList users = new ArrayList<>(); users.add(user); accountInstance.getMessagesStorage().putUsersAndChats(users, null, false, true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IUpdateLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/IUpdateLayout.java new file mode 100644 index 000000000..91d900081 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/IUpdateLayout.java @@ -0,0 +1,11 @@ +package org.telegram.ui; + +import android.app.Activity; +import android.view.ViewGroup; + +public abstract class IUpdateLayout { + public IUpdateLayout(Activity activity, ViewGroup sideMenu, ViewGroup sideMenuContainer) {} + public void updateFileProgress(Object[] args) {} + public void createUpdateUI(int currentAccount) {} + public void updateAppUpdateViews(int currentAccount, boolean animated) {} +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index fddc0ff93..44780e57c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -21,7 +21,6 @@ import android.app.Activity; import android.app.ActivityManager; import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -30,12 +29,8 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Matrix; -import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; -import android.graphics.Shader; import android.location.LocationManager; import android.media.AudioManager; import android.net.Uri; @@ -58,7 +53,6 @@ import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseIntArray; -import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; import android.view.KeyEvent; @@ -74,7 +68,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -112,7 +105,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.FingerprintController; import org.telegram.messenger.FlagSecureReason; import org.telegram.messenger.GenericProvider; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LiteMode; import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocationController; @@ -145,16 +137,14 @@ import org.telegram.messenger.voip.VoIPService; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ActionBarLayout; -import org.telegram.ui.ActionBar.ActionBarMenu; +import org.telegram.tgnet.tl.TL_stories; +import org.telegram.tgnet.tl.TL_chatlists; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; import org.telegram.ui.ActionBar.INavigationLayout; -import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Adapters.DrawerLayoutAdapter; -import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.DrawerActionCell; import org.telegram.ui.Cells.DrawerAddCell; import org.telegram.ui.Cells.DrawerProfileCell; @@ -181,15 +171,15 @@ import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.GroupCallPip; import org.telegram.ui.Components.JoinGroupAlert; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.MediaActivity; import org.telegram.ui.Components.PasscodeView; import org.telegram.ui.Components.PhonebookShareAlert; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.Premium.boosts.BoostPagerBottomSheet; +import org.telegram.ui.Components.Premium.boosts.GiftInfoBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; -import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SharingLocationsAlert; import org.telegram.ui.Components.SideMenultItemAnimator; @@ -199,7 +189,6 @@ import org.telegram.ui.Components.StickersAlert; import org.telegram.ui.Components.TermsOfServiceView; import org.telegram.ui.Components.ThemeEditorView; import org.telegram.ui.Components.UndoView; -import org.telegram.ui.Components.UpdateAppAlertDialog; import org.telegram.ui.Components.spoilers.SpoilerEffect2; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Stories.StoriesController; @@ -284,12 +273,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati private RecyclerListView sideMenu; private SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow selectAnimatedEmojiDialog; private SideMenultItemAnimator itemAnimator; - private FrameLayout updateLayout; - private RadialProgress2 updateLayoutIcon; - private SimpleTextView updateTextView; - private TextView updateSizeTextView; private FrameLayout sideMenuContainer; private View rippleAbove; + private IUpdateLayout updateLayout; private AlertDialog localeDialog; private boolean loadingLocaleDialog; @@ -564,11 +550,17 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati int id = drawerLayoutAdapter.getId(position); TLRPC.TL_attachMenuBot attachMenuBot = drawerLayoutAdapter.getAttachMenuBot(position); if (attachMenuBot != null) { - if (attachMenuBot.side_menu_disclaimer_needed) { - WebAppDisclaimerAlert.show(this, (ignore) -> { - attachMenuBot.side_menu_disclaimer_needed = false; - showAttachMenuBot(attachMenuBot, null); - MediaDataController.getInstance(currentAccount).updateAttachMenuBotsInCache(); + if (attachMenuBot.inactive || attachMenuBot.side_menu_disclaimer_needed) { + WebAppDisclaimerAlert.show(this, (allowSendMessage) -> { + TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); + botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(attachMenuBot.bot_id); + botRequest.enabled = true; + botRequest.write_allowed = true; + ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { + attachMenuBot.inactive = attachMenuBot.side_menu_disclaimer_needed = false; + showAttachMenuBot(attachMenuBot, null); + MediaDataController.getInstance(currentAccount).updateAttachMenuBotsInCache(); + }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); }, null); } else { showAttachMenuBot(attachMenuBot, null); @@ -600,7 +592,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } drawerLayoutContainer.closeDrawer(false); } else if (id == 6) { - presentFragment(new ContactsActivity(null)); + Bundle args = new Bundle(); + args.putBoolean("needFinishFragment", false); + presentFragment(new ContactsActivity(args)); drawerLayoutContainer.closeDrawer(false); } else if (id == 7) { presentFragment(new InviteContactsActivity()); @@ -781,6 +775,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } return false; }); + updateLayout = ApplicationLoader.applicationLoaderInstance.takeUpdateLayout(this, sideMenu, sideMenuContainer); drawerLayoutContainer.setParentActionBarLayout(actionBarLayout); actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer); actionBarLayout.setFragmentStack(mainFragmentsStack); @@ -957,7 +952,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } MediaController.getInstance().setBaseActivity(this, true); ApplicationLoader.startAppCenter(this); - updateAppUpdateViews(false); + if (updateLayout != null) { + updateLayout.updateAppUpdateViews(currentAccount, false); + } RemoveAfterReadingMessages.load(); Map, String>> idsToDelays = new HashMap<>(); @@ -1018,10 +1015,16 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } private void showAttachMenuBot(TLRPC.TL_attachMenuBot attachMenuBot, String startApp) { + drawerLayoutContainer.closeDrawer(); BotWebViewSheet webViewSheet = new BotWebViewSheet(this, getLastFragment().getResourceProvider()); webViewSheet.setParentActivity(this); webViewSheet.requestWebView(currentAccount, attachMenuBot.bot_id, attachMenuBot.bot_id, attachMenuBot.short_name, null, BotWebViewSheet.TYPE_SIMPLE_WEB_VIEW_BUTTON, 0, false, null, null, false, startApp, null, BotWebViewSheet.FLAG_FROM_SIDE_MENU); - webViewSheet.show(); + BaseFragment lastFragment = getLastFragment(); + if (lastFragment != null) { + lastFragment.showDialog(webViewSheet); + } else { + webViewSheet.show(); + } } @Override @@ -1700,6 +1703,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati drawerLayoutContainer.setAllowOpenDrawer(true, false); actionBarLayout.getView().setVisibility(View.VISIBLE); actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); + actionBarLayout.updateTitleOverlay(); if (AndroidUtilities.isTablet()) { layersActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -1740,6 +1744,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati @SuppressLint("Range") private boolean handleIntent(Intent intent, boolean isNew, boolean restore, boolean fromPassword, Browser.Progress progress, boolean rebuildFragments) { + if (GiftInfoBottomSheet.handleIntent(intent, progress)) { + return true; + } if (AndroidUtilities.handleProxyIntent(this, intent)) { return true; } @@ -2275,6 +2282,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati lang = path.substring(12); } else if (path.startsWith("addtheme/")) { theme = path.substring(9); + } else if (path.equalsIgnoreCase("boost") || path.startsWith("boost/")) { + isBoost = true; + String c = data.getQueryParameter("c"); + List segments = data.getPathSegments(); + if (segments.size() >= 2) { + username = segments.get(1); + } else if (!TextUtils.isEmpty(c)) { + channelId = Utilities.parseLong(c); + } } else if (path.startsWith("c/")) { List segments = data.getPathSegments(); if (segments.size() >= 3) { @@ -2760,7 +2776,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati req.settings.allow_app_hash = req.settings.allow_firebase = PushListenerController.GooglePushListenerServiceProvider.INSTANCE.hasServices(); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); if (req.settings.allow_app_hash) { - preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).apply(); + preferences.edit().putString("sms_hash", BuildVars.getSmsHash()).apply(); } else { preferences.edit().remove("sms_hash").apply(); } @@ -2786,15 +2802,16 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { if (cursor.moveToFirst()) { + long userId = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA4)); int accountId = Utilities.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.RawContacts.ACCOUNT_NAME))); - for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { - if (UserConfig.getInstance(a).getClientUserId() == accountId) { - intentAccount[0] = a; + for (int a = -1; a < UserConfig.MAX_ACCOUNT_COUNT; a++) { + int i = a == -1 ? intentAccount[0] : a; + if ((a == -1 && MessagesStorage.getInstance(i).containsLocalDialog(userId)) || UserConfig.getInstance(i).getClientUserId() == accountId) { + intentAccount[0] = i; switchToAccount(intentAccount[0], true); break; } } - long userId = cursor.getLong(cursor.getColumnIndex(ContactsContract.Data.DATA4)); NotificationCenter.getInstance(intentAccount[0]).postNotificationName(NotificationCenter.closeChats); push_user_id = userId; String mimeType = cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)); @@ -2898,7 +2915,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (mainFragmentsStack.isEmpty() || MessagesController.getInstance(intentAccount[0]).checkCanOpenChat(args, mainFragmentsStack.get(mainFragmentsStack.size() - 1))) { ChatActivity fragment = new ChatActivity(args); - if (actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { + if (getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { pushOpened = true; drawerLayoutContainer.closeDrawer(); } @@ -2927,13 +2944,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati FileLog.d("LaunchActivity openForum after load " + finalPush_chat_id + " " + finalPush_topic_id + " TL_forumTopic " + loadedTopic); if (actionBarLayout != null) { ForumUtilities.applyTopic(fragment, MessagesStorage.TopicKey.of(-finalPush_chat_id, finalPush_topic_id)); - actionBarLayout.presentFragment(fragment); + getActionBarLayout().presentFragment(fragment); } }); return true; } } - if (actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { + if (getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { pushOpened = true; drawerLayoutContainer.closeDrawer(); } @@ -2942,7 +2959,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati Bundle args = new Bundle(); args.putInt("enc_id", push_enc_id); ChatActivity fragment = new ChatActivity(args); - if (actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { + if (getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true))) { pushOpened = true; drawerLayoutContainer.closeDrawer(); } @@ -3047,7 +3064,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } boolean closePreviousFinal = closePrevious; if (open_settings == 6) { - actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); + getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); } else { AndroidUtilities.runOnUIThread(() -> presentFragment(fragment, closePreviousFinal, false)); } @@ -3062,7 +3079,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else if (open_new_dialog != 0) { Bundle args = new Bundle(); args.putBoolean("destroyAfterSelect", true); - actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(new ContactsActivity(args)).setNoAnimation(true)); + getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(new ContactsActivity(args)).setNoAnimation(true)); if (AndroidUtilities.isTablet()) { actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -3084,7 +3101,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id); VoIPHelper.startCall(user, videoCall, userFull != null && userFull.video_calls_available, LaunchActivity.this, userFull, AccountInstance.getInstance(intentAccount[0])); }); - actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(contactsFragment).setRemoveLast(actionBarLayout.getLastFragment() instanceof ContactsActivity)); + getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(contactsFragment).setRemoveLast(actionBarLayout.getLastFragment() instanceof ContactsActivity)); if (AndroidUtilities.isTablet()) { actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -3112,7 +3129,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } })); }); - actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); + getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); if (AndroidUtilities.isTablet()) { actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -3131,7 +3148,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati fragment.setInitialPhoneNumber(PhoneFormat.stripExceptNumbers(newContactPhone, true), false); } fragment.show(); - // actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); + // getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(fragment).setNoAnimation(true)); if (AndroidUtilities.isTablet()) { actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -3169,7 +3186,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati pushOpened = true; } } else if (showCallLog) { - actionBarLayout.presentFragment(new INavigationLayout.NavigationParams(new CallLogActivity()).setNoAnimation(true)); + getActionBarLayout().presentFragment(new INavigationLayout.NavigationParams(new CallLogActivity()).setNoAnimation(true)); if (AndroidUtilities.isTablet()) { actionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); rightActionBarLayout.rebuildFragments(INavigationLayout.REBUILD_FLAG_REBUILD_LAST); @@ -3300,7 +3317,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { removeLast = actionBarLayout.getFragmentStack().size() > 1 && actionBarLayout.getFragmentStack().get(actionBarLayout.getFragmentStack().size() - 1) instanceof DialogsActivity; } - actionBarLayout.presentFragment(fragment, removeLast, !animated, true, false); + getActionBarLayout().presentFragment(fragment, removeLast, !animated, true, false); if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { SecretMediaViewer.getInstance().closePhoto(false, false); } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { @@ -3325,10 +3342,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } private int runCommentRequest(int intentAccount, Runnable dismissLoading, Integer messageId, Integer commentId, Integer threadId, TLRPC.Chat chat) { - return runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, chat, null); + return runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, chat, null, null, 0); } - private int runCommentRequest(int intentAccount, Runnable dismissLoading, Integer messageId, Integer commentId, Integer threadId, TLRPC.Chat chat, Runnable onOpened) { + private int runCommentRequest(int intentAccount, Runnable dismissLoading, Integer messageId, Integer commentId, Integer threadId, TLRPC.Chat chat, Runnable onOpened, String quote, int fromMessageId) { if (chat == null) { return 0; } @@ -3347,47 +3364,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (!arrayList.isEmpty() || chat.forum && threadId != null && threadId == 1) { if (chat.forum) { - TLRPC.TL_channels_getForumTopicsByID getForumTopicsByID = new TLRPC.TL_channels_getForumTopicsByID(); - getForumTopicsByID.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id); - getForumTopicsByID.topics.add(threadId); - ConnectionsManager.getInstance(currentAccount).sendRequest(getForumTopicsByID, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { - if (error2 == null) { - TLRPC.TL_messages_forumTopics topics = (TLRPC.TL_messages_forumTopics) response2; - SparseArray messagesMap = new SparseArray<>(); - for (int i = 0; i < topics.messages.size(); i++) { - messagesMap.put(topics.messages.get(i).id, topics.messages.get(i)); - } - MessagesController.getInstance(currentAccount).putUsers(topics.users, false); - MessagesController.getInstance(currentAccount).putChats(topics.chats, false); - - MessagesController.getInstance(currentAccount).getTopicsController().processTopics(chat.id, topics.topics, messagesMap, false, TopicsController.LOAD_TYPE_LOAD_UNKNOWN, -1); - } - TLRPC.TL_forumTopic topic = MessagesController.getInstance(currentAccount).getTopicsController().findTopic(chat.id, threadId); - if (topic != null) { - Bundle args = new Bundle(); - args.putLong("chat_id", chat.id); - if (messageId != topic.id) { - args.putInt("message_id", Math.max(1, messageId)); - } - ChatActivity chatActivity = new ChatActivity(args); - if (arrayList.isEmpty()) { - TLRPC.Message message = new TLRPC.Message(); - message.id = 1; - message.action = new TLRPC.TL_messageActionChannelMigrateFrom(); - arrayList.add(new MessageObject(currentAccount, message, false, false)); - } - chatActivity.setThreadMessages(arrayList, chat, req.msg_id, topic.read_inbox_max_id, topic.read_outbox_max_id, topic); - if (commentId != null) { - chatActivity.setHighlightMessageId(commentId); - } else if (threadId != null && messageId != topic.id) { - chatActivity.setHighlightMessageId(messageId); - } - presentFragment(chatActivity); - if (onOpened != null) { - onOpened.run(); - } - } - })); + openTopicRequest(intentAccount, threadId, chat, commentId != null ? commentId : messageId, null, onOpened, quote, fromMessageId, arrayList); chatOpened = true; } else { Bundle args = new Bundle(); @@ -3396,9 +3373,17 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati ChatActivity chatActivity = new ChatActivity(args); chatActivity.setThreadMessages(arrayList, chat, req.msg_id, res.read_inbox_max_id, res.read_outbox_max_id, null); if (commentId != null) { - chatActivity.setHighlightMessageId(commentId); + if (quote != null) { + chatActivity.setHighlightQuote(commentId, quote); + } else { + chatActivity.setHighlightMessageId(commentId); + } } else if (threadId != null) { - chatActivity.setHighlightMessageId(messageId); + if (quote != null) { + chatActivity.setHighlightQuote(messageId, quote); + } else { + chatActivity.setHighlightMessageId(messageId); + } } presentFragment(chatActivity); chatOpened = true; @@ -3427,6 +3412,67 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati })); } + private void openTopicRequest(int intentAccount, int topicId, TLRPC.Chat chat, int messageId, TLRPC.TL_forumTopic forumTopic, Runnable whenDone, String quote, int fromMessageId, ArrayList arrayList) { + if (forumTopic == null) { + forumTopic = MessagesController.getInstance(intentAccount).getTopicsController().findTopic(chat.id, topicId); + } + if (forumTopic == null) { + TLRPC.TL_channels_getForumTopicsByID getForumTopicsByID = new TLRPC.TL_channels_getForumTopicsByID(); + getForumTopicsByID.channel = MessagesController.getInstance(currentAccount).getInputChannel(chat.id); + getForumTopicsByID.topics.add(topicId); + ConnectionsManager.getInstance(intentAccount).sendRequest(getForumTopicsByID, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { + if (error2 == null) { + TLRPC.TL_messages_forumTopics topics = (TLRPC.TL_messages_forumTopics) response2; + SparseArray messagesMap = new SparseArray<>(); + for (int i = 0; i < topics.messages.size(); i++) { + messagesMap.put(topics.messages.get(i).id, topics.messages.get(i)); + } + MessagesController.getInstance(intentAccount).putUsers(topics.users, false); + MessagesController.getInstance(intentAccount).putChats(topics.chats, false); + + MessagesController.getInstance(intentAccount).getTopicsController().processTopics(chat.id, topics.topics, messagesMap, false, TopicsController.LOAD_TYPE_LOAD_UNKNOWN, -1); + + TLRPC.TL_forumTopic topic = MessagesController.getInstance(intentAccount).getTopicsController().findTopic(chat.id, topicId); + openTopicRequest(intentAccount, topicId, chat, messageId, topic, whenDone, quote, fromMessageId, arrayList); + }; + })); + return; + } + BaseFragment lastFragment = !mainFragmentsStack.isEmpty() ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; + if (lastFragment instanceof ChatActivity && ((ChatActivity) lastFragment).getDialogId() == -chat.id && ((ChatActivity) lastFragment).isTopic && ((ChatActivity) lastFragment).getTopicId() == forumTopic.id) { + if (quote != null) { + ((ChatActivity) lastFragment).setHighlightQuote(messageId, quote); + } + ((ChatActivity) lastFragment).scrollToMessageId(messageId, fromMessageId, true, 0, true, 0, null); + } else { + Bundle args = new Bundle(); + args.putLong("chat_id", chat.id); + if (messageId != forumTopic.id) { + args.putInt("message_id", Math.max(1, messageId)); + } + ChatActivity chatActivity = new ChatActivity(args); + if (arrayList.isEmpty()) { + TLRPC.Message message = new TLRPC.Message(); + message.id = 1; + message.action = new TLRPC.TL_messageActionChannelMigrateFrom(); + arrayList.add(new MessageObject(intentAccount, message, false, false)); + } + chatActivity.setThreadMessages(arrayList, chat, messageId, forumTopic.read_inbox_max_id, forumTopic.read_outbox_max_id, forumTopic); + if (messageId != forumTopic.id) { + if (quote != null) { + chatActivity.setHighlightQuote(messageId, quote); + } else { + chatActivity.setHighlightMessageId(messageId); + } + chatActivity.scrollToMessageId(messageId, fromMessageId, true, 0, true, 0, null); + } + presentFragment(chatActivity); + } + if (whenDone != null) { + whenDone.run(); + } + } + private void runImportRequest(final Uri importUri, ArrayList documents) { final int intentAccount = UserConfig.selectedAccount; @@ -3527,7 +3573,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { removeLast = actionBarLayout.getFragmentStack().size() > 1 && actionBarLayout.getFragmentStack().get(actionBarLayout.getFragmentStack().size() - 1) instanceof DialogsActivity; } - actionBarLayout.presentFragment(fragment, removeLast, false, true, false); + getActionBarLayout().presentFragment(fragment, removeLast, false, true, false); } else { if (documentsUrisArray == null) { documentsUrisArray = new ArrayList<>(); @@ -3561,6 +3607,89 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati VoIPHelper.startCall(chat, null, hash, false, this, mainFragmentsStack.get(mainFragmentsStack.size() - 1), accountInstance); } + public void openMessage(long dialogId, int messageId, String quote, final Browser.Progress progress, int fromMessageId) { + if (dialogId < 0) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chat != null && ChatObject.isForum(chat)) { + if (progress != null) { + progress.init(); + } + openForumFromLink(dialogId, messageId, quote, () -> { + if (progress != null) { + progress.end(); + } + }, fromMessageId); + return; + } + } + if (progress != null) { + progress.init(); + } + Bundle args = new Bundle(); + if (dialogId >= 0) { + args.putLong("user_id", dialogId); + } else { + TLRPC.Chat chatLocal = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chatLocal != null && chatLocal.forum) { + openForumFromLink(dialogId, messageId, quote, () -> { + if (progress != null) { + progress.end(); + } + }, fromMessageId); + return; + } + args.putLong("chat_id", -dialogId); + } + args.putInt("message_id", messageId); + BaseFragment lastFragment = !mainFragmentsStack.isEmpty() ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; + if (lastFragment == null || MessagesController.getInstance(currentAccount).checkCanOpenChat(args, lastFragment)) { + AndroidUtilities.runOnUIThread(() -> { + ChatActivity chatActivity = new ChatActivity(args); + chatActivity.setHighlightQuote(messageId, quote); + if (!getActionBarLayout().presentFragment(chatActivity) && dialogId < 0) { + TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels(); + TLRPC.TL_inputChannel inputChannel = new TLRPC.TL_inputChannel(); + inputChannel.channel_id = -dialogId; + req.id.add(inputChannel); + final int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (progress != null) { + progress.end(); + } + boolean notFound = true; + if (response instanceof TLRPC.TL_messages_chats) { + TLRPC.TL_messages_chats res = (TLRPC.TL_messages_chats) response; + if (!res.chats.isEmpty()) { + notFound = false; + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + TLRPC.Chat chat = res.chats.get(0); + if (chat != null && chat.forum) { + openForumFromLink(-dialogId, messageId, null); + } + if (lastFragment == null || MessagesController.getInstance(currentAccount).checkCanOpenChat(args, lastFragment)) { + ChatActivity chatActivity2 = new ChatActivity(args); + chatActivity.setHighlightQuote(messageId, quote); + getActionBarLayout().presentFragment(chatActivity2); + } + } + } + if (notFound) { + showAlertDialog(AlertsCreator.createNoAccessAlert(LaunchActivity.this, LocaleController.getString(R.string.DialogNotAvailable), LocaleController.getString(R.string.LinkNotFound), null)); + } + })); + if (progress != null) { + progress.onCancel(() -> { + ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); + }); + } + } else { + if (progress != null) { + progress.end(); + } + } + }); + } + } + private void runLinkRequest(final int intentAccount, final String username, final String group, @@ -3667,24 +3796,24 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } })); } else if (folderSlug != null) { - TLRPC.TL_chatlists_checkChatlistInvite req = new TLRPC.TL_chatlists_checkChatlistInvite(); + TL_chatlists.TL_chatlists_checkChatlistInvite req = new TL_chatlists.TL_chatlists_checkChatlistInvite(); req.slug = folderSlug; requestId[0] = ConnectionsManager.getInstance(intentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); - if (response instanceof TLRPC.chatlist_ChatlistInvite) { - TLRPC.chatlist_ChatlistInvite inv = (TLRPC.chatlist_ChatlistInvite) response; + if (response instanceof TL_chatlists.chatlist_ChatlistInvite) { + TL_chatlists.chatlist_ChatlistInvite inv = (TL_chatlists.chatlist_ChatlistInvite) response; ArrayList chats = null; ArrayList users = null; - if (inv instanceof TLRPC.TL_chatlists_chatlistInvite) { - chats = ((TLRPC.TL_chatlists_chatlistInvite) inv).chats; - users = ((TLRPC.TL_chatlists_chatlistInvite) inv).users; - } else if (inv instanceof TLRPC.TL_chatlists_chatlistInviteAlready) { - chats = ((TLRPC.TL_chatlists_chatlistInviteAlready) inv).chats; - users = ((TLRPC.TL_chatlists_chatlistInviteAlready) inv).users; + if (inv instanceof TL_chatlists.TL_chatlists_chatlistInvite) { + chats = ((TL_chatlists.TL_chatlists_chatlistInvite) inv).chats; + users = ((TL_chatlists.TL_chatlists_chatlistInvite) inv).users; + } else if (inv instanceof TL_chatlists.TL_chatlists_chatlistInviteAlready) { + chats = ((TL_chatlists.TL_chatlists_chatlistInviteAlready) inv).chats; + users = ((TL_chatlists.TL_chatlists_chatlistInviteAlready) inv).users; } MessagesController.getInstance(intentAccount).putChats(chats, false); MessagesController.getInstance(intentAccount).putUsers(users, false); - if (!(inv instanceof TLRPC.TL_chatlists_chatlistInvite && ((TLRPC.TL_chatlists_chatlistInvite) inv).peers.isEmpty())) { + if (!(inv instanceof TL_chatlists.TL_chatlists_chatlistInvite && ((TL_chatlists.TL_chatlists_chatlistInvite) inv).peers.isEmpty())) { final FolderBottomSheet sheet = new FolderBottomSheet(fragment, folderSlug, inv); if (fragment != null) { fragment.showDialog(sheet); @@ -3764,7 +3893,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati factory.createSimpleBulletin(R.raw.story_bomb2, LocaleController.getString("StoryNotFound", R.string.StoryNotFound)).show(); } return; - } else if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + } else if (storyItem instanceof TL_stories.TL_storyItemDeleted) { BulletinFactory factory = BulletinFactory.global(); if (factory != null) { factory.createSimpleBulletin(R.raw.story_bomb1, LocaleController.getString("StoryNotFound", R.string.StoryNotFound)).show(); @@ -3795,8 +3924,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { WebAppDisclaimerAlert.show(this, ignore -> { - user.inactive = false; - processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, isBoost, user, dismissLoading); + processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, user, dismissLoading); TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId); @@ -3812,7 +3940,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } })); } else { - processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, false, storyId, isBoost, user, dismissLoading); + processWebAppBot(intentAccount, username, group, sticker, emoji, botUser, botChat, botChannel, botChatAdminParams, message, contactToken, folderSlug, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, state, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose, botAppMaybe, botAppStartParam, progress, forceNotInternalForApps, storyId, isBoost, user, dismissLoading); } return; } @@ -3821,7 +3949,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (isBoost) { TLRPC.Chat chat = MessagesController.getInstance(intentAccount).getChat(-peerId); if (ChatObject.isChannelAndNotMegaGroup(chat)) { - processBoostDialog(peerId, dismissLoading); + processBoostDialog(peerId, dismissLoading, progress); return; } } @@ -3871,7 +3999,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (MessagesController.getInstance(intentAccount).checkCanOpenChat(args1, fragment1)) { NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); - actionBarLayout.presentFragment(new ChatActivity(args1), true, false, true, false); + getActionBarLayout().presentFragment(new ChatActivity(args1), true, false, true, false); } return true; }); @@ -3881,7 +4009,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { removeLast = actionBarLayout.getFragmentStack().size() > 1 && actionBarLayout.getFragmentStack().get(actionBarLayout.getFragmentStack().size() - 1) instanceof DialogsActivity; } - actionBarLayout.presentFragment(fragment, removeLast, true, true, false); + getActionBarLayout().presentFragment(fragment, removeLast, true, true, false); if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { SecretMediaViewer.getInstance().closePhoto(false, false); } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { @@ -4024,7 +4152,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati public void didChangeOwner(TLRPC.User user) { } }); - actionBarLayout.presentFragment(editRightsActivity, false); + getActionBarLayout().presentFragment(editRightsActivity, false); } })); } else { @@ -4041,7 +4169,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati ChatActivity chatActivity = new ChatActivity(args12); NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); MessagesController.getInstance(intentAccount).addUserToChat(-did, user, 0, botHash, chatActivity, null); - actionBarLayout.presentFragment(chatActivity, true, false, true, false); + getActionBarLayout().presentFragment(chatActivity, true, false, true, false); }); builder.show(); } @@ -4101,7 +4229,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati topicId = messageId; } if (topicId != null && topicId != 0) { - openForumFromLink(dialog_id, topicId, messageId, () -> { + openForumFromLink(dialog_id, messageId, () -> { try { dismissLoading.run(); } catch (Exception e) { @@ -4147,7 +4275,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati voipLastFragment = lastFragment; } else { ChatActivity fragment = new ChatActivity(args); - actionBarLayout.presentFragment(fragment); + getActionBarLayout().presentFragment(fragment); voipLastFragment = fragment; } } else { @@ -4264,7 +4392,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (invite instanceof TLRPC.TL_chatInvitePeek) { fragment.setChatInvite(invite); } - actionBarLayout.presentFragment(fragment); + getActionBarLayout().presentFragment(fragment); } @Override @@ -4341,7 +4469,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (mainFragmentsStack.isEmpty() || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, mainFragmentsStack.get(mainFragmentsStack.size() - 1))) { ChatActivity fragment = new ChatActivity(args); NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); - actionBarLayout.presentFragment(fragment, false, true, true, false); + getActionBarLayout().presentFragment(fragment, false, true, true, false); } } } @@ -4417,7 +4545,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (MessagesController.getInstance(intentAccount).checkCanOpenChat(args13, fragment13)) { NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); MediaDataController.getInstance(intentAccount).saveDraft(did, 0, message, null, null, false); - actionBarLayout.presentFragment(new ChatActivity(args13), true, false, true, false); + getActionBarLayout().presentFragment(new ChatActivity(args13), true, false, true, false); } return true; }); @@ -4668,9 +4796,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } TLRPC.Chat chatLocal = MessagesController.getInstance(currentAccount).getChat(channelId); if (chatLocal != null && ChatObject.isChannelAndNotMegaGroup(chatLocal) && isBoost) { - processBoostDialog(-channelId, dismissLoading); + processBoostDialog(-channelId, dismissLoading, progress); } else if (chatLocal != null && chatLocal.forum) { - openForumFromLink(-channelId, 0, messageId, () -> { + openForumFromLink(-channelId, messageId, () -> { try { dismissLoading.run(); } catch (Exception e) { @@ -4681,7 +4809,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati BaseFragment lastFragment = !mainFragmentsStack.isEmpty() ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { AndroidUtilities.runOnUIThread(() -> { - if (!actionBarLayout.presentFragment(new ChatActivity(args))) { + if (!getActionBarLayout().presentFragment(new ChatActivity(args))) { TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels(); TLRPC.TL_inputChannel inputChannel = new TLRPC.TL_inputChannel(); inputChannel.channel_id = channelId; @@ -4700,16 +4828,16 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati MessagesController.getInstance(currentAccount).putChats(res.chats, false); TLRPC.Chat chat = res.chats.get(0); if (chat != null && isBoost && ChatObject.isChannelAndNotMegaGroup(chat)) { - processBoostDialog(-channelId, null); + processBoostDialog(-channelId, null, progress); } else if (chat != null && chat.forum) { if (threadId != null) { - openForumFromLink(-channelId, threadId, messageId, null); + openForumFromLink(-channelId, messageId, null); } else { - openForumFromLink(-channelId, messageId, null, null); + openForumFromLink(-channelId, null, null); } } if (lastFragment == null || MessagesController.getInstance(intentAccount).checkCanOpenChat(args, lastFragment)) { - actionBarLayout.presentFragment(new ChatActivity(args)); + getActionBarLayout().presentFragment(new ChatActivity(args)); } } } @@ -4814,7 +4942,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati BotWebViewSheet sheet = new BotWebViewSheet(LaunchActivity.this, lastFragment.getResourceProvider()); sheet.setParentActivity(LaunchActivity.this); sheet.requestWebView(intentAccount, user.id, user.id, null, null, BotWebViewSheet.TYPE_WEB_VIEW_BOT_APP, 0, false, lastFragment, botApp.app, allowWrite.get(), botAppStartParam, user); - sheet.show(); + BaseFragment currentLastFragment = getLastFragment(); + if (currentLastFragment != null) { + currentLastFragment.showDialog(sheet); + } else { + sheet.show(); + } if (botApp.inactive || forceNotInternalForApps) { sheet.showJustAddedBulletin(); } @@ -4832,14 +4965,23 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } - private void processBoostDialog(Long peerId, Runnable dismissLoading) { + private void processBoostDialog(Long peerId, Runnable dismissLoading, Browser.Progress progress) { ChannelBoostsController boostsController = MessagesController.getInstance(currentAccount).getBoostsController(); + if (progress != null) { + progress.init(); + } boostsController.getBoostsStats(peerId, boostsStatus -> { if (boostsStatus == null) { + if (progress != null) { + progress.end(); + } dismissLoading.run(); return; } - boostsController.userCanBoostChannel(peerId, canApplyBoost -> { + boostsController.userCanBoostChannel(peerId, boostsStatus, canApplyBoost -> { + if (progress != null) { + progress.end(); + } BaseFragment lastFragment = getLastFragment(); if (lastFragment == null) { return; @@ -4928,7 +5070,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (MessagesController.getInstance(intentAccount).checkCanOpenChat(args1, fragment)) { NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); - actionBarLayout.presentFragment(new ChatActivity(args1), true, false, true, false); + getActionBarLayout().presentFragment(new ChatActivity(args1), true, false, true, false); } return true; }); @@ -4982,7 +5124,11 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati })); } - private void openForumFromLink(long dialogId, int topicId, Integer messageId, Runnable onOpened) { + private void openForumFromLink(long dialogId, Integer messageId, Runnable onOpened) { + openForumFromLink(dialogId, messageId, null, onOpened, 0); + } + + private void openForumFromLink(long dialogId, Integer messageId, String quote, Runnable onOpened, int fromMessageId) { if (messageId == null) { Bundle bundle = new Bundle(); bundle.putLong("chat_id", -dialogId); @@ -5010,7 +5156,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (message != null) { - runCommentRequest(currentAccount, null, message.id, null, MessageObject.getTopicId(message, MessagesController.getInstance(currentAccount).isForum(message)), MessagesController.getInstance(currentAccount).getChat(-dialogId), onOpened); + runCommentRequest(currentAccount, null, message.id, null, MessageObject.getTopicId(message, MessagesController.getInstance(currentAccount).isForum(message)), MessagesController.getInstance(currentAccount).getChat(-dialogId), onOpened, quote, fromMessageId); return; } @@ -5108,182 +5254,6 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati return foundContacts; } - private void createUpdateUI() { - if (sideMenuContainer == null) { - return; - } - updateLayout = new FrameLayout(this) { - - private Paint paint = new Paint(); - private Matrix matrix = new Matrix(); - private LinearGradient updateGradient; - private int lastGradientWidth; - - @Override - public void draw(Canvas canvas) { - if (updateGradient != null) { - paint.setColor(0xffffffff); - paint.setShader(updateGradient); - updateGradient.setLocalMatrix(matrix); - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint); - updateLayoutIcon.setBackgroundGradientDrawable(updateGradient); - updateLayoutIcon.draw(canvas); - } - super.draw(canvas); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int width = MeasureSpec.getSize(widthMeasureSpec); - if (lastGradientWidth != width) { - updateGradient = new LinearGradient(0, 0, width, 0, new int[]{0xff69BF72, 0xff53B3AD}, new float[]{0.0f, 1.0f}, Shader.TileMode.CLAMP); - lastGradientWidth = width; - } - } - }; - updateLayout.setWillNotDraw(false); - updateLayout.setVisibility(View.INVISIBLE); - updateLayout.setTranslationY(AndroidUtilities.dp(44)); - if (Build.VERSION.SDK_INT >= 21) { - updateLayout.setBackground(Theme.getSelectorDrawable(0x40ffffff, false)); - } - sideMenuContainer.addView(updateLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 44, Gravity.LEFT | Gravity.BOTTOM)); - updateLayout.setOnClickListener(v -> { - if (!SharedConfig.isAppUpdateAvailable()) { - return; - } - if (getUpdateAccountNum() != currentAccount) { - NotificationCenter.getInstance(getUpdateAccountNum()).removeObserver(this, NotificationCenter.fileLoaded); - NotificationCenter.getInstance(getUpdateAccountNum()).removeObserver(this, NotificationCenter.fileLoadProgressChanged); - NotificationCenter.getInstance(getUpdateAccountNum()).removeObserver(this, NotificationCenter.fileLoadFailed); - } - if (updateLayoutIcon.getIcon() == MediaActionDrawable.ICON_DOWNLOAD) { - startUpdateDownloading(); - } else if (updateLayoutIcon.getIcon() == MediaActionDrawable.ICON_CANCEL) { - FileLoader.getInstance(currentAccount).cancelLoadFile(SharedConfig.pendingPtgAppUpdate.document); - updateAppUpdateViews(true); - } else { - if (!AndroidUtilities.openForView(SharedConfig.pendingPtgAppUpdate.document, true, this)) { - startUpdateDownloading(); - } - } - }); - updateLayoutIcon = new RadialProgress2(updateLayout); - updateLayoutIcon.setColors(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); - updateLayoutIcon.setProgressRect(AndroidUtilities.dp(22), AndroidUtilities.dp(11), AndroidUtilities.dp(22 + 22), AndroidUtilities.dp(11 + 22)); - updateLayoutIcon.setCircleRadius(AndroidUtilities.dp(11)); - updateLayoutIcon.setAsMini(); - - updateTextView = new SimpleTextView(this); - updateTextView.setTextSize(15); - updateTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - updateTextView.setText(LocaleController.getString("AppUpdate", R.string.AppUpdate)); - updateTextView.setTextColor(0xffffffff); - updateTextView.setGravity(Gravity.LEFT); - updateLayout.addView(updateTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 74, 0, 0, 0)); - - updateSizeTextView = new TextView(this); - updateSizeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - updateSizeTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - updateSizeTextView.setGravity(Gravity.RIGHT); - updateSizeTextView.setTextColor(0xffffffff); - updateLayout.addView(updateSizeTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.RIGHT, 0, 0, 17, 0)); - } - - private void updateAppUpdateViews(boolean animated) { - if (sideMenuContainer == null) { - return; - } - if (SharedConfig.isAppUpdateAvailable()) { - View prevUpdateLayout = updateLayout; - createUpdateUI(); - updateSizeTextView.setText(AndroidUtilities.formatFileSize(SharedConfig.pendingPtgAppUpdate.document.size)); - String fileName = FileLoader.getAttachFileName(SharedConfig.pendingPtgAppUpdate.document); - File path = FileLoader.getInstance(getUpdateAccountNum()).getPathToAttach(SharedConfig.pendingPtgAppUpdate.document, true); - boolean showSize; - if (path.exists()) { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_UPDATE, true, false); - updateTextView.setText(LocaleController.getString("AppUpdateNow", R.string.AppUpdateNow)); - showSize = false; - } else { - if (FileLoader.getInstance(getUpdateAccountNum()).isLoadingFile(fileName)) { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_CANCEL, true, false); - updateLayoutIcon.setProgress(0, false); - Float p = ImageLoader.getInstance().getFileProgress(fileName); - updateTextView.setText(LocaleController.formatString("AppUpdateDownloading", R.string.AppUpdateDownloading, (int) ((p != null ? p : 0.0f) * 100))); - showSize = false; - } else { - updateLayoutIcon.setIcon(MediaActionDrawable.ICON_DOWNLOAD, true, false); - updateTextView.setText(LocaleController.getString("AppUpdate", R.string.AppUpdate)); - showSize = true; - } - } - if (showSize) { - if (updateSizeTextView.getTag() != null) { - if (animated) { - updateSizeTextView.setTag(null); - updateSizeTextView.animate().alpha(1.0f).scaleX(1.0f).scaleY(1.0f).setDuration(180).start(); - } else { - updateSizeTextView.setAlpha(1.0f); - updateSizeTextView.setScaleX(1.0f); - updateSizeTextView.setScaleY(1.0f); - } - } - } else { - if (updateSizeTextView.getTag() == null) { - if (animated) { - updateSizeTextView.setTag(1); - updateSizeTextView.animate().alpha(0.0f).scaleX(0.0f).scaleY(0.0f).setDuration(180).start(); - } else { - updateSizeTextView.setAlpha(0.0f); - updateSizeTextView.setScaleX(0.0f); - updateSizeTextView.setScaleY(0.0f); - } - } - } - if (updateLayout.getTag() != null) { - return; - } - updateLayout.setVisibility(View.VISIBLE); - updateLayout.setTag(1); - if (animated) { - updateLayout.animate().translationY(0).setInterpolator(CubicBezierInterpolator.EASE_OUT).setListener(null).setDuration(180).withEndAction(() -> { - if (prevUpdateLayout != null) { - ViewGroup parent = (ViewGroup) prevUpdateLayout.getParent(); - parent.removeView(prevUpdateLayout); - } - }).start(); - } else { - updateLayout.setTranslationY(0); - if (prevUpdateLayout != null) { - ViewGroup parent = (ViewGroup) prevUpdateLayout.getParent(); - parent.removeView(prevUpdateLayout); - } - } - sideMenu.setPadding(0, 0, 0, AndroidUtilities.dp(44)); - } else { - if (updateLayout == null || updateLayout.getTag() == null) { - return; - } - updateLayout.setTag(null); - if (animated) { - updateLayout.animate().translationY(AndroidUtilities.dp(44)).setInterpolator(CubicBezierInterpolator.EASE_OUT).setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (updateLayout.getTag() == null) { - updateLayout.setVisibility(View.INVISIBLE); - } - } - }).setDuration(180).start(); - } else { - updateLayout.setTranslationY(AndroidUtilities.dp(44)); - updateLayout.setVisibility(View.INVISIBLE); - } - sideMenu.setPadding(0, 0, 0, 0); - } - } - public void checkAppUpdate(boolean force) { if (!force && BuildVars.DEBUG_VERSION || !force && !BuildVars.CHECK_UPDATES) { return; @@ -5312,11 +5282,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati showUpdateActivity(accountNum, data, false); } else { drawerLayoutAdapter.notifyDataSetChanged(); - try { - (new UpdateAppAlertDialog(LaunchActivity.this, data, accountNum)).show(); - } catch (Exception e) { - FileLog.e(e); - } + ApplicationLoader.applicationLoaderInstance.showUpdateAppPopup(LaunchActivity.this, data, accountNum); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.appUpdateAvailable); } @@ -5434,7 +5400,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } ChatActivity fragment = new ChatActivity(args); fragment.setOpenImport(); - actionBarLayout.presentFragment(fragment, dialogsFragment != null || param, dialogsFragment == null, true, false); + getActionBarLayout().presentFragment(fragment, dialogsFragment != null || param, dialogsFragment == null, true, false); } else { documentsUrisArray = documentsUris; if (documentsUrisArray == null) { @@ -5520,7 +5486,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati PhonebookShareAlert alert = new PhonebookShareAlert(mainFragmentsStack.get(mainFragmentsStack.size() - 1), null, null, contactsToSendUri, null, null, null); alert.setDelegate((user, notify2, scheduleDate) -> { if (fragment != null) { - actionBarLayout.presentFragment(fragment, true, false, true, false); + getActionBarLayout().presentFragment(fragment, true, false, true, false); } AccountInstance accountInstance = AccountInstance.getInstance(UserConfig.selectedAccount); for (int i = 0; i < dids.size(); i++) { @@ -5560,7 +5526,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati boolean photosEditorOpened = false, videoEditorOpened = false; if (fragment != null) { boolean withoutAnimation = dialogsFragment == null || videoPath != null || (photoPathsArray != null && photoPathsArray.size() > 0); - actionBarLayout.presentFragment(fragment, dialogsFragment != null, withoutAnimation, true, false); + getActionBarLayout().presentFragment(fragment, dialogsFragment != null, withoutAnimation, true, false); presentedFragmentWithRemoveLast = dialogsFragment != null; if (videoPath != null && topicId == 0) { fragment.openVideoEditor(videoPath, sendingText); @@ -5580,7 +5546,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } ArrayList arrayList = new ArrayList<>(); arrayList.add(videoPath); - SendMessagesHelper.prepareSendingDocuments(accountInstance, arrayList, arrayList, null, captionToSend, null, did, replyToMsg, replyToMsg, null, null, notify, 0, null); + SendMessagesHelper.prepareSendingDocuments(accountInstance, arrayList, arrayList, null, captionToSend, null, did, replyToMsg, replyToMsg, null, null, null, notify, 0, null); } } if (photoPathsArray != null && !photosEditorOpened) { @@ -5588,14 +5554,14 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati photoPathsArray.get(0).caption = sendingText; sendingText = null; } - SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, replyToMsg, replyToMsg, null, false, false, null, notify, 0, false, null); + SendMessagesHelper.prepareSendingMedia(accountInstance, photoPathsArray, did, replyToMsg, replyToMsg, null, null, false, false, null, notify, 0, false, null); } if (documentsPathsArray != null || documentsUrisArray != null) { if (sendingText != null && sendingText.length() <= 1024 && ((documentsPathsArray != null ? documentsPathsArray.size() : 0) + (documentsUrisArray != null ? documentsUrisArray.size() : 0)) == 1) { captionToSend = sendingText; sendingText = null; } - SendMessagesHelper.prepareSendingDocuments(accountInstance, documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, captionToSend, documentsMimeType, did, replyToMsg, replyToMsg, null, null, notify, 0, null); + SendMessagesHelper.prepareSendingDocuments(accountInstance, documentsPathsArray, documentsOriginalPathsArray, documentsUrisArray, captionToSend, documentsMimeType, did, replyToMsg, replyToMsg, null, null, null, notify, 0, null); } if (voicePath != null) { File file = new File(voicePath); @@ -5736,19 +5702,23 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } public void presentFragment(INavigationLayout.NavigationParams params) { - actionBarLayout.presentFragment(params); + getActionBarLayout().presentFragment(params); } public void presentFragment(BaseFragment fragment) { - actionBarLayout.presentFragment(fragment); + getActionBarLayout().presentFragment(fragment); } public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation) { - return actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, true, false); + return getActionBarLayout().presentFragment(fragment, removeLast, forceWithoutAnimation, true, false); } public INavigationLayout getActionBarLayout() { - return actionBarLayout; + INavigationLayout currentLayout = actionBarLayout; + if (!sheetFragmentsStack.isEmpty()) { + currentLayout = sheetFragmentsStack.get(sheetFragmentsStack.size() - 1); + } + return currentLayout; } public INavigationLayout getLayersActionBarLayout() { @@ -6136,6 +6106,10 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati if (embedBottomSheet != null) { embedBottomSheet.onConfigurationChanged(newConfig); } + BoostPagerBottomSheet boostPagerBottomSheet = BoostPagerBottomSheet.getInstance(); + if (boostPagerBottomSheet != null) { + boostPagerBottomSheet.onConfigurationChanged(newConfig); + } PhotoViewer photoViewer = PhotoViewer.getPipInstance(); if (photoViewer != null) { photoViewer.onConfigurationChanged(newConfig); @@ -6496,8 +6470,8 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati String path = (String) args[0]; if (SharedConfig.isAppUpdateAvailable()) { String name = FileLoader.getAttachFileName(SharedConfig.pendingPtgAppUpdate.document); - if (name.equals(path)) { - updateAppUpdateViews(true); + if (name.equals(path) && updateLayout != null) { + updateLayout.updateAppUpdateViews(currentAccount, true); } } if (loadingThemeFileName != null) { @@ -6567,8 +6541,8 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (SharedConfig.isAppUpdateAvailable()) { String name = FileLoader.getAttachFileName(SharedConfig.pendingPtgAppUpdate.document); - if (name.equals(path)) { - updateAppUpdateViews(true); + if (name.equals(path) && updateLayout != null) { + updateLayout.updateAppUpdateViews(currentAccount, true); } } } else if (id == NotificationCenter.screenStateChanged) { @@ -6675,19 +6649,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else if (id == NotificationCenter.groupCallUpdated) { checkWasMutedByAdmin(false); } else if (id == NotificationCenter.fileLoadProgressChanged) { - if (updateTextView != null && SharedConfig.isAppUpdateAvailable()) { - String location = (String) args[0]; - String fileName = FileLoader.getAttachFileName(SharedConfig.pendingPtgAppUpdate.document); - if (fileName != null && fileName.equals(location)) { - Long loadedSize = (Long) args[1]; - Long totalSize = (Long) args[2]; - float loadProgress = loadedSize / (float) totalSize; - updateLayoutIcon.setProgress(loadProgress, true); - updateTextView.setText(LocaleController.formatString("AppUpdateDownloading", R.string.AppUpdateDownloading, (int) (loadProgress * 100))); - } + if (updateLayout != null) { + updateLayout.updateFileProgress(args); } } else if (id == NotificationCenter.appUpdateAvailable) { - updateAppUpdateViews(mainFragmentsStack.size() == 1); + if (updateLayout != null) { + updateLayout.updateAppUpdateViews(currentAccount, mainFragmentsStack.size() == 1); + } } else if (id == NotificationCenter.currentUserShowLimitReachedDialog) { if (!mainFragmentsStack.isEmpty()) { BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); @@ -7527,7 +7495,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati DialogsActivity dialogsActivity = (DialogsActivity) fragment; if (dialogsActivity.isMainDialogList() && layout != actionBarLayout) { actionBarLayout.removeAllFragments(); - actionBarLayout.presentFragment(params.setRemoveLast(removeLast).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); + getActionBarLayout().presentFragment(params.setRemoveLast(removeLast).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); layersActionBarLayout.removeAllFragments(); layersActionBarLayout.getView().setVisibility(View.GONE); drawerLayoutContainer.setAllowOpenDrawer(true, false); @@ -7551,7 +7519,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati layersActionBarLayout.closeLastFragment(!forceWithoutAnimation); } if (!result) { - actionBarLayout.presentFragment(params.setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); + getActionBarLayout().presentFragment(params.setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); } return result; } else if (!tabletFullSize && layout != rightActionBarLayout) { @@ -7568,7 +7536,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } return false; } else if (tabletFullSize && layout != actionBarLayout) { - actionBarLayout.presentFragment(params.setRemoveLast(actionBarLayout.getFragmentStack().size() > 1).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); + getActionBarLayout().presentFragment(params.setRemoveLast(actionBarLayout.getFragmentStack().size() > 1).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); if (!layersActionBarLayout.getFragmentStack().isEmpty()) { for (int a = 0; a < layersActionBarLayout.getFragmentStack().size() - 1; a++) { layersActionBarLayout.removeFragmentFromStack(layersActionBarLayout.getFragmentStack().get(0)); @@ -7585,7 +7553,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } layersActionBarLayout.closeLastFragment(!forceWithoutAnimation); } - actionBarLayout.presentFragment(params.setRemoveLast(actionBarLayout.getFragmentStack().size() > 1).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); + getActionBarLayout().presentFragment(params.setRemoveLast(actionBarLayout.getFragmentStack().size() > 1).setNoAnimation(forceWithoutAnimation).setCheckPresentFromDelegate(false)); return false; } } else if (layout != layersActionBarLayout) { @@ -7942,7 +7910,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati return; } StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); - ArrayList stories = new ArrayList<>(onlyArchived ? storiesController.getHiddenList() : storiesController.getDialogListStories()); + ArrayList stories = new ArrayList<>(onlyArchived ? storiesController.getHiddenList() : storiesController.getDialogListStories()); ArrayList peerIds = new ArrayList<>(); ArrayList toLoadPeerIds = new ArrayList<>(); final long[] finalDialogIds; @@ -7979,7 +7947,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati }; for (int i = 0; i < toLoadPeerIds.size(); ++i) { long did = toLoadPeerIds.get(i); - TLRPC.TL_stories_getPeerStories req = new TLRPC.TL_stories_getPeerStories(); + TL_stories.TL_stories_getPeerStories req = new TL_stories.TL_stories_getPeerStories(); req.peer = messagesController.getInputPeer(did); if (req.peer instanceof TLRPC.TL_inputPeerEmpty) { loaded[0]--; @@ -7990,8 +7958,8 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati continue; } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { - if (res instanceof TLRPC.TL_stories_peerStories) { - TLRPC.TL_stories_peerStories r = (TLRPC.TL_stories_peerStories) res; + if (res instanceof TL_stories.TL_stories_peerStories) { + TL_stories.TL_stories_peerStories r = (TL_stories.TL_stories_peerStories) res; messagesController.putUsers(r.users, false); messagesController.getStoriesController().putStories(did, r.stories); whenDone.run(); @@ -8003,7 +7971,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { long me = UserConfig.getInstance(currentAccount).getClientUserId(); for (int i = 0; i < stories.size(); ++i) { - TLRPC.PeerStories userStories = stories.get(i); + TL_stories.PeerStories userStories = stories.get(i); long dialogId = DialogObject.getPeerDialogId(userStories.peer); if (dialogId != me && !peerIds.contains(dialogId) && storiesController.hasUnreadStories(dialogId)) { peerIds.add(dialogId); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index fbab4f1b0..d52144fe8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -2815,6 +2815,12 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No boolean allowCancelCall = getParentActivity().checkSelfPermission(Manifest.permission.CALL_PHONE) == PackageManager.PERMISSION_GRANTED; boolean allowReadCallLog = Build.VERSION.SDK_INT < Build.VERSION_CODES.P || getParentActivity().checkSelfPermission(Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED; boolean allowReadPhoneNumbers = Build.VERSION.SDK_INT < Build.VERSION_CODES.O || getParentActivity().checkSelfPermission(Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED;; + if (codeField != null && "888".equals(codeField.getText())) { + allowCall = true; + allowCancelCall = true; + allowReadCallLog = true; + allowReadPhoneNumbers = true; + } if (checkPermissions) { permissionsItems.clear(); if (!allowCall) { @@ -3022,7 +3028,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); preferences.edit().remove("sms_hash_code").apply(); if (settings.allow_app_hash) { - preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).apply(); + preferences.edit().putString("sms_hash", BuildVars.getSmsHash()).apply(); } else { preferences.edit().remove("sms_hash").apply(); } @@ -3343,11 +3349,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private TextView titleTextView; private ImageView blackImageView; private RLottieImageView blueImageView; - private TextView timeText; + private LoadingTextView timeText; private FrameLayout bottomContainer; private ViewSwitcher errorViewSwitcher; - private TextView problemText; + private LoadingTextView problemText; private FrameLayout problemFrame; private TextView wrongCode; private LinearLayout openFragmentButton; @@ -3359,6 +3365,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private TextView prefixTextView; private TextView missedCallDescriptionSubtitle; + private TextView missedCallDescriptionSubtitle2; private ImageView missedCallArrowIcon, missedCallPhoneIcon; private RLottieDrawable starsToDotsDrawable; @@ -3477,13 +3484,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 34, Gravity.CENTER_HORIZONTAL, 0, 28, 0, 0)); - missedCallDescriptionSubtitle = new TextView(context); - missedCallDescriptionSubtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - missedCallDescriptionSubtitle.setGravity(Gravity.CENTER_HORIZONTAL); - missedCallDescriptionSubtitle.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - missedCallDescriptionSubtitle.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); + missedCallDescriptionSubtitle2 = new TextView(context); + missedCallDescriptionSubtitle2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + missedCallDescriptionSubtitle2.setGravity(Gravity.CENTER_HORIZONTAL); + missedCallDescriptionSubtitle2.setLineSpacing(AndroidUtilities.dp(2), 1.0f); + missedCallDescriptionSubtitle2.setText(AndroidUtilities.replaceTags(LocaleController.getString("MissedCallDescriptionSubtitle2", R.string.MissedCallDescriptionSubtitle2))); - addView(missedCallDescriptionSubtitle, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 28, 36, 12)); + addView(missedCallDescriptionSubtitle2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 36, 28, 36, 12)); } else if (currentType == AUTH_TYPE_FLASH_CALL) { confirmTextView.setGravity(Gravity.CENTER_HORIZONTAL); centerContainer = new FrameLayout(context); @@ -3550,70 +3557,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No problemFrame = new FrameLayout(context); - timeText = new TextView(context) { - private LoadingDrawable loadingDrawable = new LoadingDrawable(); - - { - loadingDrawable.setAppearByGradient(true); - } - + timeText = new LoadingTextView(context) { @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - - updateLoadingLayout(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - updateLoadingLayout(); - } - - private void updateLoadingLayout() { - Layout layout = getLayout(); - if (layout == null) { - return; - } - CharSequence text = layout.getText(); - if (text == null) { - return; - } - LinkPath path = new LinkPath(true); - int start = 0; - int end = text.length(); - path.setCurrentLayout(layout, start, 0); - layout.getSelectionPath(start, end, path); - loadingDrawable.usePath(path); - loadingDrawable.setRadiiDp(4); - - int color = getThemedColor(Theme.key_chat_linkSelectBackground); - loadingDrawable.setColors( - Theme.multAlpha(color, 0.85f), - Theme.multAlpha(color, 2f), - Theme.multAlpha(color, 3.5f), - Theme.multAlpha(color, 6f) - ); - - loadingDrawable.updateBounds(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (isResendingCode) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - loadingDrawable.draw(canvas); - canvas.restore(); - invalidate(); - } + protected boolean isRippleEnabled() { + return getVisibility() == View.VISIBLE && !(time > 0 && timeTimer != null); } }; timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - timeText.setPadding(AndroidUtilities.dp(6), AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(16)); + timeText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); timeText.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); timeText.setOnClickListener(v-> { @@ -3628,7 +3579,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL || nextType == AUTH_TYPE_FRAGMENT_SMS) { - timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); +// timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { timeText.setText(LocaleController.getString("Calling", R.string.Calling)); } else { @@ -3676,72 +3627,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No anim.setInterpolator(Easings.easeInOutQuad); errorViewSwitcher.setOutAnimation(anim); - problemText = new TextView(context) { - private LoadingDrawable loadingDrawable = new LoadingDrawable(); - - { - loadingDrawable.setAppearByGradient(true); - } - + problemText = new LoadingTextView(context) { @Override - public void setText(CharSequence text, BufferType type) { - super.setText(text, type); - - updateLoadingLayout(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - - updateLoadingLayout(); - } - - private void updateLoadingLayout() { - Layout layout = getLayout(); - if (layout == null) { - return; - } - CharSequence text = layout.getText(); - if (text == null) { - return; - } - LinkPath path = new LinkPath(true); - int start = 0; - int end = text.length(); - path.setCurrentLayout(layout, start, 0); - layout.getSelectionPath(start, end, path); - loadingDrawable.usePath(path); - loadingDrawable.setRadiiDp(4); - - int color = getThemedColor(Theme.key_chat_linkSelectBackground); - loadingDrawable.setColors( - Theme.multAlpha(color, 0.85f), - Theme.multAlpha(color, 2f), - Theme.multAlpha(color, 3.5f), - Theme.multAlpha(color, 6f) - ); - - loadingDrawable.updateBounds(); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (isResendingCode) { - canvas.save(); - canvas.translate(getPaddingLeft(), getPaddingTop()); - loadingDrawable.draw(canvas); - canvas.restore(); - invalidate(); - } + protected boolean isRippleEnabled() { + return isClickable() && getVisibility() == View.VISIBLE && !(nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode); } }; problemText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); problemText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); problemText.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); - problemText.setPadding(AndroidUtilities.dp(6), AndroidUtilities.dp(8), AndroidUtilities.dp(6), AndroidUtilities.dp(16)); + problemText.setPadding(AndroidUtilities.dp(14), AndroidUtilities.dp(8), AndroidUtilities.dp(14), AndroidUtilities.dp(16)); problemFrame.addView(problemText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); errorViewSwitcher.addView(problemFrame, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); } else { @@ -3799,7 +3694,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType != AUTH_TYPE_FRAGMENT_SMS) { problemText.setOnClickListener(v -> { - if (nextPressed || timeText.getVisibility() != View.GONE || isResendingCode) { + if (nextPressed || timeText != null && timeText.getVisibility() != View.GONE || isResendingCode) { return; } boolean email = nextType == 0; @@ -3843,6 +3738,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (currentType == AUTH_TYPE_MISSED_CALL) { missedCallDescriptionSubtitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + missedCallDescriptionSubtitle2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); missedCallArrowIcon.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), PorterDuff.Mode.SRC_IN)); missedCallPhoneIcon.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); prefixTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -4206,6 +4102,18 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No problemText.setVisibility(time < 1000 ? VISIBLE : GONE); } createTimer(); + } else if (currentType == AUTH_TYPE_MISSED_CALL) { + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS || nextType == AUTH_TYPE_MISSED_CALL) { + setProblemTextVisible(false); + timeText.setVisibility(VISIBLE); + problemText.setVisibility(GONE); + if (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { + timeText.setText(LocaleController.formatString("CallAvailableIn", R.string.CallAvailableIn, 1, 0)); + } else if (nextType == AUTH_TYPE_SMS) { + timeText.setText(LocaleController.formatString("SmsAvailableIn", R.string.SmsAvailableIn, 1, 0)); + } + createTimer(); + } } else { timeText.setVisibility(GONE); if (problemText != null) { @@ -4233,6 +4141,104 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } + private class LoadingTextView extends TextView { + + private final Drawable rippleDrawable = Theme.createSelectorDrawable(Theme.multAlpha(Theme.getColor(Theme.key_windowBackgroundWhiteValueText), .10f), Theme.RIPPLE_MASK_ROUNDRECT_6DP); + public final LoadingDrawable loadingDrawable = new LoadingDrawable(); + + public LoadingTextView(Context context) { + super(context); + rippleDrawable.setCallback(this); + loadingDrawable.setAppearByGradient(true); + loadingDrawable.setSpeed(.8f); + } + + @Override + public void setText(CharSequence text, BufferType type) { + super.setText(text, type); + + updateLoadingLayout(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + updateLoadingLayout(); + } + + private void updateLoadingLayout() { + Layout layout = getLayout(); + if (layout == null) { + return; + } + CharSequence text = layout.getText(); + if (text == null) { + return; + } + LinkPath path = new LinkPath(true); + path.setInset(AndroidUtilities.dp(3), AndroidUtilities.dp(6)); + int start = 0; + int end = text.length(); + path.setCurrentLayout(layout, start, 0); + layout.getSelectionPath(start, end, path); + path.getBounds(AndroidUtilities.rectTmp); + rippleDrawable.setBounds((int) AndroidUtilities.rectTmp.left, (int) AndroidUtilities.rectTmp.top, (int) AndroidUtilities.rectTmp.right, (int) AndroidUtilities.rectTmp.bottom); + loadingDrawable.usePath(path); + loadingDrawable.setRadiiDp(4); + + int color = getThemedColor(Theme.key_chat_linkSelectBackground); + loadingDrawable.setColors( + Theme.multAlpha(color, 0.85f), + Theme.multAlpha(color, 2f), + Theme.multAlpha(color, 3.5f), + Theme.multAlpha(color, 6f) + ); + + loadingDrawable.updateBounds(); + } + + @Override + protected void onDraw(Canvas canvas) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + rippleDrawable.draw(canvas); + canvas.restore(); + + super.onDraw(canvas); + + if (isResendingCode || loadingDrawable.isDisappearing()) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + loadingDrawable.draw(canvas); + canvas.restore(); + invalidate(); + } + } + + @Override + protected boolean verifyDrawable(@NonNull Drawable who) { + return who == rippleDrawable || super.verifyDrawable(who); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isRippleEnabled() && event.getAction() == MotionEvent.ACTION_DOWN) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + rippleDrawable.setHotspot(event.getX(), event.getY()); + } + rippleDrawable.setState(new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}); + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_UP) { + rippleDrawable.setState(new int[]{}); + } + return super.onTouchEvent(event); + } + + protected boolean isRippleEnabled() { + return true; + } + } + private void setProblemTextVisible(boolean visible) { if (problemText == null) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index 889d494b9..c357fbf5f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -6305,7 +6305,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter req.settings.allow_app_hash = PushListenerController.GooglePushListenerServiceProvider.INSTANCE.hasServices(); SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); if (req.settings.allow_app_hash) { - preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).commit(); + preferences.edit().putString("sms_hash", BuildVars.getSmsHash()).commit(); } else { preferences.edit().remove("sms_hash").commit(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java index d6db4b34d..5fa550c65 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PaymentFormActivity.java @@ -313,6 +313,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen private PaymentFormCallback paymentFormCallback; private InvoiceStatus invoiceStatus; private boolean paymentStatusSent; + private TLRPC.TL_inputInvoicePremiumGiftCode invoicePremiumGiftCode; private final static int done_button = 1; @@ -421,6 +422,11 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen public PaymentFormActivity(TLRPC.TL_payments_paymentForm form, String invoiceSlug, BaseFragment parentFragment) { this(form, null, invoiceSlug, parentFragment); + } + + public PaymentFormActivity(TLRPC.TL_payments_paymentForm form, TLRPC.TL_inputInvoicePremiumGiftCode premiumGiftCode, BaseFragment parentFragment) { + this(premiumGiftCode, form, null, null, STEP_CHECKOUT, null, null, null, null, null, null, false, null, parentFragment); + isCheckoutPreview = true; } public PaymentFormActivity(TLRPC.TL_payments_paymentForm form, MessageObject message, BaseFragment parentFragment) { @@ -429,11 +435,11 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen public PaymentFormActivity(TLRPC.TL_payments_paymentForm form, MessageObject message, String invoiceSlug, BaseFragment parentFragment) { isCheckoutPreview = true; - init(form, message, invoiceSlug, STEP_CHECKOUT, null, null, null, null, null, null, false, null, parentFragment); + init(null, form, message, invoiceSlug, STEP_CHECKOUT, null, null, null, null, null, null, false, null, parentFragment); } - private PaymentFormActivity(TLRPC.TL_payments_paymentForm form, MessageObject message, String invoiceSlug, int step, TLRPC.TL_payments_validatedRequestedInfo validatedRequestedInfo, TLRPC.TL_shippingOption shipping, Long tips, String tokenJson, String card, TLRPC.TL_payments_validateRequestedInfo request, boolean saveCard, TLRPC.TL_inputPaymentCredentialsGooglePay googlePay, BaseFragment parent) { - init(form, message, invoiceSlug, step, validatedRequestedInfo, shipping, tips, tokenJson, card, request, saveCard, googlePay, parent); + private PaymentFormActivity(TLRPC.TL_inputInvoicePremiumGiftCode premiumGiftCode, TLRPC.TL_payments_paymentForm form, MessageObject message, String invoiceSlug, int step, TLRPC.TL_payments_validatedRequestedInfo validatedRequestedInfo, TLRPC.TL_shippingOption shipping, Long tips, String tokenJson, String card, TLRPC.TL_payments_validateRequestedInfo request, boolean saveCard, TLRPC.TL_inputPaymentCredentialsGooglePay googlePay, BaseFragment parent) { + init(premiumGiftCode, form, message, invoiceSlug, step, validatedRequestedInfo, shipping, tips, tokenJson, card, request, saveCard, googlePay, parent); } public void setPaymentFormCallback(PaymentFormCallback callback) { @@ -441,7 +447,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } private void setCurrentPassword(TLRPC.account_Password password) { - if (password.has_password) { + if (password != null && password.has_password) { if (getParentActivity() == null) { return; } @@ -466,7 +472,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen return resourcesProvider; } - private void init(TLRPC.TL_payments_paymentForm form, MessageObject message, String slug, int step, TLRPC.TL_payments_validatedRequestedInfo validatedRequestedInfo, TLRPC.TL_shippingOption shipping, Long tips, String tokenJson, String card, TLRPC.TL_payments_validateRequestedInfo request, boolean saveCard, TLRPC.TL_inputPaymentCredentialsGooglePay googlePay, BaseFragment parent) { + private void init(TLRPC.TL_inputInvoicePremiumGiftCode premiumGiftCode, TLRPC.TL_payments_paymentForm form, MessageObject message, String slug, int step, TLRPC.TL_payments_validatedRequestedInfo validatedRequestedInfo, TLRPC.TL_shippingOption shipping, Long tips, String tokenJson, String card, TLRPC.TL_payments_validateRequestedInfo request, boolean saveCard, TLRPC.TL_inputPaymentCredentialsGooglePay googlePay, BaseFragment parent) { currentStep = step; parentFragment = parent; paymentJson = tokenJson; @@ -477,6 +483,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen tipAmount = tips; messageObject = message; invoiceSlug = slug; + invoicePremiumGiftCode = premiumGiftCode; saveCardInfo = saveCard; isWebView = !"stripe".equals(paymentForm.native_provider) && !"smartglocal".equals(paymentForm.native_provider); botUser = getMessagesController().getUser(form.bot_id); @@ -1784,6 +1791,8 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen paymentInfoCell.setReceipt(paymentReceipt, currentBotName); } else if (invoiceSlug != null) { paymentInfoCell.setInfo(paymentForm.title, paymentForm.description, paymentForm.photo, currentBotName, paymentForm); + } else if (invoicePremiumGiftCode != null) { + paymentInfoCell.setInfo(paymentForm.title, paymentForm.description, paymentForm.photo, currentBotName, paymentForm); } linearLayout2.addView(paymentInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -2143,7 +2152,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (currentStep == STEP_CHECKOUT) { detailSettingsCell[2].setBackgroundDrawable(Theme.getSelectorDrawable(true)); detailSettingsCell[2].setOnClickListener(v -> { - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setDelegate(new PaymentFormActivityDelegate() { @Override public void didSelectNewAddress(TLRPC.TL_payments_validateRequestedInfo validateRequested) { @@ -2166,7 +2175,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (currentStep == STEP_CHECKOUT) { detailSettingsCell[3].setBackgroundDrawable(Theme.getSelectorDrawable(true)); detailSettingsCell[3].setOnClickListener(v -> { - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setDelegate(new PaymentFormActivityDelegate() { @Override public void didSelectNewAddress(TLRPC.TL_payments_validateRequestedInfo validateRequested) { @@ -2189,7 +2198,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (currentStep == STEP_CHECKOUT) { detailSettingsCell[4].setBackgroundDrawable(Theme.getSelectorDrawable(true)); detailSettingsCell[4].setOnClickListener(v -> { - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setDelegate(new PaymentFormActivityDelegate() { @Override public void didSelectNewAddress(TLRPC.TL_payments_validateRequestedInfo validateRequested) { @@ -2212,7 +2221,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (currentStep == STEP_CHECKOUT) { detailSettingsCell[5].setBackgroundDrawable(Theme.getSelectorDrawable(true)); detailSettingsCell[5].setOnClickListener(v -> { - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_SHIPPING_INFORMATION, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setDelegate(new PaymentFormActivityDelegate() { @Override public void didSelectNewAddress(TLRPC.TL_payments_validateRequestedInfo validateRequested) { @@ -2276,7 +2285,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (step == STEP_PAYMENT_INFO && !paymentForm.additional_methods.isEmpty()) { showChoosePaymentMethod(v::callOnClick); } else { - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, step, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, null, parentFragment)); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, step, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, null, parentFragment)); } return; } @@ -2291,7 +2300,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (UserConfig.getInstance(currentAccount).tmpPassword == null) { needPayAfterTransition = true; - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_CONFIRM_PASSWORD, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment)); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_CONFIRM_PASSWORD, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment)); needPayAfterTransition = false; return; } else if (isCheckoutPreview) { @@ -2692,12 +2701,12 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (which < titles.size() - 1) { TLRPC.TL_paymentFormMethod method = paymentForm.additional_methods.get(which - savedCredentialsCards.size() - offset); - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_PAYMENT_INFO, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_PAYMENT_INFO, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setPaymentMethod(method); activity.setDelegate(delegate); presentFragment(activity); } else if (which == titles.size() - 1) { - PaymentFormActivity activity = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_PAYMENT_INFO, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); + PaymentFormActivity activity = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_PAYMENT_INFO, requestedInfo, shippingOption, tipAmount, null, cardName, validateRequest, saveCardInfo, null, parentFragment); activity.setDelegate(delegate); presentFragment(activity); } @@ -3278,7 +3287,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (nextStep == STEP_PAYMENT_INFO && savedCredentialsCard == null && paymentJson == null && !paymentForm.additional_methods.isEmpty()) { showChoosePaymentMethod(this::goToNextStep); } else { - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, null, null, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, null, null, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); } } break; @@ -3304,13 +3313,13 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen if (nextStep == STEP_PAYMENT_INFO && cardName == null && savedCredentialsCard == null && paymentJson == null && !paymentForm.additional_methods.isEmpty()) { showChoosePaymentMethod(this::goToNextStep); } else { - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); } break; } case STEP_PAYMENT_INFO: if (paymentForm.password_missing && saveCardInfo) { - passwordFragment = new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_SET_PASSWORD_EMAIL, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment); + passwordFragment = new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_SET_PASSWORD_EMAIL, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment); passwordFragment.setCurrentPassword(currentPassword); passwordFragment.setDelegate(new PaymentFormActivityDelegate() { @Override @@ -3340,7 +3349,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen delegate.didSelectNewCard(paymentJson, cardName, saveCardInfo, googlePayCredentials, null); finishFragment(); } else { - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_CHECKOUT, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_CHECKOUT, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), isWebView); } } break; @@ -3351,7 +3360,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } else { nextStep = STEP_PAYMENT_INFO; } - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), true); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, nextStep, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), true); break; } case STEP_CHECKOUT: @@ -3379,7 +3388,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen break; case STEP_SET_PASSWORD_EMAIL: if (!delegate.didSelectNewCard(paymentJson, cardName, saveCardInfo, googlePayCredentials, savedCredentialsCard)) { - presentFragment(new PaymentFormActivity(paymentForm, messageObject, invoiceSlug, STEP_CHECKOUT, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), true); + presentFragment(new PaymentFormActivity(invoicePremiumGiftCode, paymentForm, messageObject, invoiceSlug, STEP_CHECKOUT, requestedInfo, shippingOption, tipAmount, paymentJson, cardName, validateRequest, saveCardInfo, googlePayCredentials, parentFragment), true); } else { finishFragment(); } @@ -3388,6 +3397,17 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } private boolean onCheckoutSuccess(INavigationLayout parentLayout, Activity parentActivity) { + if (invoicePremiumGiftCode != null) { + if (parentLayout != null) { + for (BaseFragment fragment : new ArrayList<>(parentLayout.getFragmentStack())) { + if (fragment instanceof PaymentFormActivity) { + fragment.removeSelfFromStack(); + } + } + return true; + } + return false; + } if (botUser.username != null && botUser.username.equalsIgnoreCase(getMessagesController().premiumBotUsername) && invoiceSlug == null || invoiceSlug != null && getMessagesController().premiumInvoiceSlug != null && Objects.equals(invoiceSlug, getMessagesController().premiumInvoiceSlug)) { if (parentLayout != null) { for (BaseFragment fragment : new ArrayList<>(parentLayout.getFragmentStack())) { @@ -3829,7 +3849,9 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } showEditDoneProgress(true, true); validateRequest = new TLRPC.TL_payments_validateRequestedInfo(); - if (messageObject != null) { + if (invoicePremiumGiftCode != null) { + validateRequest.invoice = invoicePremiumGiftCode; + } else if (messageObject != null) { TLRPC.TL_inputInvoiceMessage inputInvoice = new TLRPC.TL_inputInvoiceMessage(); inputInvoice.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id); inputInvoice.msg_id = messageObject.getId(); @@ -3869,7 +3891,9 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } showEditDoneProgress(true, true); validateRequest = new TLRPC.TL_payments_validateRequestedInfo(); - if (messageObject != null) { + if (invoicePremiumGiftCode != null) { + validateRequest.invoice = invoicePremiumGiftCode; + } else if (messageObject != null) { TLRPC.TL_inputInvoiceMessage inputInvoice = new TLRPC.TL_inputInvoiceMessage(); inputInvoice.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id); inputInvoice.msg_id = messageObject.getId(); @@ -3968,7 +3992,9 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen } showEditDoneProgress(false, true); TLRPC.TL_payments_sendPaymentForm req = new TLRPC.TL_payments_sendPaymentForm(); - if (messageObject != null) { + if (invoicePremiumGiftCode != null) { + req.invoice = invoicePremiumGiftCode; + } else if (messageObject != null) { TLRPC.TL_inputInvoiceMessage inputInvoice = new TLRPC.TL_inputInvoiceMessage(); inputInvoice.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id); inputInvoice.msg_id = messageObject.getId(); @@ -3978,6 +4004,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen inputInvoice.slug = invoiceSlug; req.invoice = inputInvoice; } + req.form_id = paymentForm.form_id; if (UserConfig.getInstance(currentAccount).tmpPassword != null && savedCredentialsCard != null) { req.credentials = new TLRPC.TL_inputPaymentCredentialsSaved(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java new file mode 100644 index 000000000..5a754e8a3 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/PeerColorActivity.java @@ -0,0 +1,1215 @@ +package org.telegram.ui; + +import static android.content.DialogInterface.BUTTON_NEGATIVE; +import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.dpf2; +import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_COLOR; +import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_BOOSTS_FOR_USERS; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.util.Log; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BotWebViewVibrationEffect; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; +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.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; +import org.telegram.ui.Cells.ThemePreviewMessagesCell; +import org.telegram.ui.Components.AnimatedEmojiDrawable; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ButtonBounce; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SimpleThemeDescription; +import org.telegram.ui.Components.Text; +import org.telegram.ui.Stories.recorder.ButtonWithCounterView; + +import java.util.ArrayList; +import java.util.List; + +public class PeerColorActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + + private final boolean isChannel; + private final long dialogId; + + private FrameLayout contentView; + private RecyclerListView listView; + private RecyclerView.Adapter listAdapter; + private FrameLayout buttonContainer; + private ButtonWithCounterView button; + private PeerColorPicker peerColorPicker; + + private int selectedColor; + private long selectedEmoji; + private ThemePreviewMessagesCell messagesCellPreview; + private SetReplyIconCell setReplyIconCell; + + private CharSequence buttonLocked, buttonUnlocked; + + int previewRow; + int colorPickerRow; + int infoRow; + int iconRow; + int info2Row; + + int rowCount; + + private static final int VIEW_TYPE_MESSAGE = 0; + private static final int VIEW_TYPE_COLOR_PICKER = 1; + private static final int VIEW_TYPE_INFO = 2; + private static final int VIEW_TYPE_ICON = 3; + + public PeerColorActivity(long dialogId) { + super(); + + this.dialogId = dialogId; + this.isChannel = dialogId != 0; + } + + private BaseFragment bulletinFragment; + public PeerColorActivity setOnApplied(BaseFragment bulletinFragment) { + this.bulletinFragment = bulletinFragment; + return this; + } + + @Override + public boolean onFragmentCreate() { + getNotificationCenter().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + Bulletin.addDelegate(this, new Bulletin.Delegate() { + @Override + public int getBottomOffset(int tag) { + return dp(62); + } + + @Override + public boolean clipWithGradient(int tag) { + return true; + } + }); + getMediaDataController().loadReplyIcons(); + if (MessagesController.getInstance(currentAccount).peerColors == null && BuildVars.DEBUG_PRIVATE_VERSION) { + MessagesController.getInstance(currentAccount).loadAppConfig(true); + } + return super.onFragmentCreate(); + } + + @Override + public View createView(Context context) { + actionBar.setTitle(LocaleController.getString(isChannel ? R.string.ChannelColorTitle : R.string.UserColorTitle)); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setAllowOverlayTitle(true); + + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + if (!isChannel && hasUnsavedChanged() && getUserConfig().isPremium()) { + showUnsavedAlert(); + return; + } + finishFragment(); + } + } + }); + + if (dialogId < 0) { + TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + if ((chat.flags2 & 32) != 0) { + selectedEmoji = chat.background_emoji_id; + } + if ((chat.flags2 & 64) != 0) { + selectedColor = chat.color; + } else { + selectedColor = (int) (chat.id % 7); + } + } else { + TLRPC.User user = getUserConfig().getCurrentUser(); + if ((user.flags2 & 64) != 0) { + selectedEmoji = user.background_emoji_id; + } + if ((user.flags2 & 128) != 0) { + selectedColor = user.color; + } else { + selectedColor = (int) (user.id % 7); + } + } + + FrameLayout frameLayout = new FrameLayout(context); + + listView = new RecyclerListView(context); + ((DefaultItemAnimator)listView.getItemAnimator()).setSupportsChangeAnimations(false); + listView.setLayoutManager(new LinearLayoutManager(context)); + listView.setAdapter(listAdapter = new RecyclerListView.SelectionAdapter() { + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == VIEW_TYPE_COLOR_PICKER || holder.getItemViewType() == VIEW_TYPE_ICON; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case VIEW_TYPE_MESSAGE: + ThemePreviewMessagesCell messagesCell = messagesCellPreview = new ThemePreviewMessagesCell(context, parentLayout, ThemePreviewMessagesCell.TYPE_PEER_COLOR, dialogId); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); + } + messagesCell.fragment = PeerColorActivity.this; + view = messagesCell; + break; + default: + case VIEW_TYPE_INFO: + TextInfoPrivacyCell cell = new TextInfoPrivacyCell(context); + view = cell; + break; + case VIEW_TYPE_COLOR_PICKER: + PeerColorPicker colorPicker = peerColorPicker = new PeerColorPicker(context, currentAccount, getResourceProvider()); + colorPicker.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, getResourceProvider())); + colorPicker.setSelected(selectedColor); + colorPicker.layoutManager.scrollToPositionWithOffset(colorPicker.selectedPosition, AndroidUtilities.displaySize.x / 2); + colorPicker.setOnItemClickListener((item, position) -> { + selectedColor = colorPicker.toColorId(position); + colorPicker.setSelectedPosition(position); + if (item.getLeft() - colorPicker.getPaddingLeft() < AndroidUtilities.dp(24)) { + colorPicker.smoothScrollBy(position == 0 ? Math.max(-(item.getLeft() - colorPicker.getPaddingLeft()), -AndroidUtilities.dp(64)) : -AndroidUtilities.dp(64), 0); + } else if (item.getRight() - colorPicker.getPaddingLeft() > AndroidUtilities.displaySize.x - colorPicker.getPaddingLeft() - colorPicker.getPaddingRight() - AndroidUtilities.dp(24)) { + colorPicker.smoothScrollBy(position == colorPicker.adapter.getItemCount() - 1 ? Math.min(AndroidUtilities.displaySize.x - item.getRight() - colorPicker.getPaddingRight(), AndroidUtilities.dp(64)) : AndroidUtilities.dp(64), 0); + } + updateMessages(); + if (setReplyIconCell != null) { + setReplyIconCell.invalidate(); + } + }); + view = colorPicker; + break; + case VIEW_TYPE_ICON: + SetReplyIconCell setcell = setReplyIconCell = new SetReplyIconCell(context); + setcell.update(false); + view = setcell; + break; + case 4: + view = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(16), MeasureSpec.EXACTLY) + ); + } + }; + view.setBackground(Theme.getThemedDrawableByKey(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + break; + } + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + switch (getItemViewType(position)) { + case VIEW_TYPE_INFO: + TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView; + if (position == infoRow) { + cell.setText(LocaleController.getString(isChannel ? R.string.ChannelColorHint : R.string.UserColorHint)); + cell.setBackground(Theme.getThemedDrawableByKey(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + } else if (position == info2Row) { + cell.setText(LocaleController.getString(isChannel ? R.string.ChannelReplyIconHint : R.string.UserReplyIconHint)); + cell.setBackground(Theme.getThemedDrawableByKey(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + } + } + } + + @Override + public int getItemCount() { + return rowCount; + } + + @Override + public int getItemViewType(int position) { + if (position == previewRow) { + return VIEW_TYPE_MESSAGE; + } + if (position == infoRow || position == info2Row) { + return VIEW_TYPE_INFO; + } + if (position == colorPickerRow) { + return VIEW_TYPE_COLOR_PICKER; + } + if (position == iconRow) { + return VIEW_TYPE_ICON; + } + if (position == getItemCount() - 1) { + return 4; + } + return VIEW_TYPE_INFO; + } + }); + listView.setOnItemClickListener((view, position) -> { + if (view instanceof SetReplyIconCell) { + showSelectStatusDialog((SetReplyIconCell) view); + } + }); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + buttonContainer = new FrameLayout(context); + buttonContainer.setPadding(dp(14), dp(14), dp(14), dp(14)); + buttonContainer.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundGray)); + + SpannableStringBuilder buttonLock = new SpannableStringBuilder("l"); + buttonLock.setSpan(new ColoredImageSpan(R.drawable.msg_mini_lock2), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + buttonUnlocked = LocaleController.getString(isChannel ? R.string.ChannelColorApply : R.string.UserColorApplyIcon); + buttonLocked = new SpannableStringBuilder(buttonLock).append(" ").append(buttonUnlocked); + + button = new ButtonWithCounterView(context, getResourceProvider()); + button.text.setHacks(true, true, true); + button.setText(isChannel ? buttonUnlocked : (!getUserConfig().isPremium() ? buttonLocked : buttonUnlocked), false); + button.setOnClickListener(v -> buttonClick()); + buttonContainer.addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + + frameLayout.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + + fragmentView = contentView = frameLayout; + + updateColors(); + updateRows(); + + return contentView; + } + + private void showBoostLimit(boolean error) { + getMessagesController().getBoostsController().getBoostsStats(dialogId, boostsStatus -> { + if (error || boostsStatus.level < getMessagesController().channelColorLevelMin) { + getMessagesController().getBoostsController().userCanBoostChannel(dialogId, boostsStatus, canApplyBoost -> { + if (getContext() == null) { + return; + } + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getContext(), TYPE_BOOSTS_FOR_COLOR, currentAccount, getResourceProvider()); + limitReachedBottomSheet.setCanApplyBoost(canApplyBoost); + + limitReachedBottomSheet.setBoostsStats(boostsStatus, true); + limitReachedBottomSheet.setDialogId(dialogId); + limitReachedBottomSheet.showStatisticButtonInLink(() -> { + TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + Bundle args = new Bundle(); + args.putLong("chat_id", -dialogId); + args.putBoolean("is_megagroup", chat.megagroup); + args.putBoolean("start_from_boosts", true); + TLRPC.ChatFull chatInfo = getMessagesController().getChatFull(-dialogId); + if (chatInfo == null || !chatInfo.can_view_stats) { + args.putBoolean("only_boosts", true); + }; + StatisticActivity fragment = new StatisticActivity(args); + presentFragment(fragment); + }); + showDialog(limitReachedBottomSheet); + AndroidUtilities.runOnUIThread(() -> button.setLoading(false), 300); + }); + } else { + apply(); + } + }); + } + + @Override + public boolean onBackPressed() { + if (!isChannel && hasUnsavedChanged() && getUserConfig().isPremium()) { + showUnsavedAlert(); + return false; + } + return super.onBackPressed(); + } + + public boolean hasUnsavedChanged() { + if (isChannel) { + final TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + if (chat == null) { + return false; + } + if (selectedColor == chat.color && selectedEmoji == ((chat.flags2 & 64) == 0 ? 0 : chat.background_emoji_id)) { + return false; + } + return true; + } else { + final TLRPC.User me = getUserConfig().getCurrentUser(); + if (selectedColor == me.color && selectedEmoji == ((me.flags2 & 64) == 0 ? 0 : me.background_emoji_id)) { + return false; + } + return true; + } + } + + @Override + public boolean isSwipeBackEnabled(MotionEvent event) { + if (!isChannel && hasUnsavedChanged() && getUserConfig().isPremium()) { + return false; + } + return super.isSwipeBackEnabled(event); + } + + private void showUnsavedAlert() { + if (getVisibleDialog() != null) { + return; + } + AlertDialog alertDialog = new AlertDialog.Builder(getContext(), getResourceProvider()) + .setTitle(LocaleController.getString(isChannel ? R.string.ChannelColorUnsaved : R.string.UserColorUnsaved)) + .setMessage(LocaleController.getString(isChannel ? R.string.ChannelColorUnsavedMessage : R.string.UserColorUnsavedMessage)) + .setNegativeButton(LocaleController.getString(R.string.Dismiss), (di, w) -> { + finishFragment(); + }) + .setPositiveButton(LocaleController.getString(R.string.ApplyTheme), (di, w) -> { + buttonClick(); + }) + .create(); + showDialog(alertDialog); + ((TextView) alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE)).setTextColor(getThemedColor(Theme.key_text_RedBold)); + } + + private void buttonClick() { + if (button.isLoading()) { + return; + } + if (isChannel) { + button.setLoading(true); + showBoostLimit(false); + return; + } else { + if (!getUserConfig().isPremium()) { + Bulletin bulletin = BulletinFactory.of(this).createSimpleBulletin(R.raw.star_premium_2, AndroidUtilities.premiumText(LocaleController.getString(R.string.UserColorApplyPremium), () -> { + presentFragment(new PremiumPreviewFragment("name_color")); + })); + bulletin.getLayout().setPadding(dp(8 + 6), dp(8), dp(8 + 6), dp(8)); + bulletin.show(); + + BotWebViewVibrationEffect.APP_ERROR.vibrate(); + return; + } + } + + apply(); + finishFragment(); + showBulletin(); + } + + private boolean applying; + private void apply() { + if (applying || peerColorPicker == null || !isChannel && !getUserConfig().isPremium()) { + return; + } + + if (isChannel) { + final TLRPC.Chat chat = getMessagesController().getChat(-dialogId); + if (chat == null) { + return; + } + if (selectedColor == chat.color && selectedEmoji == ((chat.flags2 & 64) == 0 ? 0 : chat.background_emoji_id)) { + return; + } + TLRPC.TL_channels_updateColor req = new TLRPC.TL_channels_updateColor(); + req.channel = getMessagesController().getInputChannel(-dialogId); + if (req.channel == null) { + return; + } + chat.flags2 |= 64; + req.color = chat.color = selectedColor; + if (selectedEmoji != 0) { + chat.flags2 |= 32; + chat.background_emoji_id = selectedEmoji; + + req.flags |= 1; + req.background_emoji_id = selectedEmoji; + } else { + chat.flags2 &= ~32; + chat.background_emoji_id = 0; + } + button.setLoading(true); + getMessagesController().putChat(chat, false); + getUserConfig().saveConfig(true); + getConnectionsManager().sendRequest(req, (res, err) -> AndroidUtilities.runOnUIThread(() -> { + applying = false; + if (err != null && "BOOSTS_REQUIRED".equals(err.text)) { + showBoostLimit(true); + } else { + finishFragment(); + showBulletin(); + } + })); + } else { + final TLRPC.User me = getUserConfig().getCurrentUser(); + if (selectedColor == me.color && selectedEmoji == ((me.flags2 & 64) == 0 ? 0 : me.background_emoji_id)) { + return; + } + TLRPC.TL_account_updateColor req = new TLRPC.TL_account_updateColor(); + me.flags2 |= 128; + req.color = me.color = selectedColor; + if (selectedEmoji != 0) { + me.flags2 |= 64; + me.background_emoji_id = selectedEmoji; + + req.flags |= 1; + req.background_emoji_id = selectedEmoji; + } else { + me.flags2 &= ~64; + me.background_emoji_id = 0; + } + getMessagesController().putUser(me, false); + getUserConfig().saveConfig(true); + getConnectionsManager().sendRequest(req, null); + } + applying = true; + getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_EMOJI_STATUS); + } + + private void showBulletin() { + if (bulletinFragment != null) { + BulletinFactory.of(bulletinFragment).createSimpleBulletin(PeerColorDrawable.from(currentAccount, selectedColor), LocaleController.getString(isChannel ? R.string.ChannelColorApplied : R.string.UserColorApplied)).show(); + bulletinFragment = null; + } + } + + private void updateMessages() { + if (messagesCellPreview != null) { + ChatMessageCell[] cells = messagesCellPreview.getCells(); + for (int i = 0; i < cells.length; ++i) { + if (cells[i] != null) { + MessageObject msg = cells[i].getMessageObject(); + if (msg != null) { + if (peerColorPicker != null) { + msg.overrideLinkColor = peerColorPicker.getColorId(); + } + msg.overrideLinkEmoji = selectedEmoji; + cells[i].setAvatar(msg); + cells[i].invalidate(); + } + } + } + } + } + + @Override + public void onFragmentClosed() { + super.onFragmentClosed(); + Bulletin.removeDelegate(this); + } + + private class SetReplyIconCell extends FrameLayout { + + private TextView textView; + private Text offText; + private AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable imageDrawable; + + public SetReplyIconCell(Context context) { + super(context); + + setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + + textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + textView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setText(LocaleController.getString(isChannel ? R.string.ChannelReplyIcon : R.string.UserReplyIcon)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL | Gravity.FILL_HORIZONTAL, 20, 0, 48, 0)); + + imageDrawable = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, false, dp(24), AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC); + } + + public void update(boolean animated) { + if (selectedEmoji != 0) { + imageDrawable.set(selectedEmoji, animated); + offText = null; + } else { + imageDrawable.set((Drawable) null, animated); + if (offText == null) { + offText = new Text(LocaleController.getString(isChannel ? R.string.ChannelReplyIconOff : R.string.UserReplyIconOff), 16); + } + } + } + + public void updateImageBounds() { + imageDrawable.setBounds( + getWidth() - imageDrawable.getIntrinsicWidth() - dp(21), + (getHeight() - imageDrawable.getIntrinsicHeight()) / 2, + getWidth() - dp(21), + (getHeight() + imageDrawable.getIntrinsicHeight()) / 2 + ); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + updateImageBounds(); + imageDrawable.setColor(getColor()); + if (offText != null) { + offText.draw(canvas, getMeasuredWidth() - offText.getWidth() - dp(19), getMeasuredHeight() / 2f, getThemedColor(Theme.key_windowBackgroundWhiteBlueText4), 1f); + } else { + imageDrawable.draw(canvas); + } + } + + public int getColor() { + if (selectedColor < 7) { + return getThemedColor(AvatarDrawable.getNameColorKey1For(selectedColor)); + } else { + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + if (peerColors != null) { + MessagesController.PeerColor color = peerColors.getColor(selectedColor); + if (color != null) { + return color.getColor1(); + } + } + } + return getThemedColor(AvatarDrawable.getNameColorKey1For(0)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(50), MeasureSpec.EXACTLY) + ); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + imageDrawable.detach(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + imageDrawable.attach(); + } + } + + private SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow selectAnimatedEmojiDialog; + public void showSelectStatusDialog(SetReplyIconCell cell) { + if (selectAnimatedEmojiDialog != null || cell == null) { + return; + } + final SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow[] popup = new SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow[1]; + int xoff = 0, yoff = 0; + + AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable scrimDrawable = null; + View scrimDrawableParent = null; + final int popupHeight = (int) Math.min(AndroidUtilities.dp(410 - 16 - 64), AndroidUtilities.displaySize.y * .75f); + final int popupWidth = (int) Math.min(dp(340 - 16), AndroidUtilities.displaySize.x * .95f); + if (cell != null) { + scrimDrawable = cell.imageDrawable; + scrimDrawableParent = cell; + if (cell.imageDrawable != null) { + cell.imageDrawable.play(); + cell.updateImageBounds(); + AndroidUtilities.rectTmp2.set(cell.imageDrawable.getBounds()); + yoff = -AndroidUtilities.rectTmp2.centerY() + dp(12) - popupHeight; + xoff = AndroidUtilities.rectTmp2.centerX() - (AndroidUtilities.displaySize.x - popupWidth); + } + } + SelectAnimatedEmojiDialog popupLayout = new SelectAnimatedEmojiDialog(this, getContext(), true, xoff, SelectAnimatedEmojiDialog.TYPE_SET_REPLY_ICON, true, getResourceProvider(), 24, cell.getColor()) { + @Override + protected void onEmojiSelected(View emojiView, Long documentId, TLRPC.Document document, Integer until) { + selectedEmoji = documentId == null ? 0 : documentId; + if (cell != null) { + cell.update(true); + } + updateMessages(); + if (popup[0] != null) { + selectAnimatedEmojiDialog = null; + popup[0].dismiss(); + } + } + + @Override + protected float getScrimDrawableTranslationY() { + return 0; + } + }; + popupLayout.setSelected(selectedEmoji == 0 ? null : selectedEmoji); + popupLayout.setSaveState(3); + popupLayout.setScrimDrawable(scrimDrawable, scrimDrawableParent); + popup[0] = selectAnimatedEmojiDialog = new SelectAnimatedEmojiDialog.SelectAnimatedEmojiDialogWindow(popupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + selectAnimatedEmojiDialog = null; + } + }; + popup[0].showAsDropDown(cell, 0, yoff, Gravity.TOP | Gravity.RIGHT); + popup[0].dimBehind(); + } + + private void updateRows() { + rowCount = 0; + previewRow = rowCount++; + colorPickerRow = rowCount++; + infoRow = rowCount++; + iconRow = rowCount++; + info2Row = rowCount++; + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + getNotificationCenter().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + private List getAvailableReactions() { + return getMediaDataController().getReactionsList(); + } + + @Override + public ArrayList getThemeDescriptions() { + return SimpleThemeDescription.createThemeDescriptions(this::updateColors, + Theme.key_windowBackgroundWhite, + Theme.key_windowBackgroundWhiteBlackText, + Theme.key_windowBackgroundWhiteGrayText2, + Theme.key_listSelector, + Theme.key_windowBackgroundGray, + Theme.key_windowBackgroundWhiteGrayText4, + Theme.key_text_RedRegular, + Theme.key_windowBackgroundChecked, + Theme.key_windowBackgroundCheckText, + Theme.key_switchTrackBlue, + Theme.key_switchTrackBlueChecked, + Theme.key_switchTrackBlueThumb, + Theme.key_switchTrackBlueThumbChecked + ); + } + + @SuppressLint("NotifyDataSetChanged") + private void updateColors() { + contentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + listAdapter.notifyDataSetChanged(); + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (account != currentAccount) return; + if (id == NotificationCenter.currentUserPremiumStatusChanged) { +// updateRows(); +// listAdapter.notifyDataSetChanged(); + + if (button != null) { + button.setText(isChannel ? buttonUnlocked : (!getUserConfig().isPremium() ? buttonLocked : buttonUnlocked), true); + } + } + } + + private static class PeerColorPicker extends RecyclerListView { + private final Theme.ResourcesProvider resourcesProvider; + public final LinearLayoutManager layoutManager; + public final Adapter adapter; + private final int currentAccount; + + private static final int[] order = { // key_avatar_nameInMessageRed, key_avatar_nameInMessageOrange, key_avatar_nameInMessageViolet, key_avatar_nameInMessageGreen, key_avatar_nameInMessageCyan, key_avatar_nameInMessageBlue, key_avatar_nameInMessagePink + 5, // blue + 3, // green + 1, // orange + 0, // red + 2, // violet + 4, // cyan + 6 // pink + }; + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (getParent() != null && getParent().getParent() != null) { + getParent().getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1) || canScrollHorizontally(1)); + getParent().requestDisallowInterceptTouchEvent(true); + } + return super.onInterceptTouchEvent(e); + } + + @Override + public Integer getSelectorColor(int position) { + return 0; + } + + public PeerColorPicker(Context context, final int currentAccount, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.currentAccount = currentAccount; + this.resourcesProvider = resourcesProvider; + + setPadding(dp(8), dp(8), dp(8), dp(8)); + setClipToPadding(false); + + setAdapter(adapter = new SelectionAdapter() { + @Override + public boolean isEnabled(ViewHolder holder) { + return true; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new Holder(new ColorCell(context)); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + ColorCell cell = (ColorCell) holder.itemView; + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); + cell.setSelected(position == selectedPosition, false); + if (position >= 0 && position < Theme.keys_avatar_nameInMessage.length) { + cell.set( + Theme.getColor(Theme.keys_avatar_nameInMessage[order[position]], resourcesProvider) + ); + } else { + position -= Theme.keys_avatar_nameInMessage.length; + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + if (peerColors != null && position >= 0 && position < peerColors.colors.size()) { + cell.set(peerColors.colors.get(position)); + } + } + } + + @Override + public int getItemCount() { + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + return 7 + (peerColors == null ? 0 : peerColors.colors.size()); + } + }); + layoutManager = new LinearLayoutManager(context); + layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); + setLayoutManager(layoutManager); + } + + private int selectedPosition; + public void setSelected(int color) { + setSelectedPosition(toPosition(color)); + } + + public void setSelectedPosition(int position) { + if (position != selectedPosition) { + selectedPosition = position; + AndroidUtilities.forEachViews(this, child -> ((ColorCell) child).setSelected(getChildAdapterPosition(child) == selectedPosition, true)); + } + } + + public int getColorId() { + return toColorId(selectedPosition); + } + + public int toPosition(final int colorId) { + if (colorId >= 0 && colorId < Theme.keys_avatar_nameInMessage.length) { + for (int i = 0; i < order.length; ++i) { + if (order[i] == colorId) { + return i; + } + } + } + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + if (peerColors == null) { + return 0; + } + for (int i = 0; i < peerColors.colors.size(); ++i) { + if (peerColors.colors.get(i).id == colorId) { + return 7 + i; + } + } + return 0; + } + + public int toColorId(int position) { + if (position >= 0 && position < 7) { + return order[position]; + } + position -= 7; + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + if (peerColors == null || position < 0 || position >= peerColors.colors.size()) { + return 0; + } + return peerColors.colors.get(position).id; + } + + private static class ColorCell extends View { + private final Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint paint1 = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint paint2 = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path circlePath = new Path(); + private final Path color2Path = new Path(); + private boolean hasColor2, hasColor3; + + private final ButtonBounce bounce = new ButtonBounce(this); + + public ColorCell(Context context) { + super(context); + backgroundPaint.setStyle(Paint.Style.STROKE); + } + + public void setBackgroundColor(int backgroundColor) { + backgroundPaint.setColor(backgroundColor); + } + + public void set(int color) { + hasColor2 = hasColor3 = false; + paint1.setColor(color); + } + + public void set(int color1, int color2) { + hasColor2 = true; + hasColor3 = false; + paint1.setColor(color1); + paint2.setColor(color2); + } + + public void set(MessagesController.PeerColor color) { + if (Theme.isCurrentThemeDark() && color.hasColor2() && !color.hasColor3()) { + paint1.setColor(color.getColor2()); + paint2.setColor(color.getColor1()); + } else { + paint1.setColor(color.getColor1()); + paint2.setColor(color.getColor2()); + } + paint3.setColor(color.getColor3()); + hasColor2 = color.hasColor2(); + hasColor3 = color.hasColor3(); + } + + private boolean selected; + private final AnimatedFloat selectedT = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + public void setSelected(boolean selected, boolean animated) { + this.selected = selected; + if (!animated) { + selectedT.set(selected, true); + } + invalidate(); + } + + private static final int VIEW_SIZE_DP = 56; + private static final int CIRCLE_RADIUS_DP = 20; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension(dp(VIEW_SIZE_DP), dp(VIEW_SIZE_DP)); + + circlePath.rewind(); + circlePath.addCircle(getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, dp(CIRCLE_RADIUS_DP), Path.Direction.CW); + + color2Path.rewind(); + color2Path.moveTo(getMeasuredWidth(), 0); + color2Path.lineTo(getMeasuredWidth(), getMeasuredHeight()); + color2Path.lineTo(0, getMeasuredHeight()); + color2Path.close(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.save(); + final float s = bounce.getScale(.05f); + canvas.scale(s, s, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + + canvas.save(); + canvas.clipPath(circlePath); + canvas.drawPaint(paint1); + if (hasColor2) { + canvas.drawPath(color2Path, paint2); + } + canvas.restore(); + + if (hasColor3) { + canvas.save(); + AndroidUtilities.rectTmp.set( + (getMeasuredWidth() - dp(12.4f)) / 2f, + (getMeasuredHeight() - dp(12.4f)) / 2f, + (getMeasuredWidth() + dp(12.4f)) / 2f, + (getMeasuredHeight() + dp(12.4f)) / 2f + ); + canvas.rotate(45f, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(2.33f), dp(2.33f), paint3); + canvas.restore(); + } + + final float selectT = selectedT.set(selected); + + if (selectT > 0) { + backgroundPaint.setStrokeWidth(dpf2(2)); + canvas.drawCircle( + getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, + AndroidUtilities.lerp( + dp(CIRCLE_RADIUS_DP) + backgroundPaint.getStrokeWidth() * .5f, + dp(CIRCLE_RADIUS_DP) - backgroundPaint.getStrokeWidth() * 2f, + selectT + ), + backgroundPaint + ); + } + + canvas.restore(); + } + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + bounce.setPressed(pressed); + } + } + } + + public static class ChangeNameColorCell extends View { + private final boolean isChannel; + private final Theme.ResourcesProvider resourcesProvider; + + private final Drawable drawable; + private final Text buttonText; + + private final Paint userTextBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Text userText; + private int userTextColorKey = -1; + private boolean needDivider; + + public ChangeNameColorCell(boolean isChannel, Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.isChannel = isChannel; + this.resourcesProvider = resourcesProvider; + + drawable = context.getResources().getDrawable(R.drawable.msg_palette).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider), PorterDuff.Mode.SRC_IN)); + buttonText = new Text(LocaleController.getString(isChannel ? R.string.ChangeChannelNameColor : R.string.ChangeUserNameColor), 16); + updateColors(); + } + + public void updateColors() { + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(isChannel ? Theme.key_windowBackgroundWhiteGrayIcon : Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider), PorterDuff.Mode.SRC_IN)); + buttonText.setColor(Theme.getColor(isChannel ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider)); + + if (userText != null && userTextBackgroundPaint != null && userTextColorKey != -1) { + final int color = Theme.getColor(userTextColorKey, resourcesProvider); + userText.setColor(color); + userTextBackgroundPaint.setColor(Theme.multAlpha(color, .10f)); + } + } + + public void set(TLRPC.Chat chat, boolean divider) { + if (chat == null) { + return; + } + needDivider = divider; + CharSequence text = chat.title; + text = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), false); + userText = new Text(text, 13, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + final int color; + int colorId = chat != null && (chat.flags2 & 64) != 0 ? chat.color : (int) (chat.id % 7); + if (colorId < 7) { + color = Theme.getColor(userTextColorKey = Theme.keys_avatar_nameInMessage[colorId], resourcesProvider); + } else { + MessagesController.PeerColors peerColors = MessagesController.getInstance(UserConfig.selectedAccount).peerColors; + MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(colorId); + if (peerColor != null) { + userTextColorKey = -1; + color = peerColor.getColor1(); + } else { + color = Theme.getColor(userTextColorKey = Theme.keys_avatar_nameInMessage[0], resourcesProvider); + } + } + userText.setColor(color); + userTextBackgroundPaint.setColor(Theme.multAlpha(color, .10f)); + } + + public void set(TLRPC.User user) { + if (user == null) { + return; + } + String name = user.first_name == null ? "" : user.first_name.trim(); + int index = name.indexOf(" "); + if (index > 0) { + name = name.substring(0, index); + } + CharSequence text = name; + text = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), false); + userText = new Text(text, 13, AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + final int color; + int colorId = user != null && (user.flags2 & 128) != 0 ? user.color : (int) (user.id % 7); + if (colorId < 7) { + color = Theme.getColor(userTextColorKey = Theme.keys_avatar_nameInMessage[colorId], resourcesProvider); + } else { + MessagesController.PeerColors peerColors = MessagesController.getInstance(UserConfig.selectedAccount).peerColors; + MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(colorId); + if (peerColor != null) { + userTextColorKey = -1; + color = peerColor.getColor1(); + } else { + color = Theme.getColor(userTextColorKey = Theme.keys_avatar_nameInMessage[0], resourcesProvider); + } + } + userText.setColor(color); + userTextBackgroundPaint.setColor(Theme.multAlpha(color, .10f)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(dp(50) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); + } + + private int rtl(int x) { + return LocaleController.isRTL ? getMeasuredWidth() - x : x; + } + private float rtl(float x) { + return LocaleController.isRTL ? getMeasuredWidth() - x : x; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + drawable.setBounds( + rtl(dp(64) / 2) - drawable.getIntrinsicWidth() / 2, + getMeasuredHeight() / 2 - drawable.getIntrinsicHeight() / 2, + rtl(dp(64) / 2) + drawable.getIntrinsicWidth() / 2, + getMeasuredHeight() / 2 + drawable.getIntrinsicHeight() / 2 + ); + drawable.draw(canvas); + buttonText + .ellipsize(getMeasuredWidth() - dp(64 + 7 + 100)) + .draw(canvas, LocaleController.isRTL ? getMeasuredWidth() - buttonText.getWidth() - dp(64 + 7) : dp(64 + 7), getMeasuredHeight() / 2f); + + if (userText != null) { + final int maxWidth = (int) (getMeasuredWidth() - dp(64 + 7 + 15 + 9 + 9 + 12) - Math.min(buttonText.getWidth(), getMeasuredWidth() - dp(64 + 100))); + final int w = (int) Math.min(userText.getWidth(), maxWidth); + + AndroidUtilities.rectTmp.set( + LocaleController.isRTL ? dp(15) : getMeasuredWidth() - dp(15 + 9 + 9) - w, + (getMeasuredHeight() - dp(22)) / 2f, + LocaleController.isRTL ? dp(15 + 9 + 9) + w : getMeasuredWidth() - dp(15), + (getMeasuredHeight() + dp(22)) / 2f + ); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(12), dp(12), userTextBackgroundPaint); + + userText + .ellipsize(maxWidth) + .draw(canvas, LocaleController.isRTL ? dp(15 + 9) : getMeasuredWidth() - dp(15 + 9) - w, getMeasuredHeight() / 2f); + } + + if (needDivider) { + Paint paint = resourcesProvider != null ? resourcesProvider.getPaint(Theme.key_paint_divider) : null; + if (paint == null) { + paint = Theme.dividerPaint; + } + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(64), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(64) : 0), getMeasuredHeight() - 1, paint); + } + } + } + + public static class PeerColorDrawable extends Drawable { + + public static PeerColorDrawable from(int currentAccount, int colorId) { + if (colorId < 7) { + return new PeerColorDrawable(Theme.getColor(Theme.keys_avatar_nameInMessage[colorId]), Theme.getColor(Theme.keys_avatar_nameInMessage[colorId]), Theme.getColor(Theme.keys_avatar_nameInMessage[colorId])); + } + MessagesController.PeerColors peerColors = MessagesController.getInstance(currentAccount).peerColors; + MessagesController.PeerColor peerColor = peerColors == null ? null : peerColors.getColor(colorId); + return from(peerColor); + } + + public static PeerColorDrawable from(MessagesController.PeerColor peerColor) { + if (peerColor == null) { + return new PeerColorDrawable(0, 0, 0); + } + return new PeerColorDrawable(peerColor.getColor1(), peerColor.getColor2(), peerColor.getColor3()); + } + + private final int diameter = AndroidUtilities.dp(21.333f); + private final int radius = diameter / 2; + + private final boolean hasColor3; + private final Paint color1Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint color2Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint color3Paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Path color2Path = new Path(); + private final Path clipCirclePath = new Path(); + + public PeerColorDrawable(int color1, int color2, int color3) { + hasColor3 = color3 != color1; + color1Paint.setColor(color1); + color2Paint.setColor(color2); + color3Paint.setColor(color3); + + clipCirclePath.addCircle(radius, radius, radius, Path.Direction.CW); + color2Path.moveTo(diameter, 0); + color2Path.lineTo(diameter, diameter); + color2Path.lineTo(0, diameter); + color2Path.close(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + canvas.save(); + canvas.translate(getBounds().centerX() - radius, getBounds().centerY() - radius); + canvas.clipPath(clipCirclePath); + canvas.drawPaint(color1Paint); + canvas.drawPath(color2Path, color2Paint); + if (hasColor3) { + AndroidUtilities.rectTmp.set(radius - dp(3.66f), radius - dp(3.66f), radius + dp(3.66f), radius + dp(3.66f)); + canvas.rotate(45, radius, radius); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(2.33f), dp(2.33f), color3Paint); + } + canvas.restore(); + } + + @Override + public void setAlpha(int alpha) {} + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) {} + + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public int getIntrinsicHeight() { + return diameter; + } + + @Override + public int getIntrinsicWidth() { + return diameter; + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index afbd326d8..ede5f17e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -62,6 +62,7 @@ import android.text.Layout; import android.text.Spannable; import android.text.SpannableString; import android.text.SpannableStringBuilder; +import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; @@ -75,7 +76,6 @@ import android.transition.TransitionManager; import android.transition.TransitionSet; import android.transition.TransitionValues; import android.util.FloatProperty; -import android.util.Log; import android.util.Pair; import android.util.Property; import android.util.Range; @@ -95,7 +95,6 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewOutlineProvider; -import android.view.ViewPropertyAnimator; import android.view.ViewTreeObserver; import android.view.WindowInsets; import android.view.WindowManager; @@ -109,7 +108,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.OverScroller; -import android.widget.ScrollView; import android.widget.Scroller; import android.widget.TextView; import android.widget.Toast; @@ -138,9 +136,6 @@ import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.analytics.AnalyticsListener; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; -import com.google.android.gms.vision.Frame; -import com.google.android.gms.vision.face.Face; -import com.google.android.gms.vision.face.FaceDetector; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; @@ -224,7 +219,6 @@ import org.telegram.ui.Components.Forum.ForumUtilities; import org.telegram.ui.Components.GestureDetector2; import org.telegram.ui.Components.GroupedPhotosListView; import org.telegram.ui.Components.HideViewAfterAnimation; -import org.telegram.ui.Components.IPhotoPaintView; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkPath; @@ -242,6 +236,7 @@ import org.telegram.ui.Components.PickerBottomLayoutViewer; import org.telegram.ui.Components.PipVideoOverlay; import org.telegram.ui.Components.PlayPauseDrawable; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.Components.QuoteSpan; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; @@ -875,6 +870,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean captionHwLayerEnabled; private ImageUpdater.AvatarFor setAvatarFor; private boolean lastCaptionTranslating; + private MessagesController.DialogPhotos dialogPhotos; private Paint bitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); @@ -1778,7 +1774,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; windowView.setFocusable(false); @@ -1965,7 +1964,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat NotificationCenter.closeChats, NotificationCenter.mediaCountDidLoad, NotificationCenter.mediaDidLoad, - NotificationCenter.dialogPhotosLoaded + NotificationCenter.dialogPhotosUpdate }); private class BackgroundDrawable extends ColorDrawable { @@ -3818,18 +3817,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } } - } else if (id == NotificationCenter.dialogPhotosLoaded) { - int guid = (Integer) args[3]; - long did = (Long) args[0]; - if (avatarsDialogId == did && classGuid == guid) { - boolean fromCache = (Boolean) args[2]; - + } else if (id == NotificationCenter.dialogPhotosUpdate) { + MessagesController.DialogPhotos dialogPhotos = (MessagesController.DialogPhotos) args[0]; + if (avatarsDialogId == dialogPhotos.dialogId) { + this.dialogPhotos = dialogPhotos; int setToImage = -1; - ArrayList photos = (ArrayList) args[4]; - if (photos.isEmpty()) { - return; - } - ArrayList messages = (ArrayList) args[5]; + ArrayList photos = new ArrayList<>(dialogPhotos.photos); imagesArrLocations.clear(); imagesArrLocationsSizes.clear(); imagesArrLocationsVideo.clear(); @@ -3839,6 +3832,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat for (int a = 0; a < photos.size(); a++) { TLRPC.Photo photo = photos.get(a); if (photo == null || photo instanceof TLRPC.TL_photoEmpty || photo.sizes == null) { + imagesArrLocations.add(null); + imagesArrLocationsSizes.add(null); + imagesArrLocationsVideo.add(null); + imagesArrMessages.add(null); + avatarsArr.add(null); continue; } TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 640); @@ -3870,13 +3868,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat ImageLocation videoLocation = videoSize != null ? ImageLocation.getForPhoto(videoSize, photo) : location; if (location != null) { imagesArrLocations.add(location); - imagesArrLocationsSizes.add(videoLocation.currentSize); + imagesArrLocationsSizes.add(videoLocation != null ? videoLocation.currentSize : null); imagesArrLocationsVideo.add(videoLocation); - if (messages != null) { - imagesArrMessages.add(messages.get(a)); - } else { - imagesArrMessages.add(null); - } + imagesArrMessages.add(null); avatarsArr.add(photo); } } @@ -3906,7 +3900,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat location = ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_BIG, currentAccount); } if (location != null) { - if (!imagesArrLocations.isEmpty() && imagesArrLocations.get(0).photoId == location.photoId) { + if (!imagesArrLocations.isEmpty() && imagesArrLocations.get(0) != null && imagesArrLocations.get(0).photoId == location.photoId) { imagesArrLocations.remove(0); avatarsArr.remove(0); imagesArrLocationsSizes.remove(0); @@ -3915,16 +3909,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } imagesArrLocations.add(0, location); avatarsArr.add(0, new TLRPC.TL_photoEmpty()); - imagesArrLocationsSizes.add(0, currentFileLocationVideo.currentSize); + imagesArrLocationsSizes.add(0, currentFileLocationVideo != null ? currentFileLocationVideo.currentSize : null); imagesArrLocationsVideo.add(0, currentFileLocationVideo); imagesArrMessages.add(0, null); setImageIndex(0); } } } - if (fromCache && placeProvider.canLoadMoreAvatars()) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(avatarsDialogId, 80, 0, false, classGuid); - } } } else if (id == NotificationCenter.mediaCountDidLoad) { long uid = (Long) args[0]; @@ -4499,16 +4490,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowView.addView(animatingImageView, LayoutHelper.createFrame(40, 40)); containerView = new FrameLayoutDrawer(activity, activity) { - private Bulletin.Delegate delegate = new Bulletin.Delegate() { - @Override - public int getBottomOffset(int tag) { - if (captionEdit.editText.getVisibility() == View.GONE) { - return 0; - } - return getHeight() - captionEdit.editText.getTop(); - } - }; - @Override public int getBottomPadding() { return pickerView.getHeight(); @@ -4526,20 +4507,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return super.dispatchTouchEvent(ev); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - Bulletin.addDelegate(this, delegate); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - Bulletin.removeDelegate(this); - } - @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { View overlay = textSelectionHelper.getOverlayView(windowView.getContext()); @@ -4635,7 +4602,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } paintingOverlay = new PaintingOverlay(parentActivity); @@ -7069,6 +7039,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private final LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this); private final Utilities.Callback3 onLinkLongPress; private final Utilities.Callback2 onLinkClick; + private ArrayList quoteBlocks; + private boolean hasQuote; public CaptionTextView( Context context, @@ -7189,6 +7161,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat super.onDraw(canvas); if (lastLayout != getLayout()) { animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, animatedEmojiDrawables, getLayout()); + quoteBlocks = QuoteSpan.updateQuoteBlocksSpanned(getLayout(), quoteBlocks); + hasQuote = getLayout() != null && getLayout().getText() instanceof Spanned && ((Spanned) getLayout().getText()).getSpans(0, getLayout().getText().length(), QuoteSpan.QuoteStyleSpan.class).length > 0; + ViewHelper.setPadding(this, 16, 8, (hasQuote ? 32 : 0) + 16, 8); lastLayout = getLayout(); } } @@ -7199,12 +7174,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat protected void onDetachedFromWindow() { super.onDetachedFromWindow(); AnimatedEmojiSpan.release(this, animatedEmojiDrawables); + quoteBlocks = QuoteSpan.updateQuoteBlocksSpanned(null, quoteBlocks); } @Override protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { super.onTextChanged(text, start, lengthBefore, lengthAfter); animatedEmojiDrawables = AnimatedEmojiSpan.update(AnimatedEmojiDrawable.CACHE_TYPE_MESSAGES, this, animatedEmojiDrawables, getLayout()); + quoteBlocks = QuoteSpan.updateQuoteBlocksSpanned(getLayout(), quoteBlocks); } @Override @@ -7229,6 +7206,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (loading) { canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 0xb2, Canvas.ALL_SAVE_FLAG); } + if (quoteBlocks != null && hasQuote) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + for (int i = 0; i < quoteBlocks.size(); ++i) { + quoteBlocks.get(i).draw(canvas, 0, getWidth() - getPaddingLeft() - getPaddingRight() + (hasQuote ? AndroidUtilities.dp(32) : 0), Color.WHITE, 1f); + } + canvas.restore(); + } super.dispatchDraw(canvas); if (loading) { canvas.restore(); @@ -8122,19 +8107,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } Object object = imagesArrLocals.get(currentIndex); if (apply) { - CharSequence cs = applyCaption(); -// if (cs != null) { -// setCurrentCaption(null, cs, false, false); -// } + applyCaption(); } -// updateCaptionTextForCurrentPhoto(object); if (captionEdit.editText.isPopupShowing()) { captionEdit.editText.hidePopup(true); } captionEdit.editText.closeKeyboard(); -// if (Build.VERSION.SDK_INT >= 19) { -// captionEditText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); -// } } private CharSequence applyCaption() { @@ -8144,23 +8122,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Object object = imagesArrLocals.get(currentIndex); CharSequence caption = captionEdit.getText(); - CharSequence[] result = new CharSequence[] { caption }; +// CharSequence[] result = new CharSequence[] { caption }; if (hasCaptionForAllMedia && !TextUtils.equals(captionForAllMedia, caption) && placeProvider.getPhotoIndex(currentIndex) != 0 && placeProvider.getSelectedCount() > 0) { hasCaptionForAllMedia = false; } - ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(result, supportsSendingNewEntities()); +// ArrayList entities = MediaDataController.getInstance(currentAccount).getEntities(result, supportsSendingNewEntities()); captionForAllMedia = caption; if (object instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; - photoEntry.caption = result[0]; - photoEntry.entities = entities; + photoEntry.caption = caption; +// photoEntry.entities = entities; } else if (object instanceof MediaController.SearchImage) { MediaController.SearchImage photoEntry = (MediaController.SearchImage) object; - photoEntry.caption = result[0]; - photoEntry.entities = entities; + photoEntry.caption = caption; +// photoEntry.entities = entities; } if (caption.length() != 0 && !placeProvider.isPhotoChecked(currentIndex)) { @@ -8169,7 +8147,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (placeProvider != null) { placeProvider.onApplyCaption(caption); } - return result[0]; + return caption; } private void updateVideoPlayerTime() { @@ -8551,7 +8529,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void playVideoOrWeb() { if (videoPlayer != null) { videoPlayer.play(); - } else { + } else if (photoViewerWebView != null) { photoViewerWebView.playVideo(); } } @@ -8559,7 +8537,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void pauseVideoOrWeb() { if (videoPlayer != null) { videoPlayer.pause(); - } else { + } else if (photoViewerWebView != null) { photoViewerWebView.pauseVideo(); } } @@ -8567,7 +8545,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void seekVideoOrWebToProgress(float progress) { if (videoPlayer != null) { videoPlayer.seekTo((long) (progress * videoPlayer.getDuration())); - } else { + } else if (photoViewerWebView != null) { photoViewerWebView.seekTo((long) (progress * photoViewerWebView.getVideoDuration())); } } @@ -11178,7 +11156,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (location == null) { return null; } - if (videoLocation != location) { + if (videoLocation != null && videoLocation != location) { return videoLocation.location.volume_id + "_" + videoLocation.location.local_id + ".mp4"; } else { return location.location.volume_id + "_" + location.location.local_id + ".jpg"; @@ -11230,7 +11208,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (index >= imagesArrLocations.size()) { return null; } - if (size != null) { + if (size != null && imagesArrLocationsSizes.get(index) != null) { size[0] = imagesArrLocationsSizes.get(index); } return imagesArrLocationsVideo.get(index); @@ -11311,10 +11289,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (index >= imagesArrLocations.size()) { return null; } - if (size != null) { + if (size != null && imagesArrLocationsSizes.get(index) != null) { size[0] = imagesArrLocationsSizes.get(index); } - return imagesArrLocationsVideo.get(index).location; + if (imagesArrLocationsVideo.get(index) != null) { + return imagesArrLocationsVideo.get(index).location; + } else { + return null; + } } else if (!imagesArr.isEmpty()) { if (index >= imagesArr.size()) { return null; @@ -11394,7 +11376,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return true; } } - } else if (currentLocation.location.local_id == currentAvatarLocation.location.local_id && currentLocation.location.volume_id == currentAvatarLocation.location.volume_id) { + } else if (currentLocation != null && currentLocation.location.local_id == currentAvatarLocation.location.local_id && currentLocation.location.volume_id == currentAvatarLocation.location.volume_id) { return true; } return false; @@ -11534,6 +11516,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat speedItem.setVisibility(View.GONE); speedGap.setVisibility(View.GONE); actionBar.setTranslationY(0); + dialogPhotos = null; checkImageView.setAlpha(1.0f); checkImageView.setTranslationY(0.0f); @@ -11854,6 +11837,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat setImageIndex(index); } + dialogPhotos = null; if (currentAnimation == null && !isEvent) { if (currentDialogId != 0 && totalImagesCount == 0 && currentMessageObject != null && !currentMessageObject.scheduled) { if (MediaDataController.getMediaType(currentMessageObject.messageOwner) == sharedMediaType) { @@ -11863,7 +11847,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } } else if (avatarsDialogId != 0 && placeProvider.canLoadMoreAvatars()) { - MessagesController.getInstance(currentAccount).loadDialogPhotos(avatarsDialogId, 80, 0, true, classGuid); + dialogPhotos = MessagesController.getInstance(currentAccount).getDialogPhotos(avatarsDialogId); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.dialogPhotosUpdate, dialogPhotos); } } if (currentMessageObject != null && currentMessageObject.isVideo() || currentBotInlineResult != null && (currentBotInlineResult.type.equals("video") || MessageObject.isVideoDocument(currentBotInlineResult.document)) || (pageBlocksAdapter != null && (pageBlocksAdapter.isVideo(index) || pageBlocksAdapter.isHardwarePlayer(index))) || (sendPhotoType == SELECT_TYPE_NO_SELECT && ((MediaController.PhotoEntry)imagesArrLocals.get(index)).isVideo)) { @@ -11914,6 +11899,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } boolean animateCaption = animated; + final boolean forward = index >= switchingToIndex; int wasIndex = switchingToIndex; switchingToIndex = index; @@ -12223,6 +12209,25 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.hideSubItem(gallery_menu_set_as_main); menuItem.hideSubItem(gallery_menu_delete); } + if (avatarsDialogId != 0) { + if (avatarsDialogId >= 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(avatarsDialogId); + title = UserObject.getUserName(user); + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-avatarsDialogId); + title = chat != null ? chat.title : ""; + } + ImageLocation imageLocation = imagesArrLocations.get(index); + if (imageLocation != null && imageLocation.photo != null) { + actionBarContainer.setSubtitle(LocaleController.formatDateTime(imageLocation.photo.date), animated); + } else { + actionBarContainer.setSubtitle("", animated); + } + } + + if (dialogPhotos != null) { + dialogPhotos.loadAfter(index, forward); + } if (countView != null) { countView.updateShow(imagesArrLocations.size() > 1, true); countView.set(switchingToIndex + 1, imagesArrLocations.size()); @@ -13748,7 +13753,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } - } else if (currentAnimation != null) { + } else if (imageReceiver == centerImage && currentAnimation != null) { imageReceiver.setImageBitmap(currentAnimation); currentAnimation.addSecondParentView(containerView); } @@ -13789,7 +13794,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageReceiver.setImageBitmap(parentActivity.getResources().getDrawable(R.drawable.photoview_placeholder)); } return; - } else if (currentAnimation != null) { + } else if (imageReceiver == centerImage && currentAnimation != null) { currentAnimation.addSecondParentView(containerView); imageReceiver.setImageBitmap(currentAnimation); return; @@ -14173,15 +14178,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (photoEntry.isVideo) { if (videoEditedInfo != null) { - SendMessagesHelper.prepareSendingVideo(parentChatActivity.getAccountInstance(), photoEntry.path, videoEditedInfo, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(parentChatActivity.getAccountInstance(), photoEntry.path, videoEditedInfo, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, parentChatActivity.getReplyQuote(), photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } else { - SendMessagesHelper.prepareSendingVideo(parentChatActivity.getAccountInstance(), photoEntry.path, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(parentChatActivity.getAccountInstance(), photoEntry.path, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, parentChatActivity.getReplyQuote(), photoEntry.entities, photoEntry.ttl, editingMessageObject, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } } else { if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(parentChatActivity.getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(parentChatActivity.getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, parentChatActivity.getReplyQuote(), photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(parentChatActivity.getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(parentChatActivity.getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, parentChatActivity.getDialogId(), parentChatActivity.getReplyMessage(), parentChatActivity.getThreadMessage(), null, parentChatActivity.getReplyQuote(), photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, editingMessageObject, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } } } @@ -14299,7 +14304,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; } if (chatActivity != null && chatActivity.getCurrentEncryptedChat() != null || avatarsDialogId != 0 && MessagesController.getInstance(currentAccount).isChatNoForwards(-avatarsDialogId) || @@ -14341,7 +14349,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.mediaCountDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.mediaDidLoad); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogPhotosLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.dialogPhotosUpdate); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.messagesDeleted); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.filePreparingFailed); @@ -15310,7 +15318,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.mediaCountDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.mediaDidLoad); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogPhotosLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.dialogPhotosUpdate); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDeleted); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.filePreparingFailed); @@ -15371,6 +15379,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat currentSecureDocument = null; currentPageBlock = null; currentPathObject = null; + dialogPhotos = null; if (videoPlayerControlFrameLayout != null) { setVideoPlayerControlVisible(false, false); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java index ce7568c82..1d85be5ca 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PinchToZoomHelper.java @@ -56,7 +56,8 @@ public class PinchToZoomHelper { private ZoomOverlayView overlayView; private View child; private ImageReceiver childImage; - private TextureView childTextureView; + private View childTextureViewContainer; + private View childTextureView; private ImageReceiver fullImage = new ImageReceiver(); private ImageReceiver blurImage = new ImageReceiver(); @@ -121,7 +122,7 @@ public class PinchToZoomHelper { this.isSimple = true; } - public void startZoom(View child, ImageReceiver image, TextureView textureView, MessageObject messageObject, int spoilerEffect2AttachIndex) { + public void startZoom(View child, ImageReceiver image, View textureViewContainer, View textureView, MessageObject messageObject, int spoilerEffect2AttachIndex) { this.child = child; this.messageObject = messageObject; @@ -218,15 +219,18 @@ public class PinchToZoomHelper { } else { isHardwareVideo = false; this.childImage = new ImageReceiver(); + this.childTextureViewContainer = textureViewContainer; this.childTextureView = textureView; this.childImage.onAttachedToWindow(); Drawable drawable = image.getDrawable(); this.childImage.setImageBitmap(drawable); + if (drawable instanceof AnimatedFileDrawable) { ((AnimatedFileDrawable) drawable).addSecondParentView(overlayView); ((AnimatedFileDrawable) drawable).setInvalidateParentViewWithSecond(true); } this.childImage.setImageCoords(imageX, imageY, imageWidth, imageHeight); + this.childImage.setAspectFit(image.isAspectFit()); this.childImage.setRoundRadius(image.getRoundRadius()); this.fullImage.setRoundRadius(image.getRoundRadius()); @@ -272,7 +276,11 @@ public class PinchToZoomHelper { } parentOffsetX += currentView.getLeft(); parentOffsetY += currentView.getTop(); - currentView = (View) currentView.getParent(); + if (currentView.getParent() instanceof View) { + currentView = (View) currentView.getParent(); + } else { + break; + } } float fragmentOffsetX = 0; @@ -605,10 +613,22 @@ public class PinchToZoomHelper { fullImage.draw(canvas); } } - if (childTextureView != null) { + if (childTextureViewContainer != null) { + View view = childTextureView; + if (view == null) { + view = childTextureViewContainer; + } canvas.save(); canvas.translate(childImage.getImageX(), childImage.getImageY()); - childTextureView.draw(canvas); + float scaleX = childImage.getImageWidth() / childTextureViewContainer.getMeasuredWidth(); + float scaleY = childImage.getImageHeight() / childTextureViewContainer.getMeasuredHeight(); + float maxScale = Math.max(scaleX, scaleY); + if (childImage.isAspectFit()) { + canvas.scale(maxScale, maxScale, childTextureViewContainer.getMeasuredWidth() / 2f, 0); + } else { + canvas.scale(maxScale, maxScale); + } + childTextureViewContainer.draw(canvas); canvas.restore(); } } else { @@ -740,11 +760,11 @@ public class PinchToZoomHelper { void getClipTopBottom(float[] topBottom); } - public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, TextureView textureView, MessageObject messageObject) { - return checkPinchToZoom(ev, child, image, textureView, messageObject, 0); + public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, View textureViewContainer, View textureView, MessageObject messageObject) { + return checkPinchToZoom(ev, child, image, textureViewContainer, textureView, messageObject, 0); } - public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, TextureView textureView, MessageObject messageObject, int spoilerEffect2Index) { + public boolean checkPinchToZoom(MotionEvent ev, View child, ImageReceiver image, View textureViewContainer, View textureView, MessageObject messageObject, int spoilerEffect2Index) { if (!zoomEnabled(child, image)) { return false; } @@ -785,7 +805,7 @@ public class PinchToZoomHelper { pinchTranslationX = 0f; pinchTranslationY = 0f; child.getParent().requestDisallowInterceptTouchEvent(true); - startZoom(child, image, textureView, messageObject, spoilerEffect2Index); + startZoom(child, image, textureViewContainer, textureView, messageObject, spoilerEffect2Index); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java index c0f04969c..86ca52fde 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PollCreateActivity.java @@ -743,7 +743,7 @@ public class PollCreateActivity extends BaseFragment { if (menu.findItem(android.R.id.copy) == null) { return; } - ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat()); + ChatActivity.fillActionModeMenu(menu, parentFragment.getCurrentEncryptedChat(), false); } } }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index ed8ad4268..afe24f4b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -328,7 +328,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC } @Override - public void onTextChanged(CharSequence text, boolean big) { + public void onTextChanged(CharSequence text, boolean big, boolean fromDraft) { } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java index 4b93584b8..a38904f0a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java @@ -24,8 +24,11 @@ public class PremiumFeatureCell extends FrameLayout { public ImageView imageView; boolean drawDivider; public PremiumPreviewFragment.PremiumFeatureData data; - public PremiumFeatureCell(Context context) { + this(context, null); + } + + public PremiumFeatureCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); LinearLayout linearLayout = new LinearLayout(context); @@ -36,12 +39,12 @@ public class PremiumFeatureCell extends FrameLayout { title = new SimpleTextView(context); title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); title.setTextSize(15); - title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); linearLayout.addView(title, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); description = new TextView(context); description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider)); description.setLineSpacing(AndroidUtilities.dp(2), 1f); linearLayout.addView(description, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 1, 0, 0)); @@ -54,7 +57,7 @@ public class PremiumFeatureCell extends FrameLayout { ImageView nextIcon = new ImageView(context); nextIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); nextIcon.setImageResource(R.drawable.msg_arrowright); - nextIcon.setColorFilter(Theme.getColor(Theme.key_switchTrack)); + nextIcon.setColorFilter(Theme.getColor(Theme.key_switchTrack, resourcesProvider)); addView(nextIcon, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 18, 0)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index da436625d..8923ab16f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -114,6 +114,7 @@ import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; +import org.telegram.messenger.FlagSecureReason; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; @@ -149,6 +150,7 @@ import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.INavigationLayout; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -390,6 +392,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private Animator searchViewTransition; private boolean searchMode; + private FlagSecureReason flagSecure; + private HashMap positionToOffset = new HashMap<>(); private float avatarX; @@ -769,10 +773,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ImageReceiver imageReceiver = animatedEmojiDrawable != null ? animatedEmojiDrawable.getImageReceiver() : this.imageReceiver; canvas.save(); canvas.scale(bounceScale, bounceScale, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + float inset = hasStories ? (int) AndroidUtilities.dpf2(3.5f) : 0; + inset *= (1f - progressToExpand); + inset *= progressToInsets * (1f - foregroundAlpha); if (imageReceiver != null && (foregroundAlpha < 1f || !drawForeground)) { - float inset = hasStories ? (int) AndroidUtilities.dpf2(3.5f) : 0; - inset *= (1f - progressToExpand); - inset *= progressToInsets; imageReceiver.setImageCoords(inset, inset, getMeasuredWidth() - inset * 2f, getMeasuredHeight() - inset * 2f); if (drawAvatar) { imageReceiver.draw(canvas); @@ -780,7 +784,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (foregroundAlpha > 0f && drawForeground) { if (foregroundImageReceiver.getDrawable() != null) { - foregroundImageReceiver.setImageCoords(0, 0, getMeasuredWidth(), getMeasuredHeight()); + foregroundImageReceiver.setImageCoords(inset, inset, getMeasuredWidth() - inset * 2f, getMeasuredHeight() - inset * 2f); foregroundImageReceiver.setAlpha(foregroundAlpha); foregroundImageReceiver.draw(canvas); } else { @@ -1600,6 +1604,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (dialogId != 0) { currentEncryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); } + if (flagSecure != null) { + flagSecure.invalidate(); + } TLRPC.User user = getMessagesController().getUser(userId); if (user == null) { return false; @@ -1654,6 +1661,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return false; } } + if (flagSecure != null) { + flagSecure.invalidate(); + } if (currentChat.megagroup) { getChannelParticipants(true); @@ -1692,6 +1702,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().addObserver(this, NotificationCenter.updateSearchSettings); getNotificationCenter().addObserver(this, NotificationCenter.reloadDialogPhotos); getNotificationCenter().addObserver(this, NotificationCenter.storiesUpdated); + getNotificationCenter().addObserver(this, NotificationCenter.storiesReadUpdated); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); updateRowsIds(); if (listAdapter != null) { @@ -1762,6 +1773,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().removeObserver(this, NotificationCenter.updateSearchSettings); getNotificationCenter().removeObserver(this, NotificationCenter.reloadDialogPhotos); getNotificationCenter().removeObserver(this, NotificationCenter.storiesUpdated); + getNotificationCenter().removeObserver(this, NotificationCenter.storiesReadUpdated); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); if (avatarsViewPager != null) { avatarsViewPager.onDestroy(); @@ -1852,6 +1864,19 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return actionBar; } + @Override + public void setParentLayout(INavigationLayout layout) { + super.setParentLayout(layout); + + if (flagSecure != null) { + flagSecure.detach(); + flagSecure = null; + } + if (layout != null && layout.getParentActivity() != null) { + flagSecure = new FlagSecureReason(layout.getParentActivity().getWindow(), () -> currentEncryptedChat != null || getMessagesController().isChatNoForwards(currentChat)); + } + } + @Override public View createView(Context context) { Theme.createProfileResources(context); @@ -3534,7 +3559,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. LocaleController.getString("DebugMenuClearMediaCache", R.string.DebugMenuClearMediaCache), LocaleController.getString("DebugMenuCallSettings", R.string.DebugMenuCallSettings), null, - BuildVars.DEBUG_PRIVATE_VERSION || BuildVars.isStandaloneApp() ? LocaleController.getString("DebugMenuCheckAppUpdate", R.string.DebugMenuCheckAppUpdate) : null, + BuildVars.DEBUG_PRIVATE_VERSION || ApplicationLoader.isStandaloneBuild() ? LocaleController.getString("DebugMenuCheckAppUpdate", R.string.DebugMenuCheckAppUpdate) : null, LocaleController.getString("DebugMenuReadAllDialogs", R.string.DebugMenuReadAllDialogs), BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.disableVoiceAudioEffects ? "Enable voip audio effects" : "Disable voip audio effects") : null, BuildVars.DEBUG_PRIVATE_VERSION ? "Clean app update" : null, @@ -3550,6 +3575,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. LocaleController.getString(DualCameraView.dualAvailableStatic(getContext()) ? "DebugMenuDualOff" : "DebugMenuDualOn"), BuildVars.DEBUG_VERSION ? (SharedConfig.useSurfaceInStories ? "back to TextureView in stories" : "use SurfaceView in stories") : null, BuildVars.DEBUG_PRIVATE_VERSION ? (SharedConfig.photoViewerBlur ? "do not blur in photoviewer" : "blur in photoviewer") : null, + !SharedConfig.payByInvoice ? "Enable Invoice Payment" : "Disable Invoice Payment", + BuildVars.DEBUG_PRIVATE_VERSION ? "Update Attach Bots" : null, !FakePasscodeUtils.isFakePasscodeActivated() ? "Enter tester settings password" : null }; @@ -3582,6 +3609,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. SharedConfig.lockRecordAudioVideoHint = 0; SharedConfig.stickersReorderingHintUsed = false; SharedConfig.forwardingOptionsHintShown = false; + SharedConfig.replyingOptionsHintShown = false; SharedConfig.messageSeenHintCount = 3; SharedConfig.emojiInteractionsHintCount = 3; SharedConfig.dayNightThemeSwitchHintCount = 3; @@ -3589,6 +3617,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. SharedConfig.stealthModeSendMessageConfirm = 2; SharedConfig.updateStealthModeSendMessageConfirm(2); SharedConfig.setStoriesReactionsLongPressHintUsed(false); + SharedConfig.setStoriesIntroShown(false); ChatThemeController.getInstance(currentAccount).clearCache(); getNotificationCenter().postNotificationName(NotificationCenter.newSuggestionsAvailable); RestrictedLanguagesSelectActivity.cleanup(); @@ -3777,6 +3806,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (which == 24) { SharedConfig.togglePhotoViewerBlur(); + } else if (which == 25) { + SharedConfig.togglePaymentByInvoice(); + } else if (which == 26) { + getMediaDataController().loadAttachMenuBots(false, true); } else if (which == items.length - 1) { showTesterPasswordDialog(); @@ -4303,6 +4336,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. expandAvatar(); } } + + @Override + protected void onLongPress() { + openAvatar(); + } }; updateStoriesViewBounds(false); if (userInfo != null) { @@ -5454,7 +5492,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. float px = x, py = y; View v = view; - while (v != getFragmentView()) { + while (v != getFragmentView() && v != null) { px += v.getX(); py += v.getY(); v = (View) v.getParent(); @@ -5977,26 +6015,50 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. int id = sharedMediaLayout.getClosestTab(); int[] mediaCount = sharedMediaPreloader.getLastMediaCount(); if (id == SharedMediaLayout.TAB_PHOTOVIDEO) { - if (mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] == 0 && mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] == 0) { - mediaCounterTextView.setText(LocaleController.formatPluralString("Media", mediaCount[MediaDataController.MEDIA_PHOTOVIDEO])); - } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_PHOTOS_ONLY || mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] == 0) { + if (mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] <= 0 && mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] <= 0) { + if (mediaCount[MediaDataController.MEDIA_PHOTOVIDEO] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.SharedMedia)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("Media", mediaCount[MediaDataController.MEDIA_PHOTOVIDEO])); + } + } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_PHOTOS_ONLY || mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY] <= 0) { mediaCounterTextView.setText(LocaleController.formatPluralString("Photos", mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY])); - } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_VIDEOS_ONLY || mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] == 0) { + } else if (sharedMediaLayout.getPhotosVideosTypeFilter() == SharedMediaLayout.FILTER_VIDEOS_ONLY || mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY] <= 0) { mediaCounterTextView.setText(LocaleController.formatPluralString("Videos", mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY])); } else { String str = String.format("%s, %s", LocaleController.formatPluralString("Photos", mediaCount[MediaDataController.MEDIA_PHOTOS_ONLY]), LocaleController.formatPluralString("Videos", mediaCount[MediaDataController.MEDIA_VIDEOS_ONLY])); mediaCounterTextView.setText(str); } } else if (id == SharedMediaLayout.TAB_FILES) { - mediaCounterTextView.setText(LocaleController.formatPluralString("Files", mediaCount[MediaDataController.MEDIA_FILE])); + if (mediaCount[MediaDataController.MEDIA_FILE] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.Files)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("Files", mediaCount[MediaDataController.MEDIA_FILE])); + } } else if (id == SharedMediaLayout.TAB_VOICE) { - mediaCounterTextView.setText(LocaleController.formatPluralString("Voice", mediaCount[MediaDataController.MEDIA_AUDIO])); + if (mediaCount[MediaDataController.MEDIA_AUDIO] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.Voice)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("Voice", mediaCount[MediaDataController.MEDIA_AUDIO])); + } } else if (id == SharedMediaLayout.TAB_LINKS) { - mediaCounterTextView.setText(LocaleController.formatPluralString("Links", mediaCount[MediaDataController.MEDIA_URL])); + if (mediaCount[MediaDataController.MEDIA_URL] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.SharedLinks)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("Links", mediaCount[MediaDataController.MEDIA_URL])); + } } else if (id == SharedMediaLayout.TAB_AUDIO) { - mediaCounterTextView.setText(LocaleController.formatPluralString("MusicFiles", mediaCount[MediaDataController.MEDIA_MUSIC])); + if (mediaCount[MediaDataController.MEDIA_MUSIC] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.Music)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("MusicFiles", mediaCount[MediaDataController.MEDIA_MUSIC])); + } } else if (id == SharedMediaLayout.TAB_GIF) { - mediaCounterTextView.setText(LocaleController.formatPluralString("GIFs", mediaCount[MediaDataController.MEDIA_GIF])); + if (mediaCount[MediaDataController.MEDIA_GIF] <= 0) { + mediaCounterTextView.setText(LocaleController.getString(R.string.AccDescrGIFs)); + } else { + mediaCounterTextView.setText(LocaleController.formatPluralString("GIFs", mediaCount[MediaDataController.MEDIA_GIF])); + } } else if (id == SharedMediaLayout.TAB_COMMON_GROUPS) { mediaCounterTextView.setText(LocaleController.formatPluralString("CommonGroups", userInfo.common_chats_count)); } else if (id == SharedMediaLayout.TAB_GROUPUSERS) { @@ -6092,7 +6154,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (storyView != null) { - storyView.setExpandCoords(avatarContainer2.getMeasuredWidth() - AndroidUtilities.dp(writeButtonVisible ? 111 : 40), (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight + searchTransitionOffset); + storyView.setExpandCoords(avatarContainer2.getMeasuredWidth() - AndroidUtilities.dp(40), writeButtonVisible, (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + extraHeight + searchTransitionOffset); } } @@ -6605,6 +6667,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (currentEncryptedChat != null && chat.id == currentEncryptedChat.id) { currentEncryptedChat = chat; updateListAnimated(false); + if (flagSecure != null) { + flagSecure.invalidate(); + } } } else if (id == NotificationCenter.blockedUsersDidLoad) { boolean oldValue = userBlocked; @@ -6661,6 +6726,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. currentChat = newChat; createActionBarMenu(true); } + if (flagSecure != null) { + flagSecure.invalidate(); + } if (currentChat.megagroup && (loadChannelParticipants || !byChannelUsers)) { getChannelParticipants(true); } @@ -6775,7 +6843,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (id == NotificationCenter.reloadDialogPhotos) { updateProfileData(false); - } else if (id == NotificationCenter.storiesUpdated) { + } else if (id == NotificationCenter.storiesUpdated || id == NotificationCenter.storiesReadUpdated) { if (avatarImage != null) { avatarImage.setHasStories(needInsetForStories()); } @@ -6890,6 +6958,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } } + if (flagSecure != null) { + flagSecure.attach(); + } if (getUserConfig().showSecuritySuggestions) { SecurityChecker.checkSecurityIssuesAndSave(getParentActivity(), getCurrentAccount(), false); } @@ -6904,6 +6975,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (imageUpdater != null) { imageUpdater.onPause(); } + if (flagSecure != null) { + flagSecure.detach(); + } } @Override @@ -7197,9 +7271,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. animators.add(ObjectAnimator.ofFloat(nameTextView[a], View.ALPHA, a == 0 ? 0.0f : 1.0f)); } if (storyView != null) { - storyView.setAlpha(1f); - if (dialogId > 0) { + if (getDialogId() > 0) { + storyView.setAlpha(0f); animators.add(ObjectAnimator.ofFloat(storyView, View.ALPHA, 1.0f)); + } else { + storyView.setAlpha(1f); + storyView.setFragmentTransitionProgress(0); + animators.add(ObjectAnimator.ofFloat(storyView, ProfileStoriesView.FRAGMENT_TRANSITION_PROPERTY, 1.0f)); } } if (timeItem.getTag() != null) { @@ -7268,6 +7346,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (storyView != null) { if (dialogId > 0) { animators.add(ObjectAnimator.ofFloat(storyView, View.ALPHA, 0.0f)); + } else { + animators.add(ObjectAnimator.ofFloat(storyView, ProfileStoriesView.FRAGMENT_TRANSITION_PROPERTY, 0.0f)); } } if (timeItem.getTag() != null) { @@ -8181,10 +8261,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. icon.setLayerNum(7); icon.setRoundRadius(AndroidUtilities.dp(4)); icon.setImage(mediaLocation, mediaFilter, ImageLocation.getForDocument(thumb, document), "140_140", thumbDrawable, document); - if (AnimatedEmojiDrawable.isDefaultStatusEmoji(emojiStatusDrawable[1].getDrawable())) { + if (((AnimatedEmojiDrawable) emojiStatusDrawable[1].getDrawable()).canOverrideColor()) { icon.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlueIcon), PorterDuff.Mode.SRC_IN)); - } else if (((AnimatedEmojiDrawable) emojiStatusDrawable[1].getDrawable()).canOverrideColor()) { - icon.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document); } else { premiumPreviewBottomSheet.statusStickerSet = MessageObject.getInputStickerSet(document); @@ -8235,6 +8313,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { chat = currentChat; } + if (flagSecure != null) { + flagSecure.invalidate(); + } if (isTopic) { topic = getMessagesController().getTopicsController().findTopic(chatId, topicId); @@ -9159,7 +9240,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. File src = FileLoader.getInstance(currentAccount).getPathToAttach(avatarBig, true); src.renameTo(destFile); } - getMessagesStorage().addDialogPhoto(user.id, ((TLRPC.TL_photos_photo) response).photo); + getMessagesController().getDialogPhotos(user.id).addPhotoAtStart(((TLRPC.TL_photos_photo) response).photo); ArrayList users = new ArrayList<>(); users.add(user); getMessagesStorage().putUsersAndChats(users, null, false, true); @@ -9639,7 +9720,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. break; default: case 9: - if (BuildVars.isStandaloneApp()) { + if (ApplicationLoader.isStandaloneBuild()) { abi = "direct " + Build.CPU_ABI + " " + Build.CPU_ABI2; } else { abi = "universal " + Build.CPU_ABI + " " + Build.CPU_ABI2; @@ -10746,6 +10827,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. req2.url = LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl); req2.hash = 0; getConnectionsManager().sendRequest(req2, (response2, error2) -> { + if (response2 instanceof TLRPC.TL_messages_webPage) { + TLRPC.TL_messages_webPage res = (TLRPC.TL_messages_webPage) response2; + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + response2 = res.webpage; + } if (response2 instanceof TLRPC.WebPage) { ArrayList arrayList = new ArrayList<>(); TLRPC.WebPage page = (TLRPC.WebPage) response2; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java index 71836eed4..a05cf72cd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java @@ -257,14 +257,19 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD if (duration != C.TIME_UNSET && position != C.TIME_UNSET) { progress = 1.0f - (position / (float) duration); } else { - progress = 1; + progress = 1f; } } else { - progress = 1; + progress = 1f; } } else { - long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance(currentAccount).getTimeDifference() * 1000; - progress = Math.max(0, destroyTime - msTime) / (destroyTtl * 1000.0f); + if (destroyTime == 0) { + progress = 1f; + } else { + long msTime = System.currentTimeMillis() + ConnectionsManager.getInstance(currentAccount).getTimeDifference() * 1000; + progress = Math.max(0, destroyTime - msTime) / (destroyTtl * 1000.0f); + } + } if (once) { @@ -1526,7 +1531,6 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD location =ImageLocation.getForDocument(document); } centerImage.setImage(location, null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 1); - secretDeleteTimer.setDestroyTime((long) messageObject.messageOwner.destroyTime * 1000, messageObject.messageOwner.ttl, false); } else { playerRetryPlayCount = 1; actionBar.setTitle(LocaleController.getString("DisappearingVideo", R.string.DisappearingVideo)); @@ -1544,21 +1548,11 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD isVideo = true; seekbarContainer.setVisibility(View.VISIBLE); centerImage.setImage(null, null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 2); - long destroyTime = (long) messageObject.messageOwner.destroyTime * 1000; - long currentTime = System.currentTimeMillis() + ConnectionsManager.getInstance(currentAccount).getTimeDifference() * 1000L; - long timeToDestroy = destroyTime - currentTime; - long duration = (long) (messageObject.getDuration() * 1000L); -// if (duration > timeToDestroy) { -// secretDeleteTimer.setDestroyTime(-1, -1, true); -// } else { - secretDeleteTimer.setDestroyTime((long) messageObject.messageOwner.destroyTime * 1000, messageObject.messageOwner.ttl, false); -// } } } else { actionBar.setTitle(LocaleController.getString("DisappearingPhoto", R.string.DisappearingPhoto)); TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); centerImage.setImage(ImageLocation.getForObject(sizeFull, messageObject.photoThumbsObject), null, currentThumb != null ? new BitmapDrawable(currentThumb.bitmap) : null, -1, null, messageObject, 2); - secretDeleteTimer.setDestroyTime((long) messageObject.messageOwner.destroyTime * 1000, messageObject.messageOwner.ttl, false); if (sizeFull != null) { videoWidth = sizeFull.w; @@ -1639,6 +1633,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD containerView.setLayerType(View.LAYER_TYPE_NONE, null); } containerView.invalidate(); + secretDeleteTimer.setDestroyTime(messageObject.messageOwner.destroyTimeMillis, messageObject.messageOwner.ttl, false); if (closeAfterAnimation) { closePhoto(true, true); } else { @@ -1735,6 +1730,10 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD } public void destroyPhotoViewer() { + if (onClose != null) { + onClose.run(); + onClose = null; + } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDeleted); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.updateMessageMedia); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didCreatedNewDeleteTask); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java index 7c901a7f8..7e03f09a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SelectAnimatedEmojiDialog.java @@ -29,6 +29,7 @@ import android.os.SystemClock; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; import android.util.SparseIntArray; @@ -136,6 +137,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public final static int TYPE_SET_DEFAULT_REACTION = 2; public static final int TYPE_TOPIC_ICON = 3; public static final int TYPE_AVATAR_CONSTRUCTOR = 4; + public final static int TYPE_SET_REPLY_ICON = 5; + + public boolean isBottom() { + return type == TYPE_SET_REPLY_ICON; + } private final int SPAN_COUNT_FOR_EMOJI = 8; private final int SPAN_COUNT_FOR_STICKER = 5; @@ -395,6 +401,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private int topMarginDp; DefaultItemAnimator emojiItemAnimator; + private int accentColor; protected void invalidateParent() { @@ -407,18 +414,22 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public SelectAnimatedEmojiDialog(BaseFragment baseFragment, Context context, boolean includeEmpty, Integer emojiX, int type, Theme.ResourcesProvider resourcesProvider) { this(baseFragment, context, includeEmpty, emojiX, type, true, resourcesProvider, 16); } - public SelectAnimatedEmojiDialog(BaseFragment baseFragment, Context context, boolean includeEmpty, Integer emojiX, int type, boolean shouldDrawBackground, Theme.ResourcesProvider resourcesProvider, int topPaddingDp) { + this(baseFragment, context, includeEmpty, emojiX, type, shouldDrawBackground, resourcesProvider, topPaddingDp, Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider)); + } + + public SelectAnimatedEmojiDialog(BaseFragment baseFragment, Context context, boolean includeEmpty, Integer emojiX, int type, boolean shouldDrawBackground, Theme.ResourcesProvider resourcesProvider, int topPaddingDp, int accentColor) { super(context); this.resourcesProvider = resourcesProvider; this.type = type; this.includeEmpty = includeEmpty; this.baseFragment = baseFragment; this.includeHint = MessagesController.getGlobalMainSettings().getInt("emoji" + (type == TYPE_EMOJI_STATUS ? "status" : "reaction") + "usehint", 0) < 3; + this.accentColor = accentColor; selectorPaint.setColor(Theme.getColor(Theme.key_listSelector, resourcesProvider)); - selectorAccentPaint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider), 30)); - premiumStarColorFilter = new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider), PorterDuff.Mode.SRC_IN); + selectorAccentPaint.setColor(ColorUtils.setAlphaComponent(accentColor, 30)); + premiumStarColorFilter = new PorterDuffColorFilter(accentColor, PorterDuff.Mode.SRC_IN); this.emojiX = emojiX; final Integer bubbleX = emojiX == null ? null : MathUtils.clamp(emojiX, AndroidUtilities.dp(26), AndroidUtilities.dp(340 - 48)); @@ -426,7 +437,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati setFocusableInTouchMode(true); - if (type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_SET_REPLY_ICON) { topMarginDp = topPaddingDp; setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4)); setOnTouchListener((v, e) -> { @@ -442,11 +453,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati Drawable bubble1Drawable = getResources().getDrawable(R.drawable.shadowed_bubble1).mutate(); bubble1Drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider), PorterDuff.Mode.MULTIPLY)); bubble1View.setBackground(bubble1Drawable); - addView(bubble1View, LayoutHelper.createFrame(10, 10, Gravity.TOP | Gravity.LEFT, bubbleX / AndroidUtilities.density + (bubbleRight ? -12 : 4), topMarginDp, 0, 0)); + addView(bubble1View, LayoutHelper.createFrame(10, 10, (isBottom() ? Gravity.BOTTOM : Gravity.TOP) | Gravity.LEFT, bubbleX / AndroidUtilities.density + (bubbleRight ? -12 : 4), (isBottom() ? 0 : topMarginDp), 0, (isBottom() ? topMarginDp : 0))); } backgroundView = new View(context) { - @Override protected void onDraw(Canvas canvas) { if (!drawBackground) { @@ -480,12 +490,21 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati float px = (bubbleX == null ? getWidth() / 2f : bubbleX) + AndroidUtilities.dp(20); float w = getWidth() - getPaddingLeft() - getPaddingRight(); float h = getHeight() - getPaddingBottom() - getPaddingTop(); - AndroidUtilities.rectTmp.set( - getPaddingLeft() + (px - px * scaleX), + if (isBottom()) { + AndroidUtilities.rectTmp.set( + (getPaddingLeft() + (px - px * scaleX)), + (getPaddingTop() + h * (1f - scaleY)), + (getPaddingLeft() + px + (w - px) * scaleX), + (getPaddingTop() + h) + ); + } else { + AndroidUtilities.rectTmp.set( + (getPaddingLeft() + (px - px * scaleX)), getPaddingTop(), - getPaddingLeft() + px + (w - px) * scaleX, - getPaddingTop() + h * scaleY - ); + (getPaddingLeft() + px + (w - px) * scaleX), + (getPaddingTop() + h * scaleY) + ); + } pathApi20.rewind(); pathApi20.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(12), AndroidUtilities.dp(12), Path.Direction.CW); canvas.drawPath(pathApi20, paintApi20); @@ -507,12 +526,21 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati float px = (bubbleX == null ? view.getWidth() / 2f : bubbleX) + AndroidUtilities.dp(20); float w = view.getWidth() - view.getPaddingLeft() - view.getPaddingRight(); float h = view.getHeight() - view.getPaddingBottom() - view.getPaddingTop(); - rect.set( + if (isBottom()) { + rect.set( + (int) (view.getPaddingLeft() + (px - px * scaleX)), + (int) (view.getPaddingTop() + h * (1f - scaleY) + dp(topMarginDp) * (1f - scaleY)), + (int) (view.getPaddingLeft() + px + (w - px) * scaleX), + (int) (view.getPaddingTop() + h + dp(topMarginDp) * (1f - scaleY)) + ); + } else { + rect.set( (int) (view.getPaddingLeft() + (px - px * scaleX)), view.getPaddingTop(), (int) (view.getPaddingLeft() + px + (w - px) * scaleX), (int) (view.getPaddingTop() + h * scaleY) - ); + ); + } outline.setRoundRect(rect, dp(12)); } }); @@ -522,16 +550,15 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } } - if (type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION) { + if (type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION || type == TYPE_SET_REPLY_ICON) { contentView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); } contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION ? 6 + topMarginDp : 0, 0, 0)); + addView(contentView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, type == TYPE_EMOJI_STATUS || type == TYPE_SET_DEFAULT_REACTION ? 6 + topMarginDp : 0, 0, isBottom() ? 6 + topMarginDp : 0)); if (bubbleX != null) { bubble2View = new View(context) { - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -542,10 +569,10 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati Drawable bubble2Drawable = getResources().getDrawable(R.drawable.shadowed_bubble2_half); bubble2Drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider), PorterDuff.Mode.MULTIPLY)); bubble2View.setBackground(bubble2Drawable); - addView(bubble2View, LayoutHelper.createFrame(17, 9, Gravity.TOP | Gravity.LEFT, bubbleX / AndroidUtilities.density + (bubbleRight ? -25 : 10), 6 + 8 - 9 + topMarginDp, 0, 0)); + addView(bubble2View, LayoutHelper.createFrame(17, 9, (isBottom() ? Gravity.BOTTOM : Gravity.TOP) | Gravity.LEFT, bubbleX / AndroidUtilities.density + (bubbleRight ? -25 : 10), isBottom() ? 0 : 5 + topMarginDp, 0, isBottom() ? 5 + topMarginDp + 9 : 0)); } - boolean showSettings = baseFragment != null && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR && shouldDrawBackground; + boolean showSettings = baseFragment != null && type != TYPE_TOPIC_ICON && type != TYPE_SET_REPLY_ICON && type != TYPE_AVATAR_CONSTRUCTOR && shouldDrawBackground; for (int i = 0; i < 2; i++) { EmojiTabsStrip emojiTabs = new EmojiTabsStrip(context, resourcesProvider, true, false, true, type, showSettings ? () -> { search(null, false, false); @@ -554,7 +581,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (dismiss != null) { dismiss.run(); } - } : null) { + } : null, accentColor) { @Override protected ColorFilter getEmojiColorFilter() { @@ -625,7 +652,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati cachedEmojiTabs[1].setVisibility(View.GONE); emojiTabsShadow = new View(context) { - @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -676,7 +702,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati emojiGridView.setItemAnimator(emojiItemAnimator); emojiGridView.setPadding(dp(5), dp(2), dp(5), dp(2 + 36)); adapter = new Adapter(); -// adapter.setHasStableIds(true); emojiGridView.setAdapter(adapter); emojiGridView.setLayoutManager(layoutManager = new GridLayoutManager(context, SPAN_COUNT) { @@ -1173,11 +1198,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati searchBox.setVisibility(View.VISIBLE); searchBox.setTranslationY(first.getY()); } else { -// searchBox.setVisibility(View.INVISIBLE); searchBox.setTranslationY(-AndroidUtilities.dp(52)); } } else { -// searchBox.setVisibility(View.INVISIBLE); searchBox.setTranslationY(-AndroidUtilities.dp(52)); } } @@ -1188,9 +1211,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private Drawable getPremiumStar() { if (premiumStar == null) { -// premiumStar = PremiumGradient.getInstance().premiumStarMenuDrawableGray; - premiumStar = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_settings_premium).mutate(); -// premiumStar.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_verifiedBackground, resourcesProvider), PorterDuff.Mode.MULTIPLY)); + if (type == TYPE_SET_REPLY_ICON) { + premiumStar = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_filled_blocked).mutate(); + } else { + premiumStar = ApplicationLoader.applicationContext.getResources().getDrawable(R.drawable.msg_settings_premium).mutate(); + } premiumStar.setColorFilter(premiumStarColorFilter); } return premiumStar; @@ -1207,10 +1232,13 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati private Rect emojiSelectRect; private OvershootInterpolator overshootInterpolator = new OvershootInterpolator(2f); + protected float getScrimDrawableTranslationY() { + return 0; + } + @Override protected void dispatchDraw(Canvas canvas) { if (scrimDrawable != null && emojiX != null) { -// Rect bounds = (scrimDrawableBounds == null ? scrimDrawableBounds = scrimDrawable.getBounds() : scrimDrawableBounds); Rect bounds = scrimDrawable.getBounds(); float scale = scrimDrawableParent == null ? 1f : scrimDrawableParent.getScaleY(); int wasAlpha = 255; @@ -1224,17 +1252,18 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (drawableToBounds == null) { drawableToBounds = new Rect(); } - drawableToBounds.set( - (int) (bounds.centerX() - bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), - (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? (bounds.height() * .81f + 1) : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp) - bounds.height() * scale), - (int) (bounds.centerX() + bounds.width() / 2f * scale - bounds.centerX() + emojiX + (scale > 1f && scale < 1.5f ? 2 : 0)), - (int) ((h - (h - bounds.bottom)) * scale - (scale > 1.5f ? bounds.height() * .81f + 1 : 0) - bounds.top - bounds.height() / 2f + AndroidUtilities.dp(topMarginDp)) - ); + final float xmagic = (scale > 1f && scale < 1.5f ? 2 : 0); + final float ymagic = -(scale > 1.5f ? (bounds.height() * .81f + 1) : 0); + final float cx = emojiX + xmagic; + final float cy = bounds.centerY() * (scale - 1) + ymagic + (!isBottom() ? dp(topMarginDp) : getMeasuredHeight() - dp(topMarginDp) / 2f) + getScrimDrawableTranslationY(); + final float sw = bounds.width() * scale / 2f; + final float sh = bounds.height() * scale / 2f; + drawableToBounds.set((int) (cx - sw), (int) (cy - sh), (int) (cx + sw), (int) (cy + sh)); scrimDrawable.setBounds( - drawableToBounds.left, - drawableToBounds.top, - (int) (drawableToBounds.left + drawableToBounds.width() / scale), - (int) (drawableToBounds.top + drawableToBounds.height() / scale) + drawableToBounds.left, + drawableToBounds.top, + (int) (drawableToBounds.left + drawableToBounds.width() / scale), + (int) (drawableToBounds.top + drawableToBounds.height() / scale) ); canvas.scale(scale, scale, drawableToBounds.left, drawableToBounds.top); scrimDrawable.draw(canvas); @@ -1243,12 +1272,12 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati canvas.restore(); } super.dispatchDraw(canvas); - if (emojiSelectView != null && emojiSelectRect != null && drawableToBounds != null && emojiSelectView.drawable != null) { + if (emojiSelectView != null && emojiSelectRect != null && emojiSelectView.drawable != null) { canvas.save(); canvas.translate(0, -getTranslationY()); emojiSelectView.drawable.setAlpha((int) (255 * emojiSelectAlpha)); emojiSelectView.drawable.setBounds(emojiSelectRect); - emojiSelectView.drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider), scrimColor, 1f - scrimAlpha), PorterDuff.Mode.SRC_IN)); + emojiSelectView.drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(accentColor, scrimColor, 1f - scrimAlpha), PorterDuff.Mode.SRC_IN)); emojiSelectView.drawable.draw(canvas); canvas.restore(); } @@ -1265,16 +1294,18 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati view.notDraw = true; final Rect from = new Rect(); from.set( - contentView.getLeft() + emojiGridView.getLeft() + view.getLeft(), - contentView.getTop() + emojiGridView.getTop() + view.getTop(), - contentView.getLeft() + emojiGridView.getLeft() + view.getRight(), - contentView.getTop() + emojiGridView.getTop() + view.getBottom() + contentView.getLeft() + emojiGridView.getLeft() + view.getLeft(), + contentView.getTop() + emojiGridView.getTop() + view.getTop(), + contentView.getLeft() + emojiGridView.getLeft() + view.getRight(), + contentView.getTop() + emojiGridView.getTop() + view.getBottom() ); - final AnimatedEmojiDrawable statusDrawable = - view.drawable instanceof AnimatedEmojiDrawable ? - AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_EMOJI_STATUS, ((AnimatedEmojiDrawable) view.drawable).getDocumentId()) : - null; + final AnimatedEmojiDrawable statusDrawable; + if (view.drawable instanceof AnimatedEmojiDrawable) { + statusDrawable = AnimatedEmojiDrawable.make(currentAccount, AnimatedEmojiDrawable.CACHE_TYPE_EMOJI_STATUS, ((AnimatedEmojiDrawable) view.drawable).getDocumentId()); + } else { + statusDrawable = null; + } emojiSelectView = view; emojiSelectRect = new Rect(); @@ -1300,7 +1331,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati done[0] = true; onDone.run(); if (statusDrawable != null && scrimDrawable != null) { -// scrimDrawable.set(statusDrawable, false); scrimDrawable.play(); } } @@ -1341,13 +1371,11 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati scrollHelper.setScrollDirection(layoutManager.findFirstVisibleItemPosition() < p ? RecyclerAnimationScrollHelper.SCROLL_DIRECTION_DOWN : RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UP); scrollHelper.scrollToPosition(p, offset, false, true); } else { -// ignoreStickersScroll = true; LinearSmoothScrollerCustom linearSmoothScroller = new LinearSmoothScrollerCustom(emojiGridView.getContext(), LinearSmoothScrollerCustom.POSITION_TOP) { @Override public void onEnd() { smoothScrolling = false; } - @Override protected void onStart() { smoothScrolling = true; @@ -1421,9 +1449,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati .setDuration(160) .start(); if (gridSearch && liftUp) { - emojiSearchGridView.setPadding(dp(5), dp(52 + 2), dp(5), dp(2)); + emojiSearchGridView.setPadding(dp(5), dp(54), dp(5), dp(2)); } else { - emojiSearchGridView.setPadding(dp(5), dp(52 + 2), dp(5), dp(36 + 2)); + emojiSearchGridView.setPadding(dp(5), dp(54), dp(5), dp(38)); } checkScroll(); } @@ -1630,16 +1658,18 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati String emoticon; for (int i = 0; i < stickerSets.size(); ++i) { - if (stickerSets.get(i).documents != null) { - ArrayList documents = stickerSets.get(i).documents; - if (documents != null) { - for (int j = 0; j < documents.size(); ++j) { - emoticon = MessageObject.findAnimatedEmojiEmoticon(documents.get(j), null); - long id = documents.get(j).id; - if (emoticon != null && !documentIds.contains(id) && query.contains(emoticon.toLowerCase())) { - documentIds.add(id); - } - } + if (stickerSets.get(i).documents == null) { + continue; + } + ArrayList documents = stickerSets.get(i).documents; + if (documents == null) { + continue; + } + for (int j = 0; j < documents.size(); ++j) { + emoticon = MessageObject.findAnimatedEmojiEmoticon(documents.get(j), null); + long id = documents.get(j).id; + if (emoticon != null && !documentIds.contains(id) && query.contains(emoticon.toLowerCase())) { + documentIds.add(id); } } } @@ -1649,13 +1679,14 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (featuredStickerSets.get(i) instanceof TLRPC.TL_stickerSetFullCovered && ((TLRPC.TL_stickerSetFullCovered) featuredStickerSets.get(i)).keywords != null) { ArrayList documents = ((TLRPC.TL_stickerSetFullCovered) featuredStickerSets.get(i)).documents; - if (documents != null) { - for (int j = 0; j < documents.size(); ++j) { - emoticon = MessageObject.findAnimatedEmojiEmoticon(documents.get(j), null); - long id = documents.get(j).id; - if (emoticon != null && !documentIds.contains(id) && query.contains(emoticon)) { - documentIds.add(id); - } + if (documents == null) { + continue; + } + for (int j = 0; j < documents.size(); ++j) { + emoticon = MessageObject.findAnimatedEmojiEmoticon(documents.get(j), null); + final long id = documents.get(j).id; + if (emoticon != null && !documentIds.contains(id) && query.contains(emoticon)) { + documentIds.add(id); } } } @@ -2175,7 +2206,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati int index = positionToSection.get(position); if (index >= 0) { EmojiView.EmojiPack pack = packs.get(index); - header.setText(pack.set.title, !pack.free && !UserConfig.getInstance(currentAccount).isPremium() && type != TYPE_AVATAR_CONSTRUCTOR); + header.setText(pack.set.title, !pack.free && !UserConfig.getInstance(currentAccount).isPremium() && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON); } else { header.setText(null, false); } @@ -2230,11 +2261,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati emojiGridView.animatedEmojiDrawables.put(imageView.span.getDocumentId(), (AnimatedEmojiDrawable) drawable); } imageView.setDrawable(drawable); - -// if (!UserConfig.getInstance(currentAccount).isPremium() && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_TOPIC_ICON) { -// imageView.createPremiumLockView(); -// imageView.premiumLockIconView.setVisibility(View.VISIBLE); -// } } } else if (viewType == VIEW_TYPE_EXPAND) { EmojiPackExpand button = (EmojiPackExpand) holder.itemView; @@ -2295,23 +2321,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } else if (viewType == VIEW_TYPE_SEARCH) { } else if (viewType == VIEW_TYPE_STICKER) { - final int maxlen = SPAN_COUNT_FOR_EMOJI * EXPAND_MAX_LINES; - for (int i = 0; i < positionToSection.size(); ++i) { - int startPosition = positionToSection.keyAt(i); - int index = i - (defaultStatuses.isEmpty() ? 0 : 1); - EmojiView.EmojiPack pack = index >= 0 ? packs.get(index) : null; - if (pack == null) { - continue; - } - int count = pack.expanded ? pack.documents.size() : Math.min(pack.documents.size(), maxlen); - if (position > startPosition && position <= startPosition + 1 + count) { - TLRPC.Document document = pack.documents.get(position - startPosition - 1); - if (document != null) { -// imageView.span = new AnimatedEmojiSpan(document, null); -// imageView.document = document; - } - } - } + } else { ImageViewEmoji imageView = (ImageViewEmoji) holder.itemView; imageView.empty = false; @@ -3027,14 +3037,29 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati stickerSets.clear(); recentStickers.clear(); - if (!installedEmojipacks.isEmpty() || type == TYPE_AVATAR_CONSTRUCTOR) { + if ((!installedEmojipacks.isEmpty() || type == TYPE_AVATAR_CONSTRUCTOR) && type != TYPE_SET_REPLY_ICON) { searchRow = totalCount++; rowHashCodes.add(9L); } else { searchRow = -1; } - if (type == TYPE_AVATAR_CONSTRUCTOR) { + if (type == TYPE_SET_REPLY_ICON) { + if (includeEmpty) { + totalCount++; + rowHashCodes.add(2L); + } + TLRPC.TL_emojiList emojiList = MediaDataController.getInstance(currentAccount).replyIconsDefault; + if (emojiList != null && emojiList.document_id != null && !emojiList.document_id.isEmpty()) { + for (int i = 0; i < emojiList.document_id.size(); ++i) { + recent.add(new AnimatedEmojiSpan(emojiList.document_id.get(i), null)); + } + for (int i = 0; i < recent.size(); ++i) { + rowHashCodes.add(43223L + 13L * recent.get(i).getDocumentId()); + totalCount++; + } + } + } else if (type == TYPE_AVATAR_CONSTRUCTOR) { if (showStickers) { recentStickers.addAll(MediaDataController.getInstance(currentAccount).getRecentStickersNoCopy(MediaDataController.TYPE_IMAGE)); for (int i = 0; i < recentStickers.size(); ++i) { @@ -3089,7 +3114,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } - if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR) { + if (includeHint && type != TYPE_SET_DEFAULT_REACTION && type != TYPE_TOPIC_ICON && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON) { longtapHintRow = totalCount++; rowHashCodes.add(6L); } @@ -3221,7 +3246,13 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (installedEmojipacks != null) { for (int i = 0, j = 0; i < installedEmojipacks.size(); ++i) { TLRPC.TL_messages_stickerSet set = installedEmojipacks.get(i); - if (set != null && set.set != null && (set.set.emojis || showStickers) && !installedEmojiSets.contains(set.set.id)) { + if (set == null || set.set == null) { + continue; + } + if (type == TYPE_SET_REPLY_ICON && !MessageObject.isTextColorSet(set)) { + continue; + } + if ((set.set.emojis || showStickers) && !installedEmojiSets.contains(set.set.id)) { positionToSection.put(totalCount, packs.size()); sectionToPosition.put(packs.size(), totalCount); totalCount++; @@ -3273,43 +3304,49 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati isPremiumPack = MessageObject.isPremiumEmojiPack(set1); } - if (documents != null) { - positionToSection.put(totalCount, packs.size()); - sectionToPosition.put(packs.size(), totalCount); - totalCount++; - rowHashCodes.add(9211 + 13L * set.id); - - EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); - pack.installed = installedEmojiSets.contains(set.id); - pack.featured = true; - pack.free = !isPremiumPack; - pack.set = set; - pack.documents = documents; - pack.index = packs.size(); - pack.expanded = expandedEmojiSets.contains(pack.set.id); - - if (pack.documents.size() > maxlen && !pack.expanded) { - totalCount += maxlen; - for (int k = 0; k < maxlen - 1; ++k) { - rowHashCodes.add(3212 + 13L * pack.documents.get(k).id); - } - rowHashCodes.add(-5531 + 13L * set.id + 169L * (pack.documents.size() - maxlen + 1)); - positionToExpand.put(totalCount - 1, packs.size()); - } else { - totalCount += pack.documents.size(); - for (int k = 0; k < pack.documents.size(); ++k) { - rowHashCodes.add(3212 + 13L * pack.documents.get(k).id); - } - } - - if (!pack.installed && type != TYPE_AVATAR_CONSTRUCTOR) { - positionToButton.put(totalCount, packs.size()); - totalCount++; - rowHashCodes.add(3321 + 13L * set.id); - } - - packs.add(pack); + if (documents == null) { + continue; } + + if (type == TYPE_SET_REPLY_ICON && (documents.isEmpty() || !MessageObject.isTextColorEmoji(documents.get(0)))) { + continue; + } + + positionToSection.put(totalCount, packs.size()); + sectionToPosition.put(packs.size(), totalCount); + totalCount++; + rowHashCodes.add(9211 + 13L * set.id); + + EmojiView.EmojiPack pack = new EmojiView.EmojiPack(); + pack.installed = installedEmojiSets.contains(set.id); + pack.featured = true; + pack.free = !isPremiumPack; + pack.set = set; + pack.documents = documents; + pack.index = packs.size(); + pack.expanded = expandedEmojiSets.contains(pack.set.id); + + if (pack.documents.size() > maxlen && !pack.expanded) { + totalCount += maxlen; + for (int k = 0; k < maxlen - 1; ++k) { + rowHashCodes.add(3212 + 13L * pack.documents.get(k).id); + } + rowHashCodes.add(-5531 + 13L * set.id + 169L * (pack.documents.size() - maxlen + 1)); + positionToExpand.put(totalCount - 1, packs.size()); + } else { + totalCount += pack.documents.size(); + for (int k = 0; k < pack.documents.size(); ++k) { + rowHashCodes.add(3212 + 13L * pack.documents.get(k).id); + } + } + + if (!pack.installed && type != TYPE_AVATAR_CONSTRUCTOR && type != TYPE_SET_REPLY_ICON) { + positionToButton.put(totalCount, packs.size()); + totalCount++; + rowHashCodes.add(3321 + 13L * set.id); + } + + packs.add(pack); } } @@ -3431,6 +3468,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } private int getCacheType() { + if (type == TYPE_SET_REPLY_ICON) { + return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC; + } if (type == TYPE_TOPIC_ICON || type == TYPE_AVATAR_CONSTRUCTOR) { return AnimatedEmojiDrawable.CACHE_TYPE_ALERT_PREVIEW_STATIC; } @@ -3439,7 +3479,6 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati public class EmojiListView extends RecyclerListView { - public EmojiListView(Context context) { super(context); @@ -3469,7 +3508,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati @Override protected boolean canHighlightChildAt(View child, float x, float y) { if (child instanceof ImageViewEmoji && (((ImageViewEmoji) child).empty || ((ImageViewEmoji) child).drawable instanceof AnimatedEmojiDrawable && ((AnimatedEmojiDrawable) ((ImageViewEmoji) child).drawable).canOverrideColor())) { - setSelectorDrawableColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider), 30)); + setSelectorDrawableColor(ColorUtils.setAlphaComponent(accentColor, 30)); } else { setSelectorDrawableColor(Theme.getColor(Theme.key_listSelector, resourcesProvider)); } @@ -3738,7 +3777,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati ImageReceiver imageReceiver; if (imageView.empty) { Drawable drawable = getPremiumStar(); - float scale = 1f; + float scale = type == TYPE_SET_REPLY_ICON ? 1.15f : 1f; if (imageView.pressedProgress != 0 || imageView.selected) { scale *= 0.8f + 0.2f * (1f - (imageView.selected ? .7f : imageView.pressedProgress)); } @@ -3901,6 +3940,9 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati Drawable drawable = null; if (imageView.empty) { drawable = getPremiumStar(); + if (type == TYPE_SET_REPLY_ICON) { + AndroidUtilities.rectTmp2.inset((int) (-AndroidUtilities.rectTmp2.width() * .15f), (int) (-AndroidUtilities.rectTmp2.height() * .15f)); + } drawable.setBounds(AndroidUtilities.rectTmp2); drawable.setAlpha(255); } else if (!imageView.isDefaultReaction && !imageView.isStaticIcon) { @@ -4132,8 +4174,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati if (animated) { showAnimator = ValueAnimator.ofFloat(0f, 1f); showAnimator.addUpdateListener(anm -> { - final float t = (float) anm.getAnimatedValue(); - updateShow(t); + updateShow((float) anm.getAnimatedValue()); }); showAnimator.addListener(new AnimatorListenerAdapter() { @@ -4174,7 +4215,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } }); - if (isFirstOpen) { + if (isFirstOpen && type != TYPE_SET_REPLY_ICON) { isFirstOpen = false; AnimatedEmojiDrawable.getDocumentFetcher(currentAccount).setUiDbCallback(() -> { HwEmojis.enableHw(); @@ -4554,7 +4595,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati bubble1t = CubicBezierInterpolator.EASE_OUT.getInterpolation(bubble1t); bubble1View.setAlpha(bubble1t); bubble1View.setScaleX(bubble1t); - bubble1View.setScaleY(bubble1t); + bubble1View.setScaleY(bubble1t * (isBottom() ? -1 : 1)); } if (bubble2View != null) { @@ -4562,7 +4603,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati // bubble2t = CubicBezierInterpolator.EASE_OUT.getInterpolation(bubble2t); bubble2View.setAlpha(bubble2t); bubble2View.setScaleX(bubble2t); - bubble2View.setScaleY(bubble2t); + bubble2View.setScaleY(bubble2t * (isBottom() ? -1 : 1)); } float containerx = MathUtils.clamp((t * showDuration - 40) / 700, 0, 1); @@ -4614,8 +4655,12 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati } else if (t == 1) { child.setLayerType(LAYER_TYPE_NONE, null); } - float ccx = child.getLeft() + child.getWidth() / 2f, ccy = child.getTop() + child.getHeight() / 2f; - float distance = (float) Math.sqrt((ccx - px) * (ccx - px) + ccy * ccy * .4f); + final float ccx = child.getLeft() + child.getWidth() / 2f - px; + float ccy = child.getTop() + child.getHeight() / 2f; + if (isBottom()) { + ccy = getMeasuredHeight() - ccy; + } + final float distance = (float) Math.sqrt(ccx * ccx + ccy * ccy * .4f); float scale = AndroidUtilities.cascade(containeritemst, distance, fullr, child.getHeight() * 1.75f); if (Float.isNaN(scale)) { scale = 0; @@ -4627,8 +4672,12 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati View child = emojiGridView.getChildAt(i); if (child instanceof ImageViewEmoji) { ImageViewEmoji imageViewEmoji = (ImageViewEmoji) child; - float cx = child.getLeft() + child.getWidth() / 2f, cy = child.getTop() + child.getHeight() / 2f; - float distance = (float) Math.sqrt((cx - px) * (cx - px) + cy * cy * .2f); + float cx = child.getLeft() + child.getWidth() / 2f - px; + float cy = child.getTop() + child.getHeight() / 2f; + if (isBottom()) { + cy = getMeasuredHeight() - cy; + } + float distance = (float) Math.sqrt(cx * cx + cy * cy * .2f); float scale = AndroidUtilities.cascade(containeritemst, distance, fullr, child.getHeight() * 1.75f); if (Float.isNaN(scale)) { scale = 0; @@ -4872,7 +4921,7 @@ public class SelectAnimatedEmojiDialog extends FrameLayout implements Notificati Drawable drawable = imageViewEmoji.drawable; if (drawable != null) { if (changeToScrimColor) { - drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(scrimColor, Theme.getColor(Theme.key_windowBackgroundWhiteBlueIcon, resourcesProvider), showT), PorterDuff.Mode.MULTIPLY)); + drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(scrimColor, accentColor, showT), PorterDuff.Mode.MULTIPLY)); } else { drawable.setColorFilter(premiumStarColorFilter); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 7900dce8c..21786c03f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -647,6 +647,10 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter listAdapter.notifyDataSetChanged(); } + if (delegate != null) { + delegate.sessionsLoaded(); + } + if (repeatLoad > 0) { repeatLoad--; if (repeatLoad > 0) { @@ -1287,7 +1291,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter if (sessions.size() == 0 && loading) { return 0; } - return sessions.size() + 1; + return sessions.size() + (currentType == TYPE_DEVICES ? 1 : 0); } public void setDelegate(Delegate delegate) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index fed8ca45c..8938e2bc0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -50,6 +50,7 @@ import org.telegram.messenger.UserConfig; 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.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; @@ -83,14 +84,15 @@ import org.telegram.ui.Components.ChatAvatarContainer; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.FlatCheckBox; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.boosts.BoostDialogs; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.ViewPagerFixed; -import org.telegram.ui.Components.voip.VoIPHelper; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Locale; public class StatisticActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { @@ -145,7 +147,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente private AlertDialog[] progressDialog = new AlertDialog[1]; private ViewPagerFixed viewPagerFixed; - private ChannelBoostLayout boosLayout; + private ChannelBoostLayout boostLayout; private boolean onlyBoostsStat; public StatisticActivity(Bundle args) { @@ -177,6 +179,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.messagesDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.boostByChannelCreated); if (chat != null) { loadStatistic(); } else { @@ -353,6 +356,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente @Override public void onFragmentDestroy() { + getNotificationCenter().removeObserver(this, NotificationCenter.boostByChannelCreated); getNotificationCenter().removeObserver(this, NotificationCenter.messagesDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoDidLoad); if (progressDialog[0] != null) { @@ -365,7 +369,24 @@ public class StatisticActivity extends BaseFragment implements NotificationCente @SuppressWarnings("unchecked") @Override public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.messagesDidLoad) { + if (id == NotificationCenter.boostByChannelCreated) { + TLRPC.Chat chat = (TLRPC.Chat) args[0]; + boolean isGiveaway = (boolean) args[1]; + if (isGiveaway) { + List fragmentStack = getParentLayout().getFragmentStack(); + BaseFragment profileFragment = fragmentStack.size() >= 2 ? fragmentStack.get(fragmentStack.size() - 2) : null; + BaseFragment chatFragment = fragmentStack.size() >= 3 ? fragmentStack.get(fragmentStack.size() - 3) : null; + if (profileFragment instanceof ProfileActivity) { + getParentLayout().removeFragmentFromStack(profileFragment); + } + finishFragment(); + if (chatFragment instanceof ChatActivity) { + BoostDialogs.showBulletin(chatFragment, chat, true); + } + } else { + BoostDialogs.showBulletin(this, chat, false); + } + } else if (id == NotificationCenter.messagesDidLoad) { int guid = (Integer) args[10]; if (guid == classGuid) { ArrayList messArr = (ArrayList) args[2]; @@ -457,7 +478,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente }); FrameLayout statisticLayout = new FrameLayout(context); if (isChannel) { - boosLayout = new ChannelBoostLayout(StatisticActivity.this, -chatId, getResourceProvider()); + boostLayout = new ChannelBoostLayout(StatisticActivity.this, -chatId, getResourceProvider()); } boolean showTabs = isChannel && !onlyBoostsStat; if (showTabs && startFromBoosts) { @@ -478,9 +499,9 @@ public class StatisticActivity extends BaseFragment implements NotificationCente @Override public View createView(int viewType) { if (onlyBoostsStat) { - return boosLayout; + return boostLayout; } - return viewType == 0 ? statisticLayout : boosLayout; + return viewType == 0 ? statisticLayout : boostLayout; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java index d45995789..327871467 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DarkThemeResourceProvider.java @@ -114,7 +114,8 @@ public class DarkThemeResourceProvider implements Theme.ResourcesProvider { sparseIntArray.put(Theme.key_switchTrack, 0xFF636363); sparseIntArray.put(Theme.key_switchTrackChecked, 0xFF1A9CFF); - sparseIntArray.put(Theme.key_dialogRoundCheckBox, -10177041); + sparseIntArray.put(Theme.key_dialogRoundCheckBox, 0xFF1A9CFF); + sparseIntArray.put(Theme.key_dialogRadioBackgroundChecked, 0xFF1A9CFF); sparseIntArray.put(Theme.key_dialogTextBlue2, 0xFF1A9CFF); sparseIntArray.put(Theme.key_color_red, -832444); sparseIntArray.put(Theme.key_checkboxDisabled, 0xff626262); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java index 0272dd737..52c8c3e24 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/DialogStoriesCell.java @@ -48,6 +48,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; @@ -332,7 +333,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter if (!storiesController.hasStories(cell.dialogId) && !storiesController.hasUploadingStories(cell.dialogId)) { return; } - TLRPC.PeerStories userStories = storiesController.getStories(cell.dialogId); + TL_stories.PeerStories userStories = storiesController.getStories(cell.dialogId); long startFromDialogId = cell.dialogId; if (globalCancelable != null) { globalCancelable.cancel(); @@ -432,7 +433,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter items.add(new Item(UserConfig.getInstance(currentAccount).getClientUserId())); } - ArrayList allStories = type == TYPE_ARCHIVE ? storiesController.getHiddenList() : storiesController.getDialogListStories(); + ArrayList allStories = type == TYPE_ARCHIVE ? storiesController.getHiddenList() : storiesController.getDialogListStories(); for (int i = 0; i < allStories.size(); i++) { long dialogId = DialogObject.getPeerDialogId(allStories.get(i).peer); if (dialogId != UserConfig.getInstance(currentAccount).getClientUserId() && !FakePasscodeUtils.isHidePeer(allStories.get(i).peer, currentAccount)) { @@ -947,7 +948,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter public void onResume() { storiesController.checkExpiredStories(); for (int i = 0; i < items.size(); i++) { - TLRPC.PeerStories stories = storiesController.getStories(items.get(i).dialogId); + TL_stories.PeerStories stories = storiesController.getStories(items.get(i).dialogId); if (stories != null) { storiesController.preloadUserStories(stories); } @@ -1345,7 +1346,7 @@ public class DialogStoriesCell extends FrameLayout implements NotificationCenter radialProgress.setDiff(0); Paint paint = closeFriends ? StoriesUtilities.getCloseFriendsPaint(avatarImage) : - StoriesUtilities.getActiveCirclePaint(avatarImage, true); + StoriesUtilities.getUnreadCirclePaint(avatarImage, true); paint.setAlpha(255); radialProgress.setPaint(paint); radialProgress.setProgressRect( diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull.java index 80cc43583..deddc5b95 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull.java @@ -1,10 +1,10 @@ package org.telegram.ui.Stories; -import org.telegram.messenger.DialogObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; public class MessageMediaStoryFull extends TLRPC.TL_messageMediaStory { @@ -13,7 +13,7 @@ public class MessageMediaStoryFull extends TLRPC.TL_messageMediaStory { public void readParams(AbstractSerializedData stream, boolean exception) { user_id = stream.readInt64(exception); id = stream.readInt32(exception); - storyItem = TLRPC.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); via_mention = stream.readBool(exception); peer = MessagesController.getInstance(UserConfig.selectedAccount).getPeer(user_id); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull_old.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull_old.java index 4921a7762..25659bcc5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull_old.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/MessageMediaStoryFull_old.java @@ -2,6 +2,7 @@ package org.telegram.ui.Stories; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; public class MessageMediaStoryFull_old extends TLRPC.TL_messageMediaStory { @@ -14,7 +15,7 @@ public class MessageMediaStoryFull_old extends TLRPC.TL_messageMediaStory { public void readParams(AbstractSerializedData stream, boolean exception) { user_id = stream.readInt64(exception); id = stream.readInt32(exception); - storyItem = TLRPC.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); + storyItem = TL_stories.StoryItem.TLdeserialize(stream, stream.readInt32(exception), exception); } public void serializeToStream(AbstractSerializedData stream) { 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 383e6310c..b215313a0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/PeerStoriesView.java @@ -1,7 +1,6 @@ package org.telegram.ui.Stories; import static org.telegram.messenger.AndroidUtilities.dp; -import static org.telegram.ui.Stories.StoryMediaAreasView.getMediaAreasFor; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -34,6 +33,7 @@ import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -59,6 +59,7 @@ import androidx.recyclerview.widget.ChatListItemAnimator; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; @@ -89,6 +90,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; @@ -227,8 +229,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica ActionBarMenuSubItem editStoryItem; CustomPopupMenu popupMenu; - TLRPC.PeerStories userStories; - final ArrayList storyItems; + TL_stories.PeerStories userStories; + final ArrayList storyItems; final ArrayList uploadingStories; final SharedResources sharedResources; RoundRectOutlineProvider outlineProvider; @@ -294,8 +296,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica final VideoPlayerSharedScope playerSharedScope; final AnimationNotificationsLocker notificationsLocker; private AnimatedFloat progressToHideInterface = new AnimatedFloat(this); + private AnimatedFloat linesAlpha = new AnimatedFloat(this); private float prevToHideProgress; - private long videoDuration; + public long videoDuration; private boolean allowShare, allowShareLink; public boolean forceUpdateOffsets; private HintView mediaBanTooltip; @@ -517,6 +520,15 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } else { canvas.drawColor(ColorUtils.blendARGB(Color.BLACK, Color.WHITE, 0.2f)); } + if (storyCaptionView.getAlpha() > 0) { + if (storyCaptionView.getAlpha() == 1f) { + canvas.save(); + } else { + canvas.saveLayerAlpha(0, 0, storyCaptionView.getMeasuredWidth(), storyCaptionView.getMeasuredHeight(), (int) (255 * storyCaptionView.getAlpha()), Canvas.ALL_SAVE_FLAG); + } + storyAreasView.draw(canvas); + canvas.restore(); + } if (!lastNoThumb && imageReceiver.hasNotThumb()) { lastNoThumb = true; @@ -524,8 +536,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } float hideInterfaceAlpha = getHideInterfaceAlpha(); - - sharedResources.topOverlayGradient.setAlpha((int) (255 * hideInterfaceAlpha)); + sharedResources.topOverlayGradient.setAlpha(0xFF); sharedResources.topOverlayGradient.draw(canvas); float progressToFullBlackout = 0; if ((isSelf || !BIG_SCREEN) || storyCaptionView.getVisibility() == View.VISIBLE) { @@ -622,6 +633,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == storyAreasView) { + return true; + } if (splitDrawing) { if (Bulletin.getVisibleBulletin() != null && child == Bulletin.getVisibleBulletin().getLayout()) { if (drawOverlayed) { @@ -670,7 +684,12 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica timeProgress = Utilities.clamp(currentImageTime / (float) IMAGE_LIVE_TIME, 1f, 0f); } - if (!switchEventSent && timeProgress == 1f && !(currentStory.isVideo && isCaptionPartVisible)) { + float zoomTimeProgress = timeProgress; + if (playerSharedScope != null && playerSharedScope.player != null && playerSharedScope.player.currentSeek >= 0) { + zoomTimeProgress = playerSharedScope.player.currentSeek; + } + + if (!switchEventSent && timeProgress == 1f && !(currentStory.isVideo && isCaptionPartVisible) && !isLongPressed) { switchEventSent = true; post(() -> { if (delegate != null) { @@ -692,10 +711,13 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } storyPositionView.draw(canvas, hideInterfaceAlpha * alpha * (1f - outT), listPosition, storyViewer.storiesList.getCount(), this, headerView); } + canvas.save(); canvas.translate(0, dp(8) - dp(8) * outT); boolean buffering = currentStory.isVideo() && playerSharedScope.isBuffering(); - storyLines.draw(canvas, getMeasuredWidth(), linesPosition, timeProgress, linesCount, hideInterfaceAlpha, alpha * (1f - outT), buffering); + boolean zoom = isLongPressed && (currentStory != null && currentStory.isVideo) && (storyViewer != null && storyViewer.inSeekingMode); + float linesInterfaceAlpha = linesAlpha.set(!isLongPressed || zoom); + storyLines.draw(canvas, getMeasuredWidth(), linesPosition, timeProgress, linesCount, linesInterfaceAlpha, alpha * (1f - outT), buffering, zoom, zoomTimeProgress); canvas.restore(); } @@ -798,7 +820,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (forceAlert || AndroidUtilities.shouldShowUrlInAlert(url)) { if (type == 0 || type == 2) { boolean forceNotInternalForApps = false; - if (span instanceof URLSpanReplacement && (((URLSpanReplacement) span).getTextStyleRun().flags & TextStyleSpan.FLAG_STYLE_TEXT_URL) != 0) { + if (span instanceof URLSpanReplacement && ((URLSpanReplacement) span).getTextStyleRun() != null && (((URLSpanReplacement) span).getTextStyleRun().flags & TextStyleSpan.FLAG_STYLE_TEXT_URL) != 0) { forceNotInternalForApps = true; } AlertsCreator.showOpenUrlAlert(storyViewer.fragment, url, true, true, true, forceNotInternalForApps, null, resourcesProvider); @@ -984,7 +1006,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica final boolean userCanEditStory = isSelf || MessagesController.getInstance(currentAccount).getStoriesController().canEditStory(currentStory.storyItem); boolean canEditStory = isSelf || (isChannel && userCanEditStory); if (canEditStory || currentStory.uploadingStory != null) { - TLRPC.StoryItem storyItem = currentStory.storyItem; + TL_stories.StoryItem storyItem = currentStory.storyItem; if (currentStory.uploadingStory != null) { ActionBarMenuSubItem item = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_cancel, LocaleController.getString("Cancel", R.string.Cancel), false, resourcesProvider); item.setOnClickListener(v -> { @@ -1108,7 +1130,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica title = pin ? LocaleController.getString("SaveToPosts", R.string.SaveToPosts) : LocaleController.getString("RemoveFromPosts", R.string.RemoveFromPosts); } ActionBarMenuItem.addItem(popupLayout, pin ? R.drawable.msg_save_story : R.drawable.menu_unsave_story, title, false, resourcesProvider).setOnClickListener(v -> { - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); storyItems.add(storyItem); MessagesController.getInstance(currentAccount).getStoriesController().updateStoriesPinned(dialogId, storyItems, pin, success -> { if (success) { @@ -1196,7 +1218,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } else { object = chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); } - String name = user == null ? (chat == null ? "" : chat.title) : user.first_name.trim(); + String name = user == null ? (chat == null ? "" : chat.title) : UserObject.getFirstName(user).trim(); int index = name.indexOf(" "); if (index > 0) { name = name.substring(0, index); @@ -1421,7 +1443,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica privacyButton = new StoryPrivacyButton(context); privacyButton.setOnClickListener(v -> { - TLRPC.StoryItem storyItem = currentStory.storyItem; + TL_stories.StoryItem storyItem = currentStory.storyItem; if (storyItem == null) { return; } @@ -1510,7 +1532,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica private void createStealthModeItem(ActionBarPopupWindow.ActionBarPopupWindowLayout popupLayout) { if (UserConfig.getInstance(currentAccount).isPremium()) { - ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString("StealthMode", R.string.StealthMode), false, resourcesProvider).setOnClickListener(v -> { + ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.StealthModeButton), false, resourcesProvider).setOnClickListener(v -> { if (stealthModeIsActive) { StealthModeAlert.showStealthModeEnabledBulletin(); } else { @@ -1533,7 +1555,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } }; - ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString("StealthMode", R.string.StealthMode), false, resourcesProvider); + ActionBarMenuSubItem item2 = ActionBarMenuItem.addItem(popupLayout, R.drawable.msg_stories_stealth2, LocaleController.getString(R.string.StealthModeButton), false, resourcesProvider); item2.setOnClickListener(v -> { StealthModeAlert stealthModeAlert = new StealthModeAlert(getContext(), getY() + storyContainer.getY(), resourcesProvider); delegate.showDialog(stealthModeAlert); @@ -1638,7 +1660,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } if (isChannel && counterChanged) { if (currentStory.storyItem.views == null) { - currentStory.storyItem.views = new TLRPC.TL_storyViews(); + currentStory.storyItem.views = new TL_stories.TL_storyViews(); } currentStory.storyItem.views.reactions_count += added ? 1 : -1; if (currentStory.storyItem.views.reactions_count < 0) { @@ -1670,9 +1692,30 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica private ArrayList getAnimatedEmojiSets(StoryItemHolder storyHolder) { if (storyHolder != null) { + HashSet ids = new HashSet<>(); + ArrayList inputStickerSets = new ArrayList<>(); + if (storyHolder.storyItem.media_areas != null) { + for (int i = 0; i < storyHolder.storyItem.media_areas.size(); ++i) { + TL_stories.MediaArea mediaArea = storyHolder.storyItem.media_areas.get(i); + if (mediaArea instanceof TL_stories.TL_mediaAreaSuggestedReaction && mediaArea.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + long documentId = ((TLRPC.TL_reactionCustomEmoji) mediaArea.reaction).document_id; + TLRPC.Document document = AnimatedEmojiDrawable.findDocument(currentAccount, documentId); + if (document == null) { + continue; + } + TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document); + if (set == null) { + continue; + } + if (ids.contains(set.id)) { + continue; + } + ids.add(set.id); + inputStickerSets.add(set); + } + } + } if (storyHolder.storyItem != null && storyHolder.storyItem.entities != null && !storyHolder.storyItem.entities.isEmpty()) { - HashSet ids = new HashSet<>(); - ArrayList inputStickerSets = new ArrayList<>(); for (int i = 0; i < storyHolder.storyItem.entities.size(); ++i) { TLRPC.MessageEntity messageEntity = storyHolder.storyItem.entities.get(i); if (!(messageEntity instanceof TLRPC.TL_messageEntityCustomEmoji)) { @@ -1692,18 +1735,36 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica ids.add(set.id); inputStickerSets.add(set); } - return inputStickerSets; } else if (storyHolder.uploadingStory != null && storyHolder.uploadingStory.entry != null) { + if (storyHolder.uploadingStory.entry.mediaEntities != null) { + for (int i = 0; i < storyHolder.uploadingStory.entry.mediaEntities.size(); ++i) { + VideoEditedInfo.MediaEntity entity = storyHolder.uploadingStory.entry.mediaEntities.get(i); + if (entity.type == VideoEditedInfo.MediaEntity.TYPE_REACTION && entity.mediaArea != null && entity.mediaArea.reaction instanceof TLRPC.TL_reactionCustomEmoji) { + long documentId = ((TLRPC.TL_reactionCustomEmoji) entity.mediaArea.reaction).document_id; + TLRPC.Document document = AnimatedEmojiDrawable.findDocument(currentAccount, documentId); + if (document == null) { + continue; + } + TLRPC.InputStickerSet set = MessageObject.getInputStickerSet(document); + if (set == null) { + continue; + } + if (ids.contains(set.id)) { + continue; + } + ids.add(set.id); + inputStickerSets.add(set); + } + } + } CharSequence caption = storyHolder.uploadingStory.entry.caption; if (!(caption instanceof Spanned)) { - return null; + return inputStickerSets; } AnimatedEmojiSpan[] spans = ((Spanned) caption).getSpans(0, caption.length(), AnimatedEmojiSpan.class); if (spans == null) { - return null; + return inputStickerSets; } - HashSet ids = new HashSet<>(); - ArrayList inputStickerSets = new ArrayList<>(); for (int i = 0; i < spans.length; ++i) { TLRPC.Document document = spans[i].document; if (document == null) { @@ -1719,8 +1780,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica ids.add(set.id); inputStickerSets.add(set); } - return inputStickerSets; } + return inputStickerSets; } return null; } @@ -1905,7 +1966,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica @Override public void extendActionMode(Menu menu) { - ChatActivity.fillActionModeMenu(menu, null); + ChatActivity.fillActionModeMenu(menu, null, false); } }; chatActivityEnterView.getEditField().useAnimatedTextDrawable(); @@ -1929,7 +1990,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } @Override - public void onTextChanged(CharSequence text, boolean bigChange) { + public void onTextChanged(CharSequence text, boolean bigChange, boolean fromDraft) { if (mentionContainer == null) { createMentionsContainer(); } @@ -2049,7 +2110,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } @Override - public TLRPC.StoryItem getReplyToStory() { + public TL_stories.StoryItem getReplyToStory() { return currentStory.storyItem; } @@ -2089,7 +2150,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica mentionContainer.withDelegate(new MentionsContainerView.Delegate() { @Override public void onStickerSelected(TLRPC.TL_document document, String query, Object parent) { - SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialogId, null, null, currentStory.storyItem, null, true, 0, false, parent); + SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialogId, null, null, currentStory.storyItem, null, null, true, 0, false, parent); chatActivityEnterView.addStickerToRecent(document); chatActivityEnterView.setFieldText(""); afterMessageSend(); @@ -2118,7 +2179,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); params.put("bot_name", mentionContainer.getAdapter().getContextBotName()); - SendMessagesHelper.prepareSendingBotContextResult(storyViewer.fragment, getAccountInstance(), result, params, dialogId, null, null, currentStory.storyItem, notify, scheduleDate); + SendMessagesHelper.prepareSendingBotContextResult(storyViewer.fragment, getAccountInstance(), result, params, dialogId, null, null, currentStory.storyItem, null, notify, scheduleDate); chatActivityEnterView.setFieldText(""); afterMessageSend(); MediaDataController.getInstance(currentAccount).increaseInlineRaiting(uid); @@ -2149,7 +2210,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (currentStory.storyItem == null && currentStory.uploadingStory == null) { return; } - if (currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (currentStory.storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } File f = currentStory.getPath(); @@ -2225,8 +2286,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (!storyViewer.isShowing) { return; } - TLRPC.StoryItem storyItem = currentStory.storyItem; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = currentStory.storyItem; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } if (button == 8 || button == 7 || button == 4 && !chatAttachAlert.getPhotoLayout().getSelectedPhotos().isEmpty()) { @@ -2268,7 +2329,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (i == 0) { updateStickersOrder = photos.get(0).updateStickersOrder; } - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialogId, null, null, storyItem, button == 4 || forceDocument, arg, null, notify, scheduleDate, updateStickersOrder, null); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialogId, null, null, storyItem, null, button == 4 || forceDocument, arg, null, notify, scheduleDate, updateStickersOrder, null); } chatActivityEnterView.setFieldText(""); afterMessageSend(); @@ -2304,8 +2365,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica @Override public void sendAudio(ArrayList audios, CharSequence caption, boolean notify, int scheduleDate) { - TLRPC.StoryItem storyItem = currentStory.storyItem; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = currentStory.storyItem; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } SendMessagesHelper.prepareSendingAudioDocuments(getAccountInstance(), audios, caption != null ? caption : null, dialogId, null, null, storyItem, notify, scheduleDate, null); @@ -2323,11 +2384,11 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica chatAttachAlert.setDocumentsDelegate(new ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate() { @Override public void didSelectFiles(ArrayList files, String caption, ArrayList fmessages, boolean notify, int scheduleDate) { - TLRPC.StoryItem storyItem = currentStory.storyItem; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = currentStory.storyItem; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } - SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, null, dialogId, null, null, storyItem, null, notify, scheduleDate, null); + SendMessagesHelper.prepareSendingDocuments(getAccountInstance(), files, files, null, caption, null, dialogId, null, null, storyItem, null, null, notify, scheduleDate, null); afterMessageSend(); } @@ -2351,7 +2412,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica private void shareStory(boolean internal) { if (currentStory.storyItem != null && storyViewer.fragment != null) { - TLRPC.StoryItem storyItem = currentStory.storyItem; + TL_stories.StoryItem storyItem = currentStory.storyItem; String link = currentStory.createLink(); if (internal) { Theme.ResourcesProvider shareResourceProvider = new WrappedResourceProvider(resourcesProvider) { @@ -2415,7 +2476,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (currentStory.storyItem == null) { return; } - TLRPC.TL_stories_exportStoryLink exportStoryLink = new TLRPC.TL_stories_exportStoryLink(); + TL_stories.TL_stories_exportStoryLink exportStoryLink = new TL_stories.TL_stories_exportStoryLink(); exportStoryLink.id = currentStory.storyItem.id; exportStoryLink.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); ConnectionsManager.getInstance(currentAccount).sendRequest(exportStoryLink, new RequestDelegate() { @@ -2620,7 +2681,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider), 30)) ); buttonTextView.setOnClickListener(v -> { - if (BuildVars.isStandaloneApp()) { + if (ApplicationLoader.isStandaloneBuild()) { if (LaunchActivity.instance != null) { LaunchActivity.instance.checkAppUpdate(true); } @@ -3047,7 +3108,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica @Override public boolean presentFragment(BaseFragment fragment) { - storyViewer.presentFragment(fragment); + if (storyViewer != null) { + storyViewer.presentFragment(fragment); + } return true; } }, activity, storyLimit.getLimitReachedType(), currentAccount, null); @@ -3062,7 +3125,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica return; } AndroidUtilities.cancelRunOnUIThread(updateStealthModeTimer); - TLRPC.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); + TL_stories.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); if (stealthMode != null && ConnectionsManager.getInstance(currentAccount).getCurrentTime() < stealthMode.active_until_date) { stealthModeIsActive = true; int time = stealthMode.active_until_date - ConnectionsManager.getInstance(currentAccount).getCurrentTime(); @@ -3091,7 +3154,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica return; } forceUpdateOffsets = true; - TLRPC.StoryItem oldStoryItem = currentStory.storyItem; + TL_stories.StoryItem oldStoryItem = currentStory.storyItem; StoriesController.UploadingStory oldUploadingStory = currentStory.uploadingStory; String filter = StoriesUtilities.getStoryImageFilter(); @@ -3139,7 +3202,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica storyViewer.close(true); return; } - TLRPC.StoryItem storyItem = storyItems.get(position); + TL_stories.StoryItem storyItem = storyItems.get(position); StoriesController.UploadingStory editingStory = storiesController.findEditingStory(dialogId, storyItem); if (editingStory != null) { isEditing = true; @@ -3218,7 +3281,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica storyItem.dialogId = dialogId; storyAreasView.set(preload ? null : storyItem, emojiAnimationsOverlay); currentStory.set(storyItem); - allowShare = allowShareLink = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TLRPC.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TLRPC.TL_storyItemSkipped); + allowShare = allowShareLink = !unsupported && currentStory.storyItem != null && !(currentStory.storyItem instanceof TL_stories.TL_storyItemDeleted) && !(currentStory.storyItem instanceof TL_stories.TL_storyItemSkipped); if (allowShare) { allowShare = currentStory.allowScreenshots() && currentStory.storyItem.isPublic; } @@ -3423,7 +3486,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } else if (currentStory.storyItem != null) { privacyButton.set(isSelf, currentStory.storyItem, sameId && editedPrivacy); } else { - privacyButton.set(isSelf, (TLRPC.StoryItem) null, sameId && editedPrivacy); + privacyButton.set(isSelf, (TL_stories.StoryItem) null, sameId && editedPrivacy); } editedPrivacy = false; privacyButton.setTranslationX(muteIconContainer.getVisibility() == View.VISIBLE ? -AndroidUtilities.dp(44) : 0); @@ -3475,7 +3538,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica MessagesController.getInstance(currentAccount).getTranslateController().detectStoryLanguage(currentStory.storyItem); - if (!preload && !isSelf && reactionsTooltipRunnable == null && !SharedConfig.storyReactionsLongPressHint) { + if (!preload && !isSelf && reactionsTooltipRunnable == null && !SharedConfig.storyReactionsLongPressHint && SharedConfig.storiesIntroShown) { AndroidUtilities.runOnUIThread(reactionsTooltipRunnable = () -> { if (!storyViewer.isShown()) { return; @@ -3569,7 +3632,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (position >= storyItems.size()) { position = storyItems.size() - 1; } - TLRPC.StoryItem storyItem = storyItems.get(position); + TL_stories.StoryItem storyItem = storyItems.get(position); storyItem.dialogId = dialogId; setStoryImage(storyItem, imageReceiver, filter); @@ -3599,8 +3662,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (storyItem.media_areas != null) { for (int k = 0; k < storyItem.media_areas.size(); k++) { - if (storyItem.media_areas.get(k) instanceof TLRPC.TL_mediaAreaSuggestedReaction) { - TLRPC.TL_mediaAreaSuggestedReaction reaction = (TLRPC.TL_mediaAreaSuggestedReaction) storyItem.media_areas.get(k); + if (storyItem.media_areas.get(k) instanceof TL_stories.TL_mediaAreaSuggestedReaction) { + TL_stories.TL_mediaAreaSuggestedReaction reaction = (TL_stories.TL_mediaAreaSuggestedReaction) storyItem.media_areas.get(k); ReactionImageHolder reactionImageHolder = new ReactionImageHolder(this); reactionImageHolder.setVisibleReaction(ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(reaction.reaction)); reactionImageHolder.onAttachedToWindow(attachedToWindow); @@ -3616,7 +3679,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica delegate.preparePlayer(documentsToPrepare, uriesToPrepare); } - private void setStoryImage(TLRPC.StoryItem storyItem, ImageReceiver imageReceiver, String filter) { + private void setStoryImage(TL_stories.StoryItem storyItem, ImageReceiver imageReceiver, String filter) { StoriesController.UploadingStory editingStory = storiesController.findEditingStory(dialogId, storyItem); if (editingStory != null) { setStoryImage(editingStory, imageReceiver, filter); @@ -3674,7 +3737,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } private void updateUserViews(boolean animated) { - TLRPC.StoryItem storyItem = currentStory.storyItem; + TL_stories.StoryItem storyItem = currentStory.storyItem; if (storyItem == null) { storyItem = currentStory.editingSourceItem; } @@ -3684,7 +3747,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (storyItem != null) { if (isChannel) { if (storyItem.views == null) { - storyItem.views = new TLRPC.TL_storyViews(); + storyItem.views = new TL_stories.TL_storyViews(); } if (storyItem.views.views_count <= 0) { storyItem.views.views_count = 1; @@ -4135,8 +4198,8 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (uri == null) { return; } - TLRPC.StoryItem storyItem = currentStory.storyItem; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = currentStory.storyItem; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } String extractUriFrom = uri.toString(); @@ -4168,9 +4231,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } if (sendAsUri) { - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialogId, null, null, storyItem, null, true, 0, null); + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialogId, null, null, storyItem, null, null, true, 0, null); } else { - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialogId, null, null, storyItem, null, true, 0, null); + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialogId, null, null, storyItem, null, null, true, 0, null); } } @@ -4199,7 +4262,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public void checkPinchToZoom(MotionEvent ev) { - pinchToZoomHelper.checkPinchToZoom(ev, storyContainer, null, null,null); + pinchToZoomHelper.checkPinchToZoom(ev, storyContainer, null, null, null,null); } @@ -4214,7 +4277,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } - public ArrayList getStoryItems() { + public ArrayList getStoryItems() { return storyItems; } @@ -4490,7 +4553,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } if (allowDraw) { if (progressToOpen != 1f) { - Paint paint = StoriesUtilities.getActiveCirclePaint(imageReceiver, false); + Paint paint = StoriesUtilities.getUnreadCirclePaint(imageReceiver, false); paint.setAlpha((int) (255 * progressToUploading)); radialProgress.setPaint(paint); radialProgress.draw(canvas); @@ -4577,9 +4640,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public class StoryItemHolder { - public TLRPC.StoryItem storyItem = null; + public TL_stories.StoryItem storyItem = null; public StoriesController.UploadingStory uploadingStory = null; - public TLRPC.StoryItem editingSourceItem; + public TL_stories.StoryItem editingSourceItem; boolean skipped; private boolean isVideo; @@ -4631,10 +4694,10 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } - void set(TLRPC.StoryItem storyItem) { + void set(TL_stories.StoryItem storyItem) { this.storyItem = storyItem; this.uploadingStory = null; - skipped = storyItem instanceof TLRPC.TL_storyItemSkipped; + skipped = storyItem instanceof TL_stories.TL_storyItemSkipped; isVideo = isVideoInternal(); } @@ -4676,7 +4739,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public void checkSendView() { - TLRPC.PeerStories userStories = PeerStoriesView.this.userStories; + TL_stories.PeerStories userStories = PeerStoriesView.this.userStories; if (userStories == null) { userStories = storiesController.getStories(dialogId); if (userStories == null) { @@ -4731,6 +4794,9 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } public String createLink() { + if (currentStory.storyItem == null) { + return null; + } if (dialogId > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); if (UserObject.getPublicUsername(user) == null) { @@ -4792,7 +4858,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } } - public static int getStoryId(TLRPC.StoryItem storyItem, StoriesController.UploadingStory uploadingStory) { + public static int getStoryId(TL_stories.StoryItem storyItem, StoriesController.UploadingStory uploadingStory) { if (storyItem != null) { return storyItem.id; } else if (uploadingStory != null && uploadingStory.entry != null) { @@ -5249,22 +5315,22 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica if (photoEntry == null) { return; } - TLRPC.StoryItem storyItem = currentStory.storyItem; - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = currentStory.storyItem; + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemSkipped) { return; } storyItem.dialogId = dialogId; if (photoEntry.isVideo) { if (videoEditedInfo != null) { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, dialogId, null, null, storyItem, photoEntry.entities, photoEntry.ttl, null, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, videoEditedInfo, dialogId, null, null, storyItem, null, photoEntry.entities, photoEntry.ttl, null, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } else { - SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialogId, null, null, storyItem, photoEntry.entities, photoEntry.ttl, null, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); + SendMessagesHelper.prepareSendingVideo(getAccountInstance(), photoEntry.path, null, dialogId, null, null, storyItem, null, photoEntry.entities, photoEntry.ttl, null, notify, scheduleDate, forceDocument, photoEntry.hasSpoiler, photoEntry.caption); } } else { if (photoEntry.imagePath != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialogId, null, null, storyItem, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.imagePath, photoEntry.thumbPath, null, dialogId, null, null, storyItem, null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } else if (photoEntry.path != null) { - SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialogId, null, null, storyItem, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); + SendMessagesHelper.prepareSendingPhoto(getAccountInstance(), photoEntry.path, photoEntry.thumbPath, null, dialogId, null, null, storyItem, null, photoEntry.entities, photoEntry.stickers, null, photoEntry.ttl, null, videoEditedInfo, notify, scheduleDate, forceDocument, photoEntry.caption); } } afterMessageSend(); @@ -5509,7 +5575,7 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica storiesLikeButton.setReaction(visibleReaction); if (isChannel && currentStory.storyItem.sent_reaction == null) { if (currentStory.storyItem.views == null) { - currentStory.storyItem.views = new TLRPC.TL_storyViews(); + currentStory.storyItem.views = new TL_stories.TL_storyViews(); } currentStory.storyItem.views.reactions_count++; ReactionsUtils.applyForStoryViews(null, currentStory.storyItem.sent_reaction, currentStory.storyItem.views); @@ -5694,14 +5760,14 @@ public class PeerStoriesView extends SizeNotifierFrameLayout implements Notifica } private boolean editedPrivacy; - private void editPrivacy(StoryPrivacyBottomSheet.StoryPrivacy currentPrivacy, TLRPC.StoryItem storyItem) { + private void editPrivacy(StoryPrivacyBottomSheet.StoryPrivacy currentPrivacy, TL_stories.StoryItem storyItem) { delegate.showDialog(new StoryPrivacyBottomSheet(getContext(), storyItem.pinned ? Integer.MAX_VALUE : storyItem.expire_date - storyItem.date, resourcesProvider) .setValue(currentPrivacy) .enableSharing(false) // .allowSmallChats(false) .isEdit(true) .whenSelectedRules((privacy, a, b, sendAs, whenDone) -> { - TLRPC.TL_stories_editStory editStory = new TLRPC.TL_stories_editStory(); + TL_stories.TL_stories_editStory editStory = new TL_stories.TL_stories_editStory(); editStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(storyItem.dialogId); editStory.id = storyItem.id; editStory.flags |= 4; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java index 88fd69c6a..07fa34e56 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ProfileStoriesView.java @@ -3,7 +3,6 @@ package org.telegram.ui.Stories; 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.AndroidUtilities.rectTmp; import static org.telegram.messenger.Utilities.clamp; import android.animation.Animator; @@ -24,6 +23,7 @@ import android.view.View; import android.view.ViewConfiguration; import android.view.animation.OvershootInterpolator; +import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; @@ -37,7 +37,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; @@ -52,8 +52,8 @@ import java.util.List; public class ProfileStoriesView extends View implements NotificationCenter.NotificationCenterDelegate { private static final int CIRCLES_MAX = 3; + public static final String FRAGMENT_TRANSITION_PROPERTY = "fragmentTransitionProgress"; - private final StoriesGradientTools storiesGradientTools; private int readPaintAlpha; private final Paint readPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private final Paint whitePaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -80,6 +80,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif private boolean progressIsDone; private float bounceScale = 1f; private float progressToInsets = 1f; + private float fragmentTransitionProgress; + private int uploadingStoriesCount; + private StoriesController.UploadingStory lastUploadingStory; public void setProgressToStoriesInsets(float progressToInsets) { if (this.progressToInsets == progressToInsets) { @@ -90,7 +93,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } private class StoryCircle { - public StoryCircle(TLRPC.StoryItem storyItem) { + public StoryCircle(TL_stories.StoryItem storyItem) { this.storyId = storyItem.id; this.imageReceiver.setRoundRadius(dp(200)); this.imageReceiver.setParentView(ProfileStoriesView.this); @@ -141,10 +144,6 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif this.avatarImage = avatarImage; storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); - storiesGradientTools = new StoriesGradientTools(); - storiesGradientTools.paint.setStyle(Paint.Style.STROKE); - storiesGradientTools.paint.setStrokeCap(Paint.Cap.ROUND); - readPaint.setColor(0x5affffff); readPaintAlpha = readPaint.getAlpha(); readPaint.setStrokeWidth(dpf2(1.5f)); @@ -171,21 +170,19 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif return who == titleDrawable || super.verifyDrawable(who); } - private TLRPC.PeerStories peerStories; - public void setStories(TLRPC.PeerStories peerStories) { + private TL_stories.PeerStories peerStories; + public void setStories(TL_stories.PeerStories peerStories) { this.peerStories = peerStories; updateStories(true, false); } private void updateStories(boolean animated, boolean asUpdate) { final boolean me = dialogId == UserConfig.getInstance(currentAccount).getClientUserId(); - TLRPC.PeerStories userFullStories = peerStories; - TLRPC.PeerStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(dialogId); - final TLRPC.PeerStories userStories; + TL_stories.PeerStories userFullStories = MessagesController.getInstance(currentAccount).getStoriesController().getStoriesFromFullPeer(dialogId); + TL_stories.PeerStories stateStories = MessagesController.getInstance(currentAccount).getStoriesController().getStories(dialogId); + final TL_stories.PeerStories userStories; if (dialogId == 0) { userStories = null; -// } else if (stateStories != null) { -// userStories = stateStories; } else { userStories = userFullStories; } @@ -196,15 +193,15 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif if (stateStories != null) { max_read_id = Math.max(max_read_id, stateStories.max_read_id); } - List stories = userStories == null || userStories.stories == null ? new ArrayList() : userStories.stories; - ArrayList storiesToShow = new ArrayList<>(); + List stories = userStories == null || userStories.stories == null ? new ArrayList() : userStories.stories; + ArrayList storiesToShow = new ArrayList<>(); int count = 0; final int lastUnreadCount = unreadCount; unreadCount = 0; if (stories != null) { for (int i = 0; i < stories.size(); ++i) { - TLRPC.StoryItem storyItem = stories.get(i); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = stories.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } if (storyItem.id > max_read_id) { @@ -213,11 +210,11 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif count++; } for (int i = 0; i < stories.size(); ++i) { - TLRPC.StoryItem storyItem = stories.get(i); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = stories.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { int id = storyItem.id; if (stateStories != null) { for (int j = 0; j < stateStories.stories.size(); ++j) { @@ -227,7 +224,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } } } - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { if (userFullStories != null) { for (int j = 0; j < userFullStories.stories.size(); ++j) { if (userFullStories.stories.get(j).id == id) { @@ -238,7 +235,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } continue; } - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { continue; } } @@ -252,8 +249,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } if (storiesToShow.size() < CIRCLES_MAX) { for (int i = 0; i < stories.size(); ++i) { - TLRPC.StoryItem storyItem = stories.get(i); - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + TL_stories.StoryItem storyItem = stories.get(i); + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { int id = storyItem.id; if (stateStories != null) { for (int j = 0; j < stateStories.stories.size(); ++j) { @@ -263,7 +260,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } } } - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { if (userFullStories != null) { for (int j = 0; j < userFullStories.stories.size(); ++j) { if (userFullStories.stories.get(j).id == id) { @@ -274,11 +271,11 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } continue; } - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { continue; } } - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } if (!storiesToShow.contains(storyItem)) { @@ -295,9 +292,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif StoryCircle circle = circles.get(i); int index = -1; - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; for (int j = 0; j < storiesToShow.size(); ++j) { - TLRPC.StoryItem storyItem2 = storiesToShow.get(j); + TL_stories.StoryItem storyItem2 = storiesToShow.get(j); if (storyItem2.id == circle.storyId) { index = j; storyItem = storyItem2; @@ -310,7 +307,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif circle.scale = 0f; } else { circle.index = index; - circle.read = me || userStories != null && storyItem != null && storyItem.id <= userStories.max_read_id; + circle.read = me || userStories != null && storyItem != null && storyItem.id <= storiesController.getMaxStoriesReadId(dialogId); } if (!animated) { circle.apply(); @@ -319,7 +316,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif // add new for (int i = 0; i < storiesToShow.size(); ++i) { - TLRPC.StoryItem storyItem = storiesToShow.get(i); + TL_stories.StoryItem storyItem = storiesToShow.get(i); int index = -1; for (int j = 0; j < circles.size(); ++j) { @@ -352,8 +349,13 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif break; } } + ArrayList uploadingStories = storiesController.getUploadingStories(dialogId); + uploadingStoriesCount = uploadingStories == null ? 0 : uploadingStories.size(); - final int newCount = Math.max(storiesToShow.size(), count); + int newCount = Math.max(storiesToShow.size(), count); + if (newCount == 0 && uploadingStoriesCount != 0) { + newCount = 1; + } if (asUpdate && animated && newCount == this.count + 1 && unreadCount == lastUnreadCount + 1) { animateNewStory(); } @@ -369,8 +371,10 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif private float expandProgress; public void setExpandProgress(float progress) { - this.expandProgress = progress; - invalidate(); + if (this.expandProgress != progress) { + this.expandProgress = progress; + invalidate(); + } } private float actionBarProgress; @@ -391,7 +395,6 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif private final AnimatedFloat segmentsCountAnimated = new AnimatedFloat(this, 0, 240 * 2, CubicBezierInterpolator.EASE_OUT_QUINT); private final AnimatedFloat segmentsUnreadCountAnimated = new AnimatedFloat(this, 0, 240, CubicBezierInterpolator.EASE_OUT_QUINT); private final AnimatedFloat progressToUploading = new AnimatedFloat(this, 0, 150, CubicBezierInterpolator.DEFAULT); - private final AnimatedFloat progressToFail = new AnimatedFloat(this, 0, 150, CubicBezierInterpolator.DEFAULT); private float newStoryBounceT = 1; private ValueAnimator newStoryBounce; @@ -449,7 +452,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif @Override protected void dispatchDraw(Canvas canvas) { float rright = rightAnimated.set(this.right); - float insetMain = AndroidUtilities.dpf2(3.5f); + float avatarPullProgress = Utilities.clamp((avatarContainer.getScaleX() - 1f) / 0.4f, 1f, 0f); + float insetMain = AndroidUtilities.lerp(AndroidUtilities.dpf2(4f), AndroidUtilities.dpf2(3.5f), avatarPullProgress); insetMain *= progressToInsets; float ax = avatarContainer.getX() + insetMain * avatarContainer.getScaleX(); float ay = avatarContainer.getY() + insetMain * avatarContainer.getScaleY(); @@ -481,18 +485,27 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif float segmentsAlpha = clamp(1f - expandProgress / 0.2f, 1, 0); boolean isFailed = storiesController.isLastUploadingFailed(dialogId); - boolean isUploading = (storiesController.hasUploadingStories(dialogId) && !isFailed) || progressWasDrawn && !progressIsDone; - + boolean hasUploadingStories = storiesController.hasUploadingStories(dialogId); + if (!hasUploadingStories && lastUploadingStory != null && lastUploadingStory.canceled) { + progressWasDrawn = false; + progressIsDone = false; + this.progressToUploading.set(false, true); + } + boolean isUploading = (hasUploadingStories && !isFailed) || progressWasDrawn && !progressIsDone; float progressToUploading = this.progressToUploading.set(isUploading); + progressToUploading = lerp(0f, progressToUploading, fragmentTransitionProgress); canvas.save(); canvas.scale(bounceScale, bounceScale, rect1.centerX(), rect1.centerY()); float cy = lerp(rect1.centerY(), this.expandY, expandProgress); - storiesGradientTools.setBounds(this.left, cy - dp(24), this.right, cy + dp(24)); + + Paint unreadPaint = null; + lastUploadingStory = null; if (progressToUploading > 0) { rect2.set(rect1); rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2)); + unreadPaint = StoriesUtilities.getUnreadCirclePaint(rect2, true); if (radialProgress == null) { radialProgress = new RadialProgress(this); radialProgress.setBackground(null, true, false); @@ -502,22 +515,33 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif uploadingProgress = 1f; } else { ArrayList uploadingOrEditingStories = storiesController.getUploadingStories(dialogId); - for (int i = 0; i < uploadingOrEditingStories.size(); i++) { - uploadingProgress += uploadingOrEditingStories.get(i).progress; + if (uploadingOrEditingStories != null) { + if (uploadingOrEditingStories.size() > 0) { + lastUploadingStory = uploadingOrEditingStories.get(0); + } + for (int i = 0; i < uploadingOrEditingStories.size(); i++) { + uploadingProgress += uploadingOrEditingStories.get(i).progress; + } + uploadingProgress = uploadingProgress / uploadingOrEditingStories.size(); + } else { + uploadingProgress = 0f; } - uploadingProgress = uploadingProgress / uploadingOrEditingStories.size(); } radialProgress.setDiff(0); - storiesGradientTools.paint.setAlpha((int) (255 * segmentsAlpha * progressToUploading)); - storiesGradientTools.paint.setStrokeWidth(dpf2(2.33f)); - radialProgress.setPaint(storiesGradientTools.paint); + unreadPaint.setAlpha((int) (255 * segmentsAlpha * progressToUploading)); + unreadPaint.setStrokeWidth(dpf2(2.33f)); + radialProgress.setPaint(unreadPaint); radialProgress.setProgressRect((int) rect2.left, (int) rect2.top, (int) rect2.right, (int) rect2.bottom); - radialProgress.setProgress(Utilities.clamp(uploadingProgress, 1f, 0.2f), true); - radialProgress.draw(canvas); + radialProgress.setProgress(Utilities.clamp(uploadingProgress, 1f, 0), true); + if (avatarImage.drawAvatar) { + radialProgress.draw(canvas); + } progressWasDrawn = true; boolean oldIsDone = progressIsDone; progressIsDone = radialProgress.getAnimatedProgress() >= 0.98f; if (oldIsDone != progressIsDone) { + segmentsCountAnimated.set(count, true); + segmentsUnreadCountAnimated.set(unreadCount, true); animateBounce(); } } else { @@ -528,7 +552,6 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif final float segmentsCount = segmentsCountAnimated.set(count); final float segmentsUnreadCount = segmentsUnreadCountAnimated.set(unreadCount); - storiesGradientTools.setBounds(this.left, cy - dp(24), this.right, cy + dp(24)); if (isFailed) { rect2.set(rect1); rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2)); @@ -536,18 +559,27 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif paint.setStrokeWidth(AndroidUtilities.dp(2)); paint.setAlpha((int) (255 * segmentsAlpha)); canvas.drawCircle(rect2.centerX(), rect2.centerY(), rect2.width() / 2f, paint); - } else if (mainCircle != null && segmentsAlpha > 0) { + } else if ((mainCircle != null || uploadingStoriesCount > 0) && segmentsAlpha > 0) { rect2.set(rect1); rect2.inset(-dpf2(2.66f + 2.23f / 2), -dpf2(2.66f + 2.23f / 2)); rect3.set(rect1); rect3.inset(-dpf2(2.66f + 1.5f / 2), -dpf2(2.66f + 1.5f / 2)); + AndroidUtilities.lerp(rect2, rect3, avatarPullProgress, rect3); - final float separatorAngle = lerp(0, (float) (dpf2(2 + 2.23f) / (rect1.width() * Math.PI) * 360f), clamp(segmentsCount - 1, 1, 0) * segmentsAlpha); - final float maxCount = 50; // (float) (AndroidUtilities.dp(60) * Math.PI / dpf2(4)); + float separatorAngle = lerp(0, (float) (dpf2(2 + 2.23f) / (rect1.width() * Math.PI) * 360f), clamp(segmentsCount - 1, 1, 0) * segmentsAlpha); + final float maxCount = 50; final int mcount = Math.min(count, (int) maxCount); final float animcount = Math.min(segmentsCount, maxCount); + int gap = mcount > 20 ? 3 : 5; + if (mcount <= 1) { + gap = 0; + } + float collapsedGapAngle = gap * 2; + + separatorAngle = lerp(collapsedGapAngle, separatorAngle, avatarPullProgress); + final float widthAngle = (360 - Math.max(0, animcount) * separatorAngle) / Math.max(1, animcount); readPaint.setColor(ColorUtils.blendARGB(0x5affffff, 0x3a000000, actionBarProgress)); readPaintAlpha = readPaint.getAlpha(); @@ -568,9 +600,10 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } if (read < 1) { - storiesGradientTools.paint.setAlpha((int) (0xFF * (1f - read) * segmentsAlpha)); - storiesGradientTools.paint.setStrokeWidth(dpf2(2.33f)); - canvas.drawArc(rect2, a, -widthAngle * appear, false, storiesGradientTools.paint); + unreadPaint = StoriesUtilities.getUnreadCirclePaint(rect2, true); + unreadPaint.setAlpha((int) (0xFF * (1f - read) * segmentsAlpha)); + unreadPaint.setStrokeWidth(dpf2(2.33f)); + canvas.drawArc(rect2, a, -widthAngle * appear, false, unreadPaint); } if (read > 0) { @@ -588,6 +621,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } } + final float expandRight = getExpandRight(); if (expandProgress > 0 && segmentsAlpha < 1) { float ix = 0; w = 0; @@ -619,7 +653,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } readPaint.setColor(ColorUtils.blendARGB(0x5affffff, 0x80BBC4CC, expandProgress)); readPaintAlpha = readPaint.getAlpha(); - storiesGradientTools.paint.setStrokeWidth(lerp(dpf2(2.33f), dpf2(1.5f), expandProgress)); + unreadPaint = StoriesUtilities.getUnreadCirclePaint(rect2, true); + unreadPaint.setStrokeWidth(lerp(dpf2(2.33f), dpf2(1.5f), expandProgress)); readPaint.setStrokeWidth(lerp(dpf2(1.125f), dpf2(1.5f), expandProgress)); if (expandProgress > 0) { for (int i = 0; i < circles.size(); ++i) { @@ -631,7 +666,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif circle.cachedRect.centerY(), Math.min(circle.cachedRect.width(), circle.cachedRect.height()) / 2f + lerp( - dpf2(2.66f) + storiesGradientTools.paint.getStrokeWidth() / 2f, + dpf2(2.66f) + unreadPaint.getStrokeWidth() / 2f, dpf2(2.33f) - readPaint.getStrokeWidth() / 2f, circle.cachedRead ) * expandProgress, @@ -659,8 +694,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } if (B.cachedRead < 1) { - storiesGradientTools.paint.setAlpha((int) (0xFF * B.cachedScale * (1f - B.cachedRead) * (1f - segmentsAlpha))); - drawArcs(canvas, A, B, C, storiesGradientTools.paint); + unreadPaint.setAlpha((int) (0xFF * B.cachedScale * (1f - B.cachedRead) * (1f - segmentsAlpha))); + drawArcs(canvas, A, B, C, unreadPaint); } if (B.cachedRead > 0) { readPaint.setAlpha((int) (readPaintAlpha * B.cachedScale * B.cachedRead * (1f - segmentsAlpha))); @@ -683,17 +718,11 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif canvas.restore(); } - canvas.restore(); + if (unreadPaint != null) { + unreadPaint.setStrokeWidth(dpf2(2.3f)); + } -// float titleAlpha = Math.max(0, (expandProgress - .5f) * 2f); -// if (titleAlpha > 0) { -// float left = lerp(rect1.right + dp(16), maxX + dp(12), expandProgress); -// float right = lerp(getWidth(), rright, expandProgress); -// float y = lerp(rect1.centerY(), this.cy, expandProgress); -// titleDrawable.setBounds((int) (left), (int) (y - dp(18)), (int) (right), (int) (y + dp(18))); -// titleDrawable.setAlpha((int) (0xFF * titleAlpha)); -// titleDrawable.draw(canvas); -// } + canvas.restore(); } private void animateBounce() { @@ -730,9 +759,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif return; } - rectTmp.set(nextCircle.cachedRect); + AndroidUtilities.rectTmp.set(nextCircle.cachedRect); final float inset = dpf2(1.66f) * nextCircle.cachedScale; - rectTmp.inset(-inset, -inset); + AndroidUtilities.rectTmp.inset(-inset, -inset); float xA = nextCircle.cachedRect.centerX(), rA = nextCircle.cachedRect.width() / 2f; float xB = circle.cachedRect.centerX(), rB = circle.cachedRect.width() / 2f; @@ -742,13 +771,13 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif mx = ((xA - rA) + (xB + rB)) / 2f; d = Math.abs(mx - xB); float angle = (float) Math.toDegrees(Math.acos(d / rB)); - clipPath.arcTo(rectTmp, 180 + angle, -angle * 2); + clipPath.arcTo(AndroidUtilities.rectTmp, 180 + angle, -angle * 2); clipPath.arcTo(circle.cachedRect, angle, 360 - angle * 2); } else { mx = ((xA + rA) + (xB - rB)) / 2f; d = Math.abs(mx - xB); float angle = (float) Math.toDegrees(Math.acos(d / rB)); - clipPath.arcTo(rectTmp, -angle, angle * 2); + clipPath.arcTo(AndroidUtilities.rectTmp, -angle, angle * 2); clipPath.arcTo(circle.cachedRect, 180 - angle, -(360 - angle * 2)); } clipPath.close(); @@ -856,6 +885,8 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif private float left, right, cy; private float expandRight, expandY; + private boolean expandRightPad; + private final AnimatedFloat expandRightPadAnimated = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); private final AnimatedFloat rightAnimated = new AnimatedFloat(this, 0, 350, CubicBezierInterpolator.EASE_OUT_QUINT); public void setBounds(float left, float right, float cy, boolean animated) { @@ -871,8 +902,9 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } } - public void setExpandCoords(float right, float y) { + public void setExpandCoords(float right, boolean rightPadded, float y) { this.expandRight = right; + this.expandRightPad = rightPadded; this.expandY = y; invalidate(); } @@ -920,6 +952,7 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif holder.clipTop = 0; holder.clipBottom = AndroidUtilities.displaySize.y; holder.clipParent = (View) getParent(); + holder.radialProgressUpload = radialProgress; return true; } @@ -986,31 +1019,58 @@ public class ProfileStoriesView extends View implements NotificationCenter.Notif } + protected void onLongPress() { + + } + + private Runnable onLongPressRunnable = () -> onLongPress(); + private long tapTime; private float tapX, tapY; + private float getExpandRight() { + return expandRight - expandRightPadAnimated.set(expandRightPad) * dp(71); + } + @Override public boolean onTouchEvent(MotionEvent event) { boolean hit; if (expandProgress < .9f) { hit = rect2.contains(event.getX(), event.getY()); } else { -// hit = event.getX() >= left && event.getX() <= right && Math.abs(event.getY() - cy) < dp(32); - hit = event.getX() >= expandRight - w - dp(32) && event.getX() <= expandRight + dp(32) && Math.abs(event.getY() - expandY) < dp(32); + hit = event.getX() >= getExpandRight() - w - dp(32) && event.getX() <= getExpandRight() + dp(32) && Math.abs(event.getY() - expandY) < dp(32); } if (hit && event.getAction() == MotionEvent.ACTION_DOWN) { tapTime = System.currentTimeMillis(); tapX = event.getX(); tapY = event.getY(); + AndroidUtilities.cancelRunOnUIThread(onLongPressRunnable); + AndroidUtilities.runOnUIThread(onLongPressRunnable, ViewConfiguration.getLongPressTimeout()); return true; } else if (event.getAction() == MotionEvent.ACTION_UP) { + AndroidUtilities.cancelRunOnUIThread(onLongPressRunnable); if (hit && System.currentTimeMillis() - tapTime <= ViewConfiguration.getTapTimeout() && MathUtils.distance(tapX, tapY, event.getX(), event.getY()) <= AndroidUtilities.dp(12) && (storiesController.hasUploadingStories(dialogId) || storiesController.hasStories(dialogId) || !circles.isEmpty())) { onTap(provider); return true; } } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { tapTime = -1; + AndroidUtilities.cancelRunOnUIThread(onLongPressRunnable); } return super.onTouchEvent(event); } + + @Keep + public void setFragmentTransitionProgress(float fragmentTransitionProgress) { + if (this.fragmentTransitionProgress == fragmentTransitionProgress) { + return; + } + this.fragmentTransitionProgress = fragmentTransitionProgress; + invalidate(); + } + + @Keep + public float getFragmentTransitionProgress() { + return fragmentTransitionProgress; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java index b87a37045..7aa350978 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoriesPreviewView.java @@ -6,14 +6,12 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.drawable.GradientDrawable; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; -import android.text.TextUtils; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; @@ -25,10 +23,8 @@ import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageReceiver; -import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.Theme; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.StaticLayoutEx; @@ -473,7 +469,7 @@ public abstract class SelfStoriesPreviewView extends View { } } - private void formatCounterText(SpannableStringBuilder spannableStringBuilder, TLRPC.StoryViews storyViews, boolean twoLines) { + private void formatCounterText(SpannableStringBuilder spannableStringBuilder, TL_stories.StoryViews storyViews, boolean twoLines) { int count = storyViews == null ? 0 : storyViews.views_count; if (count > 0) { spannableStringBuilder.append("d"); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java index 0fc79d8ef..dcd21c654 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsPage.java @@ -42,6 +42,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.ActionBarPopupWindow; @@ -135,7 +136,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente private boolean showServerErrorText; private long dialogId; - private boolean isStoryShownToUser(TLRPC.TL_storyView view) { + private boolean isStoryShownToUser(TL_stories.TL_storyView view) { if (MessagesController.getInstance(currentAccount).getStoriesController().isBlocked(view)) { return false; } @@ -229,7 +230,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente if (position < 0 || position >= listAdapter.items.size()) { return; } - TLRPC.TL_storyView user = listAdapter.items.get(position).user; + TL_stories.TL_storyView user = listAdapter.items.get(position).user; if (user != null) { storyViewer.presentFragment(ProfileActivity.of(user.user_id)); } @@ -244,7 +245,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente if (storyViewer == null || storyViewer.containerView == null) { return false; } - TLRPC.TL_storyView viewUser = listAdapter.items.get(position).user; + TL_stories.TL_storyView viewUser = listAdapter.items.get(position).user; if (viewUser == null) { return false; } @@ -496,7 +497,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente this.showReactionsSort = false; boolean forceHideTitle = false; if (storyItem.storyItem != null) { - TLRPC.StoryItem serverItem = storyItem.storyItem; + TL_stories.StoryItem serverItem = storyItem.storyItem; if (serverItem.views != null) { showSearch = serverItem.views.views_count >= 15; showReactionsSort = serverItem.views.reactions_count >= (BuildVars.DEBUG_PRIVATE_VERSION ? 5 : 10); @@ -582,7 +583,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente ((MarginLayoutParams) shadowView2.getLayoutParams()).topMargin = AndroidUtilities.dp(TOP_PADDING - 17); } - public static void preload(int currentAccount, long dialogId, TLRPC.StoryItem storyItem) { + public static void preload(int currentAccount, long dialogId, TL_stories.StoryItem storyItem) { if (storyItem == null) { return; } @@ -652,10 +653,10 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.storiesUpdated) { if (storyItem.uploadingStory != null) { - TLRPC.PeerStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId); + TL_stories.PeerStories stories = MessagesController.getInstance(currentAccount).storiesController.getStories(UserConfig.getInstance(currentAccount).clientUserId); if (stories != null) { for (int i = 0; i < stories.stories.size(); i++) { - TLRPC.StoryItem storyItem = stories.stories.get(i); + TL_stories.StoryItem storyItem = stories.stories.get(i); if (storyItem.attachPath != null && storyItem.attachPath.equals(this.storyItem.uploadingStory.path)) { this.storyItem.uploadingStory = null; this.storyItem.storyItem = storyItem; @@ -940,13 +941,13 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente private class Item { final int viewType; - TLRPC.TL_storyView user; + TL_stories.TL_storyView user; private Item(int viewType) { this.viewType = viewType; } - private Item(int viewType, TLRPC.TL_storyView user) { + private Item(int viewType, TL_stories.TL_storyView user) { this.viewType = viewType; this.user = user; } @@ -955,12 +956,12 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente public static class ViewsModel { public int totalCount; - TLRPC.StoryItem storyItem; + TL_stories.StoryItem storyItem; private long dialogId; int currentAccount; boolean loading; - ArrayList views = new ArrayList<>(); - ArrayList originalViews = new ArrayList<>(); + ArrayList views = new ArrayList<>(); + ArrayList originalViews = new ArrayList<>(); boolean isExpiredViews; boolean showReactionOnly; boolean initial; @@ -973,7 +974,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente ArrayList listeners = new ArrayList<>(); FiltersState state = new FiltersState(); - public ViewsModel(int currentAccount, long dialogId, TLRPC.StoryItem storyItem, boolean isDefault) { + public ViewsModel(int currentAccount, long dialogId, TL_stories.StoryItem storyItem, boolean isDefault) { this.currentAccount = currentAccount; this.storyItem = storyItem; this.dialogId = dialogId; @@ -994,7 +995,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente if (MessagesController.getInstance(currentAccount).getUser(uid) == null) { continue; } - TLRPC.TL_storyView storyView = new TLRPC.TL_storyView(); + TL_stories.TL_storyView storyView = new TL_stories.TL_storyView(); storyView.user_id = uid; storyView.date = 0; views.add(storyView); @@ -1007,7 +1008,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente if (loading || !hasNext || isExpiredViews) { return; } - TLRPC.TL_stories_getStoryViewsList req = new TLRPC.TL_stories_getStoryViewsList(); + TL_stories.TL_stories_getStoryViewsList req = new TL_stories.TL_stories_getStoryViewsList(); req.id = storyItem.id; req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); if (useLocalFilters) { @@ -1039,7 +1040,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente loading = false; reqId = -1; if (response != null) { - TLRPC.TL_stories_storyViewsList res = (TLRPC.TL_stories_storyViewsList) response; + TL_stories.TL_stories_storyViewsList res = (TL_stories.TL_stories_storyViewsList) response; MessagesController.getInstance(currentAccount).getStoriesController().applyStoryViewsBlocked(res); MessagesController.getInstance(currentAccount).putUsers(res.users, false); if (initial) { @@ -1068,7 +1069,7 @@ public class SelfStoryViewsPage extends FrameLayout implements NotificationCente } if (storyItem.views == null) { - storyItem.views = new TLRPC.TL_storyViews(); + storyItem.views = new TL_stories.TL_storyViews(); } boolean counterUpdated = false; if (res.count > storyItem.views.views_count) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java index 94addcd90..bd82c9809 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/SelfStoryViewsView.java @@ -24,7 +24,7 @@ import org.telegram.messenger.MessagesController; 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_stories; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.LayoutHelper; @@ -348,7 +348,7 @@ public class SelfStoryViewsView extends FrameLayout { viewPagerContainer.setTranslationY(-bottomPadding + getMeasuredHeight() - selfStoriesViewsOffset); } - public void setItems(long dialogId, ArrayList storyItems, int selectedPosition) { + public void setItems(long dialogId, ArrayList storyItems, int selectedPosition) { this.storyItems.clear(); this.dialogId = dialogId; for (int i = 0; i < storyItems.size(); i++) { @@ -384,7 +384,7 @@ public class SelfStoryViewsView extends FrameLayout { return false; } - public TLRPC.StoryItem getSelectedStory() { + public TL_stories.StoryItem getSelectedStory() { int p = selfStoriesPreviewView.getClosestPosition(); if (p < 0 || p >= storyItems.size()) { return null; @@ -499,10 +499,10 @@ public class SelfStoryViewsView extends FrameLayout { } public class StoryItemInternal { - public TLRPC.StoryItem storyItem; + public TL_stories.StoryItem storyItem; public StoriesController.UploadingStory uploadingStory; - public StoryItemInternal(TLRPC.StoryItem storyItem) { + public StoryItemInternal(TL_stories.StoryItem storyItem) { this.storyItem = storyItem; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java index 9e690d573..8e1382bd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StealthModeAlert.java @@ -4,11 +4,9 @@ import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.text.Layout; -import android.text.SpannableStringBuilder; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; -import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -23,20 +21,19 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; 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.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; -import org.telegram.ui.Components.ColoredImageSpan; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Premium.PremiumButtonView; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.LaunchActivity; import org.telegram.ui.PremiumPreviewFragment; -import org.telegram.ui.Stories.recorder.ButtonWithCounterView; import java.util.Locale; @@ -80,7 +77,7 @@ public class StealthModeAlert extends BottomSheet { title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); - title.setText(LocaleController.getString("StealthMode", R.string.StealthMode)); + title.setText(LocaleController.getString("StealthModeTitle", R.string.StealthModeTitle)); linearLayout.addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); SimpleTextView subtitle = new SimpleTextView(getContext()); @@ -148,12 +145,12 @@ public class StealthModeAlert extends BottomSheet { return; } StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); - TLRPC.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); + TL_stories.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); if (stealthMode == null || ConnectionsManager.getInstance(currentAccount).getCurrentTime() > stealthMode.cooldown_until_date) { - TLRPC.TL_stories_activateStealthMode req = new TLRPC.TL_stories_activateStealthMode(); + TL_stories.TL_stories_activateStealthMode req = new TL_stories.TL_stories_activateStealthMode(); req.future = true; req.past = true; - stealthMode = new TLRPC.TL_storiesStealthMode(); + stealthMode = new TL_stories.TL_storiesStealthMode(); stealthMode.flags |= 1 + 2; stealthMode.cooldown_until_date = ConnectionsManager.getInstance(currentAccount).getCurrentTime() +MessagesController.getInstance(currentAccount).stealthModeCooldown; stealthMode.active_until_date = ConnectionsManager.getInstance(currentAccount).getCurrentTime() + MessagesController.getInstance(currentAccount).stealthModeFuture; @@ -202,7 +199,7 @@ public class StealthModeAlert extends BottomSheet { private void updateButton(boolean animated) { StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); - TLRPC.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); + TL_stories.TL_storiesStealthMode stealthMode = storiesController.getStealthMode(); if (stealthMode != null && ConnectionsManager.getInstance(currentAccount).getCurrentTime() < stealthMode.active_until_date) { stealthModeIsActive = true; button.setOverlayText(LocaleController.getString("StealthModeIsActive", R.string.StealthModeIsActive), true, animated); 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 27bca19df..f79669f7a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesController.java @@ -48,6 +48,7 @@ import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.Bulletin; @@ -90,17 +91,17 @@ public class StoriesController { private final LongSparseArray> editingStories = new LongSparseArray<>(); public LongSparseIntArray dialogIdToMaxReadId = new LongSparseIntArray(); - TLRPC.PeerStories currentUserStories; + TL_stories.PeerStories currentUserStories; - private ArrayList dialogListStories = new ArrayList<>(); - private ArrayList hiddenListStories = new ArrayList<>(); - private LongSparseArray allStoriesMap = new LongSparseArray(); + private ArrayList dialogListStories = new ArrayList<>(); + private ArrayList hiddenListStories = new ArrayList<>(); + private LongSparseArray allStoriesMap = new LongSparseArray(); private LongSparseIntArray loadingDialogsStories = new LongSparseIntArray(); StoriesStorage storiesStorage; SharedPreferences mainSettings; final LongSparseArray pollingViewsForSelfStoriesRequester = new LongSparseArray<>(); - public final static Comparator storiesComparator = Comparator.comparingInt(o -> o.date); + public final static Comparator storiesComparator = Comparator.comparingInt(o -> o.date); //load all stories once and manage they by updates //reload only if user get diffToLong @@ -122,7 +123,7 @@ public class StoriesController { private String stateHidden; private boolean hasMoreHidden = true; private boolean firstLoad = true; - private TLRPC.TL_storiesStealthMode stealthMode; + private TL_stories.TL_storiesStealthMode stealthMode; public StoriesController(int currentAccount) { this.currentAccount = currentAccount; @@ -145,13 +146,13 @@ public class StoriesController { draftsController = new DraftsController(currentAccount); } - private TLRPC.TL_storiesStealthMode readStealthMode(String string) { + private TL_stories.TL_storiesStealthMode readStealthMode(String string) { if (string == null) { return null; } SerializedData serializedData = new SerializedData(Utilities.hexToBytes(string)); try { - TLRPC.TL_storiesStealthMode storiesStealthMode = TLRPC.TL_storiesStealthMode.TLdeserialize(serializedData, serializedData.readInt32(true), true); + TL_stories.TL_storiesStealthMode storiesStealthMode = TL_stories.TL_storiesStealthMode.TLdeserialize(serializedData, serializedData.readInt32(true), true); return storiesStealthMode; } catch (Throwable e) { @@ -160,7 +161,7 @@ public class StoriesController { return null; } - private void writeStealthMode(TLRPC.TL_storiesStealthMode mode) { + private void writeStealthMode(TL_stories.TL_storiesStealthMode mode) { SharedPreferences.Editor editor = MessagesController.getInstance(currentAccount).getMainSettings().edit(); if (mode == null) { editor.remove("stories_stealth_mode").apply(); @@ -182,7 +183,7 @@ public class StoriesController { if (storiesReadLoaded) { return; } - TLRPC.TL_stories_getAllReadPeerStories allReadUserStories = new TLRPC.TL_stories_getAllReadPeerStories(); + TL_stories.TL_stories_getAllReadPeerStories allReadUserStories = new TL_stories.TL_stories_getAllReadPeerStories(); ConnectionsManager.getInstance(currentAccount).sendRequest(allReadUserStories, (response, error) -> { TLRPC.Updates updates = (TLRPC.Updates) response; if (updates == null) { @@ -196,14 +197,14 @@ public class StoriesController { }); } - private void sortDialogStories(ArrayList list) { + private void sortDialogStories(ArrayList list) { fixDeletedAndNonContactsStories(list); Collections.sort(list, peerStoriesComparator); } - private void fixDeletedAndNonContactsStories(ArrayList list) { + private void fixDeletedAndNonContactsStories(ArrayList list) { for (int k = 0; k < list.size(); k++) { - TLRPC.PeerStories userStories = list.get(k); + TL_stories.PeerStories userStories = list.get(k); long dialogId = DialogObject.getPeerDialogId(userStories.peer); boolean removed = false; if (dialogId > 0) { @@ -215,7 +216,7 @@ public class StoriesController { } } for (int i = 0; i < userStories.stories.size(); i++) { - if (userStories.stories.get(i) instanceof TLRPC.TL_storyItemDeleted) { + if (userStories.stories.get(i) instanceof TL_stories.TL_storyItemDeleted) { userStories.stories.remove(i); i--; } @@ -242,14 +243,14 @@ public class StoriesController { if (isLastUploadingFailed(dialogId)) { return true; } - TLRPC.PeerStories stories = allStoriesMap.get(dialogId); + TL_stories.PeerStories stories = allStoriesMap.get(dialogId); if (stories == null) { stories = getStoriesFromFullPeer(dialogId); } return stories != null && !stories.stories.isEmpty(); } - public TLRPC.PeerStories getStoriesFromFullPeer(long dialogId) { + public TL_stories.PeerStories getStoriesFromFullPeer(long dialogId) { if (dialogId > 0) { TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); return userFull == null ? null : userFull.stories; @@ -291,8 +292,8 @@ public class StoriesController { } public void toggleHidden(long dialogId, boolean hide, boolean request, boolean notify) { - ArrayList removeFrom; - ArrayList insertTo; + ArrayList removeFrom; + ArrayList insertTo; boolean remove = true; if (hide) { // remove = true; @@ -303,7 +304,7 @@ public class StoriesController { insertTo = dialogListStories; } - TLRPC.PeerStories removed = null; + TL_stories.PeerStories removed = null; for (int i = 0; i < removeFrom.size(); i++) { if (DialogObject.getPeerDialogId(removeFrom.get(i).peer) == dialogId) { if (remove) { @@ -344,7 +345,7 @@ public class StoriesController { MessagesStorage.getInstance(currentAccount).putUsersAndChats(null, Collections.singletonList(chat), false, true); MessagesController.getInstance(currentAccount).putChat(chat, false); } - TLRPC.TL_stories_togglePeerStoriesHidden req = new TLRPC.TL_stories_togglePeerStoriesHidden(); + TL_stories.TL_stories_togglePeerStoriesHidden req = new TL_stories.TL_stories_togglePeerStoriesHidden(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); req.hidden = hide; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { @@ -361,7 +362,7 @@ public class StoriesController { } else { loadingFromServer = true; } - TLRPC.TL_stories_getAllStories req = new TLRPC.TL_stories_getAllStories(); + TL_stories.TL_stories_getAllStories req = new TL_stories.TL_stories_getAllStories(); String state = hidden ? stateHidden : this.state; boolean hasMore = hidden ? hasMoreHidden : this.hasMore; if (!TextUtils.isEmpty(state)) { @@ -381,20 +382,20 @@ public class StoriesController { loadingFromServer = false; } FileLog.d("StoriesController loaded stories from server state=" + req.state + " more=" + req.next + " " + response); - if (response instanceof TLRPC.TL_stories_allStories) { - TLRPC.TL_stories_allStories storiesResponse = (TLRPC.TL_stories_allStories) response; + if (response instanceof TL_stories.TL_stories_allStories) { + TL_stories.TL_stories_allStories storiesResponse = (TL_stories.TL_stories_allStories) response; MessagesStorage.getInstance(currentAccount).putUsersAndChats(storiesResponse.users, null, true, true); if (!hidden) { - this.totalStoriesCount = ((TLRPC.TL_stories_allStories) response).count; - this.hasMore = ((TLRPC.TL_stories_allStories) response).has_more; + this.totalStoriesCount = ((TL_stories.TL_stories_allStories) response).count; + this.hasMore = ((TL_stories.TL_stories_allStories) response).has_more; this.state = storiesResponse.state; mainSettings.edit().putString("last_stories_state", this.state) .putBoolean("last_stories_has_more", this.hasMore) .putInt("total_stores", this.totalStoriesCount) .apply(); } else { - this.totalStoriesCountHidden = ((TLRPC.TL_stories_allStories) response).count; - this.hasMoreHidden = ((TLRPC.TL_stories_allStories) response).has_more; + this.totalStoriesCountHidden = ((TL_stories.TL_stories_allStories) response).count; + this.hasMoreHidden = ((TL_stories.TL_stories_allStories) response).has_more; this.stateHidden = storiesResponse.state; mainSettings.edit().putString("last_stories_state_hidden", this.stateHidden) .putBoolean("last_stories_has_more_hidden", this.hasMoreHidden) @@ -402,14 +403,14 @@ public class StoriesController { .apply(); } processAllStoriesResponse(storiesResponse, hidden, false, finalIsNext); - } else if (response instanceof TLRPC.TL_stories_allStoriesNotModified) { + } else if (response instanceof TL_stories.TL_stories_allStoriesNotModified) { if (!hidden) { this.hasMore = mainSettings.getBoolean("last_stories_has_more", false); - this.state = ((TLRPC.TL_stories_allStoriesNotModified) response).state; + this.state = ((TL_stories.TL_stories_allStoriesNotModified) response).state; mainSettings.edit().putString("last_stories_state", this.state).apply(); } else { this.hasMoreHidden = mainSettings.getBoolean("last_stories_has_more_hidden", false); - this.stateHidden = ((TLRPC.TL_stories_allStoriesNotModified) response).state; + this.stateHidden = ((TL_stories.TL_stories_allStoriesNotModified) response).state; mainSettings.edit().putString("last_stories_state_hidden", this.stateHidden).apply(); } boolean hasMoreLocal = hidden ? hasMoreHidden : this.hasMore; @@ -420,7 +421,7 @@ public class StoriesController { })); } - private void processAllStoriesResponse(TLRPC.TL_stories_allStories storiesResponse, boolean hidden, boolean fromCache, boolean isNext) { + private void processAllStoriesResponse(TL_stories.TL_stories_allStories storiesResponse, boolean hidden, boolean fromCache, boolean isNext) { if (!isNext) { if (!hidden) { //allStoriesMap.clear(); @@ -444,10 +445,10 @@ public class StoriesController { MessagesController.getInstance(currentAccount).putChats(storiesResponse.chats, fromCache); for (int i = 0; i < storiesResponse.peer_stories.size(); i++) { - TLRPC.PeerStories userStories = storiesResponse.peer_stories.get(i); + TL_stories.PeerStories userStories = storiesResponse.peer_stories.get(i); long dialogId = DialogObject.getPeerDialogId(userStories.peer); for (int j = 0; j < userStories.stories.size(); j++) { - if (userStories.stories.get(j) instanceof TLRPC.TL_storyItemDeleted) { + if (userStories.stories.get(j) instanceof TL_stories.TL_storyItemDeleted) { NotificationsController.getInstance(currentAccount).processDeleteStory(dialogId, userStories.stories.get(j).id); userStories.stories.remove(j); j--; @@ -456,7 +457,7 @@ public class StoriesController { if (!userStories.stories.isEmpty()) { allStoriesMap.put(dialogId, userStories); for (int k = 0; k < 2; k++) { - ArrayList storiesList = k == 0 ? hiddenListStories : dialogListStories; + ArrayList storiesList = k == 0 ? hiddenListStories : dialogListStories; for (int j = 0; j < storiesList.size(); j++) { if (DialogObject.getPeerDialogId(storiesList.get(j).peer) == dialogId) { storiesList.remove(j); @@ -507,7 +508,7 @@ public class StoriesController { sortUserStories(); } - private void addUserToHiddenList(TLRPC.PeerStories userStories) { + private void addUserToHiddenList(TL_stories.PeerStories userStories) { boolean found = false; long dialogId = DialogObject.getPeerDialogId(userStories.peer); if (dialogId == UserConfig.getInstance(currentAccount).getClientUserId()) { @@ -529,7 +530,7 @@ public class StoriesController { sortStoriesRunnable.run(); } - public void preloadUserStories(TLRPC.PeerStories userStories) { + public void preloadUserStories(TL_stories.PeerStories userStories) { int preloadPosition = 0; for (int i = 0; i < userStories.stories.size(); i++) { if (userStories.stories.get(i).id > userStories.max_read_id) { @@ -550,7 +551,7 @@ public class StoriesController { } } - private void preloadStory(long dialogId, TLRPC.StoryItem storyItem) { + private void preloadStory(long dialogId, TL_stories.StoryItem storyItem) { if (storyItem.attachPath != null) { return; } @@ -593,7 +594,7 @@ public class StoriesController { for (int i = 0; i < dialogListStories.size(); i++) { if (DialogObject.getPeerDialogId(dialogListStories.get(i).peer) == dialogId) { found = true; - TLRPC.PeerStories peerStories = dialogListStories.remove(i); + TL_stories.PeerStories peerStories = dialogListStories.remove(i); dialogListStories.add(0, peerStories); break; } @@ -602,14 +603,14 @@ public class StoriesController { for (int i = 0; i < hiddenListStories.size(); i++) { if (DialogObject.getPeerDialogId(hiddenListStories.get(i).peer) == dialogId) { found = true; - TLRPC.PeerStories peerStories = hiddenListStories.remove(i); + TL_stories.PeerStories peerStories = hiddenListStories.remove(i); hiddenListStories.add(0, peerStories); break; } } } if (!found) { - TLRPC.PeerStories peerStories = new TLRPC.TL_peerStories(); + TL_stories.PeerStories peerStories = new TL_stories.TL_peerStories(); peerStories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId); allStoriesMap.put(dialogId, peerStories); dialogListStories.add(0, peerStories); @@ -639,11 +640,11 @@ public class StoriesController { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); } - public ArrayList getDialogListStories() { + public ArrayList getDialogListStories() { return dialogListStories; } - public TLRPC.PeerStories getStories(long peerId) { + public TL_stories.PeerStories getStories(long peerId) { return allStoriesMap.get(peerId); } @@ -665,14 +666,14 @@ public class StoriesController { public int getMyStoriesCount() { int count = uploadingAndEditingStories.size(); - TLRPC.PeerStories userStories = getStories(getSelfUserId()); + TL_stories.PeerStories userStories = getStories(getSelfUserId()); if (userStories != null && userStories.stories != null) { count += userStories.stories.size(); } return count; } - public UploadingStory findEditingStory(long dialogId, TLRPC.StoryItem storyItem) { + public UploadingStory findEditingStory(long dialogId, TL_stories.StoryItem storyItem) { if (storyItem == null) { return null; } @@ -695,7 +696,7 @@ public class StoriesController { return values.iterator().next(); } - private void applyNewStories(TLRPC.PeerStories stories) { + private void applyNewStories(TL_stories.PeerStories stories) { long dialogId = DialogObject.getPeerDialogId(stories.peer); allStoriesMap.put(dialogId, stories); if (dialogId != UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { @@ -709,7 +710,7 @@ public class StoriesController { updateStoriesInLists(dialogId, stories.stories); } - public static TLRPC.StoryItem applyStoryUpdate(TLRPC.StoryItem oldStoryItem, TLRPC.StoryItem newStoryItem) { + public static TL_stories.StoryItem applyStoryUpdate(TL_stories.StoryItem oldStoryItem, TL_stories.StoryItem newStoryItem) { if (newStoryItem == null) { return oldStoryItem; } @@ -737,7 +738,7 @@ public class StoriesController { return newStoryItem; } - public void processUpdate(TLRPC.TL_updateStory updateStory) { + public void processUpdate(TL_stories.TL_updateStory updateStory) { //stage queue if (updateStory.story == null) { return; @@ -758,29 +759,30 @@ public class StoriesController { } TLRPC.User finalUser = user; AndroidUtilities.runOnUIThread(() -> { - TLRPC.PeerStories currentUserStory = allStoriesMap.get(dialogId); FileLog.d("StoriesController update stories for dialog " + dialogId); updateStoriesInLists(dialogId, Collections.singletonList(updateStory.story)); - - ArrayList newStoryItems = new ArrayList<>(); + updateStoriesForFullPeer(dialogId, Collections.singletonList(updateStory.story)); + TL_stories.PeerStories currentUserStory = allStoriesMap.get(dialogId); + ArrayList newStoryItems = new ArrayList<>(); int oldStoriesCount = totalStoriesCount; boolean notify = false; + if (currentUserStory != null) { boolean changed = false; - TLRPC.StoryItem newStory = updateStory.story; - if (newStory instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem newStory = updateStory.story; + if (newStory instanceof TL_stories.TL_storyItemDeleted) { NotificationsController.getInstance(currentAccount).processDeleteStory(dialogId, newStory.id); } boolean found = false; for (int i = 0; i < currentUserStory.stories.size(); i++) { if (currentUserStory.stories.get(i).id == newStory.id) { found = true; - if (newStory instanceof TLRPC.TL_storyItemDeleted) { + if (newStory instanceof TL_stories.TL_storyItemDeleted) { currentUserStory.stories.remove(i); FileLog.d("StoriesController remove story id=" + newStory.id); changed = true; } else { - TLRPC.StoryItem oldStory = currentUserStory.stories.get(i); + TL_stories.StoryItem oldStory = currentUserStory.stories.get(i); newStory = applyStoryUpdate(oldStory, newStory); newStoryItems.add(newStory); currentUserStory.stories.set(i, newStory); @@ -796,7 +798,7 @@ public class StoriesController { } } if (!found) { - if (newStory instanceof TLRPC.TL_storyItemDeleted) { + if (newStory instanceof TL_stories.TL_storyItemDeleted) { FileLog.d("StoriesController can't add new story DELETED"); return; } @@ -828,7 +830,7 @@ public class StoriesController { notify = true; } } else { - if (updateStory.story instanceof TLRPC.TL_storyItemDeleted) { + if (updateStory.story instanceof TL_stories.TL_storyItemDeleted) { FileLog.d("StoriesController can't add user " + dialogId + " with new story DELETED"); return; } @@ -840,7 +842,7 @@ public class StoriesController { FileLog.d("StoriesController can't add user cause is not contact"); return; } - currentUserStory = new TLRPC.TL_peerStories(); + currentUserStory = new TL_stories.TL_peerStories(); currentUserStory.peer = updateStory.peer; currentUserStory.stories.add(updateStory.story); FileLog.d("StoriesController add new user with story id=" + updateStory.story.id); @@ -861,11 +863,70 @@ public class StoriesController { }); } + private void updateStoriesForFullPeer(long dialogId, List newStories) { + TL_stories.PeerStories peerStories; + if (dialogId > 0) { + TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(dialogId); + if (userFull == null) { + return; + } + if (userFull.stories == null) { + userFull.stories = new TL_stories.TL_peerStories(); + userFull.stories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId); + userFull.stories.max_read_id = getMaxStoriesReadId(dialogId); + } + peerStories = userFull.stories; + } else { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-dialogId); + if (chatFull == null) { + return; + } + if (chatFull.stories == null) { + chatFull.stories = new TL_stories.TL_peerStories(); + chatFull.stories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId); + chatFull.stories.max_read_id = getMaxStoriesReadId(dialogId); + } + peerStories = chatFull.stories; + } + for (int k = 0; k < newStories.size(); k++) { + boolean found = false; + TL_stories.StoryItem newStory = newStories.get(k); + for (int i = 0; i < peerStories.stories.size(); i++) { + if (peerStories.stories.get(i).id == newStory.id) { + found = true; + if (newStory instanceof TL_stories.TL_storyItemDeleted) { + peerStories.stories.remove(i); + } else { + TL_stories.StoryItem oldStory = peerStories.stories.get(i); + newStory = applyStoryUpdate(oldStory, newStory); + peerStories.stories.set(i, newStory); + if (newStory.attachPath == null) { + newStory.attachPath = oldStory.attachPath; + } + if (newStory.firstFramePath == null) { + newStory.firstFramePath = oldStory.firstFramePath; + } + FileLog.d("StoriesController update story for full peer storyId=" + newStory.id); + } + break; + } + } + if (!found) { + if (newStory instanceof TL_stories.TL_storyItemDeleted) { + FileLog.d("StoriesController story is not found, but already deleted storyId=" + newStory.id); + } else { + FileLog.d(" StoriesController add new story for full peer storyId=" + newStory.id); + peerStories.stories.add(newStory); + } + } + } + } + private boolean isContactOrService(TLRPC.User user) { return user != null && (user.contact || user.id == MessagesController.getInstance(currentAccount).storiesChangelogUserId); } - private void applyToList(TLRPC.PeerStories currentUserStory) { + private void applyToList(TL_stories.PeerStories currentUserStory) { long dialogId = DialogObject.getPeerDialogId(currentUserStory.peer); TLRPC.User user = null; TLRPC.Chat chat = null; @@ -921,17 +982,17 @@ public class StoriesController { } allStoriesLoading.add(user_id); FileLog.d("StoriesController loadAllStoriesForDialog " + user_id); - TLRPC.TL_stories_getPeerStories userStories = new TLRPC.TL_stories_getPeerStories(); + TL_stories.TL_stories_getPeerStories userStories = new TL_stories.TL_stories_getPeerStories(); userStories.peer = MessagesController.getInstance(currentAccount).getInputPeer(user_id); ConnectionsManager.getInstance(currentAccount).sendRequest(userStories, (response, error) -> AndroidUtilities.runOnUIThread(() -> { allStoriesLoading.remove(user_id); if (response == null) { return; } - TLRPC.TL_stories_peerStories stories_userStories = (TLRPC.TL_stories_peerStories) response; + TL_stories.TL_stories_peerStories stories_userStories = (TL_stories.TL_stories_peerStories) response; MessagesController.getInstance(currentAccount).putUsers(stories_userStories.users, false); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(user_id); - TLRPC.PeerStories stories = stories_userStories.stories; + TL_stories.PeerStories stories = stories_userStories.stories; long dialogId = DialogObject.getPeerDialogId(stories.peer); allStoriesMap.put(dialogId, stories); if (user != null && (isContactOrService(user) || user.self)) { @@ -946,7 +1007,7 @@ public class StoriesController { public boolean hasSelfStories() { long clientUserId = UserConfig.getInstance(currentAccount).clientUserId; - TLRPC.PeerStories storyItem = allStoriesMap.get(clientUserId); + TL_stories.PeerStories storyItem = allStoriesMap.get(clientUserId); if (storyItem != null && !storyItem.stories.isEmpty()) { return true; } @@ -958,7 +1019,7 @@ public class StoriesController { public int getSelfStoriesCount() { int count = 0; - TLRPC.PeerStories storyItem = allStoriesMap.get(UserConfig.getInstance(currentAccount).clientUserId); + TL_stories.PeerStories storyItem = allStoriesMap.get(UserConfig.getInstance(currentAccount).clientUserId); if (storyItem != null) { count += storyItem.stories.size(); } @@ -966,12 +1027,12 @@ public class StoriesController { return count; } - public void deleteStory(long dialogId, TLRPC.StoryItem storyItem) { - if (storyItem == null || storyItem instanceof TLRPC.TL_storyItemDeleted) { + public void deleteStory(long dialogId, TL_stories.StoryItem storyItem) { + if (storyItem == null || storyItem instanceof TL_stories.TL_storyItemDeleted) { return; } for (int k = 0; k < 2; k++) { - TLRPC.PeerStories stories = null; + TL_stories.PeerStories stories = null; TLRPC.UserFull userFull = null; TLRPC.ChatFull chatFull = null; if (k == 0) { @@ -994,10 +1055,24 @@ public class StoriesController { for (int i = 0; i < stories.stories.size(); i++) { if (stories.stories.get(i).id == storyItem.id) { stories.stories.remove(i); - if (stories.stories.size() == 0 && !hasUploadingStories(dialogId)) { - allStoriesMap.remove(dialogId); - dialogListStories.remove(stories); - hiddenListStories.remove(stories); + if (stories.stories.size() == 0) { + if (!hasUploadingStories(dialogId)) { + allStoriesMap.remove(dialogId); + dialogListStories.remove(stories); + hiddenListStories.remove(stories); + } + if (dialogId > 0) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + if (user != null) { + user.stories_unavailable = true; + } + } else { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (chat != null) { + chat.stories_unavailable = true; + } + } + } break; } @@ -1010,7 +1085,7 @@ public class StoriesController { MessagesStorage.getInstance(currentAccount).updateUserInfo(userFull, false); } } - TLRPC.TL_stories_deleteStories req = new TLRPC.TL_stories_deleteStories(); + TL_stories.TL_stories_deleteStories req = new TL_stories.TL_stories_deleteStories(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); req.id.add(storyItem.id); ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { @@ -1024,15 +1099,19 @@ public class StoriesController { updateDeletedStoriesInLists(dialogId, Arrays.asList(storyItem)); } - public void deleteStories(ArrayList storyItems) { + public void deleteStories(long dialogId, ArrayList storyItems) { if (storyItems == null) { return; } - TLRPC.TL_stories_deleteStories req = new TLRPC.TL_stories_deleteStories(); - TLRPC.PeerStories stories = allStoriesMap.get(getSelfUserId()); + TL_stories.TL_stories_deleteStories req = new TL_stories.TL_stories_deleteStories(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + if (req.peer == null) { + return; + } + TL_stories.PeerStories stories = allStoriesMap.get(dialogId); for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } if (stories != null) { @@ -1040,7 +1119,7 @@ public class StoriesController { if (stories.stories.get(j).id == storyItem.id) { stories.stories.remove(j); if (stories.stories.isEmpty()) { - allStoriesMap.remove(getSelfUserId()); + allStoriesMap.remove(dialogId); } break; } @@ -1051,17 +1130,17 @@ public class StoriesController { ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { AndroidUtilities.runOnUIThread(this::invalidateStoryLimit); }); - updateDeletedStoriesInLists(getSelfUserId(), storyItems); - storiesStorage.deleteStories(getSelfUserId(), req.id); + updateDeletedStoriesInLists(dialogId, storyItems); + storiesStorage.deleteStories(dialogId, req.id); NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); } - public void updateStoriesPinned(long dialogId, ArrayList storyItems, boolean pinned, Utilities.Callback whenDone) { - TLRPC.TL_stories_togglePinned req = new TLRPC.TL_stories_togglePinned(); - TLRPC.PeerStories peerStories = getStories(dialogId); + public void updateStoriesPinned(long dialogId, ArrayList storyItems, boolean pinned, Utilities.Callback whenDone) { + TL_stories.TL_stories_togglePinned req = new TL_stories.TL_stories_togglePinned(); + TL_stories.PeerStories peerStories = getStories(dialogId); for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { continue; } storyItem.pinned = pinned; @@ -1078,6 +1157,7 @@ public class StoriesController { } FileLog.d("StoriesController updateStoriesPinned"); updateStoriesInLists(dialogId, storyItems); + updateStoriesForFullPeer(dialogId, storyItems); req.pinned = pinned; req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); @@ -1092,21 +1172,22 @@ public class StoriesController { return UserConfig.getInstance(currentAccount).getClientUserId(); } - public void updateStoryItem(long dialogId, TLRPC.StoryItem storyItem) { + public void updateStoryItem(long dialogId, TL_stories.StoryItem storyItem) { FileLog.d("StoriesController updateStoryItem " + dialogId + " " + (storyItem == null ? "null" : storyItem.id + "@" + storyItem.dialogId)); storiesStorage.updateStoryItem(dialogId, storyItem); updateStoriesInLists(dialogId, Collections.singletonList(storyItem)); + updateStoriesForFullPeer(dialogId, Collections.singletonList(storyItem)); } - public boolean markStoryAsRead(long dialogId, TLRPC.StoryItem storyItem) { - TLRPC.PeerStories userStories = getStories(dialogId); + public boolean markStoryAsRead(long dialogId, TL_stories.StoryItem storyItem) { + TL_stories.PeerStories userStories = getStories(dialogId); if (userStories == null) { userStories = getStoriesFromFullPeer(dialogId); } return markStoryAsRead(userStories, storyItem, false); } - public boolean markStoryAsRead(TLRPC.PeerStories userStories, TLRPC.StoryItem storyItem, boolean profile) { + public boolean markStoryAsRead(TL_stories.PeerStories userStories, TL_stories.StoryItem storyItem, boolean profile) { if (storyItem == null || userStories == null) { return false; } @@ -1123,22 +1204,34 @@ public class StoriesController { if (!profile) { storiesStorage.updateMaxReadId(dialogId, newReadId); } - TLRPC.TL_stories_readStories req = new TLRPC.TL_stories_readStories(); + TL_stories.TL_stories_readStories req = new TL_stories.TL_stories_readStories(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); req.max_id = storyItem.id; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {}); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesReadUpdated); return true; } return false; } + public int getMaxStoriesReadId(long dialogId) { + TL_stories.PeerStories peerStories = getStories(dialogId); + if (peerStories == null) { + peerStories = getStoriesFromFullPeer(dialogId); + } + if (peerStories != null) { + return Math.max(peerStories.max_read_id, dialogIdToMaxReadId.get(dialogId, 0)); + } + return dialogIdToMaxReadId.get(dialogId, 0); + } + public void markStoriesAsReadFromServer(long dialogId, int maxStoryId) { //stage queue AndroidUtilities.runOnUIThread(() -> { int maxStoryReadId = Math.max(dialogIdToMaxReadId.get(dialogId, 0), maxStoryId); dialogIdToMaxReadId.put(dialogId, maxStoryReadId); storiesStorage.updateMaxReadId(dialogId, maxStoryReadId); - TLRPC.PeerStories userStories = getStories(dialogId); + TL_stories.PeerStories userStories = getStories(dialogId); if (userStories == null) { return; } @@ -1151,7 +1244,10 @@ public class StoriesController { } public boolean hasUnreadStories(long dialogId) { - TLRPC.PeerStories userStories = allStoriesMap.get(dialogId); + TL_stories.PeerStories userStories = allStoriesMap.get(dialogId); + if (userStories == null) { + userStories = getStoriesFromFullPeer(dialogId); + } if (userStories == null) { return false; } @@ -1179,7 +1275,7 @@ public class StoriesController { if (dialogId == 0) { return STATE_READ; } - TLRPC.PeerStories peerStories = allStoriesMap.get(dialogId); + TL_stories.PeerStories peerStories = allStoriesMap.get(dialogId); if (peerStories == null) { peerStories = getStoriesFromFullPeer(dialogId); } @@ -1257,7 +1353,7 @@ public class StoriesController { loadSkippedStories(getStories(dialogId), false); } - void loadSkippedStories(TLRPC.PeerStories userStories, boolean profile) { + void loadSkippedStories(TL_stories.PeerStories userStories, boolean profile) { if (userStories == null) { return; } @@ -1269,7 +1365,7 @@ public class StoriesController { ArrayList storyIdsToLoad = null; if (userStories != null) { for (int i = 0; i < userStories.stories.size(); i++) { - if (userStories.stories.get(i) instanceof TLRPC.TL_storyItemSkipped) { + if (userStories.stories.get(i) instanceof TL_stories.TL_storyItemSkipped) { if (storyIdsToLoad == null) { storyIdsToLoad = new ArrayList<>(); } @@ -1278,17 +1374,17 @@ public class StoriesController { } if (storyIdsToLoad != null) { loadingAllStories.add(key); - TLRPC.TL_stories_getStoriesByID stories = new TLRPC.TL_stories_getStoriesByID(); + TL_stories.TL_stories_getStoriesByID stories = new TL_stories.TL_stories_getStoriesByID(); stories.id = storyIdsToLoad; stories.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); ConnectionsManager.getInstance(currentAccount).sendRequest(stories, (response, error) -> AndroidUtilities.runOnUIThread(() -> { loadingAllStories.remove(key); - TLRPC.PeerStories userStories2 = profile ? userStories : getStories(dialogId); + TL_stories.PeerStories userStories2 = profile ? userStories : getStories(dialogId); if (userStories2 == null) { return; } - if (response instanceof TLRPC.TL_stories_stories) { - TLRPC.TL_stories_stories res = (TLRPC.TL_stories_stories) response; + if (response instanceof TL_stories.TL_stories_stories) { + TL_stories.TL_stories_stories res = (TL_stories.TL_stories_stories) response; for (int i = 0; i < res.stories.size(); i++) { for (int j = 0; j < userStories2.stories.size(); j++) { if (userStories2.stories.get(j).id == res.stories.get(i).id) { @@ -1317,34 +1413,34 @@ public class StoriesController { storiesStorage.fillMessagesWithStories(messagesWithUnknownStories, callback, classGuid); } - LongSparseArray resolvedStories = new LongSparseArray<>(); + LongSparseArray resolvedStories = new LongSparseArray<>(); - public void resolveStoryLink(long peerId, int storyId, Consumer consumer) { - TLRPC.PeerStories userStoriesLocal = getStories(peerId); + public void resolveStoryLink(long peerId, int storyId, Consumer consumer) { + TL_stories.PeerStories userStoriesLocal = getStories(peerId); if (userStoriesLocal != null) { for (int i = 0; i < userStoriesLocal.stories.size(); i++) { - if (userStoriesLocal.stories.get(i).id == storyId && !(userStoriesLocal.stories.get(i) instanceof TLRPC.TL_storyItemSkipped)) { + if (userStoriesLocal.stories.get(i).id == storyId && !(userStoriesLocal.stories.get(i) instanceof TL_stories.TL_storyItemSkipped)) { consumer.accept(userStoriesLocal.stories.get(i)); return; } } } long hash = peerId + storyId << 12; - TLRPC.StoryItem storyItem = resolvedStories.get(hash); + TL_stories.StoryItem storyItem = resolvedStories.get(hash); if (storyItem != null) { consumer.accept(storyItem); return; } - TLRPC.TL_stories_getStoriesByID stories = new TLRPC.TL_stories_getStoriesByID(); + TL_stories.TL_stories_getStoriesByID stories = new TL_stories.TL_stories_getStoriesByID(); stories.id.add(storyId); stories.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId); ConnectionsManager.getInstance(currentAccount).sendRequest(stories, new RequestDelegate() { @Override public void run(TLObject res, TLRPC.TL_error error) { AndroidUtilities.runOnUIThread(() -> { - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; if (res != null) { - TLRPC.TL_stories_stories response = (TLRPC.TL_stories_stories) res; + TL_stories.TL_stories_stories response = (TL_stories.TL_stories_stories) res; if (response.stories.size() > 0) { storyItem = response.stories.get(0); resolvedStories.put(hash, storyItem); @@ -1356,12 +1452,12 @@ public class StoriesController { }); } - public ArrayList getHiddenList() { - return (ArrayList)filteredHiddenStories(); + public ArrayList getHiddenList() { + return (ArrayList)filteredHiddenStories(); } public int getUnreadStoriesCount(long dialogId) { - TLRPC.PeerStories userStories = allStoriesMap.get(dialogId); + TL_stories.PeerStories userStories = allStoriesMap.get(dialogId); for (int i = 0; i < userStories.stories.size(); i++) { if (userStories.max_read_id < userStories.stories.get(i).id) { return userStories.stories.size() - i; @@ -1378,7 +1474,7 @@ public class StoriesController { } } - public void putStories(long dialogId, TLRPC.PeerStories stories) { + public void putStories(long dialogId, TL_stories.PeerStories stories) { allStoriesMap.put(dialogId, stories); if (dialogId > 0) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); @@ -1438,10 +1534,10 @@ public class StoriesController { checkExpireStories(hiddenListStories); } - private void checkExpireStories(ArrayList dialogListStories) { + private void checkExpireStories(ArrayList dialogListStories) { boolean notify = false; for (int k = 0; k < dialogListStories.size(); k++) { - TLRPC.PeerStories stories = dialogListStories.get(k); + TL_stories.PeerStories stories = dialogListStories.get(k); long dialogId = DialogObject.getPeerDialogId(stories.peer); for (int i = 0; i < stories.stories.size(); i++) { if (StoriesUtilities.isExpired(currentAccount, stories.stories.get(i))) { @@ -1461,7 +1557,7 @@ public class StoriesController { } public void checkExpiredStories(long dialogId) { - TLRPC.PeerStories userStories = getStories(dialogId); + TL_stories.PeerStories userStories = getStories(dialogId); if (userStories == null) { return; } @@ -1482,21 +1578,21 @@ public class StoriesController { return loadingDialogsStories.size() > 0; } - public TLRPC.TL_storiesStealthMode getStealthMode() { + public TL_stories.TL_storiesStealthMode getStealthMode() { return stealthMode; } - public void setStealthMode(TLRPC.TL_storiesStealthMode stealthMode) { + public void setStealthMode(TL_stories.TL_storiesStealthMode stealthMode) { this.stealthMode = stealthMode; NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.stealthModeChanged); writeStealthMode(stealthMode); } - public void setStoryReaction(long dialogId, TLRPC.StoryItem storyItem, ReactionsLayoutInBubble.VisibleReaction visibleReaction) { + public void setStoryReaction(long dialogId, TL_stories.StoryItem storyItem, ReactionsLayoutInBubble.VisibleReaction visibleReaction) { if (storyItem == null) { return; } - TLRPC.TL_stories_sendReaction req = new TLRPC.TL_stories_sendReaction(); + TL_stories.TL_stories_sendReaction req = new TL_stories.TL_stories_sendReaction(); req.story_id = storyItem.id; req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); if (visibleReaction == null) { @@ -1525,7 +1621,7 @@ public class StoriesController { } public void updateStoryReaction(long dialogId, int storyId, TLRPC.Reaction reaction) { - TLRPC.StoryItem storyItem = findStory(dialogId, storyId); + TL_stories.StoryItem storyItem = findStory(dialogId, storyId); if (storyItem != null) { storyItem.sent_reaction = reaction; if (storyItem.sent_reaction != null) { @@ -1537,8 +1633,8 @@ public class StoriesController { } } - private TLRPC.StoryItem findStory(long dialogId, int storyId) { - TLRPC.PeerStories stories = allStoriesMap.get(dialogId); + private TL_stories.StoryItem findStory(long dialogId, int storyId) { + TL_stories.PeerStories stories = allStoriesMap.get(dialogId); if (stories != null) { for (int i = 0; i < stories.stories.size(); i++) { if (stories.stories.get(i).id == storyId) { @@ -1553,6 +1649,19 @@ public class StoriesController { selfViewsModel.clear(); } + public void updateStoriesFromFullPeer(long dialogId, TL_stories.PeerStories stories) { + if (stories == null) { + return; + } + TL_stories.PeerStories peerStories = allStoriesMap.get(dialogId); + if (peerStories == null) { + return; + } + FileLog.d("StoriesController update stories from full peer " + dialogId); + peerStories.stories.clear(); + peerStories.stories.addAll(stories.stories); + } + public class UploadingStory implements NotificationCenter.NotificationCenterDelegate { public final long random_id; @@ -1831,7 +1940,7 @@ public class StoriesController { final int captionLimit = UserConfig.getInstance(currentAccount).isPremium() ? MessagesController.getInstance(currentAccount).storyCaptionLengthLimitPremium : MessagesController.getInstance(currentAccount).storyCaptionLengthLimitDefault; if (edit) { - TLRPC.TL_stories_editStory editStory = new TLRPC.TL_stories_editStory(); + TL_stories.TL_stories_editStory editStory = new TL_stories.TL_stories_editStory(); editStory.id = entry.editStoryId; editStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); @@ -1879,7 +1988,7 @@ public class StoriesController { req = editStory; } else { - TLRPC.TL_stories_sendStory sendStory = new TLRPC.TL_stories_sendStory(); + TL_stories.TL_stories_sendStory sendStory = new TL_stories.TL_stories_sendStory(); sendStory.random_id = random_id; sendStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); sendStory.media = media; @@ -1931,10 +2040,10 @@ public class StoriesController { failed = false; TLRPC.Updates updates = (TLRPC.Updates) response; int storyId = 0; - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; for (int i = 0; i < updates.updates.size(); i++) { - if (updates.updates.get(i) instanceof TLRPC.TL_updateStory) { - TLRPC.TL_updateStory updateStory = (TLRPC.TL_updateStory) updates.updates.get(i); + if (updates.updates.get(i) instanceof TL_stories.TL_updateStory) { + TL_stories.TL_updateStory updateStory = (TL_stories.TL_updateStory) updates.updates.get(i); updateStory.story.attachPath = path; updateStory.story.firstFramePath = firstFramePath; updateStory.story.justUploaded = !edit; @@ -1948,7 +2057,7 @@ public class StoriesController { if (updates.updates.get(i) instanceof TLRPC.TL_updateStoryID) { TLRPC.TL_updateStoryID updateStory = (TLRPC.TL_updateStoryID) updates.updates.get(i); if (storyItem == null) { - storyItem = new TLRPC.TL_storyItem(); + storyItem = new TL_stories.TL_storyItem(); storyItem.date = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); storyItem.expire_date = storyItem.date + (entry.period == Integer.MAX_VALUE ? 86400 : entry.period); storyItem.parsedPrivacy = null; @@ -1964,21 +2073,24 @@ public class StoriesController { } final long did = dialogId; if (canceled) { - TLRPC.TL_stories_deleteStories stories_deleteStory = new TLRPC.TL_stories_deleteStories(); - stories_deleteStory.id.add(storyId); - ConnectionsManager.getInstance(currentAccount).sendRequest(stories_deleteStory, (response1, error1) -> { - AndroidUtilities.runOnUIThread(StoriesController.this::invalidateStoryLimit); - }); + TL_stories.TL_stories_deleteStories stories_deleteStory = new TL_stories.TL_stories_deleteStories(); + stories_deleteStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); + if (stories_deleteStory.peer != null) { + stories_deleteStory.id.add(storyId); + ConnectionsManager.getInstance(currentAccount).sendRequest(stories_deleteStory, (response1, error1) -> { + AndroidUtilities.runOnUIThread(StoriesController.this::invalidateStoryLimit); + }); + } } else { if ((storyId == 0 || edit) && storyItem != null) { - TLRPC.TL_updateStory tl_updateStory = new TLRPC.TL_updateStory(); + TL_stories.TL_updateStory tl_updateStory = new TL_stories.TL_updateStory(); tl_updateStory.peer = MessagesController.getInstance(currentAccount).getPeer(did); tl_updateStory.story = storyItem; AndroidUtilities.runOnUIThread(() -> { MessagesController.getInstance(currentAccount).getStoriesController().processUpdate(tl_updateStory); }); } - final TLRPC.StoryItem storyItemFinal = storyItem; + final TL_stories.StoryItem storyItemFinal = storyItem; if (storyItemFinal.media != null && storyItemFinal.attachPath != null) { if (storyItemFinal.media.document != null) { FileLoader.getInstance(currentAccount).setLocalPathTo(storyItemFinal.media.document, storyItemFinal.attachPath); @@ -2039,9 +2151,9 @@ public class StoriesController { for (int i = 0; i < count; ++i) { long userId = entry.shareUserIds.get(i); if (entry.wouldBeVideo()) { - SendMessagesHelper.prepareSendingVideo(AccountInstance.getInstance(currentAccount), path, null, userId, null, null, null, captionEntities, 0, null, !entry.silent, entry.scheduleDate, false, false, caption); + SendMessagesHelper.prepareSendingVideo(AccountInstance.getInstance(currentAccount), path, null, userId, null, null, null, null, captionEntities, 0, null, !entry.silent, entry.scheduleDate, false, false, caption); } else { - SendMessagesHelper.prepareSendingPhoto(AccountInstance.getInstance(currentAccount), path, null, null, userId, null, null, null, captionEntities, null, null, 0, null, null, !entry.silent, entry.scheduleDate, false, caption /* TODO: */); + SendMessagesHelper.prepareSendingPhoto(AccountInstance.getInstance(currentAccount), path, null, null, userId, null, null, null, null, captionEntities, null, null, 0, null, null, !entry.silent, entry.scheduleDate, false, caption /* TODO: */); } } putMessages = true; @@ -2087,7 +2199,7 @@ public class StoriesController { return list; } - private static String storyItemIds(List storyItems) { + private static String storyItemIds(List storyItems) { try { if (storyItems == null) { return "null"; @@ -2111,7 +2223,7 @@ public class StoriesController { String s = ""; for (int i = 0; i < storyItems.size(); ++i) { if (i > 0) s += ", "; - TLRPC.StoryItem storyItem = storyItems.get(i).storyItem; + TL_stories.StoryItem storyItem = storyItems.get(i).storyItem; if (storyItem == null) { s += "null"; } else @@ -2123,7 +2235,7 @@ public class StoriesController { } } - public void updateStoriesInLists(long dialogId, List storyItems) { + public void updateStoriesInLists(long dialogId, List storyItems) { FileLog.d("updateStoriesInLists " + dialogId + " storyItems[" + storyItems.size() + "] {" + storyItemIds(storyItems) + "}"); StoriesList pinned = getStoriesList(dialogId, StoriesList.TYPE_PINNED, false); StoriesList archived = getStoriesList(dialogId, StoriesList.TYPE_ARCHIVE, false); @@ -2135,7 +2247,7 @@ public class StoriesController { } } - public void updateDeletedStoriesInLists(long dialogId, List storyItems) { + public void updateDeletedStoriesInLists(long dialogId, List storyItems) { FileLog.d("updateDeletedStoriesInLists " + dialogId + " storyItems[" + storyItems.size() + "] {" + storyItemIds(storyItems) + "}"); StoriesList pinned = getStoriesList(dialogId, StoriesList.TYPE_PINNED, false); StoriesList archived = getStoriesList(dialogId, StoriesList.TYPE_ARCHIVE, false); @@ -2291,7 +2403,7 @@ public class StoriesController { while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { - TLRPC.StoryItem storyItem = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(true), true); + TL_stories.StoryItem storyItem = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(true), true); storyItem.dialogId = dialogId; storyItem.messageId = storyItem.id; MessageObject msg = new MessageObject(currentAccount, storyItem); @@ -2457,7 +2569,7 @@ public class StoriesController { for (int i = 0; i < toSave.size(); ++i) { MessageObject messageObject = toSave.get(i); - TLRPC.StoryItem storyItem = messageObject.storyItem; + TL_stories.StoryItem storyItem = messageObject.storyItem; if (storyItem == null) { continue; } @@ -2518,7 +2630,7 @@ public class StoriesController { final int offset_id; TLObject request; if (type == TYPE_PINNED) { - TLRPC.TL_stories_getPinnedStories req = new TLRPC.TL_stories_getPinnedStories(); + TL_stories.TL_stories_getPinnedStories req = new TL_stories.TL_stories_getPinnedStories(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); if (!loadedObjects.isEmpty()) { req.offset_id = offset_id = loadedObjects.last(); @@ -2528,7 +2640,7 @@ public class StoriesController { req.limit = count; request = req; } else { - TLRPC.TL_stories_getStoriesArchive req = new TLRPC.TL_stories_getStoriesArchive(); + TL_stories.TL_stories_getStoriesArchive req = new TL_stories.TL_stories_getStoriesArchive(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); if (!loadedObjects.isEmpty()) { req.offset_id = offset_id = loadedObjects.last(); @@ -2542,11 +2654,11 @@ public class StoriesController { loading = true; ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, err) -> { - if (response instanceof TLRPC.TL_stories_stories) { + if (response instanceof TL_stories.TL_stories_stories) { ArrayList newMessageObjects = new ArrayList<>(); - TLRPC.TL_stories_stories stories = (TLRPC.TL_stories_stories) response; + TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; for (int i = 0; i < stories.stories.size(); ++i) { - TLRPC.StoryItem storyItem = stories.stories.get(i); + TL_stories.StoryItem storyItem = stories.stories.get(i); newMessageObjects.add(toMessageObject(storyItem)); } AndroidUtilities.runOnUIThread(() -> { @@ -2618,14 +2730,14 @@ public class StoriesController { // load(true, Utilities.clamp(wasCount, 50, 10)); // } - public void updateDeletedStories(List storyItems) { + public void updateDeletedStories(List storyItems) { FileLog.d("StoriesList " + type + "{"+ dialogId +"} updateDeletedStories {" + storyItemIds(storyItems) + "}"); if (storyItems == null) { return; } boolean changed = false; for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); + TL_stories.StoryItem storyItem = storyItems.get(i); if (storyItem == null) { continue; } @@ -2646,20 +2758,41 @@ public class StoriesController { } } - public void updateStories(List storyItems) { + public void updateStoryViews(List ids, ArrayList storyViews) { + if (ids == null || storyViews == null) { + return; + } + boolean changed = false; + for (int i = 0; i < ids.size(); ++i) { + int id = ids.get(i); + if (i >= storyViews.size()) break; + TL_stories.StoryViews storyView = storyViews.get(i); + + MessageObject messageObject = messageObjectsMap.get(id); + if (messageObject != null && messageObject.storyItem != null) { + messageObject.storyItem.views = storyView; + changed = true; + } + } + if (changed) { + saveCache(); + } + } + + public void updateStories(List storyItems) { FileLog.d("StoriesList " + type + "{"+ dialogId +"} updateStories {" + storyItemIds(storyItems) + "}"); if (storyItems == null) { return; } boolean changed = false; for (int i = 0; i < storyItems.size(); ++i) { - TLRPC.StoryItem storyItem = storyItems.get(i); + TL_stories.StoryItem storyItem = storyItems.get(i); if (storyItem == null) { continue; } boolean contains = loadedObjects.contains(storyItem.id) || cachedObjects.contains(storyItem.id); boolean shouldContain = type == TYPE_ARCHIVE ? true : storyItem.pinned; - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { shouldContain = false; } if (contains != shouldContain) { @@ -2696,7 +2829,7 @@ public class StoriesController { return messageObjectsMap.get(storyId); } - public boolean equal(TLRPC.StoryItem a, TLRPC.StoryItem b) { + public boolean equal(TL_stories.StoryItem a, TL_stories.StoryItem b) { if (a == null && b == null) { return true; } @@ -2711,7 +2844,7 @@ public class StoriesController { ); } - private MessageObject toMessageObject(TLRPC.StoryItem storyItem) { + private MessageObject toMessageObject(TL_stories.StoryItem storyItem) { storyItem.dialogId = dialogId; storyItem.messageId = storyItem.id; MessageObject msg = new MessageObject(currentAccount, storyItem); @@ -2747,7 +2880,7 @@ public class StoriesController { } } - private final Comparator peerStoriesComparator = (o1, o2) -> { + private final Comparator peerStoriesComparator = (o1, o2) -> { long dialogId1 = DialogObject.getPeerDialogId(o1.peer); long dialogId2 = DialogObject.getPeerDialogId(o2.peer); boolean hasUploading1 = hasUploadingStories(dialogId1); @@ -2803,11 +2936,11 @@ public class StoriesController { return hasSelfStories() && (getDialogListStories().isEmpty() || (getDialogListStories().size() == 1 && DialogObject.getPeerDialogId(getDialogListStories().get(0).peer) == UserConfig.getInstance(currentAccount).clientUserId)); } - private List filteredHiddenStories() { + private List filteredHiddenStories() { return FakePasscodeUtils.filterStories(hiddenListStories, currentAccount); } - private List filteredStories() { + private List filteredStories() { return FakePasscodeUtils.filterStories(dialogListStories, currentAccount); } @@ -2926,7 +3059,7 @@ public class StoriesController { })); } - public boolean isBlocked(TLRPC.TL_storyView storyView) { + public boolean isBlocked(TL_stories.TL_storyView storyView) { if (storyView == null) { return false; } @@ -2949,12 +3082,12 @@ public class StoriesController { return blocklist.contains(did); } - public void applyStoryViewsBlocked(TLRPC.TL_stories_storyViewsList res) { + public void applyStoryViewsBlocked(TL_stories.TL_stories_storyViewsList res) { if (res == null || res.views == null) { return; } for (int i = 0; i < res.views.size(); ++i) { - TLRPC.TL_storyView view = res.views.get(i); + TL_stories.TL_storyView view = res.views.get(i); if (blockedOverride.containsKey(view.user_id)) { blockedOverride.put(view.user_id, view.blocked_my_stories_from); } @@ -3017,7 +3150,7 @@ public class StoriesController { return storyLimitCached; } - TLRPC.TL_stories_canSendStory tl_stories_canSendStory = new TLRPC.TL_stories_canSendStory(); + TL_stories.TL_stories_canSendStory tl_stories_canSendStory = new TL_stories.TL_stories_canSendStory(); tl_stories_canSendStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(UserConfig.getInstance(currentAccount).getClientUserId()); ConnectionsManager.getInstance(currentAccount).sendRequest(tl_stories_canSendStory, (res, err) -> AndroidUtilities.runOnUIThread(() -> { storyLimitFetched = true; @@ -3032,7 +3165,7 @@ public class StoriesController { } public void canSendStoryFor(long dialogId, Consumer consumer, boolean showLimitsBottomSheet, Theme.ResourcesProvider resourcesProvider) { - TLRPC.TL_stories_canSendStory tl_stories_canSendStory = new TLRPC.TL_stories_canSendStory(); + TL_stories.TL_stories_canSendStory tl_stories_canSendStory = new TL_stories.TL_stories_canSendStory(); tl_stories_canSendStory.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); ConnectionsManager.getInstance(currentAccount).sendRequest(tl_stories_canSendStory, (res, err) -> AndroidUtilities.runOnUIThread(() -> { if (err != null) { @@ -3181,7 +3314,7 @@ public class StoriesController { return; } loadingSendAs = true; - ConnectionsManager.getInstance(currentAccount).sendRequest(new TLRPC.TL_stories_getChatsToSend(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { + ConnectionsManager.getInstance(currentAccount).sendRequest(new TL_stories.TL_stories_getChatsToSend(), (res, err) -> AndroidUtilities.runOnUIThread(() -> { sendAs.clear(); sendAs.add(new TLRPC.TL_inputPeerSelf()); if (res instanceof TLRPC.TL_messages_chats) { @@ -3225,7 +3358,7 @@ public class StoriesController { return false; } - public boolean canEditStory(TLRPC.StoryItem storyItem) { + public boolean canEditStory(TL_stories.StoryItem storyItem) { if (storyItem == null) { return false; } @@ -3250,7 +3383,7 @@ public class StoriesController { return false; } - public boolean canDeleteStory(TLRPC.StoryItem storyItem) { + public boolean canDeleteStory(TL_stories.StoryItem storyItem) { if (storyItem == null) { return false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesIntro.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesIntro.java new file mode 100644 index 000000000..8b45f6a74 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesIntro.java @@ -0,0 +1,289 @@ +package org.telegram.ui.Stories; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.drawable.BitmapDrawable; +import android.text.TextPaint; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewTreeObserver; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieDrawable; + +import java.util.ArrayList; + +@SuppressLint("ViewConstructor") +public class StoriesIntro extends FrameLayout { + + private final ArrayList items; + private ValueAnimator valueAnimator; + private int prev = -1; + private int current = 0; + private final Runnable startItemAnimationRunnable = () -> { + updateCurrentAnimatedItem(); + startAnimation(true); + }; + + public StoriesIntro(Context context, View parentView) { + super(context); + ImageView backgroundImageView = new ImageView(context); + addView(backgroundImageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + View scrim = new View(context); + scrim.setBackgroundColor(0x64000000); // 40% + addView(scrim, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(0, AndroidUtilities.dp(48), 0, AndroidUtilities.dp(48)); + linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); + + TextView header = new TextView(context); + header.setTextColor(Color.WHITE); + header.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + header.setText(LocaleController.getString("StoriesIntroHeader", R.string.StoriesIntroHeader)); + header.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + linearLayout.addView(header, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + + TextView subHeader = new TextView(context); + subHeader.setTextColor(0x96FFFFFF); // 60% + subHeader.setText(LocaleController.getString("StoriesIntroSubHeader", R.string.StoriesIntroSubHeader)); + subHeader.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subHeader.setGravity(Gravity.CENTER_HORIZONTAL); + linearLayout.addView(subHeader, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 68, 8, 68, 36)); + + items = new ArrayList<>(4); + items.add(new StoriesIntroItemView(context, R.raw.stories_intro_go_forward, LocaleController.getString("StoriesIntroGoForwardHeader", R.string.StoriesIntroGoForwardHeader), LocaleController.getString("StoriesIntroGoForwardSubHeader", R.string.StoriesIntroGoForwardSubHeader))); + items.add(new StoriesIntroItemView(context, R.raw.stories_intro_pause, LocaleController.getString("StoriesIntroPauseAndSeekHeader", R.string.StoriesIntroPauseAndSeekHeader), LocaleController.getString("StoriesIntroPauseAndSeekSubHeader", R.string.StoriesIntroPauseAndSeekSubHeader))); + items.add(new StoriesIntroItemView(context, R.raw.stories_intro_go_back, LocaleController.getString("StoriesIntroGoBackHeader", R.string.StoriesIntroGoBackHeader), LocaleController.getString("StoriesIntroGoBackSubHeader", R.string.StoriesIntroGoBackSubHeader))); + items.add(new StoriesIntroItemView(context, R.raw.stories_intro_go_to_next, LocaleController.getString("StoriesIntroGoToNextAuthorHeader", R.string.StoriesIntroGoToNextAuthorHeader), LocaleController.getString("StoriesIntroGoToNextAuthorSubHeader", R.string.StoriesIntroGoToNextAuthorSubHeader))); + + // adjust the width for small devices + int storiesIntroItemViewWidth = parentView.getMeasuredWidth() - AndroidUtilities.dp(100); + for (StoriesIntroItemView storiesIntroItemView : items) { + int w = storiesIntroItemView.getRequiredWidth(); + if (w > storiesIntroItemViewWidth) { + storiesIntroItemViewWidth = w; + } + } + if (storiesIntroItemViewWidth + AndroidUtilities.dp(8) > parentView.getMeasuredWidth()) { + storiesIntroItemViewWidth = parentView.getMeasuredWidth() - AndroidUtilities.dp(8); + } + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(storiesIntroItemViewWidth, AndroidUtilities.dp(64)); + layoutParams.setMargins(0, AndroidUtilities.dp(5), 0, AndroidUtilities.dp(5)); + for (StoriesIntroItemView storiesIntroItemView : items) { + linearLayout.addView(storiesIntroItemView, layoutParams); + } + TextView bottomText = new TextView(context); + bottomText.setTextColor(Color.WHITE); + bottomText.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + bottomText.setText(LocaleController.getString("StoriesIntroDismiss", R.string.StoriesIntroDismiss)); + bottomText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + linearLayout.addView(bottomText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 73, 0, 0)); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + + BitmapDrawable bitmap = new BitmapDrawable(getContext().getResources(), AndroidUtilities.makeBlurBitmap(parentView, 12f, 10)); + bitmap.setColorFilter(new PorterDuffColorFilter(0xdd000000, PorterDuff.Mode.DST_OVER)); + backgroundImageView.setImageDrawable(bitmap); + + // adjusts for small devices + getViewTreeObserver().addOnGlobalLayoutListener( + new ViewTreeObserver.OnGlobalLayoutListener() { + public void onGlobalLayout() { + int[] bottomTextLocation = new int[2]; + bottomText.getLocationOnScreen(bottomTextLocation); + if (bottomTextLocation[1] + AndroidUtilities.dp(24) > parentView.getMeasuredHeight()) { + bottomText.setLayoutParams(LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 13, 0, 0)); + subHeader.setLayoutParams(LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 68, 8, 68, 13)); + requestLayout(); + } + getViewTreeObserver().removeOnGlobalLayoutListener(this); + } + } + ); + } + + void startAnimation(boolean delay) { + if (valueAnimator != null) { + valueAnimator.cancel(); + } + valueAnimator = ValueAnimator.ofFloat(0f, 1f); + if (delay) { + valueAnimator.setStartDelay(50L); + } + valueAnimator.setDuration(350L); + valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); + valueAnimator.getCurrentPlayTime(); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + items.get(current).startIconAnimation(); + } + }); + valueAnimator.addUpdateListener(animation -> { + float progress = (float) animation.getAnimatedValue(); + items.get(current).setProgress(progress); + if (prev != -1) { + items.get(prev).setProgress(1f - progress); + } + }); + valueAnimator.start(); + AndroidUtilities.runOnUIThread(startItemAnimationRunnable, items.get(current).getLottieAnimationDuration() + 100); + } + + public void stopAnimation() { + AndroidUtilities.cancelRunOnUIThread(startItemAnimationRunnable); + if (valueAnimator != null) { + valueAnimator.cancel(); + valueAnimator = null; + } + if (prev != -1) { + items.get(prev).stopAnimation(); + } + items.get(current).stopAnimation(); + updateCurrentAnimatedItem(); + } + + private void updateCurrentAnimatedItem() { + current++; + if (current >= items.size()) { + current = 0; + } + prev++; + if (prev >= items.size()) { + prev = 0; + } + } + + @SuppressLint("ViewConstructor") + static class StoriesIntroItemView extends View { + + private final String header; + private final String subHeader; + private final RLottieDrawable lottieDrawable; + private final Paint backgroundPaint; + private final TextPaint headerTextPaint; + private final TextPaint subHeaderTextPaint; + private final RectF rectF; + private float progress; + private final Rect textBounds = new Rect(); + + public StoriesIntroItemView(Context context, int rawRes, String header, String subHeader) { + super(context); + this.header = header; + this.subHeader = subHeader; + lottieDrawable = new RLottieDrawable(rawRes, "" + rawRes, AndroidUtilities.dp(36), AndroidUtilities.dp(36), true, null); + lottieDrawable.setAutoRepeat(1); + lottieDrawable.setMasterParent(this); + + backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint.setColor(0x16D8D8D8); + + headerTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + headerTextPaint.setColor(Color.WHITE); + headerTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics())); + headerTextPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + + subHeaderTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + subHeaderTextPaint.setColor(0x96FFFFFF); + + subHeaderTextPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 14, getResources().getDisplayMetrics())); + rectF = new RectF(); + } + + public int getRequiredWidth() { + headerTextPaint.getTextBounds(header, 0, header.length(), textBounds); + int headerWidth = textBounds.width(); + subHeaderTextPaint.getTextBounds(subHeader, 0, subHeader.length(), textBounds); + int subHeaderWidth = textBounds.width(); + return AndroidUtilities.dp(88) + AndroidUtilities.dp(8) + Math.max(headerWidth, subHeaderWidth); + } + + public long getLottieAnimationDuration() { + return lottieDrawable.getDuration() * 2; + } + + public void startAnimation() { + lottieDrawable.start(); + progress = 1f; + invalidate(); + } + + public void stopAnimation() { + lottieDrawable.setCurrentFrame(0); + lottieDrawable.stop(); + progress = 0f; + invalidate(); + } + + public void startIconAnimation() { + lottieDrawable.setAutoRepeatCount(2); + lottieDrawable.start(); + } + + public void setProgress(float progress) { + this.progress = progress; + invalidate(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int iconCx = AndroidUtilities.dp(40); + int iconCy = getMeasuredHeight() / 2; + int size = AndroidUtilities.dp(36); + int left = iconCx - size / 2; + int top = iconCy - size / 2; + int right = left + size; + int bottom = top + size; + lottieDrawable.setBounds(left, top, right, bottom); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + int iconCx = AndroidUtilities.dp(40); + int iconCy = getMeasuredHeight() / 2; + int size = (int) (AndroidUtilities.dp(36) + AndroidUtilities.dp(8) * progress); + int left = iconCx - size / 2; + int top = iconCy - size / 2; + int right = left + size; + int bottom = top + size; + lottieDrawable.setBounds(left, top, right, bottom); + lottieDrawable.draw(canvas); + if (progress > 0f) { + float backgroundOffset = AndroidUtilities.dpf2(4) * (1f - progress); + rectF.set(backgroundOffset, backgroundOffset, getMeasuredWidth() - backgroundOffset * 2, getMeasuredHeight() - backgroundOffset * 2); + backgroundPaint.setAlpha((int) (30 * progress)); + canvas.drawRoundRect(rectF, AndroidUtilities.dpf2(12f), AndroidUtilities.dpf2(12f), backgroundPaint); + canvas.save(); + canvas.scale(1 + 0.05f * progress, 1 + 0.05f * progress, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + } + canvas.drawText(header, AndroidUtilities.dpf2(80), getMeasuredHeight() / 2f - AndroidUtilities.dpf2(4), headerTextPaint); + canvas.drawText(subHeader, AndroidUtilities.dpf2(80), getMeasuredHeight() / 2f + AndroidUtilities.dpf2(18), subHeaderTextPaint); + if (progress > 0) { + canvas.restore(); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java index 258a6b1ef..cd3998657 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesListPlaceProvider.java @@ -8,13 +8,10 @@ import android.graphics.Path; import android.graphics.Region; import android.view.View; -import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.Utilities; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.Cells.ChatMessageCell; @@ -25,7 +22,6 @@ import org.telegram.ui.Cells.SharedPhotoVideoCell2; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Components.BlurredRecyclerView; import org.telegram.ui.Components.RecyclerListView; -import org.telegram.ui.Components.SharedMediaLayout; public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { @@ -154,7 +150,7 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { ChatActionCell cell = (ChatActionCell) child; if (cell.getMessageObject().getId() == messageId) { holder.view = child; - TLRPC.StoryItem storyItem = cell.getMessageObject().messageOwner.media.storyItem; + TL_stories.StoryItem storyItem = cell.getMessageObject().messageOwner.media.storyItem; if (storyItem.noforwards) { holder.avatarImage = cell.getPhotoImage(); } else { @@ -181,6 +177,7 @@ public class StoriesListPlaceProvider implements StoryViewer.PlaceProvider { holder.storyImage = cell.imageReceiver; holder.drawAbove = (canvas, bounds, alpha, opening) -> { cell.drawDuration(canvas, bounds, alpha); + cell.drawViews(canvas, bounds, alpha); if (fastScroll != null && fastScroll.isVisible && fastScroll.getVisibility() == View.VISIBLE) { canvas.saveLayerAlpha(0, 0, canvas.getWidth(), canvas.getHeight(), (int) (0xFF * alpha), Canvas.ALL_SAVE_FLAG); canvas.translate(loc[0], loc[1]); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java index 515872641..e43c492ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesStorage.java @@ -22,6 +22,7 @@ import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import java.util.ArrayList; import java.util.Collections; @@ -41,11 +42,11 @@ public class StoriesStorage { } - public void getAllStories(Consumer consumer) { + public void getAllStories(Consumer consumer) { storage.getStorageQueue().postRunnable(() -> { SQLiteDatabase database = storage.getDatabase(); SQLiteCursor cursor = null; - ArrayList userStoriesArray = new ArrayList<>(); + ArrayList userStoriesArray = new ArrayList<>(); ArrayList usersToLoad = new ArrayList<>(); ArrayList chatsToLoad = new ArrayList<>(); boolean failed = false; @@ -70,12 +71,12 @@ public class StoriesStorage { long dialogId = dialogsCounter.keyAt(i); int maxReadId = dialogsCounter.valueAt(i); cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, custom_params FROM stories WHERE dialog_id = %d", dialogId)); - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); NativeByteBuffer customData = cursor.byteBufferValue(1); if (data != null) { - TLRPC.StoryItem storyItem = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(true), true); + TL_stories.StoryItem storyItem = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(true), true); storyItem.dialogId = dialogId; StoryCustomParamsHelper.readLocalParams(storyItem, customData); storyItems.add(storyItem); @@ -87,8 +88,8 @@ public class StoriesStorage { } cursor.dispose(); cursor = null; - TLRPC.PeerStories userStories; - userStories = new TLRPC.TL_peerStories(); + TL_stories.PeerStories userStories; + userStories = new TL_stories.TL_peerStories(); userStories.stories = storyItems; userStories.max_read_id = maxReadId; userStories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId); @@ -106,12 +107,12 @@ public class StoriesStorage { AndroidUtilities.runOnUIThread(() -> consumer.accept(null)); return; } - TLRPC.TL_stories_allStories storiesResponse = new TLRPC.TL_stories_allStories(); + TL_stories.TL_stories_allStories storiesResponse = new TL_stories.TL_stories_allStories(); storiesResponse.peer_stories = userStoriesArray; storiesResponse.users = storage.getUsers(usersToLoad); storiesResponse.chats = storage.getChats(chatsToLoad); for (int i = 0; i < storiesResponse.peer_stories.size(); i++) { - TLRPC.PeerStories userStories = storiesResponse.peer_stories.get(i); + TL_stories.PeerStories userStories = storiesResponse.peer_stories.get(i); long dialogId = DialogObject.getPeerDialogId(userStories.peer); checkExpiredStories(dialogId, userStories.stories); if (userStories.stories.isEmpty()) { @@ -127,13 +128,13 @@ public class StoriesStorage { }); } - private void checkExpiredStories(long dialogId, ArrayList stories) { + private void checkExpiredStories(long dialogId, ArrayList stories) { int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); SQLiteDatabase database = storage.getDatabase(); ArrayList storiesToDeleteIds = null; - ArrayList storiesToDelete = null; + ArrayList storiesToDelete = null; for (int i = 0; i < stories.size(); i++) { - TLRPC.StoryItem storyItem = stories.get(i); + TL_stories.StoryItem storyItem = stories.get(i); if (currentTime > stories.get(i).expire_date) { if (storiesToDeleteIds == null) { storiesToDeleteIds = new ArrayList<>(); @@ -153,21 +154,21 @@ public class StoriesStorage { } catch (SQLiteException e) { FileLog.e(e); } - ArrayList finalStoriesToDelete = storiesToDelete; + ArrayList finalStoriesToDelete = storiesToDelete; } } - public void putStoriesInternal(long dialogId, TLRPC.PeerStories userStories) { + public void putStoriesInternal(long dialogId, TL_stories.PeerStories userStories) { SQLiteDatabase database = storage.getDatabase(); try { if (userStories != null) { - ArrayList storyItems = userStories.stories; + ArrayList storyItems = userStories.stories; SQLitePreparedStatement state = database.executeFast("REPLACE INTO stories VALUES(?, ?, ?, ?)"); for (int i = 0; i < storyItems.size(); i++) { state.requery(); - TLRPC.StoryItem storyItem = storyItems.get(i); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { FileLog.e("try write deleted story"); continue; } @@ -197,11 +198,11 @@ public class StoriesStorage { } } - public void putStoryInternal(long dialogId, TLRPC.StoryItem storyItem) { + public void putStoryInternal(long dialogId, TL_stories.StoryItem storyItem) { SQLiteDatabase database = storage.getDatabase(); try { SQLitePreparedStatement state = database.executeFast("REPLACE INTO stories VALUES(?, ?, ?, ?)"); - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { FileLog.e("putStoryInternal: try write deleted story"); return; } @@ -228,11 +229,11 @@ public class StoriesStorage { } } - public void saveAllStories(ArrayList user_stories, boolean isNext, boolean hidden, Runnable callback) { + public void saveAllStories(ArrayList user_stories, boolean isNext, boolean hidden, Runnable callback) { storage.getStorageQueue().postRunnable(() -> { SQLiteDatabase database = storage.getDatabase(); for (int i = 0; i < user_stories.size(); i++) { - TLRPC.PeerStories stories = user_stories.get(i); + TL_stories.PeerStories stories = user_stories.get(i); fillSkippedStories(DialogObject.getPeerDialogId(stories.peer), stories); } if (!isNext) { @@ -269,7 +270,7 @@ public class StoriesStorage { } } for (int i = 0; i < user_stories.size(); i++) { - TLRPC.PeerStories stories = user_stories.get(i); + TL_stories.PeerStories stories = user_stories.get(i); putStoriesInternal(DialogObject.getPeerDialogId(stories.peer), stories); } if (callback != null) { @@ -278,15 +279,15 @@ public class StoriesStorage { }); } - private void fillSkippedStories(long user_id, TLRPC.PeerStories userStories) { + private void fillSkippedStories(long user_id, TL_stories.PeerStories userStories) { try { if (userStories != null) { - ArrayList storyItems = userStories.stories; + ArrayList storyItems = userStories.stories; for (int i = 0; i < storyItems.size(); i++) { - TLRPC.StoryItem storyItem = storyItems.get(i); - if (storyItem instanceof TLRPC.TL_storyItemSkipped) { - TLRPC.StoryItem storyInDatabase = getStoryInternal(user_id, storyItems.get(i).id); - if (storyInDatabase instanceof TLRPC.TL_storyItem) { + TL_stories.StoryItem storyItem = storyItems.get(i); + if (storyItem instanceof TL_stories.TL_storyItemSkipped) { + TL_stories.StoryItem storyInDatabase = getStoryInternal(user_id, storyItems.get(i).id); + if (storyInDatabase instanceof TL_stories.TL_storyItem) { storyItems.set(i, storyInDatabase); } } @@ -297,10 +298,10 @@ public class StoriesStorage { } } - private TLRPC.StoryItem getStoryInternal(long user_id, int storyId) { + private TL_stories.StoryItem getStoryInternal(long user_id, int storyId) { SQLiteDatabase database = storage.getDatabase(); SQLiteCursor cursor = null; - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; try { cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, custom_params FROM stories WHERE dialog_id = %d AND story_id = %d", user_id, storyId)); @@ -308,7 +309,7 @@ public class StoriesStorage { NativeByteBuffer data = cursor.byteBufferValue(0); NativeByteBuffer customData = cursor.byteBufferValue(1); if (data != null) { - storyItem = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(true), true); + storyItem = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(true), true); storyItem.dialogId = user_id; data.reuse(); } @@ -327,17 +328,17 @@ public class StoriesStorage { } - public void getStories(long dialogId, Consumer consumer) { + public void getStories(long dialogId, Consumer consumer) { storage.getStorageQueue().postRunnable(() -> { - TLRPC.PeerStories finalUserStories = getStoriesInternal(dialogId); + TL_stories.PeerStories finalUserStories = getStoriesInternal(dialogId); AndroidUtilities.runOnUIThread(() -> consumer.accept(finalUserStories)); }); } - private TLRPC.PeerStories getStoriesInternal(long dialogId) { + private TL_stories.PeerStories getStoriesInternal(long dialogId) { SQLiteDatabase database = storage.getDatabase(); SQLiteCursor cursor = null; - TLRPC.PeerStories userStories = null; + TL_stories.PeerStories userStories = null; try { cursor = database.queryFinalized(String.format(Locale.US, "SELECT count, max_read FROM stories_counter WHERE dialog_id = %d", dialogId)); int count = 0; @@ -350,12 +351,12 @@ public class StoriesStorage { cursor = null; cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, custom_params FROM stories WHERE dialog_id = %d", dialogId)); - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); NativeByteBuffer customData = cursor.byteBufferValue(1); if (data != null) { - TLRPC.StoryItem storyItem = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(true), true); + TL_stories.StoryItem storyItem = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(true), true); StoryCustomParamsHelper.readLocalParams(storyItem, customData); storyItems.add(storyItem); data.reuse(); @@ -366,7 +367,7 @@ public class StoriesStorage { } cursor.dispose(); cursor = null; - userStories = new TLRPC.TL_peerStories(); + userStories = new TL_stories.TL_peerStories(); userStories.max_read_id = maxReadId; userStories.stories = storyItems; userStories.peer = MessagesController.getInstance(currentAccount).getPeer(dialogId); @@ -381,7 +382,7 @@ public class StoriesStorage { return userStories; } - public void updateStoryItem(long dialogId, TLRPC.StoryItem storyItem) { + public void updateStoryItem(long dialogId, TL_stories.StoryItem storyItem) { if (dialogId == 0) { return; } @@ -390,11 +391,11 @@ public class StoriesStorage { }); } - private void updateStoryItemInternal(long dialogId, TLRPC.StoryItem storyItem) { + private void updateStoryItemInternal(long dialogId, TL_stories.StoryItem storyItem) { if (dialogId == 0 || storyItem == null) { return; } - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { FileLog.e("StoriesStorage: try write deleted story"); } if (StoriesUtilities.isExpired(currentAccount, storyItem)) { @@ -452,7 +453,7 @@ public class StoriesStorage { }); } - public void processUpdate(TLRPC.TL_updateStory updateStory) { + public void processUpdate(TL_stories.TL_updateStory updateStory) { storage.getStorageQueue().postRunnable(() -> { SQLiteDatabase database = storage.getDatabase(); SQLiteCursor cursor = null; @@ -461,13 +462,13 @@ public class StoriesStorage { int count = 0; int storyId = updateStory.story.id; boolean storyExist = false; - if (updateStory.story instanceof TLRPC.TL_storyItemDeleted) { + if (updateStory.story instanceof TL_stories.TL_storyItemDeleted) { cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, custom_params FROM stories WHERE dialog_id = %d AND story_id = %d", dialogId, storyId)); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); NativeByteBuffer customData = cursor.byteBufferValue(1); if (data != null) { - TLRPC.StoryItem storyItem = TLRPC.StoryItem.TLdeserialize(data, data.readInt32(true), true); + TL_stories.StoryItem storyItem = TL_stories.StoryItem.TLdeserialize(data, data.readInt32(true), true); StoryCustomParamsHelper.readLocalParams(storyItem, customData); data.reuse(); } @@ -481,7 +482,7 @@ public class StoriesStorage { if (storyExist) { count--; } - } else if (updateStory.story instanceof TLRPC.TL_storyItem) { + } else if (updateStory.story instanceof TL_stories.TL_storyItem) { updateStoryItemInternal(dialogId, updateStory.story); cursor = database.queryFinalized(String.format(Locale.US, "SELECT story_id FROM stories WHERE dialog_id = %d AND story_id = %d", dialogId, storyId)); if (cursor.next()) { @@ -509,7 +510,7 @@ public class StoriesStorage { }); } - public void updateStories(TLRPC.PeerStories currentStories) { + public void updateStories(TL_stories.PeerStories currentStories) { storage.getStorageQueue().postRunnable(() -> { for (int i = 0; i < currentStories.stories.size(); i++) { updateStoryItemInternal(DialogObject.getPeerDialogId(currentStories.peer), currentStories.stories.get(i)); @@ -542,6 +543,9 @@ public class StoriesStorage { //storage queue public void fillMessagesWithStories(LongSparseArray> messagesWithUnknownStories, Runnable runnable, int classGuid) { + fillMessagesWithStories(messagesWithUnknownStories, runnable, classGuid, true); + } + public void fillMessagesWithStories(LongSparseArray> messagesWithUnknownStories, Runnable runnable, int classGuid, boolean updateDatabase) { if (runnable == null) { return; } @@ -556,8 +560,8 @@ public class StoriesStorage { for (int j = 0; j < messageObjects.size(); j++) { MessageObject messageObject = messageObjects.get(j); int storyId = getStoryId(messageObject); - TLRPC.StoryItem storyItem = getStoryInternal(dialogId, storyId); - if (storyItem != null && !(storyItem instanceof TLRPC.TL_storyItemSkipped)) { + TL_stories.StoryItem storyItem = getStoryInternal(dialogId, storyId); + if (storyItem != null && !(storyItem instanceof TL_stories.TL_storyItemSkipped)) { applyStory(currentAccount, dialogId, messageObject, storyItem); updatedMessages.add(messageObject); @@ -571,21 +575,23 @@ public class StoriesStorage { } } - updateMessagesWithStories(updatedMessages); + if (updateDatabase) { + updateMessagesWithStories(updatedMessages); + } if (!messagesWithUnknownStories.isEmpty()) { int requestsCount[] = new int[]{messagesWithUnknownStories.size()}; for (int i = 0; i < messagesWithUnknownStories.size(); i++) { long dialogId = messagesWithUnknownStories.keyAt(i); ArrayList messageObjects = messagesWithUnknownStories.valueAt(i); - TLRPC.TL_stories_getStoriesByID request = new TLRPC.TL_stories_getStoriesByID(); + TL_stories.TL_stories_getStoriesByID request = new TL_stories.TL_stories_getStoriesByID(); request.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); for (int j = 0; j < messageObjects.size(); j++) { request.id.add(getStoryId(messageObjects.get(j))); } int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { if (response != null) { - TLRPC.TL_stories_stories stories = (TLRPC.TL_stories_stories) response; + TL_stories.TL_stories_stories stories = (TL_stories.TL_stories_stories) response; for (int j = 0; j < messageObjects.size(); j++) { MessageObject messageObject = messageObjects.get(j); boolean found = false; @@ -597,13 +603,15 @@ public class StoriesStorage { } } if (!found) { - TLRPC.TL_storyItemDeleted storyItemDeleted = new TLRPC.TL_storyItemDeleted(); + TL_stories.TL_storyItemDeleted storyItemDeleted = new TL_stories.TL_storyItemDeleted(); storyItemDeleted.id = getStoryId(messageObject); applyStory(currentAccount, dialogId, messageObject, storyItemDeleted); } - storage.getStorageQueue().postRunnable(() -> { - updateMessagesWithStories(messageObjects); - }); + if (updateDatabase) { + storage.getStorageQueue().postRunnable(() -> { + updateMessagesWithStories(messageObjects); + }); + } } } requestsCount[0]--; @@ -620,7 +628,7 @@ public class StoriesStorage { } } - public static void applyStory(int currentAccount, long dialogId, MessageObject messageObject, TLRPC.StoryItem storyItem) { + public static void applyStory(int currentAccount, long dialogId, MessageObject messageObject, TL_stories.StoryItem storyItem) { if (messageObject.messageOwner.reply_to instanceof TLRPC.TL_messageReplyStoryHeader && messageObject.messageOwner.reply_to.story_id == storyItem.id) { messageObject.messageOwner.replyStory = checkExpiredStateLocal(currentAccount, dialogId, storyItem); } @@ -716,8 +724,8 @@ public class StoriesStorage { } } - public static TLRPC.StoryItem checkExpiredStateLocal(int currentAccount, long dialogId, TLRPC.StoryItem storyItem) { - if (storyItem instanceof TLRPC.TL_storyItemDeleted) { + public static TL_stories.StoryItem checkExpiredStateLocal(int currentAccount, long dialogId, TL_stories.StoryItem storyItem) { + if (storyItem instanceof TL_stories.TL_storyItemDeleted) { return storyItem; } int currentTime = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); @@ -728,7 +736,7 @@ public class StoriesStorage { expired = currentTime - storyItem.date > EXPIRE_AFTER; } if (!storyItem.pinned && expired && dialogId != 0 && dialogId != UserConfig.getInstance(currentAccount).clientUserId) { - TLRPC.TL_storyItemDeleted storyItemDeleted = new TLRPC.TL_storyItemDeleted(); + TL_stories.TL_storyItemDeleted storyItemDeleted = new TL_stories.TL_storyItemDeleted(); storyItemDeleted.id = storyItem.id; return storyItemDeleted; } @@ -756,7 +764,7 @@ public class StoriesStorage { }); } - public void putPeerStories(TLRPC.PeerStories userStories) { + public void putPeerStories(TL_stories.PeerStories userStories) { storage.getStorageQueue().postRunnable(() -> { putStoriesInternal(DialogObject.getPeerDialogId(userStories.peer), userStories); }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java index 2bc804ded..c5b4ab3eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesUtilities.java @@ -21,6 +21,7 @@ import android.view.ViewParent; import android.widget.TextView; import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DialogObject; @@ -37,6 +38,7 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; @@ -103,11 +105,7 @@ public class StoriesUtilities { params.reset(); animated = false; } -// if (!scheduled) { -// scheduled = true; -// AndroidUtilities.runOnUIThread(debugRunnable); -// } -// int state = debugState; + int state; int unreadState = 0; boolean showProgress = storiesController.isLoading(dialogId); @@ -131,7 +129,6 @@ public class StoriesUtilities { } } else if (hasStories) { if (params.drawSegments) { - // unreadState = storiesController.getUnreadState(dialogId, params.storyId); unreadState = state = STATE_READ; } else { unreadState = storiesController.getUnreadState(dialogId, params.storyId); @@ -201,7 +198,7 @@ public class StoriesUtilities { getCloseFriendsPaint(avatarImage); gradientTools = closeFriendsGradientTools; } else { - getActiveCirclePaint(avatarImage, params.isStoryCell); + getUnreadCirclePaint(avatarImage, params.isStoryCell); gradientTools = storiesGradientTools[params.isStoryCell ? 1 : 0]; } boolean animateOut = params.prevState == STATE_HAS_UNREAD && params.progressToSate != 1f; @@ -232,7 +229,7 @@ public class StoriesUtilities { Paint unreadPaint = null; Paint closeFriendsPaint = null; if (params.drawSegments) { - unreadPaint = getActiveCirclePaint(avatarImage, params.isStoryCell); + unreadPaint = getUnreadCirclePaint(avatarImage, params.isStoryCell); unreadPaint.setAlpha((int) (0xFF * params.alpha)); closeFriendsPaint = getCloseFriendsPaint(avatarImage); closeFriendsPaint.setAlpha((int) (0xFF * params.alpha)); @@ -262,7 +259,7 @@ public class StoriesUtilities { if ((params.prevState == STATE_PROGRESS && params.progressToSate != 1f) || params.currentState == STATE_PROGRESS) { Paint paint; if (params.animateFromUnreadState == STATE_HAS_UNREAD) { - getActiveCirclePaint(avatarImage, params.isStoryCell); + getUnreadCirclePaint(avatarImage, params.isStoryCell); paint = storiesGradientTools[params.isStoryCell ? 1 : 0].paint; } else { if (params.isStoryCell) { @@ -278,7 +275,7 @@ public class StoriesUtilities { Paint unreadPaint = null; Paint closeFriendsPaint = null; if (params.drawSegments) { - unreadPaint = getActiveCirclePaint(avatarImage, params.isStoryCell); + unreadPaint = getUnreadCirclePaint(avatarImage, params.isStoryCell); unreadPaint.setAlpha((int) (0xFF * params.alpha)); closeFriendsPaint = getCloseFriendsPaint(avatarImage); closeFriendsPaint.setAlpha((int) (0xFF * params.alpha)); @@ -354,7 +351,7 @@ public class StoriesUtilities { } params.globalState = globalState == StoriesController.STATE_READ ? STATE_READ : STATE_HAS_UNREAD; - TLRPC.PeerStories userStories = storiesController.getStories(params.dialogId); + TL_stories.PeerStories userStories = storiesController.getStories(params.dialogId); if (userStories == null) { userStories = storiesController.getStoriesFromFullPeer(params.dialogId); } @@ -369,11 +366,12 @@ public class StoriesUtilities { getCloseFriendsPaint(avatarImage); globalPaint = closeFriendsGradientTools.paint; } else if (globalState == STATE_UNREAD) { - getActiveCirclePaint(avatarImage, params.isStoryCell); + getUnreadCirclePaint(avatarImage, params.isStoryCell); globalPaint = storiesGradientTools[params.isStoryCell ? 1 : 0].paint; } else { globalPaint = params.isStoryCell ? storyCellGreyPaint[params.isArchive ? 1 : 0] : grayPaint; } + // 0 - if has only uploading stories. displayed as unread if (storiesCount <= 1) { Paint localPaint = paint; if (storiesController.hasUnreadStories(params.dialogId)) { @@ -417,6 +415,9 @@ public class StoriesUtilities { segmentPaint = unreadPaint; } } else { + if (i >= userStories.stories.size()) { + segmentPaint = unreadPaint; + } if (userStories.stories.get(i).justUploaded || userStories.stories.get(i).id > maxUnread) { if (userStories.stories.get(i).close_friends) { segmentPaint = closeFriendsPaint; @@ -443,7 +444,7 @@ public class StoriesUtilities { } } - private static int getPredictiveUnreadState(StoriesController storiesController, long dialogId) { + public static int getPredictiveUnreadState(StoriesController storiesController, long dialogId) { if (dialogId == 0) { return STATE_EMPTY; } @@ -580,7 +581,21 @@ public class StoriesUtilities { return 0; } - public static Paint getActiveCirclePaint(ImageReceiver avatarImage, boolean isDialogCell) { + public static Paint getUnreadCirclePaint(ImageReceiver avatarImage, boolean isDialogCell) { + int i = isDialogCell ? 1 : 0; + checkStoriesGradientTools(isDialogCell); + storiesGradientTools[i].setBounds(avatarImage.getImageX(), avatarImage.getImageY(), avatarImage.getImageX2(), avatarImage.getImageY2()); + return storiesGradientTools[i].paint; + } + + public static Paint getUnreadCirclePaint(RectF bounds, boolean isDialogCell) { + int i = isDialogCell ? 1 : 0; + checkStoriesGradientTools(isDialogCell); + storiesGradientTools[i].setBounds(bounds.left, bounds.top, bounds.right, bounds.bottom); + return storiesGradientTools[i].paint; + } + + private static void checkStoriesGradientTools(boolean isDialogCell) { int i = isDialogCell ? 1 : 0; if (storiesGradientTools[i] == null) { storiesGradientTools[i] = new GradientTools(); @@ -595,8 +610,6 @@ public class StoriesUtilities { storiesGradientTools[i].paint.setStyle(Paint.Style.STROKE); storiesGradientTools[i].paint.setStrokeCap(Paint.Cap.ROUND); } - storiesGradientTools[i].setBounds(avatarImage.getImageX(), avatarImage.getImageY(), avatarImage.getImageX2(), avatarImage.getImageY2()); - return storiesGradientTools[i].paint; } public static void updateColors() { @@ -665,7 +678,7 @@ public class StoriesUtilities { return errorGradientTools.paint; } - public static void setStoryMiniImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem) { + public static void setStoryMiniImage(ImageReceiver imageReceiver, TL_stories.StoryItem storyItem) { if (storyItem == null) { return; } @@ -683,11 +696,11 @@ public class StoriesUtilities { } } - public static void setImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem) { + public static void setImage(ImageReceiver imageReceiver, TL_stories.StoryItem storyItem) { setImage(imageReceiver, storyItem, "320_320"); } - public static void setImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem, String filter) { + public static void setImage(ImageReceiver imageReceiver, TL_stories.StoryItem storyItem, String filter) { if (storyItem == null) { return; } @@ -720,7 +733,7 @@ public class StoriesUtilities { } } - public static void setThumbImage(ImageReceiver imageReceiver, TLRPC.StoryItem storyItem, int w, int h) { + public static void setThumbImage(ImageReceiver imageReceiver, TL_stories.StoryItem storyItem, int w, int h) { if (storyItem.media != null && storyItem.media.document != null) { TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(storyItem.media.document.thumbs, AndroidUtilities.dp(Math.max(w, h)), false, null, true); imageReceiver.setImage(ImageLocation.getForDocument(size, storyItem.media.document), w + "_" + h, null, null, ImageLoader.createStripedBitmap(storyItem.media.document.thumbs), 0, null, storyItem, 0); @@ -812,7 +825,7 @@ public class StoriesUtilities { spannableStringBuilder.append("d ").append(LocaleController.formatString(strKey, strRes, args)); ColoredImageSpan coloredImageSpan = new ColoredImageSpan(R.drawable.msg_mini_bomb); if (useScale) { - coloredImageSpan.setScale(0.8f); + coloredImageSpan.setScale(0.8f, 0.8f); } else { coloredImageSpan.setTopOffset(-1); } @@ -828,20 +841,20 @@ public class StoriesUtilities { return spannableStringBuilder; } - public static boolean hasExpiredViews(TLRPC.StoryItem storyItem) { + public static boolean hasExpiredViews(TL_stories.StoryItem storyItem) { if (storyItem == null) { return false; } return ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime() > storyItem.expire_date + 86400; } - public static void applyViewedUser(TLRPC.StoryItem storyItem, TLRPC.User currentUser) { + public static void applyViewedUser(TL_stories.StoryItem storyItem, TLRPC.User currentUser) { if (currentUser == null) { return; } if (storyItem.dialogId == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId && !hasExpiredViews(storyItem)) { if (storyItem.views == null) { - storyItem.views = new TLRPC.TL_storyViews(); + storyItem.views = new TL_stories.TL_storyViews(); } if (storyItem.views.views_count == 0) { storyItem.views.views_count = 1; @@ -873,7 +886,7 @@ public class StoriesUtilities { canvas.drawArc(rect, startAngle, endAngle - startAngle, false, paint); } - public static boolean isExpired(int currentAccount, TLRPC.StoryItem storyItem) { + public static boolean isExpired(int currentAccount, TL_stories.StoryItem storyItem) { return ConnectionsManager.getInstance(currentAccount).getCurrentTime() > storyItem.expire_date; } @@ -903,12 +916,12 @@ public class StoriesUtilities { } } - public static EnsureStoryFileLoadedObject ensureStoryFileLoaded(TLRPC.PeerStories stories, Runnable onDoneOrTimeout) { + public static EnsureStoryFileLoadedObject ensureStoryFileLoaded(TL_stories.PeerStories stories, Runnable onDoneOrTimeout) { if (stories == null || stories.stories.isEmpty() || DialogObject.getPeerDialogId(stories.peer) == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { onDoneOrTimeout.run(); return null; } - TLRPC.StoryItem storyItem = null; + TL_stories.StoryItem storyItem = null; StoriesController storiesController = MessagesController.getInstance(UserConfig.selectedAccount).storiesController; int maxReadId = storiesController.dialogIdToMaxReadId.get(DialogObject.getPeerDialogId(stories.peer)); @@ -1010,7 +1023,7 @@ public class StoriesUtilities { public boolean drawSegments = true; public boolean animate = true; public int storyId; - public TLRPC.StoryItem storyItem; + public TL_stories.StoryItem storyItem; public float progressToSegments = 1f; public float progressToArc = 0; public boolean isLast; @@ -1199,7 +1212,12 @@ public class StoriesUtilities { BaseFragment fragment = LaunchActivity.getLastFragment(); if (fragment != null && child != null) { fragment.getOrCreateStoryViewer().doOnAnimationReady(onDone); - fragment.getOrCreateStoryViewer().open(fragment.getContext(), dialogId, StoriesListPlaceProvider.of((RecyclerListView) child.getParent())); + ViewParent parent = child.getParent(); + StoriesListPlaceProvider placeProvider = null; + if (parent instanceof RecyclerView) { + placeProvider = StoriesListPlaceProvider.of((RecyclerListView) parent); + } + fragment.getOrCreateStoryViewer().open(fragment.getContext(), dialogId, placeProvider); } } @@ -1243,16 +1261,16 @@ public class StoriesUtilities { storiesController.setLoading(dialogId, true); view.invalidate(); - TLRPC.TL_stories_getPeerStories req = new TLRPC.TL_stories_getPeerStories(); + TL_stories.TL_stories_getPeerStories req = new TL_stories.TL_stories_getPeerStories(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { boolean openned = false; boolean finished = true; if (response != null) { - TLRPC.TL_stories_peerStories stories_userStories = (TLRPC.TL_stories_peerStories) response; + TL_stories.TL_stories_peerStories stories_userStories = (TL_stories.TL_stories_peerStories) response; MessagesController.getInstance(currentAccount).putUsers(stories_userStories.users, false); MessagesController.getInstance(currentAccount).putChats(stories_userStories.chats, false); - TLRPC.PeerStories stories = stories_userStories.stories; + TL_stories.PeerStories stories = stories_userStories.stories; if (!stories.stories.isEmpty()) { MessagesController.getInstance(currentAccount).getStoriesController().putStories(dialogId, stories); finished = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java index 66beedaae..2c4f56532 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesViewPager.java @@ -3,6 +3,7 @@ package org.telegram.ui.Stories; import android.content.Context; import android.graphics.Canvas; import android.os.Build; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeContorl.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeControl.java similarity index 79% rename from TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeContorl.java rename to TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeControl.java index b891e1fbd..758ae836f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeContorl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoriesVolumeControl.java @@ -5,22 +5,23 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.media.AudioManager; +import android.util.Log; import android.view.KeyEvent; import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.Components.AnimatedFloat; -public class StoriesVolumeContorl extends View { +public class StoriesVolumeControl extends View { Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); boolean isVisible; - public StoriesVolumeContorl(Context context) { + public StoriesVolumeControl(Context context) { super(context); paint.setColor(Color.WHITE); } - Runnable hideRunnuble = new Runnable() { + Runnable hideRunnable = new Runnable() { @Override public void run() { isVisible = false; @@ -34,10 +35,10 @@ public class StoriesVolumeContorl extends View { @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { + if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_VOLUME_UP) { adjustVolume(true); return true; - } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { + } else if (event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { adjustVolume(false); return true; } @@ -61,8 +62,8 @@ public class StoriesVolumeContorl extends View { volumeProgress.set(currentProgress, true); isVisible = true; invalidate(); - AndroidUtilities.cancelRunOnUIThread(hideRunnuble); - AndroidUtilities.runOnUIThread(hideRunnuble, 2000); + AndroidUtilities.cancelRunOnUIThread(hideRunnable); + AndroidUtilities.runOnUIThread(hideRunnable, 2000); } } @@ -71,13 +72,15 @@ public class StoriesVolumeContorl extends View { int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); int currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); + int step = (int) Math.max(1, maxVolume / 15f); + if (increase) { - currentVolume++; + currentVolume += step; if (currentVolume > maxVolume) { currentVolume = maxVolume; } } else { - currentVolume--; + currentVolume -= step; if (currentVolume < 0) { currentVolume = 0; } @@ -91,8 +94,8 @@ public class StoriesVolumeContorl extends View { } invalidate(); isVisible = true; - AndroidUtilities.cancelRunOnUIThread(hideRunnuble); - AndroidUtilities.runOnUIThread(hideRunnuble, 2000); + AndroidUtilities.cancelRunOnUIThread(hideRunnable); + AndroidUtilities.runOnUIThread(hideRunnable, 2000); } @Override @@ -109,7 +112,7 @@ public class StoriesVolumeContorl extends View { } public void hide() { - AndroidUtilities.cancelRunOnUIThread(hideRunnuble); - hideRunnuble.run(); + AndroidUtilities.cancelRunOnUIThread(hideRunnable); + hideRunnable.run(); } } 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 d9add7657..1187a302a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCaptionView.java @@ -701,7 +701,7 @@ public class StoryCaptionView extends NestedScrollView { if (x < showMoreX - AndroidUtilities.dp(16)) { lineInfo.collapsedY = collapsedY; lineInfo.collapsedX = x; - x += layout.getLineRight(0) + space; + x += Math.abs(layout.getLineRight(0) - layout.getLineLeft(0)) + space; } else { lineInfo.collapsedY = lineInfo.finalY; lineInfo.collapsedX = lineInfo.finalX; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCustomParamsHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCustomParamsHelper.java index 8ffaf3436..ace3abb7e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCustomParamsHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryCustomParamsHelper.java @@ -4,21 +4,22 @@ import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; public class StoryCustomParamsHelper { - public static boolean isEmpty(TLRPC.StoryItem storyItem) { + public static boolean isEmpty(TL_stories.StoryItem storyItem) { return storyItem.detectedLng == null && storyItem.translatedLng == null && !storyItem.translated && storyItem.translatedText == null; } - public static void copyParams(TLRPC.StoryItem fromStory, TLRPC.StoryItem toStory) { + public static void copyParams(TL_stories.StoryItem fromStory, TL_stories.StoryItem toStory) { toStory.translated = fromStory.translated; toStory.detectedLng = fromStory.detectedLng; toStory.translatedText = fromStory.translatedText; toStory.translatedLng = fromStory.translatedLng; } - public static void readLocalParams(TLRPC.StoryItem storyItem, NativeByteBuffer byteBuffer) { + public static void readLocalParams(TL_stories.StoryItem storyItem, NativeByteBuffer byteBuffer) { if (byteBuffer == null) { return; } @@ -34,7 +35,7 @@ public class StoryCustomParamsHelper { params.readParams(byteBuffer, true); } - public static NativeByteBuffer writeLocalParams(TLRPC.StoryItem storyItem) { + public static NativeByteBuffer writeLocalParams(TL_stories.StoryItem storyItem) { if (isEmpty(storyItem)) { return null; } @@ -52,10 +53,10 @@ public class StoryCustomParamsHelper { private static class Params_v1 extends TLObject { private final static int VERSION = 1; - final TLRPC.StoryItem storyItem; + final TL_stories.StoryItem storyItem; int flags = 0; - private Params_v1(TLRPC.StoryItem storyItem) { + private Params_v1(TL_stories.StoryItem storyItem) { this.storyItem = storyItem; flags += storyItem.translated ? 1 : 0; flags += storyItem.detectedLng != null ? 2 : 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryLinesDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryLinesDrawable.java index 84101258a..95bbb120f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryLinesDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryLinesDrawable.java @@ -1,15 +1,23 @@ package org.telegram.ui.Stories; import static org.telegram.messenger.AndroidUtilities.dp; +import static org.telegram.messenger.AndroidUtilities.dpf2; import static org.telegram.messenger.AndroidUtilities.rectTmp; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.RectF; +import android.text.Layout; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.util.Log; import android.view.View; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -18,33 +26,47 @@ public class StoryLinesDrawable { private final View view; private final PeerStoriesView.SharedResources sharedResources; - private final AnimatedFloat scrollT; + private final AnimatedFloat zoomT; + + private final TextPaint zoomHintPaint; + private final StaticLayout zoomHintLayout; + private final float zoomHintLayoutLeft, zoomHintLayoutWidth; public StoryLinesDrawable(View view, PeerStoriesView.SharedResources sharedResources) { this.view = view; this.sharedResources = sharedResources; - scrollT = new AnimatedFloat(view, 0, 230, CubicBezierInterpolator.EASE_OUT_QUINT); - } + zoomT = new AnimatedFloat(view, 0, 360, CubicBezierInterpolator.EASE_OUT_QUINT); + zoomHintPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + zoomHintPaint.setTextSize(dp(14)); + zoomHintPaint.setColor(0xffffffff); + zoomHintPaint.setShadowLayer(dp(3), 0, dp(1), 0x30000000); + zoomHintLayout = new StaticLayout(LocaleController.getString(R.string.StorySeekHelp), zoomHintPaint, AndroidUtilities.displaySize.x, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false); + zoomHintLayoutLeft = zoomHintLayout.getLineCount() > 0 ? zoomHintLayout.getLineLeft(0) : 0; + zoomHintLayoutWidth = zoomHintLayout.getLineCount() > 0 ? zoomHintLayout.getLineWidth(0) : 0; + } float bufferingProgress; boolean incrementBuffering; int lastPosition; - public void draw( - Canvas canvas, - int fullWidth, - int index, - float progress, - int count, - float hideInterfaceAlpha, - float alpha, - boolean buffering + Canvas canvas, + int fullWidth, + int index, + float progress, + int count, + float hideInterfaceAlpha, + float alpha, + boolean buffering, + boolean zoom, + float zoomProgress ) { if (count <= 0) { return; } + + buffering = buffering && !zoom; if (lastPosition != index) { bufferingProgress = 0; incrementBuffering = true; @@ -69,18 +91,36 @@ public class StoryLinesDrawable { final float scrollX = 0;//scrollT.set(Utilities.clamp(indexX - fullWidth / 2f, scrollWidth - (fullWidth - dp(10)), 0)); float roundRadius = Math.min(sectionWidth / 2f, dp(1)); - selectedBarPaint.setAlpha((int) (255 * alpha * hideInterfaceAlpha)); + + // zoom + float zoomT = this.zoomT.set(zoom); + if (zoomT > 0) { + progress = AndroidUtilities.lerp(progress, zoomProgress, zoomT); + + canvas.save(); + zoomHintPaint.setAlpha((int) (0xFF * zoomT)); + zoomHintPaint.setShadowLayer(dp(3), 0, dp(1), Theme.multAlpha(0x30000000, zoomT)); + canvas.translate((fullWidth - zoomHintLayoutWidth) / 2f - zoomHintLayoutLeft, AndroidUtilities.lerp(dp(4), dp(16), zoomT)); + zoomHintLayout.draw(canvas); + canvas.restore(); + } + for (int a = 0; a < count; a++) { + float aalpha = alpha; float x = -scrollX + dp(5) + gapWidth * a + sectionWidth * a; - if (x > fullWidth || x + sectionWidth < 0) { + if (zoomT > 0 && index != a) { +// aalpha *= (1f - zoomT); + } + if (x > fullWidth || x + sectionWidth < 0 || aalpha <= 0) { continue; } + float rr = AndroidUtilities.lerp(roundRadius, dpf2(2), zoomT); float currentProgress; int baseAlpha = 0x55; if (a <= index) { if (a == index) { currentProgress = progress; - rectTmp.set(x, 0, x + sectionWidth, dp(2)); + rectTmp.set(x, 0, x + sectionWidth, AndroidUtilities.lerp(dpf2(2), dpf2(5), zoomT * (index == a ? 1 : 0))); int bufferingAlpha = 0; if (buffering) { if (incrementBuffering) { @@ -94,10 +134,14 @@ public class StoryLinesDrawable { incrementBuffering = true; } } - bufferingAlpha = (int) ((0x33) * alpha * hideInterfaceAlpha * bufferingProgress); + bufferingAlpha = (int) ((0x33) * aalpha * hideInterfaceAlpha * bufferingProgress); } - barPaint.setAlpha((int) ((0x55) * alpha * hideInterfaceAlpha) + bufferingAlpha); - canvas.drawRoundRect(rectTmp, roundRadius, roundRadius, barPaint); + barPaint.setAlpha((int) ((0x55) * aalpha * hideInterfaceAlpha) + bufferingAlpha); + if (zoomT > 0) { + rectTmp.left = Utilities.clamp(AndroidUtilities.lerp(rectTmp.left, (a - index) * fullWidth + dp(5), zoomT), fullWidth - dp(5), dp(5)); + rectTmp.right = Utilities.clamp(AndroidUtilities.lerp(rectTmp.right, (a - index + 1) * fullWidth - dp(5), zoomT), fullWidth - dp(5), dp(5)); + } + canvas.drawRoundRect(rectTmp, rr, rr, barPaint); // baseAlpha = 0x50; } else { currentProgress = 1.0f; @@ -105,12 +149,22 @@ public class StoryLinesDrawable { } else { currentProgress = 1.0f; } - rectTmp.set(x, 0, x + sectionWidth * currentProgress, dp(2)); - - if (a > index) { - barPaint.setAlpha((int) (baseAlpha * alpha * hideInterfaceAlpha)); + rectTmp.set(x, 0, x + sectionWidth, AndroidUtilities.lerp(dpf2(2), dpf2(5), zoomT * (index == a ? 1 : 0))); + if (zoomT > 0) { + rectTmp.left = Utilities.clamp(AndroidUtilities.lerp(rectTmp.left, (a - index) * fullWidth + dp(5), zoomT), fullWidth - dp(5), dp(5)); + rectTmp.right = Utilities.clamp(AndroidUtilities.lerp(rectTmp.right, (a - index + 1) * fullWidth - dp(5), zoomT), fullWidth - dp(5), dp(5)); } - canvas.drawRoundRect(rectTmp, roundRadius, roundRadius, a <= index ? selectedBarPaint : barPaint); + rectTmp.right = AndroidUtilities.lerp(rectTmp.left, rectTmp.right, currentProgress); + + Paint paint; + if (a <= index) { + selectedBarPaint.setAlpha((int) (0xFF * aalpha * hideInterfaceAlpha)); + paint = selectedBarPaint; + } else { + barPaint.setAlpha((int) (baseAlpha * aalpha * hideInterfaceAlpha)); + paint = barPaint; + } + canvas.drawRoundRect(rectTmp, rr, rr, paint); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryMediaAreasView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryMediaAreasView.java index 52d690fe4..f99371302 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryMediaAreasView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryMediaAreasView.java @@ -7,40 +7,30 @@ import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Matrix; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; -import android.graphics.Region; import android.graphics.Shader; -import android.graphics.Xfermode; import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; -import com.google.android.exoplayer2.extractor.CeaUtil; -import com.google.zxing.qrcode.decoder.Mode; - -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.ChatActivity; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.ColoredImageSpan; -import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.Paint.Views.ReactionWidgetEntityView; import org.telegram.ui.Components.ScaleStateListAnimator; import org.telegram.ui.EmojiAnimationsOverlay; import org.telegram.ui.LocationActivity; @@ -69,13 +59,13 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList addView(hintsContainer = new FrameLayout(context)); } - public static ArrayList getMediaAreasFor(StoryEntry entry) { + public static ArrayList getMediaAreasFor(StoryEntry entry) { if (entry == null || entry.mediaEntities == null) { return null; } - ArrayList areas = new ArrayList<>(); + ArrayList areas = new ArrayList<>(); for (int i = 0; i < entry.mediaEntities.size(); i++) { - if (entry.mediaEntities.get(i).mediaArea instanceof TLRPC.TL_mediaAreaSuggestedReaction) { + if (entry.mediaEntities.get(i).mediaArea instanceof TL_stories.TL_mediaAreaSuggestedReaction) { areas.add(entry.mediaEntities.get(i).mediaArea); } } @@ -90,14 +80,14 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList } - private ArrayList lastMediaAreas; + private ArrayList lastMediaAreas; - public void set(TLRPC.StoryItem storyItem, EmojiAnimationsOverlay animationsOverlay) { - ArrayList mediaAreas = storyItem != null ? storyItem.media_areas : null; + public void set(TL_stories.StoryItem storyItem, EmojiAnimationsOverlay animationsOverlay) { + ArrayList mediaAreas = storyItem != null ? storyItem.media_areas : null; set(storyItem, mediaAreas, animationsOverlay); } - public void set(TLRPC.StoryItem storyItem, ArrayList mediaAreas, EmojiAnimationsOverlay animationsOverlay) { + public void set(TL_stories.StoryItem storyItem, ArrayList mediaAreas, EmojiAnimationsOverlay animationsOverlay) { if (mediaAreas == lastMediaAreas && (mediaAreas == null || lastMediaAreas == null || mediaAreas.size() == lastMediaAreas.size())) { return; } @@ -130,11 +120,11 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList double totalArea = 0; for (int i = 0; i < mediaAreas.size(); ++i) { - TLRPC.MediaArea mediaArea = mediaAreas.get(i); + TL_stories.MediaArea mediaArea = mediaAreas.get(i); if (mediaArea != null && mediaArea.coordinates != null) { View areaView; - if (mediaArea instanceof TLRPC.TL_mediaAreaSuggestedReaction) { - StoryReactionWidgetView storyReactionWidgetView = new StoryReactionWidgetView(getContext(), this, (TLRPC.TL_mediaAreaSuggestedReaction) mediaArea, animationsOverlay); + if (mediaArea instanceof TL_stories.TL_mediaAreaSuggestedReaction) { + StoryReactionWidgetView storyReactionWidgetView = new StoryReactionWidgetView(getContext(), this, (TL_stories.TL_mediaAreaSuggestedReaction) mediaArea, animationsOverlay); areaView = storyReactionWidgetView; if (storyItem != null) { storyReactionWidgetView.setViews(storyItem.views, false); @@ -203,8 +193,8 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList }; fragment.setResourceProvider(resourcesProvider); TLRPC.TL_message message = new TLRPC.TL_message(); - if (selectedArea.mediaArea instanceof TLRPC.TL_mediaAreaVenue) { - TLRPC.TL_mediaAreaVenue areaVenue = (TLRPC.TL_mediaAreaVenue) selectedArea.mediaArea; + if (selectedArea.mediaArea instanceof TL_stories.TL_mediaAreaVenue) { + TL_stories.TL_mediaAreaVenue areaVenue = (TL_stories.TL_mediaAreaVenue) selectedArea.mediaArea; TLRPC.TL_messageMediaVenue media = new TLRPC.TL_messageMediaVenue(); media.venue_id = areaVenue.venue_id; media.venue_type = areaVenue.venue_type; @@ -213,9 +203,9 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList media.provider = areaVenue.provider; media.geo = areaVenue.geo; message.media = media; - } else if (selectedArea.mediaArea instanceof TLRPC.TL_mediaAreaGeoPoint) { + } else if (selectedArea.mediaArea instanceof TL_stories.TL_mediaAreaGeoPoint) { fragment.setInitialMaxZoom(true); - TLRPC.TL_mediaAreaGeoPoint areaGeo = (TLRPC.TL_mediaAreaGeoPoint) selectedArea.mediaArea; + TL_stories.TL_mediaAreaGeoPoint areaGeo = (TL_stories.TL_mediaAreaGeoPoint) selectedArea.mediaArea; TLRPC.TL_messageMediaGeo media = new TLRPC.TL_messageMediaGeo(); media.geo = areaGeo.geo; message.media = media; @@ -256,8 +246,7 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList imageSpan.translate(dp(-2), dp(1)); imageSpan.setScale(-1, 1); arrowLeft.setSpan(imageSpan, 0, arrowLeft.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - AndroidUtilities.replaceCharSequence(">", text, arrowRight); - AndroidUtilities.replaceCharSequence("<", text, arrowLeft); + AndroidUtilities.replaceCharSequence(">", text, AndroidUtilities.isRTL(text) ? arrowLeft : arrowRight); final HintView2 thisHint = hintView = new HintView2(getContext(), top ? HintView2.DIRECTION_TOP : HintView2.DIRECTION_BOTTOM) .setText(text) @@ -405,7 +394,39 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList return selectedArea != null; } - public void onStoryItemUpdated(TLRPC.StoryItem storyItem, boolean animated) { + // returns true when widget that is drawn above the story (f.ex. reaction) is at these coordinates + // used to detect that back gesture safety measure should not occur + public boolean hasAreaAboveAt(float x, float y) { + for (int i = 0; i < getChildCount(); ++i) { + View child = getChildAt(i); + if (child instanceof StoryReactionWidgetView) { + if (rotatedRectContainsPoint( + child.getTranslationX(), + child.getTranslationY(), + child.getMeasuredWidth(), + child.getMeasuredHeight(), + child.getRotation(), + x, y + )) { + return true; + } + } + } + return false; + } + + private static boolean rotatedRectContainsPoint(float rcx, float rcy, float rw, float rh, float rr, float x, float y) { + float xt = x - rcx; + float yt = y - rcy; + + double rad = Math.toRadians(-rr); + float xr = (float) (xt * Math.cos(rad) - yt * Math.sin(rad)); + float yr = (float) (xt * Math.sin(rad) + yt * Math.cos(rad)); + + return xr >= -rw/2 && xr <= rw/2 && yr >= -rh/2 && yr <= rh/2; + } + + public void onStoryItemUpdated(TL_stories.StoryItem storyItem, boolean animated) { if (storyItem == null) { return; } @@ -442,9 +463,9 @@ public class StoryMediaAreasView extends FrameLayout implements View.OnClickList public final AnimatedFloat highlightAlpha; - public final TLRPC.MediaArea mediaArea; + public final TL_stories.MediaArea mediaArea; - public AreaView(Context context, View parent, TLRPC.MediaArea mediaArea) { + public AreaView(Context context, View parent, TL_stories.MediaArea mediaArea) { super(context); this.mediaArea = mediaArea; highlightAlpha = new AnimatedFloat(parent, 0, 120, new LinearInterpolator()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java index 5b30b972b..afb5002da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryPrivacyButton.java @@ -14,12 +14,11 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Shader; import android.graphics.drawable.Drawable; -import android.util.Log; import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.R; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.ButtonBounce; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -53,7 +52,7 @@ public class StoryPrivacyButton extends View { arrowPaint.setColor(Color.WHITE); } - public boolean set(boolean mine, TLRPC.StoryItem storyItem, boolean animated) { + public boolean set(boolean mine, TL_stories.StoryItem storyItem, boolean animated) { drawArrow = mine; draw = true; if (storyItem == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryReactionWidgetView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryReactionWidgetView.java index 95c43914e..972b14587 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryReactionWidgetView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryReactionWidgetView.java @@ -3,23 +3,19 @@ package org.telegram.ui.Stories; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; import android.view.Gravity; import android.view.View; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.DocumentObject; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MediaDataController; -import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.Theme; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.AnimatedEmojiDrawable; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; -import org.telegram.ui.Components.Reactions.AnimatedEmojiEffect; import org.telegram.ui.Components.Reactions.ReactionImageHolder; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; import org.telegram.ui.Components.Reactions.ReactionsUtils; @@ -35,7 +31,7 @@ public class StoryReactionWidgetView extends StoryMediaAreasView.AreaView { AnimatedTextView.AnimatedTextDrawable animatedTextDrawable = new AnimatedTextView.AnimatedTextDrawable(); boolean hasCounter; - public StoryReactionWidgetView(Context context, View parent, TLRPC.TL_mediaAreaSuggestedReaction mediaArea, EmojiAnimationsOverlay overlay) { + public StoryReactionWidgetView(Context context, View parent, TL_stories.TL_mediaAreaSuggestedReaction mediaArea, EmojiAnimationsOverlay overlay) { super(context, parent, mediaArea); visibleReaction = ReactionsLayoutInBubble.VisibleReaction.fromTLReaction(mediaArea.reaction); if (mediaArea.flipped) { @@ -52,8 +48,9 @@ public class StoryReactionWidgetView extends StoryMediaAreasView.AreaView { } } animatedTextDrawable.setGravity(Gravity.CENTER); - animatedTextDrawable.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - animatedTextDrawable.setTextSize(AndroidUtilities.dp(14)); + animatedTextDrawable.setTypeface(AndroidUtilities.getTypeface("fonts/rcondensedbold.ttf")); + animatedTextDrawable.setTextSize(AndroidUtilities.dp(18)); + animatedTextDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); if (mediaArea.dark) { storyReactionWidgetBackground.nextStyle(); @@ -61,7 +58,13 @@ public class StoryReactionWidgetView extends StoryMediaAreasView.AreaView { } } - public void setViews(TLRPC.StoryViews storyViews, boolean animated) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + animatedTextDrawable.setTextSize(Math.min(AndroidUtilities.dp(18), .8f * ((1f - 0.61f) / 2f) * getMeasuredHeight())); + } + + public void setViews(TL_stories.StoryViews storyViews, boolean animated) { if (storyViews != null) { for (int i = 0; i < storyViews.reactions.size(); i++) { if (ReactionsUtils.compare(storyViews.reactions.get(i).reaction, visibleReaction)) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java index a7809e74b..90000e988 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryViewer.java @@ -21,6 +21,7 @@ import android.graphics.RectF; import android.media.AudioManager; import android.net.Uri; import android.os.Build; +import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; import android.view.GestureDetector; @@ -47,6 +48,7 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AnimationNotificationsLocker; +import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLoader; @@ -62,6 +64,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.messenger.video.VideoPlayerHolderBase; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; @@ -100,7 +103,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat Paint inputBackgroundPaint; boolean keyboardVisible; - private static TLRPC.StoryItem lastStoryItem; + private static TL_stories.StoryItem lastStoryItem; Theme.ResourcesProvider resourcesProvider = new DarkThemeResourceProvider(); private boolean opening; @@ -145,6 +148,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat boolean allowSwipeToDissmiss; GestureDetector gestureDetector; boolean inSwipeToDissmissMode; + boolean inSeekingMode; boolean allowSwipeToReply; boolean isShowing; public StoriesViewPager storiesViewPager; @@ -182,10 +186,10 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat boolean isSingleStory; StoriesController.StoriesList storiesList; public int dayStoryId; - TLRPC.PeerStories overrideUserStories; + TL_stories.PeerStories overrideUserStories; boolean reversed; - TLRPC.StoryItem singleStory; + TL_stories.StoryItem singleStory; private int messageId; private boolean animateAvatar; private int fromRadius; @@ -199,7 +203,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat Runnable longPressRunnable = () -> setLongPressed(true); public boolean unreadStateChanged; - private StoriesVolumeContorl volumeControl; + private StoriesVolumeControl volumeControl; private static boolean checkSilentMode = true; private static boolean isInSilentMode; @@ -223,6 +227,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat public boolean fromBottomSheet; private boolean paused; private long playerSavedPosition; + private StoriesIntro storiesIntro; public static boolean isShowingImage(MessageObject messageObject) { if (lastStoryItem == null || messageObject.type != MessageObject.TYPE_STORY && !messageObject.isWebpage() || runOpenAnimationAfterLayout) { @@ -241,6 +246,19 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat private void setLongPressed(boolean b) { if (isLongpressed != b) { isLongpressed = b; + if (b && !isInPinchToZoom) { + PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); + if (peerView != null && peerView.currentStory != null && peerView.currentStory.uploadingStory == null) { + if (!inSeekingMode && !inSwipeToDissmissMode && currentPlayerScope != null && currentPlayerScope.player != null) { + peerView.storyContainer.invalidate(); + BotWebViewVibrationEffect.IMPACT_LIGHT.vibrate(); + } + if (currentPlayerScope != null && currentPlayerScope.player != null && !inSeekingMode) { + currentPlayerScope.player.setSeeking(true); + } + inSeekingMode = true; + } + } updatePlayingMode(); if (storiesViewPager != null) { PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); @@ -256,7 +274,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat this.fragment = fragment; } - public void open(Context context, TLRPC.StoryItem storyItem, PlaceProvider placeProvider) { + public void open(Context context, TL_stories.StoryItem storyItem, PlaceProvider placeProvider) { if (storyItem == null) { return; } @@ -289,7 +307,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat open(context, null, peerIds, 0, storiesList, null, placeProvider, false); } - public void open(Context context, TLRPC.PeerStories userStories, PlaceProvider placeProvider) { + public void open(Context context, TL_stories.PeerStories userStories, PlaceProvider placeProvider) { if (userStories == null || userStories.stories == null || userStories.stories.isEmpty()) { doOnAnimationReadyRunnables.clear(); return; @@ -300,7 +318,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat open(context, userStories.stories.get(0), peerIds, 0, null, userStories, placeProvider, false); } - public void open(Context context, TLRPC.StoryItem storyItem, int startStoryId, StoriesController.StoriesList storiesList, boolean reversed, PlaceProvider placeProvider) { + public void open(Context context, TL_stories.StoryItem storyItem, int startStoryId, StoriesController.StoriesList storiesList, boolean reversed, PlaceProvider placeProvider) { currentAccount = UserConfig.selectedAccount; ArrayList peerIds = new ArrayList<>(); peerIds.add(storiesList.dialogId); @@ -309,7 +327,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } @SuppressLint("WrongConstant") - public void open(Context context, TLRPC.StoryItem storyItem, ArrayList peerIds, int position, StoriesController.StoriesList storiesList, TLRPC.PeerStories userStories, PlaceProvider placeProvider, boolean reversed) { + public void open(Context context, TL_stories.StoryItem storyItem, ArrayList peerIds, int position, StoriesController.StoriesList storiesList, TL_stories.PeerStories userStories, PlaceProvider placeProvider, boolean reversed) { if (context == null) { doOnAnimationReadyRunnables.clear(); return; @@ -339,6 +357,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat swipeToDismissHorizontalOffset = 0; if (storiesViewPager != null) { storiesViewPager.setHorizontalProgressToDismiss(0); + storiesViewPager.currentState = ViewPager.SCROLL_STATE_IDLE; } swipeToReplyProgress = 0; swipeToReplyOffset = 0; @@ -458,7 +477,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat @Override public boolean onFling(@NonNull MotionEvent e1, @NonNull MotionEvent e2, float velocityX, float velocityY) { - if (swipeToReplyOffset != 0) { + if (swipeToReplyOffset != 0 && storiesIntro == null) { if (velocityY < -1000 && !swipeToReplyWaitingKeyboard) { swipeToReplyWaitingKeyboard = true; windowView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); @@ -482,8 +501,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat }); windowView = new SizeNotifierFrameLayout(context) { - float startY; - float startX; + float startX, startY; + float lastTouchX; final Path path = new Path(); final RectF rect1 = new RectF(); @@ -639,7 +658,6 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat canvas.save(); canvas.clipPath(path); - // canvas.drawColor(Color.RED); super.dispatchDraw(canvas); if (transitionViewHolder != null && transitionViewHolder.storyImage != null) { PeerStoriesView page = storiesViewPager.getCurrentPeerView(); @@ -738,9 +756,10 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat transitionViewHolder.crossfadeToAvatarImage.setRoundRadius(oldRadius); // transitionViewHolder.crossfadeToAvatarImage.setVisible(false, false); } - } - if (transitionViewHolder != null && transitionViewHolder.drawAbove != null) { - transitionViewHolder.drawAbove.draw(canvas, rect3, 1f - progress2, opening); + + if (transitionViewHolder != null && transitionViewHolder.drawAbove != null) { + transitionViewHolder.drawAbove.draw(canvas, rect3, 1f - progress2, opening); + } } canvas.restoreToCount(r); } @@ -885,7 +904,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN && progressToOpen == 1f) { - startX = ev.getX(); + startX = lastTouchX = ev.getX(); startY = ev.getY(); verticalScrollDetected = false; allowIntercept = !findClickableView(windowView, ev.getX(), ev.getY(), false); @@ -901,10 +920,32 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } else if (ev.getAction() == MotionEvent.ACTION_MOVE) { float dy = Math.abs(startY - ev.getY()); float dx = Math.abs(startX - ev.getX()); - if (dy > dx && !verticalScrollDetected && dy > AndroidUtilities.touchSlop * 2) { + if (isLongpressed && inSeekingMode && !isInPinchToZoom && !inSwipeToDissmissMode && currentPlayerScope != null && currentPlayerScope.player != null) { + PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); + if (peerView != null && peerView.currentStory != null && peerView.currentStory.uploadingStory == null && peerView.currentStory.isVideo()) { + long videoDuration = peerView.videoDuration; + if (videoDuration <= 0 && peerView.currentStory.storyItem != null && peerView.currentStory.storyItem.media != null && peerView.currentStory.storyItem.media.document != null) { + videoDuration = (long) (MessageObject.getDocumentDuration(peerView.currentStory.storyItem.media.document) * 1000L); + } + if (videoDuration > 0) { + final float x = ev.getX(); + final float wasSeek = currentPlayerScope.player.currentSeek; + final float nowSeek = currentPlayerScope.player.seek((x - lastTouchX) / AndroidUtilities.dp(220), videoDuration); + if ((int) (nowSeek * 10) != (int) (wasSeek * 10)) { + try { + peerView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) { + } + } + peerView.storyContainer.invalidate(); + lastTouchX = x; + } + } + } + if (dy > dx && !inSeekingMode && !verticalScrollDetected && dy > AndroidUtilities.touchSlop * 2) { verticalScrollDetected = true; } - if (!inSwipeToDissmissMode && !keyboardVisible && allowSwipeToDissmiss) { + if (!inSwipeToDissmissMode && !inSeekingMode && !keyboardVisible && allowSwipeToDissmiss) { if (dy > dx && dy > AndroidUtilities.touchSlop * 2) { inSwipeToDissmissMode = true; PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); @@ -912,8 +953,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat peerView.cancelTextSelection(); } boolean viewsAllowed = peerView != null && peerView.viewsAllowed(); - allowSwipeToReply = !viewsAllowed && peerView != null && !peerView.isChannel; - allowSelfStoriesView = viewsAllowed && !peerView.unsupported && peerView.currentStory.storyItem != null; + allowSwipeToReply = !viewsAllowed && peerView != null && !peerView.isChannel && storiesIntro == null; + allowSelfStoriesView = viewsAllowed && !peerView.unsupported && peerView.currentStory.storyItem != null && storiesIntro == null; if (allowSelfStoriesView && keyboardHeight != 0) { allowSelfStoriesView = false; } @@ -938,6 +979,10 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } setInTouchMode(false); verticalScrollDetected = false; + inSeekingMode = false; + if (currentPlayerScope != null && currentPlayerScope.player != null) { + currentPlayerScope.player.setSeeking(false); + } } boolean selfViewsViewVisible = selfStoryViewsView != null && selfStoryViewsView.progressToOpen == 1f; if (!inSwipeToDissmissMode && !selfViewsViewVisible) { @@ -1382,6 +1427,16 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat @Override public void setIsInPinchToZoom(boolean b) { + if (!StoryViewer.this.isInPinchToZoom && b && StoryViewer.this.inSeekingMode) { + StoryViewer.this.inSeekingMode = false; + if (currentPlayerScope != null && currentPlayerScope.player != null) { + currentPlayerScope.player.setSeeking(false); + } + PeerStoriesView peerView = getCurrentPeerView(); + if (peerView != null) { + peerView.invalidate(); + } + } StoryViewer.this.isInPinchToZoom = b; updatePlayingMode(); } @@ -1435,6 +1490,12 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat for (int i = 0; i < uries.size(); i++) { Uri uri = uries.get(i); VideoPlayerHolder playerHolder = new VideoPlayerHolder(surfaceView, textureView); + playerHolder.setOnSeekUpdate(() -> { + PeerStoriesView currentPeerView = storiesViewPager.getCurrentPeerView(); + if (currentPeerView != null && currentPeerView.storyContainer != null && currentPlayerScope != null && currentPlayerScope.player == playerHolder) { + currentPeerView.storyContainer.invalidate(); + } + }); playerHolder.uri = uri; playerHolder.document = documents.get(i); FileStreamLoadOperation.setPriorityForDocument(playerHolder.document, FileLoader.PRIORITY_LOW); @@ -1468,7 +1529,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat aspectRatioFrameLayout.addView(textureView); } - volumeControl = new StoriesVolumeContorl(context); + volumeControl = new StoriesVolumeControl(context); containerView.addView(volumeControl, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 4, 0, 4, 0)); } AndroidUtilities.removeFromParent(aspectRatioFrameLayout); @@ -1497,6 +1558,9 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + if (fragment == null || fragment.getLayoutContainer() == null) { + ATTACH_TO_FRAGMENT = false; + } if (ATTACH_TO_FRAGMENT) { AndroidUtilities.removeFromParent(windowView); windowView.setFitsSystemWindows(true); @@ -1620,7 +1684,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat PeerStoriesView peerStoriesView = storiesViewPager.getCurrentPeerView(); if (peerStoriesView != null) { if (storiesList != null) { - ArrayList storyItems = new ArrayList<>(); + ArrayList storyItems = new ArrayList<>(); for (int i = 0; i < storiesList.messageObjects.size(); i++) { storyItems.add(storiesList.messageObjects.get(i).storyItem); } @@ -1822,7 +1886,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat final PeerStoriesView peerView = storiesViewPager.getCurrentPeerView(); int position = peerView == null ? 0 : peerView.getSelectedPosition(); int storyId = peerView == null || position < 0 || position >= peerView.storyItems.size() ? 0 : peerView.storyItems.get(position).id; - TLRPC.StoryItem storyItem = peerView == null || position < 0 || position >= peerView.storyItems.size() ? null : peerView.storyItems.get(position); + TL_stories.StoryItem storyItem = peerView == null || position < 0 || position >= peerView.storyItems.size() ? null : peerView.storyItems.get(position); if (storyItem == null && isSingleStory) { storyItem = singleStory; } @@ -1924,7 +1988,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } public boolean isPaused() { - return isPopupVisible || isTranslating || isBulletinVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible || isInTextSelectionMode || isLikesReactions || progressToDismiss != 0; + return isPopupVisible || isTranslating || isBulletinVisible || isCaption || isWaiting || isInTouchMode || keyboardVisible || currentDialog != null || allowTouchesByViewpager || isClosed || isRecording || progressToOpen != 1f || selfStoriesViewsOffset != 0 || isHintVisible || (isSwiping && USE_SURFACE_VIEW) || isOverlayVisible || isInTextSelectionMode || isLikesReactions || progressToDismiss != 0 || storiesIntro != null; } public void updatePlayingMode() { @@ -1982,6 +2046,9 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat if (currentPeerView != null && currentPeerView.chatActivityEnterView != null && currentPeerView.chatActivityEnterView.isRecordingAudioVideo()) { return true; } + if (storiesIntro != null) { + return true; + } return AndroidUtilities.findClickableView(windowView, x, y, currentPeerView); } @@ -2065,6 +2132,47 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat if (peerStoriesView != null) { peerStoriesView.updatePosition(); } + + if (!SharedConfig.storiesIntroShown) { + if (storiesIntro == null) { + storiesIntro = new StoriesIntro(containerView.getContext(), windowView); + storiesIntro.setAlpha(0f); + containerView.addView(storiesIntro); + } + + storiesIntro.setOnClickListener(v -> { + storiesIntro.animate() + .alpha(0f) + .setDuration(150L) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (storiesIntro != null) { + storiesIntro.stopAnimation(); + containerView.removeView(storiesIntro); + } + storiesIntro = null; + updatePlayingMode(); + } + }) + .start(); + }); + storiesIntro.animate() + .alpha(1f) + .setDuration(150L) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + if (storiesIntro != null) { + storiesIntro.startAnimation(true); + } + } + }).start(); + + SharedConfig.setStoriesIntroShown(true); + } updatePlayingMode(); locker.unlock(); } @@ -2159,6 +2267,11 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat containerView.disableHwAcceleration(); checkNavBarColor(); locker.unlock(); + if (storiesIntro != null) { + storiesIntro.stopAnimation(); + containerView.removeView(storiesIntro); + storiesIntro = null; + } if (transitionViewHolder.avatarImage != null) { transitionViewHolder.avatarImage.setVisible(true, true); transitionViewHolder.avatarImage = null; @@ -2410,6 +2523,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat if (BuildVars.DEBUG_PRIVATE_VERSION) { return; } + allowScreenshots = !isShowing || allowScreenshots; if (this.allowScreenshots != allowScreenshots) { this.allowScreenshots = allowScreenshots; @@ -2445,7 +2559,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat return; } if (messageObject.type == MessageObject.TYPE_STORY_MENTION) { - TLRPC.StoryItem storyItem = messageObject.messageOwner.media.storyItem; + TL_stories.StoryItem storyItem = messageObject.messageOwner.media.storyItem; storyItem.dialogId = DialogObject.getPeerDialogId(messageObject.messageOwner.media.peer); storyItem.messageId = messageObject.getId(); open(fragment.getContext(), messageObject.messageOwner.media.storyItem, StoriesListPlaceProvider.of(recyclerListView)); @@ -2466,8 +2580,8 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat PeerStoriesView peerStoriesView = getCurrentPeerView(); storiesViewPager.setDays(storiesList.dialogId, storiesList.getDays(), currentAccount); if (selfStoryViewsView != null) { - TLRPC.StoryItem currentSelectedStory = selfStoryViewsView.getSelectedStory(); - ArrayList storyItems = new ArrayList<>(); + TL_stories.StoryItem currentSelectedStory = selfStoryViewsView.getSelectedStory(); + ArrayList storyItems = new ArrayList<>(); int selectedPosition = 0; for (int i = 0; i < storiesList.messageObjects.size(); i++) { if (currentSelectedStory != null && currentSelectedStory.id == storiesList.messageObjects.get(i).storyItem.id) { @@ -2485,11 +2599,11 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat return; } StoriesController storiesController = MessagesController.getInstance(currentAccount).getStoriesController(); - ArrayList allStories = storiesListPlaceProvider.hiddedStories ? storiesController.getHiddenList() : storiesController.getDialogListStories(); + ArrayList allStories = storiesListPlaceProvider.hiddedStories ? storiesController.getHiddenList() : storiesController.getDialogListStories(); boolean changed = false; ArrayList dialogs = storiesViewPager.getDialogIds(); for (int i = 0; i < allStories.size(); i++) { - TLRPC.PeerStories userStories = allStories.get(i); + TL_stories.PeerStories userStories = allStories.get(i); long dialogId = DialogObject.getPeerDialogId(userStories.peer); if (storiesListPlaceProvider.onlyUnreadStories && !storiesController.hasUnreadStories(dialogId)) { continue; @@ -2525,28 +2639,28 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat } } - public void saveDraft(long dialogId, TLRPC.StoryItem storyItem, CharSequence text) { + public void saveDraft(long dialogId, TL_stories.StoryItem storyItem, CharSequence text) { if (dialogId == 0 || storyItem == null) { return; } replyDrafts.put(draftHash(dialogId, storyItem), text); } - public CharSequence getDraft(long dialogId, TLRPC.StoryItem storyItem) { + public CharSequence getDraft(long dialogId, TL_stories.StoryItem storyItem) { if (dialogId == 0 || storyItem == null) { return ""; } return replyDrafts.get(draftHash(dialogId, storyItem), ""); } - public void clearDraft(long dialogId, TLRPC.StoryItem storyItem) { + public void clearDraft(long dialogId, TL_stories.StoryItem storyItem) { if (dialogId == 0 || storyItem == null) { return; } replyDrafts.remove(draftHash(dialogId, storyItem)); } - private long draftHash(long dialogId, TLRPC.StoryItem oldStoryItem) { + private long draftHash(long dialogId, TL_stories.StoryItem oldStoryItem) { return dialogId + (dialogId >> 16) + ((long) oldStoryItem.id << 16); } @@ -2558,6 +2672,9 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat getCurrentPeerView().updatePosition(); } } + if (storiesIntro != null) { + storiesIntro.startAnimation(false); + } } public void onPause() { @@ -2566,12 +2683,18 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat playerHolder.release(null); playerHolder = null; } + if (storiesIntro != null) { + storiesIntro.stopAnimation(); + } } public interface PlaceProvider { boolean findView(long dialogId, int messageId, int storyId, int type, TransitionViewHolder holder); - void preLayout(long currentDialogId, int messageId, Runnable o); + default void preLayout(long currentDialogId, int messageId, Runnable o) { + o.run(); + } + default void loadNext(boolean forward) { } @@ -2598,7 +2721,7 @@ public class StoryViewer implements NotificationCenter.NotificationCenterDelegat public Paint bgPaint; public float alpha = 1; public ImageReceiver crossfadeToAvatarImage; - StoriesUtilities.AvatarStoryParams params; + public StoriesUtilities.AvatarStoryParams params; public int storyId; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java index 20507423e..e991d8081 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/StoryWidgetsImageDecorator.java @@ -6,7 +6,7 @@ import android.view.View; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageReceiver; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Components.Reactions.ReactionImageHolder; import org.telegram.ui.Components.Reactions.ReactionsLayoutInBubble; @@ -15,13 +15,13 @@ import java.util.ArrayList; public class StoryWidgetsImageDecorator extends ImageReceiver.Decorator { ArrayList drawingObjects; - public StoryWidgetsImageDecorator(TLRPC.StoryItem storyItem) { + public StoryWidgetsImageDecorator(TL_stories.StoryItem storyItem) { for (int i = 0; i < storyItem.media_areas.size(); i++) { - if (storyItem.media_areas.get(i) instanceof TLRPC.TL_mediaAreaSuggestedReaction) { + if (storyItem.media_areas.get(i) instanceof TL_stories.TL_mediaAreaSuggestedReaction) { if (drawingObjects == null) { drawingObjects = new ArrayList<>(); } - drawingObjects.add(new ReactionWidget((TLRPC.TL_mediaAreaSuggestedReaction) storyItem.media_areas.get(i))); + drawingObjects.add(new ReactionWidget((TL_stories.TL_mediaAreaSuggestedReaction) storyItem.media_areas.get(i))); } } } @@ -84,10 +84,10 @@ public class StoryWidgetsImageDecorator extends ImageReceiver.Decorator { StoryReactionWidgetBackground storyReactionWidgetBackground = new StoryReactionWidgetBackground(null); - TLRPC.TL_mediaAreaSuggestedReaction mediaArea; + TL_stories.TL_mediaAreaSuggestedReaction mediaArea; ReactionImageHolder imageHolder = new ReactionImageHolder(null); - public ReactionWidget(TLRPC.TL_mediaAreaSuggestedReaction mediaArea) { + public ReactionWidget(TL_stories.TL_mediaAreaSuggestedReaction mediaArea) { this.mediaArea = mediaArea; if (mediaArea.flipped) { storyReactionWidgetBackground.setMirror(true, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java index 7edc237b7..baba039fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/UserListPoller.java @@ -2,9 +2,6 @@ package org.telegram.ui.Stories; import android.view.View; -import com.google.android.exoplayer2.util.Log; - -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.MessagesController; @@ -14,9 +11,9 @@ import org.telegram.messenger.UserConfig; import org.telegram.messenger.support.LongSparseLongArray; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.UserCell; -import org.telegram.ui.Components.Paint.Path; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; @@ -50,7 +47,7 @@ public class UserListPoller { if (!collectedDialogIds.isEmpty()) { ArrayList dialogsFinal = new ArrayList<>(collectedDialogIds); collectedDialogIds.clear(); - TLRPC.TL_stories_getPeerMaxIDs request = new TLRPC.TL_stories_getPeerMaxIDs(); + TL_stories.TL_stories_getPeerMaxIDs request = new TL_stories.TL_stories_getPeerMaxIDs(); for (int i = 0; i < dialogsFinal.size(); i++) { request.id.add(MessagesController.getInstance(currentAccount).getInputPeer(dialogsFinal.get(i))); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ViewsForPeerStoriesRequester.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ViewsForPeerStoriesRequester.java index ab3570641..899fa46c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/ViewsForPeerStoriesRequester.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/ViewsForPeerStoriesRequester.java @@ -3,9 +3,10 @@ package org.telegram.ui.Stories; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; + +import java.util.ArrayList; public class ViewsForPeerStoriesRequester { @@ -16,7 +17,7 @@ public class ViewsForPeerStoriesRequester { int currentReqId; boolean isRunning; - final Runnable scheduleRequestRunnable = () -> requestInternal(); + final Runnable scheduleRequestRunnable = () -> step(); public ViewsForPeerStoriesRequester(StoriesController storiesController, long dialogId, int currentAccount) { this.currentAccount = currentAccount; @@ -25,10 +26,12 @@ public class ViewsForPeerStoriesRequester { } public void start(boolean start) { - if (isRunning != start) { - if (requestInternal()) { - isRunning = start; - } + if (isRunning == start) { + return; + } + if (start) { + isRunning = true; + step(); } else { isRunning = false; AndroidUtilities.cancelRunOnUIThread(scheduleRequestRunnable); @@ -37,44 +40,86 @@ public class ViewsForPeerStoriesRequester { } } - private boolean requestInternal() { - TLRPC.PeerStories stories = storiesController.getStories(dialogId); - if (stories == null || stories.stories.isEmpty() || currentReqId != 0) { + protected void getStoryIds(ArrayList ids) { + TL_stories.PeerStories stories = storiesController.getStories(dialogId); + if (stories != null && stories.stories != null) { + for (int i = 0; i < stories.stories.size(); i++) { + ids.add(stories.stories.get(i).id); + } + } + } + + protected boolean updateStories(ArrayList reqIds, TL_stories.TL_stories_storyViews storyViews) { + if (storyViews == null || storyViews.views == null) { return false; } - TLRPC.TL_stories_getStoriesViews req = new TLRPC.TL_stories_getStoriesViews(); - for (int i = 0; i < stories.stories.size(); i++) { - req.id.add(stories.stories.get(i).id); + TL_stories.PeerStories currentStories = storiesController.getStories(dialogId); + if (currentStories == null || currentStories.stories.isEmpty()) { + return false; + } + for (int i = 0; i < storyViews.views.size(); i++) { + for (int j = 0; j < currentStories.stories.size(); j++) { + if (currentStories.stories.get(j).id == reqIds.get(i)) { + currentStories.stories.get(j).views = storyViews.views.get(i); + } + } + } + storiesController.storiesStorage.updateStories(currentStories); + return true; + } + + private static final long interval = 10_000; + private static long lastRequestTime; + + private void step() { + if (!isRunning) { + return; + } + long wait = interval - (System.currentTimeMillis() - lastRequestTime); + if (wait > 0) { + AndroidUtilities.cancelRunOnUIThread(scheduleRequestRunnable); + AndroidUtilities.runOnUIThread(scheduleRequestRunnable, wait); + } else { + if (!requestInternal()) { + currentReqId = 0; + isRunning = false; + } + } + } + + private boolean requestInternal() { + if (currentReqId != 0) { + return false; + } + TL_stories.TL_stories_getStoriesViews req = new TL_stories.TL_stories_getStoriesViews(); + getStoryIds(req.id); + if (req.id.isEmpty()) { + return false; } req.peer = MessagesController.getInstance(currentAccount).getInputPeer(dialogId); currentReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + lastRequestTime = System.currentTimeMillis(); + if (response != null) { - TLRPC.PeerStories currentStories = storiesController.getStories(dialogId); - if (currentStories == null || currentStories.stories.isEmpty()) { + TL_stories.TL_stories_storyViews storyViews = (TL_stories.TL_stories_storyViews) response; + MessagesController.getInstance(currentAccount).putUsers(storyViews.users, false); + + if (!updateStories(req.id, storyViews)) { currentReqId = 0; isRunning = false; return; } - TLRPC.TL_stories_storyViews storyViews = (TLRPC.TL_stories_storyViews) response; - MessagesController.getInstance(currentAccount).putUsers(storyViews.users, false); - for (int i = 0; i < storyViews.views.size(); i++) { - for (int j = 0; j < currentStories.stories.size(); j++) { - if (currentStories.stories.get(j).id == req.id.get(i)) { - currentStories.stories.get(j).views = storyViews.views.get(i); - } - } - } NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesUpdated); - storiesController.storiesStorage.updateStories(currentStories); } currentReqId = 0; if (isRunning) { AndroidUtilities.cancelRunOnUIThread(scheduleRequestRunnable); - AndroidUtilities.runOnUIThread(scheduleRequestRunnable, 10_000); + AndroidUtilities.runOnUIThread(scheduleRequestRunnable, interval); } })); + return true; } } 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 edcf47e0a..b45faddfd 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 @@ -4,13 +4,14 @@ import static org.telegram.messenger.AndroidUtilities.dp; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; -import android.animation.StateListAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; -import android.graphics.drawable.ShapeDrawable; import android.text.TextUtils; import android.view.Gravity; import android.view.View; @@ -19,9 +20,11 @@ import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; 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.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; @@ -35,7 +38,7 @@ public class ButtonWithCounterView extends FrameLayout { private Theme.ResourcesProvider resourcesProvider; private final Paint paint; - private final AnimatedTextView.AnimatedTextDrawable text; + public final AnimatedTextView.AnimatedTextDrawable text; private final AnimatedTextView.AnimatedTextDrawable countText; private float countAlpha; private final AnimatedFloat countAlphaAnimated = new AnimatedFloat(350, CubicBezierInterpolator.EASE_OUT_QUINT); @@ -85,6 +88,11 @@ public class ButtonWithCounterView extends FrameLayout { setWillNotDraw(false); } + public void setCounterColor(int color) { + countText.setTextColor(color); + counterDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); + } + private boolean countFilled = true; public void setCountFilled(boolean filled) { countFilled = filled; @@ -189,6 +197,14 @@ public class ButtonWithCounterView extends FrameLayout { private int lastCount; private boolean showZero; + private boolean withCounterIcon; + private Drawable counterDrawable; + + public void withCounterIcon() { + withCounterIcon = true; + counterDrawable = ContextCompat.getDrawable(getContext(), R.drawable.mini_boost_button).mutate(); + counterDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider), PorterDuff.Mode.SRC_IN)); + } public void setShowZero(boolean showZero) { this.showZero = showZero; @@ -279,7 +295,8 @@ public class ButtonWithCounterView extends FrameLayout { float textWidth = text.getCurrentWidth(); float countAlpha = countAlphaAnimated.set(this.countAlpha); - float width = textWidth + (dp(5.66f + 5 + 5) + countText.getCurrentWidth()) * countAlpha; + float lightningWidth = withCounterIcon ? AndroidUtilities.dp(12) : 0; + float width = textWidth + lightningWidth + (dp(5.66f + 5 + 5) + countText.getCurrentWidth()) * countAlpha; AndroidUtilities.rectTmp2.set( (int) ((getMeasuredWidth() - width - getWidth()) / 2f), (int) ((getMeasuredHeight() - text.getHeight()) / 2f - dp(1)), @@ -293,7 +310,7 @@ public class ButtonWithCounterView extends FrameLayout { AndroidUtilities.rectTmp2.set( (int) ((getMeasuredWidth() - width) / 2f + textWidth + dp(countFilled ? 5 : 2)), (int) ((getMeasuredHeight() - dp(18)) / 2f), - (int) ((getMeasuredWidth() - width) / 2f + textWidth + dp((countFilled ? 5 : 2) + 4 + 4) + Math.max(dp(9), countText.getCurrentWidth())), + (int) ((getMeasuredWidth() - width) / 2f + textWidth + dp((countFilled ? 5 : 2) + 4 + 4) + Math.max(dp(9), countText.getCurrentWidth() + lightningWidth)), (int) ((getMeasuredHeight() + dp(18)) / 2f) ); AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); @@ -304,13 +321,26 @@ public class ButtonWithCounterView extends FrameLayout { } if (countFilled) { paint.setAlpha((int) (globalAlpha * (1f - loadingT) * countAlpha * countAlpha * AndroidUtilities.lerp(.5f, 1f, enabledT))); - canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(10), dp(10), paint); + int radius = withCounterIcon ? dp(4) : dp(10); + canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, paint); } AndroidUtilities.rectTmp2.offset(-dp(.3f), -dp(.4f)); countText.setAlpha((int) (globalAlpha * (1f - loadingT) * countAlpha * (countFilled ? 1 : .5f))); countText.setBounds(AndroidUtilities.rectTmp2); + canvas.save(); + if (countFilled && withCounterIcon) { + counterDrawable.setAlpha((int) (globalAlpha * (1f - loadingT) * countAlpha * 1)); + counterDrawable.setBounds( + dp(1) + AndroidUtilities.rectTmp2.left, + dp(2) + AndroidUtilities.rectTmp2.top, + dp(1) + AndroidUtilities.rectTmp2.left + counterDrawable.getIntrinsicWidth(), + dp(2) + AndroidUtilities.rectTmp2.top + counterDrawable.getIntrinsicHeight()); + counterDrawable.draw(canvas); + canvas.translate(lightningWidth / 2, 0); + } countText.draw(canvas); + canvas.restore(); if (countScale != 1) { canvas.restore(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java index 556273338..da32c7d62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/CaptionContainerView.java @@ -212,7 +212,7 @@ public class CaptionContainerView extends FrameLayout { return true; } }; - editText.getEditText().setShadowLayer(dp(10), 0, 0, 0); + editText.getEditText().wrapCanvasToFixClipping = true; editText.setFocusable(true); editText.setFocusableInTouchMode(true); editText.getEditText().hintLayoutYFix = true; @@ -220,7 +220,7 @@ public class CaptionContainerView extends FrameLayout { editText.getEditText().setSupportRtlHint(true); captionBlur = new BlurringShader.StoryBlurDrawer(blurManager, editText.getEditText(), customBlur() ? BlurringShader.StoryBlurDrawer.BLUR_TYPE_CAPTION : BlurringShader.StoryBlurDrawer.BLUR_TYPE_CAPTION_XFER); editText.getEditText().setHintColor(0x80ffffff); - editText.getEditText().setHintText(LocaleController.getString("AddCaption", R.string.AddCaption), false); + editText.getEditText().setHintText(LocaleController.getString(R.string.AddCaption), false); hintTextBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); editText.getEditText().setTranslationX(AndroidUtilities.dp(-40 + 18)); editText.getEmojiButton().setAlpha(0f); @@ -368,15 +368,27 @@ public class CaptionContainerView extends FrameLayout { return super.dispatchTouchEvent(ev); } } + editText.getEditText().setForceCursorEnd(true); editText.getEditText().requestFocus(); // editText.getEditText().setSelection(editText.getEditText().length(), editText.getEditText().length()); editText.openKeyboard(); editText.getEditText().setScrollY(0); + bounce.setPressed(true); return true; + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + bounce.setPressed(false); } return super.dispatchTouchEvent(ev); } + private final ButtonBounce bounce = new ButtonBounce(this, 1f, 3.0f); + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + bounce.setPressed(pressed && !keyboardShown); + } + private ObjectAnimator scrollAnimator; private void animateScrollTo(boolean end) { final EditTextCaption et = editText.getEditText(); @@ -388,6 +400,7 @@ public class CaptionContainerView extends FrameLayout { } int sy = et.getScrollY(); editText.setSelection(end ? editText.length() : 0); + editText.getEditText().setForceCursorEnd(false); int totalLineHeight = et.getLayout().getLineTop(et.getLineCount()); int visibleHeight = et.getHeight() - et.getPaddingTop() - et.getPaddingBottom(); int nsy = end ? totalLineHeight - visibleHeight : 0; @@ -765,6 +778,10 @@ public class CaptionContainerView extends FrameLayout { getHeight() - pad ); + canvas.save(); + final float s = bounce.getScale(.018f); + canvas.scale(s, s, bounds.centerX(), bounds.centerY()); + final float r = lerp(AndroidUtilities.dp(21), 0, keyboardT); if (customBlur()) { drawBlur(backgroundBlur, canvas, bounds, r, false, 0, 0, true); @@ -788,6 +805,8 @@ public class CaptionContainerView extends FrameLayout { } super.dispatchDraw(canvas); + + canvas.restore(); } public RectF getBounds() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java index 6b3f16f63..ce6cc86be 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/DraftsController.java @@ -23,6 +23,7 @@ import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.AbstractSerializedData; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import java.io.File; @@ -303,7 +304,7 @@ public class DraftsController { NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.storiesDraftsUpdated); } - public void deleteForEdit(TLRPC.StoryItem storyItem) { + public void deleteForEdit(TL_stories.StoryItem storyItem) { if (storyItem == null) { return; } @@ -328,7 +329,7 @@ public class DraftsController { delete(toDelete); } - public void saveForEdit(StoryEntry entry, long dialogId, TLRPC.StoryItem storyItem) { + public void saveForEdit(StoryEntry entry, long dialogId, TL_stories.StoryItem storyItem) { if (entry == null || storyItem == null || storyItem.media == null) { return; } @@ -359,7 +360,7 @@ public class DraftsController { append(draft); } - public StoryEntry getForEdit(long dialogId, TLRPC.StoryItem storyItem) { + public StoryEntry getForEdit(long dialogId, TL_stories.StoryItem storyItem) { if (storyItem == null) { return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java index 8b957ff46..298ec2462 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/EmojiBottomSheet.java @@ -96,7 +96,6 @@ import org.telegram.ui.Components.EmojiTabsStrip; import org.telegram.ui.Components.EmojiView; import org.telegram.ui.Components.ExtendedGridLayoutManager; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.Paint.Views.ReactionWidgetEntityView; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.Reactions.ReactionImageHolder; @@ -117,7 +116,6 @@ import org.telegram.ui.WrappedResourceProvider; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -1122,7 +1120,7 @@ public class EmojiBottomSheet extends BottomSheet implements NotificationCenter. listView.scrollToPosition(0, 0); searchField.showProgress(false); tabsStrip.showSelected(false); - }, null, false, false, false, true, 50); + }, null, false, false, false, true, 50, false); }; @NonNull diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/FlashViews.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/FlashViews.java new file mode 100644 index 000000000..0f10e11c4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/FlashViews.java @@ -0,0 +1,276 @@ +package org.telegram.ui.Stories.recorder; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.ContentResolver; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorSpace; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RadialGradient; +import android.graphics.Shader; +import android.hardware.Camera; +import android.os.Build; +import android.provider.Settings; +import android.util.Log; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.ViewAnimator; + +import androidx.core.graphics.ColorUtils; + +import com.google.android.gms.vision.Frame; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.Utilities; +import org.telegram.ui.Components.CubicBezierInterpolator; + +import java.util.ArrayList; + +public class FlashViews { + + public static final int[] COLORS = new int[]{0xffffffff, 0xfffeee8c, 0xff8cdfff}; + public static int getColor(float warmth) { + if (warmth < .5f) { + return ColorUtils.blendARGB(0xff8cdfff, 0xffffffff, Utilities.clamp(warmth / .5f, 1, 0)); + } + return ColorUtils.blendARGB(0xffffffff, 0xfffeee8c, Utilities.clamp((warmth - .5f) / .5f, 1, 0)); + } + + private final Context context; + public final View backgroundView; + public final View foregroundView; + + private final ArrayList invertableViews = new ArrayList<>(); + + private final WindowManager windowManager; + private final View windowView; + private final WindowManager.LayoutParams windowViewParams; + + public FlashViews(Context context, WindowManager windowManager, View windowView, WindowManager.LayoutParams windowViewParams) { + this.context = context; + this.windowManager = windowManager; + this.windowView = windowView; + this.windowViewParams = windowViewParams; + + backgroundView = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + invalidateGradient(); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + gradientMatrix.reset(); + drawGradient(canvas, true); + } + }; + foregroundView = new View(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + gradientMatrix.reset(); + gradientMatrix.postTranslate(-getX(), -getY()); + gradientMatrix.postScale(1f / getScaleX(), 1f / getScaleY(), getPivotX(), getPivotY()); + drawGradient(canvas, false); + } + }; + + paint.setAlpha(0); + } + + public void flash(Utilities.Callback> takePicture) { + windowViewParams.screenBrightness = intensityValue(); + windowManager.updateViewLayout(windowView, windowViewParams); + flashTo(1f, 320, () -> { + AndroidUtilities.runOnUIThread(() -> { + takePicture.run(done -> { + windowViewParams.screenBrightness = -1f; + windowManager.updateViewLayout(windowView, windowViewParams); + AndroidUtilities.runOnUIThread(() -> { + flashTo(0f, 240, done); + }, 80); + }); + }, 320); + }); + } + + public void previewStart() { + flashTo(.85f, 240, null); + } + + public void previewEnd() { + flashTo(0, 240, null); + } + + public void flashIn(Runnable done) { + windowViewParams.screenBrightness = intensityValue(); + windowManager.updateViewLayout(windowView, windowViewParams); + flashTo(1f, 320, done); + } + + public void flashOut() { + windowViewParams.screenBrightness = -1f; + windowManager.updateViewLayout(windowView, windowViewParams); + flashTo(0f, 240, null); + } + + private float invert = 0f; + private ValueAnimator animator; + + private void flashTo(float value, long duration, Runnable whenDone) { + if (animator != null) { + animator.cancel(); + animator = null; + } + if (duration <= 0) { + invert = value; + update(); + if (whenDone != null) { + whenDone.run(); + } + } else { + animator = ValueAnimator.ofFloat(invert, value); + animator.addUpdateListener(anm -> { + invert = (float) anm.getAnimatedValue(); + update(); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + invert = value; + update(); + if (whenDone != null) { + whenDone.run(); + } + } + }); + animator.setDuration(duration); + animator.setInterpolator(CubicBezierInterpolator.EASE_IN); + animator.start(); + } + } + + private void update() { + for (int i = 0; i < invertableViews.size(); i++) { + invertableViews.get(i).setInvert(invert); + invertableViews.get(i).invalidate(); + } + paint.setAlpha((int) (0xff * intensityValue() * invert)); + backgroundView.invalidate(); + foregroundView.invalidate(); + } + + private float intensityValue() { + return intensity; + } + + public void add(Invertable view) { + view.setInvert(invert); + invertableViews.add(view); + } + + private int lastWidth, lastHeight, lastColor; + private float lastInvert; + private int color; + public int colorIndex; + + public float warmth = .75f, intensity = 1f; + + public void setIntensity(float intensity) { + this.intensity = intensity; + update(); + } + + public void setWarmth(float warmth) { + this.warmth = warmth; + this.color = getColor(warmth); + invalidateGradient(); + } + + private final Matrix gradientMatrix = new Matrix(); + private RadialGradient gradient; + private final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private void invalidateGradient() { + if (lastColor != color || lastWidth != backgroundView.getMeasuredWidth() || lastHeight != backgroundView.getMeasuredHeight() || Math.abs(lastInvert - invert) > 0.005f) { + lastColor = color; + lastWidth = backgroundView.getMeasuredWidth(); + lastHeight = backgroundView.getMeasuredHeight(); + lastInvert = invert; + + if (lastWidth > 0 && lastHeight > 0) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + gradient = new RadialGradient( + lastWidth * .5f, lastHeight * .4f, + Math.min(lastWidth, lastHeight) / 2f * 1.35f * (2f - invert), + new long[]{ + Color.valueOf(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f, 0.0f, ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)).pack(), + Color.valueOf(Color.red(color) / 255f, Color.green(color) / 255f, Color.blue(color) / 255f, 1.0f, ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)).pack() + }, + new float[]{AndroidUtilities.lerp(.9f, 0.22f, invert), 1}, + Shader.TileMode.CLAMP + ); + } else { + gradient = new RadialGradient( + lastWidth * .5f, lastHeight * .4f, + Math.min(lastWidth, lastHeight) / 2f * 1.35f * (2f - invert), + new int[]{ ColorUtils.setAlphaComponent(color, 0), color }, + new float[]{AndroidUtilities.lerp(.9f, 0.22f, invert), 1}, + Shader.TileMode.CLAMP + ); + } + paint.setShader(gradient); + invalidate(); + } + } + } + + private void invalidate() { + backgroundView.invalidate(); + foregroundView.invalidate(); + } + + public void drawGradient(Canvas canvas, boolean bg) { + if (gradient != null) { + invalidateGradient(); + gradient.setLocalMatrix(gradientMatrix); + if (bg) { + canvas.drawRect(0, 0, lastWidth, lastHeight, paint); + } else { + AndroidUtilities.rectTmp.set(0, 0, foregroundView.getMeasuredWidth(), foregroundView.getMeasuredHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(12) - 2, dp(12) - 2, paint); + } + } + } + + public interface Invertable { + void setInvert(float invert); + + void invalidate(); + } + + public static class ImageViewInvertable extends ImageView implements Invertable { + public ImageViewInvertable(Context context) { + super(context); + } + + public void setInvert(float invert) { + setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(Color.WHITE, Color.BLACK, invert), PorterDuff.Mode.MULTIPLY)); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java index 540a7e70b..366dceb58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/HintTextView.java @@ -7,12 +7,13 @@ import android.view.Gravity; import android.view.View; import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CubicBezierInterpolator; -public class HintTextView extends View { +public class HintTextView extends View implements FlashViews.Invertable { private final AnimatedTextView.AnimatedTextDrawable textDrawable; @@ -23,7 +24,7 @@ public class HintTextView extends View { textDrawable.setAnimationProperties(.35f, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); textDrawable.setTextColor(0xffffffff); textDrawable.setTextSize(AndroidUtilities.dp(14)); - textDrawable.getPaint().setShadowLayer(AndroidUtilities.dp(1.4f), 0, AndroidUtilities.dp(.4f), 0x4C000000); + textDrawable.setShadowLayer(AndroidUtilities.dp(1.4f), 0, AndroidUtilities.dp(.4f), 0x4C000000); textDrawable.setGravity(Gravity.CENTER_HORIZONTAL); textDrawable.setCallback(this); textDrawable.setOverrideFullWidth(AndroidUtilities.displaySize.x); @@ -52,4 +53,8 @@ public class HintTextView extends View { super.onMeasure(widthMeasureSpec, heightMeasureSpec); textDrawable.setOverrideFullWidth(getMeasuredWidth()); } + + public void setInvert(float invert) { + textDrawable.setTextColor(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert)); + } } 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 728df74cb..6daf24ffd 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 @@ -35,7 +35,6 @@ import android.text.Layout; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.TypedValue; @@ -53,7 +52,6 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.dynamicanimation.animation.FloatValueHolder; import androidx.dynamicanimation.animation.SpringAnimation; @@ -82,6 +80,7 @@ import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; @@ -1127,7 +1126,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai animator.start(); } - private LocationView createLocationSticker(TLRPC.MessageMedia location, TLRPC.MediaArea mediaArea, boolean select) { + private LocationView createLocationSticker(TLRPC.MessageMedia location, TL_stories.MediaArea mediaArea, boolean select) { onTextAdd(); forceChanges = true; @@ -1164,6 +1163,11 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai Size paintingSize = getPaintingSize(); Point position = startPositionRelativeToEntity(null); TextPaintView view = new TextPaintView(getContext(), position, (int) (paintingSize.width / 9), "", colorSwatch, selectedTextType); + view.setMinMaxFontSize((int) (0.5f * (paintingSize.width / 9f)), (int) (2f * (paintingSize.width / 9f)), () -> { + if (weightChooserView != null) { + weightChooserView.invalidate(); + } + }); if (position.x == entitiesView.getMeasuredWidth() / 2f) { view.setStickyX(EntityView.STICKY_CENTER); } @@ -1345,6 +1349,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai if (currentEntityView instanceof TextPaintView) { TextPaintView textPaintView = (TextPaintView) currentEntityView; textPaintView.getSwatch().brushWeight = colorSwatch.brushWeight; + textPaintView.disableAutoresize(false); setCurrentSwatch(textPaintView.getSwatch(), true); float base = (int) (paintingSize.width / 9); @@ -1356,6 +1361,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai @Override public void set(float val) { + textPaintView.disableAutoresize(true); textPaintView.setBaseFontSize((int) (base * val)); } }); @@ -1819,7 +1825,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai return true; } - private void showLocationAlert(LocationView editingLocationView, Utilities.Callback2 onLocationSelected) { + private void showLocationAlert(LocationView editingLocationView, Utilities.Callback2 onLocationSelected) { ChatAttachAlert locationAlert = new ChatAttachAlert(getContext(), new ChatActivity(null) { @Override public long getDialogId() { @@ -1853,15 +1859,15 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai @Override public void didSelectLocation(TLRPC.MessageMedia location, int locationType, boolean notify, int scheduleDate) { - TLRPC.MediaArea mediaArea; + TL_stories.MediaArea mediaArea; if (location instanceof TLRPC.TL_messageMediaGeo) { - TLRPC.TL_mediaAreaGeoPoint areaGeo = new TLRPC.TL_mediaAreaGeoPoint(); + TL_stories.TL_mediaAreaGeoPoint areaGeo = new TL_stories.TL_mediaAreaGeoPoint(); areaGeo.geo = location.geo; mediaArea = areaGeo; } else if (location instanceof TLRPC.TL_messageMediaVenue) { TLRPC.TL_messageMediaVenue loc = (TLRPC.TL_messageMediaVenue) location; if (loc.query_id == -1 || loc.query_id == -2) { - TLRPC.TL_mediaAreaGeoPoint areaGeo = new TLRPC.TL_mediaAreaGeoPoint(); + TL_stories.TL_mediaAreaGeoPoint areaGeo = new TL_stories.TL_mediaAreaGeoPoint(); areaGeo.geo = location.geo; Utilities.globalQueue.postRunnable(() -> { try { @@ -1876,7 +1882,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai }); mediaArea = areaGeo; } else { - TLRPC.TL_inputMediaAreaVenue areaVenue = new TLRPC.TL_inputMediaAreaVenue(); + TL_stories.TL_inputMediaAreaVenue areaVenue = new TL_stories.TL_inputMediaAreaVenue(); areaVenue.query_id = ((TLRPC.TL_messageMediaVenue) location).query_id; areaVenue.result_id = ((TLRPC.TL_messageMediaVenue) location).result_id; mediaArea = areaVenue; @@ -2425,7 +2431,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai mediaEntity.density = locationView.marker.density; mediaEntity.mediaGeo = locationView.location; mediaEntity.mediaArea = locationView.mediaArea; - mediaEntity.mediaArea.coordinates = new TLRPC.TL_mediaAreaCoordinates(); + mediaEntity.mediaArea.coordinates = new TL_stories.TL_mediaAreaCoordinates(); TLRPC.Document emojiDocument = locationView.marker.getCountryCodeEmojiDocument(); if (emojiDocument != null) { VideoEditedInfo.EmojiEntity tlentity = new VideoEditedInfo.EmojiEntity(); @@ -2442,11 +2448,11 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai skipDrawToBitmap = true; ReactionWidgetEntityView reactionView = (ReactionWidgetEntityView) entity; mediaEntity.type = VideoEditedInfo.MediaEntity.TYPE_REACTION; - mediaEntity.mediaArea = new TLRPC.TL_mediaAreaSuggestedReaction(); + mediaEntity.mediaArea = new TL_stories.TL_mediaAreaSuggestedReaction(); mediaEntity.mediaArea.reaction = ReactionsUtils.toTLReaction(reactionView.getCurrentReaction()); mediaEntity.mediaArea.dark = reactionView.isDark(); mediaEntity.mediaArea.flipped = reactionView.isMirrored(); - mediaEntity.mediaArea.coordinates = new TLRPC.TL_mediaAreaCoordinates(); + mediaEntity.mediaArea.coordinates = new TL_stories.TL_mediaAreaCoordinates(); } else { continue; } @@ -4346,7 +4352,7 @@ public class PaintView extends SizeNotifierFrameLayoutPhoto implements IPhotoPai if (emojiView != null) { return; } - emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider); + emojiView = new EmojiView(null, true, false, false, getContext(), false, null, null, true, resourcesProvider, false); emojiView.fixBottomTabContainerTranslation = false; emojiView.allowEmojisForNonPremium(true); emojiView.setVisibility(GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PhotoVideoSwitcherView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PhotoVideoSwitcherView.java index 838ab15fb..78e318f4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PhotoVideoSwitcherView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/PhotoVideoSwitcherView.java @@ -18,6 +18,8 @@ import android.view.View; import android.view.ViewConfiguration; import android.widget.Scroller; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; @@ -25,7 +27,7 @@ import org.telegram.messenger.Utilities; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.CubicBezierInterpolator; -public class PhotoVideoSwitcherView extends View { +public class PhotoVideoSwitcherView extends View implements FlashViews.Invertable { private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); private Paint selectorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -46,8 +48,8 @@ public class PhotoVideoSwitcherView extends View { super(context); selectorPaint.setColor(0x32ffffff); - textPaint.setColor(0xffffffff); + textPaint.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); textPaint.setTextSize(AndroidUtilities.dpf2(14)); textPaint.setShadowLayer(AndroidUtilities.dpf2(1), 0, AndroidUtilities.dpf2(0.4f), 0x33000000); @@ -245,4 +247,9 @@ public class PhotoVideoSwitcherView extends View { public boolean scrolledEnough() { return scrolledEnough || (scrolledEnough = Math.abs(mode - modeAtTouchDown) > .1f); } + + public void setInvert(float invert) { + selectorPaint.setColor(ColorUtils.blendARGB(0x32ffffff, 0x20000000, invert)); + textPaint.setColor(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert)); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java index 2026ff82c..753887802 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/RecordControl.java @@ -1,5 +1,6 @@ package org.telegram.ui.Stories.recorder; +import static android.graphics.Color.BLACK; import static org.telegram.messenger.AndroidUtilities.dp; import static org.telegram.messenger.AndroidUtilities.dpf2; import static org.telegram.messenger.AndroidUtilities.lerp; @@ -46,7 +47,7 @@ import org.telegram.ui.Components.Point; import java.util.ArrayList; -public class RecordControl extends View { +public class RecordControl extends View implements FlashViews.Invertable { public interface Delegate { void onPhotoShoot(); @@ -130,9 +131,9 @@ public class RecordControl extends View { buttonPaint.setColor(BG); buttonPaintWhite.setColor(WHITE); hintLinePaintWhite.setColor(0x58ffffff); + hintLinePaintBlack.setColor(0x18000000); hintLinePaintWhite.setStyle(Paint.Style.STROKE); hintLinePaintWhite.setStrokeCap(Paint.Cap.ROUND); - hintLinePaintBlack.setColor(0x18000000); hintLinePaintBlack.setStyle(Paint.Style.STROKE); hintLinePaintBlack.setStrokeCap(Paint.Cap.ROUND); @@ -201,6 +202,15 @@ public class RecordControl extends View { super.onDetachedFromWindow(); } + public void setInvert(float invert) { + outlinePaint.setColor(ColorUtils.blendARGB(WHITE, BLACK, invert)); + buttonPaint.setColor(ColorUtils.blendARGB(BG, 0x16000000, invert)); + hintLinePaintWhite.setColor(ColorUtils.blendARGB(0x58ffffff, 0x10ffffff, invert)); + hintLinePaintBlack.setColor(ColorUtils.blendARGB(0x18000000, 0x30000000, invert)); + flipDrawableWhite.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert), PorterDuff.Mode.MULTIPLY)); + unlockDrawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert), PorterDuff.Mode.MULTIPLY)); + } + private float cx, cy; private float leftCx, rightCx; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VolumeSliderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/SliderView.java similarity index 54% rename from TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VolumeSliderView.java rename to TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/SliderView.java index 3ff01db57..ef432b18e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VolumeSliderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/SliderView.java @@ -13,7 +13,7 @@ import android.graphics.PorterDuffXfermode; import android.graphics.drawable.Drawable; import android.text.TextPaint; import android.text.TextUtils; -import android.util.Log; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; @@ -29,10 +29,16 @@ import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CubicBezierInterpolator; -public class VolumeSliderView extends View { +public class SliderView extends View { + + public static final int TYPE_VOLUME = 0; + public static final int TYPE_WARMTH = 1; + public static final int TYPE_INTENSITY = 2; + + private final int currentType; private float minVolume = 0; - private float maxVolume = 1.5f; + private float maxVolume = 1f; private float value; private boolean valueIsAnimated; private AnimatedFloat valueAnimated = new AnimatedFloat(this, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); @@ -45,41 +51,63 @@ public class VolumeSliderView extends View { private final Paint speakerWave2Paint = new Paint(Paint.ANTI_ALIAS_FLAG); private final AnimatedTextView.AnimatedTextDrawable text = new AnimatedTextView.AnimatedTextDrawable(false, true, true); + private final AnimatedTextView.AnimatedTextDrawable text2; - public VolumeSliderView(Context context) { + public SliderView(Context context, int type) { super(context); - text.setTextSize(dp(15)); + currentType = type; + text.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); text.setAnimationProperties(.3f, 0, 40, CubicBezierInterpolator.EASE_OUT_QUINT); text.setCallback(this); text.setTextColor(0xffffffff); - text.setText(""); + text.setOverrideFullWidth(AndroidUtilities.displaySize.x); - speaker1Paint.setColor(0xffffffff); - speaker2Paint.setColor(0xffffffff); - speakerWave1Paint.setColor(0xffffffff); - speakerWave2Paint.setColor(0xffffffff); - speakerWave2Paint.setStyle(Paint.Style.STROKE); - speakerWave2Paint.setStrokeCap(Paint.Cap.ROUND); + if (currentType == TYPE_VOLUME) { + text.setTextSize(dp(15)); + text2 = null; + speaker1Paint.setColor(0xffffffff); + speaker2Paint.setColor(0xffffffff); + speakerWave1Paint.setColor(0xffffffff); + speakerWave2Paint.setColor(0xffffffff); + speakerWave2Paint.setStyle(Paint.Style.STROKE); + speakerWave2Paint.setStrokeCap(Paint.Cap.ROUND); + } else { + text.setTextSize(dp(14)); + text.setGravity(Gravity.RIGHT); + text2 = new AnimatedTextView.AnimatedTextDrawable(false, true, true); + text2.setOverrideFullWidth(AndroidUtilities.displaySize.x); + text2.setTextSize(dp(14)); + text2.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + text2.setAnimationProperties(.3f, 0, 40, CubicBezierInterpolator.EASE_OUT_QUINT); + text2.setCallback(this); + text2.setTextColor(0xffffffff); + if (currentType == TYPE_WARMTH) { + text2.setText(LocaleController.getString(R.string.FlashWarmth)); + } else if (currentType == TYPE_INTENSITY) { + text2.setText(LocaleController.getString(R.string.FlashIntensity)); + } + } + text.setText(""); whitePaint.setColor(0xffffffff); whitePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); } - public VolumeSliderView setMinMax(float min, float max) { + public SliderView setMinMax(float min, float max) { this.minVolume = min; this.maxVolume = max; return this; } - public VolumeSliderView setVolume(float volume) { + public SliderView setValue(float volume) { this.value = (volume - this.minVolume) / (this.maxVolume - this.minVolume); updateText(volume); return this; } - public VolumeSliderView setOnValueChange(Utilities.Callback listener) { + public SliderView setOnValueChange(Utilities.Callback listener) { onValueChange = listener; return this; } @@ -107,26 +135,36 @@ public class VolumeSliderView extends View { canvas.saveLayerAlpha(0, 0, w, h, 0xFF, Canvas.ALL_SAVE_FLAG); - text.setBounds(dp(42), -dp(1), w, h - dp(1)); - text.draw(canvas); + if (currentType == TYPE_VOLUME) { + text.setBounds(dp(42), -dp(1), w, h - dp(1)); + text.draw(canvas); + } else { + text2.setBounds(dp(12.33f), -dp(1), w - (int) text.getCurrentWidth() - dp(6), h - dp(1)); + text2.draw(canvas); - canvas.drawPath(speaker1Path, speaker1Paint); - canvas.drawPath(speaker2Path, speaker2Paint); + text.setBounds(w - dp(11 + 100), -dp(1), w - dp(11), h - dp(1)); + text.draw(canvas); + } - final float volume = this.maxVolume - this.minVolume != 0 ? this.minVolume + this.value * (this.maxVolume - this.minVolume) : 0; - final float wave1Alpha = this.wave1Alpha.set(volume > .25); - canvas.save(); - canvas.translate(-dpf2(0.33f) * (1f - wave1Alpha), 0); - speakerWave1Paint.setAlpha((int) (0xFF * wave1Alpha)); - canvas.drawPath(speakerWave1Path, speakerWave1Paint); - canvas.restore(); + if (currentType == TYPE_VOLUME) { + canvas.drawPath(speaker1Path, speaker1Paint); + canvas.drawPath(speaker2Path, speaker2Paint); - final float wave2Alpha = this.wave2Alpha.set(volume > .5); - canvas.save(); - canvas.translate(-dpf2(0.66f) * (1f - wave2Alpha), 0); - speakerWave2Paint.setAlpha((int) (0xFF * wave2Alpha)); - canvas.drawPath(speakerWave2Path, speakerWave2Paint); - canvas.restore(); + final float volume = this.maxVolume - this.minVolume != 0 ? this.minVolume + this.value * (this.maxVolume - this.minVolume) : 0; + final float wave1Alpha = this.wave1Alpha.set(volume > .25); + canvas.save(); + canvas.translate(-dpf2(0.33f) * (1f - wave1Alpha), 0); + speakerWave1Paint.setAlpha((int) (0xFF * wave1Alpha)); + canvas.drawPath(speakerWave1Path, speakerWave1Paint); + canvas.restore(); + + final float wave2Alpha = this.wave2Alpha.set(volume > .5); + canvas.save(); + canvas.translate(-dpf2(0.66f) * (1f - wave2Alpha), 0); + speakerWave2Paint.setAlpha((int) (0xFF * wave2Alpha)); + canvas.drawPath(speakerWave2Path, speakerWave2Paint); + canvas.restore(); + } canvas.save(); canvas.drawRect(0, 0, w * value, h, whitePaint); @@ -180,19 +218,26 @@ public class VolumeSliderView extends View { if (onValueChange != null) { onValueChange.run(volume); } - invalidate(); } lastTouchX = x; return true; } - private void updateText(float volume) { - String string = Math.round(volume * 100) + "%"; + private void updateText(float value) { + String string = Math.round(value * 100) + "%"; if (!TextUtils.equals(text.getText(), string)) { text.cancelAnimation(); text.setAnimationProperties(.3f, 0, valueIsAnimated ? 320 : 40, CubicBezierInterpolator.EASE_OUT_QUINT); text.setText(string); } + + if (currentType == TYPE_WARMTH) { + final int warmthColor = FlashViews.getColor(value); +// text.setTextColor(warmthColor); +// text2.setTextColor(warmthColor); + whitePaint.setColor(warmthColor); + } + invalidate(); } private float r; @@ -204,42 +249,49 @@ public class VolumeSliderView extends View { r = dpf2(6.33f); textPaint.setTextSize(dp(16)); text.setTextSize(dp(15)); - // TODO: fix this nonsense - w = (int) Math.min(textPaint.measureText(LocaleController.getString(R.string.StoryAudioRemove)) + dp(88), MeasureSpec.getSize(widthMeasureSpec)); - h = dp(48); + if (currentType == TYPE_VOLUME) { + // TODO: fix this nonsense + w = (int) Math.min(textPaint.measureText(LocaleController.getString(R.string.StoryAudioRemove)) + dp(88), MeasureSpec.getSize(widthMeasureSpec)); + h = dp(48); + } else { + w = dp(190); + h = dp(44); + } setMeasuredDimension(w, h); - final float cx = dp(25), cy = h / 2f; + if (currentType == TYPE_VOLUME) { + final float cx = dp(25), cy = h / 2f; - speaker1Paint.setPathEffect(new CornerPathEffect(dpf2(1.33f))); - speaker1Path.rewind(); - speaker1Path.moveTo(cx - dpf2(8.66f), cy - dpf2(2.9f)); - speaker1Path.lineTo(cx - dpf2(3f), cy - dpf2(2.9f)); - speaker1Path.lineTo(cx - dpf2(3f), cy + dpf2(2.9f)); - speaker1Path.lineTo(cx - dpf2(8.66f), cy + dpf2(2.9f)); - speaker1Path.close(); + speaker1Paint.setPathEffect(new CornerPathEffect(dpf2(1.33f))); + speaker1Path.rewind(); + speaker1Path.moveTo(cx - dpf2(8.66f), cy - dpf2(2.9f)); + speaker1Path.lineTo(cx - dpf2(3f), cy - dpf2(2.9f)); + speaker1Path.lineTo(cx - dpf2(3f), cy + dpf2(2.9f)); + speaker1Path.lineTo(cx - dpf2(8.66f), cy + dpf2(2.9f)); + speaker1Path.close(); - speaker2Paint.setPathEffect(new CornerPathEffect(dpf2(2.66f))); - speaker2Path.rewind(); - speaker2Path.moveTo(cx - dpf2(7.5f), cy); - speaker2Path.lineTo(cx, cy - dpf2(7.33f)); - speaker2Path.lineTo(cx, cy + dpf2(7.33f)); - speaker2Path.close(); + speaker2Paint.setPathEffect(new CornerPathEffect(dpf2(2.66f))); + speaker2Path.rewind(); + speaker2Path.moveTo(cx - dpf2(7.5f), cy); + speaker2Path.lineTo(cx, cy - dpf2(7.33f)); + speaker2Path.lineTo(cx, cy + dpf2(7.33f)); + speaker2Path.close(); - speakerWave1Path.rewind(); - AndroidUtilities.rectTmp.set(cx - dpf2(0.33f) - dp(4.33f), cy - dp(4.33f), cx - dpf2(0.33f) + dp(4.33f), cy + dp(4.33f)); - speakerWave1Path.arcTo(AndroidUtilities.rectTmp, -60, 120); - speakerWave1Path.close(); + speakerWave1Path.rewind(); + AndroidUtilities.rectTmp.set(cx - dpf2(0.33f) - dp(4.33f), cy - dp(4.33f), cx - dpf2(0.33f) + dp(4.33f), cy + dp(4.33f)); + speakerWave1Path.arcTo(AndroidUtilities.rectTmp, -60, 120); + speakerWave1Path.close(); - speakerWave2Paint.setStyle(Paint.Style.STROKE); - speakerWave2Paint.setStrokeWidth(dp(2)); - speakerWave2Path.rewind(); - AndroidUtilities.rectTmp.set(cx - dpf2(0.33f) - dp(8), cy - dp(8), cx - dpf2(0.33f) + dp(8), cy + dp(8)); - speakerWave2Path.arcTo(AndroidUtilities.rectTmp, -70, 140); + speakerWave2Paint.setStyle(Paint.Style.STROKE); + speakerWave2Paint.setStrokeWidth(dp(2)); + speakerWave2Path.rewind(); + AndroidUtilities.rectTmp.set(cx - dpf2(0.33f) - dp(8), cy - dp(8), cx - dpf2(0.33f) + dp(8), cy + dp(8)); + speakerWave2Path.arcTo(AndroidUtilities.rectTmp, -70, 140); + } } @Override protected boolean verifyDrawable(@NonNull Drawable who) { - return who == text || super.verifyDrawable(who); + return who == text || who == text2 || super.verifyDrawable(who); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java index 284dea419..e46654cb1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryEntry.java @@ -3,7 +3,6 @@ package org.telegram.ui.Stories.recorder; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapShader; -import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Matrix; @@ -11,11 +10,9 @@ import android.graphics.Paint; import android.graphics.Shader; import android.media.MediaExtractor; import android.media.MediaFormat; -import android.net.Uri; import android.os.Build; import android.provider.MediaStore; import android.text.SpannableString; -import android.util.Log; import androidx.annotation.NonNull; @@ -27,10 +24,8 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.FileRefController; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MediaController; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -41,6 +36,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; +import org.telegram.tgnet.tl.TL_stories; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.PhotoFilterView; @@ -48,7 +44,6 @@ import org.telegram.ui.Components.RLottieDrawable; import java.io.File; import java.io.FileOutputStream; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; @@ -66,7 +61,7 @@ public class StoryEntry extends IStoryPart { public boolean isEditSaved; public double fileDuration = -1; public boolean editedMedia, editedCaption, editedPrivacy; - public ArrayList editedMediaAreas; + public ArrayList editedMediaAreas; public boolean isError; public TLRPC.TL_error error; @@ -514,7 +509,7 @@ public class StoryEntry extends IStoryPart { cancelCheckStickers(); } - public static StoryEntry fromStoryItem(File file, TLRPC.StoryItem storyItem) { + public static StoryEntry fromStoryItem(File file, TL_stories.StoryItem storyItem) { StoryEntry entry = new StoryEntry(); entry.isEdit = true; entry.editStoryId = storyItem.id; @@ -958,7 +953,7 @@ public class StoryEntry extends IStoryPart { }); } - public void checkStickers(TLRPC.StoryItem storyItem) { + public void checkStickers(TL_stories.StoryItem storyItem) { if (storyItem == null || storyItem.media == null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java index d73f391b0..5b11bd555 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/StoryRecorder.java @@ -15,6 +15,7 @@ import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.graphics.Bitmap; @@ -51,8 +52,10 @@ import android.text.style.ClickableSpan; 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.view.Gravity; +import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.ScaleGestureDetector; @@ -144,6 +147,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class StoryRecorder implements NotificationCenter.NotificationCenterDelegate { @@ -160,6 +164,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private final WindowManager.LayoutParams windowLayoutParams; private WindowView windowView; private ContainerView containerView; + private FlashViews flashViews; private static StoryRecorder instance; private boolean wasSend; @@ -270,7 +275,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg src.screenRect.set(x, y, x + size, y + size); src.backgroundImageReceiver = avatarImage.getImageReceiver(); - src.rounding = Math.max(src.screenRect.width(), src.screenRect.height()) / 2f; + src.rounding = radius * 2; return src; } @@ -788,8 +793,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg br = Math.min(rectF.width(), rectF.height()) / 2f; if (fromSourceView.backgroundImageReceiver != null) { fromSourceView.backgroundImageReceiver.setImageCoords(rectF); + int prevRoundRadius = fromSourceView.backgroundImageReceiver.getRoundRadius()[0]; + fromSourceView.backgroundImageReceiver.setRoundRadius((int) r); fromSourceView.backgroundImageReceiver.setAlpha(alpha); fromSourceView.backgroundImageReceiver.draw(canvas); + fromSourceView.backgroundImageReceiver.setRoundRadius(prevRoundRadius); } else if (fromSourceView.backgroundPaint != null) { fromSourceView.backgroundPaint.setShadowLayer(dp(2), 0, dp(3), Theme.multAlpha(0x33000000, alpha)); fromSourceView.backgroundPaint.setAlpha((int) (0xFF * alpha)); @@ -1033,6 +1041,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg cameraView.switchCamera(); recordControl.rotateFlip(180); saveCameraFace(cameraView.isFrontface()); + if (useDisplayFlashlight()) { + flashViews.flashIn(null); + } else { + flashViews.flashOut(); + } return true; } @@ -1091,6 +1104,10 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg MeasureSpec.makeMeasureSpec(previewW, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(previewH + underControls, MeasureSpec.EXACTLY) ); + flashViews.backgroundView.measure( + MeasureSpec.makeMeasureSpec(W, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(H, MeasureSpec.EXACTLY) + ); if (galleryListView != null) { galleryListView.measure(MeasureSpec.makeMeasureSpec(previewW, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(H, MeasureSpec.EXACTLY)); @@ -1172,6 +1189,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } containerView.layout(l, t, r, b); + flashViews.backgroundView.layout(0, 0, W, H); if (galleryListView != null) { galleryListView.layout((W - galleryListView.getMeasuredWidth()) / 2, 0, (W + galleryListView.getMeasuredWidth()) / 2, H); @@ -1302,12 +1320,16 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg protected void onLayout(boolean changed, int left, int top, int right, int bottom) { final int t = underStatusBar ? insetTop : 0; + final int w = right - left; + final int h = bottom - top; + previewContainer.layout(0, 0, previewW, previewH); previewContainer.setPivotX(previewW * .5f); actionBarContainer.layout(0, t, previewW, t + actionBarContainer.getMeasuredHeight()); controlContainer.layout(0, previewH - controlContainer.getMeasuredHeight(), previewW, previewH); navbarContainer.layout(0, previewH, previewW, previewH + navbarContainer.getMeasuredHeight()); captionContainer.layout(0, 0, previewW, previewH); + flashViews.foregroundView.layout(0, 0, w, h); if (captionEdit.mentionContainer != null) { captionEdit.mentionContainer.layout(0, 0, previewW, previewH); @@ -1321,9 +1343,6 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg paintView.layout(0, 0, paintView.getMeasuredWidth(), paintView.getMeasuredHeight()); } - final int w = right - left; - final int h = bottom - top; - for (int i = 0; i < getChildCount(); ++i) { View child = getChildAt(i); if (child instanceof ItemOptions.DimView) { @@ -1346,6 +1365,8 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg measureChildExactly(controlContainer, previewW, dp(220)); measureChildExactly(navbarContainer, previewW, underControls); measureChildExactly(captionContainer, previewW, previewH); + measureChildExactly(flashViews.foregroundView, W, H); + if (captionEdit.mentionContainer != null) { measureChildExactly(captionEdit.mentionContainer, previewW, previewH); } @@ -1384,7 +1405,8 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg topGradientPaint.setShader(topGradient); } topGradientPaint.setAlpha((int) (0xFF * openProgress)); - canvas.drawRect(0, 0, getWidth(), dp(72) + top, topGradientPaint); + AndroidUtilities.rectTmp.set(0, 0, getWidth(), dp(72 + 12) + top); + canvas.drawRoundRect(AndroidUtilities.rectTmp, dp(12), dp(12), topGradientPaint); } return r; } @@ -1405,7 +1427,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private FrameLayout captionContainer; private FrameLayout navbarContainer; - private ImageView backButton; + private FlashViews.ImageViewInvertable backButton; private SimpleTextView titleTextView; private StoryPrivacyBottomSheet privacySheet; private BlurringShader.BlurManager blurManager; @@ -1415,7 +1437,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg private DualCameraView cameraView; private int flashButtonResId; - private ImageView flashButton; + private ToggleButton2 flashButton; private ToggleButton dualButton; private VideoTimerView videoTimerView; private boolean wasGalleryOpen; @@ -1518,8 +1540,18 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } windowView.setFocusable(true); + flashViews = new FlashViews(context, windowManager, windowView, windowLayoutParams); + flashViews.add(new FlashViews.Invertable() { + @Override + public void setInvert(float invert) { + AndroidUtilities.setLightNavigationBar(windowView, invert > 0.5f); + AndroidUtilities.setLightStatusBar(windowView, invert > 0.5f); + } + @Override + public void invalidate() {} + }); + windowView.addView(flashViews.backgroundView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); windowView.addView(containerView = new ContainerView(context)); - containerView.addView(previewContainer = new FrameLayout(context) { @Override public boolean onTouchEvent(MotionEvent event) { @@ -1541,7 +1573,24 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg photoFilterViewBlurControl.setActualAreaSize(photoFilterViewBlurControl.getMeasuredWidth(), photoFilterViewBlurControl.getMeasuredHeight()); } } + + private final Rect leftExclRect = new Rect(); + private final Rect rightExclRect = new Rect(); + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + final int w = right - left; + final int h = bottom - top; + leftExclRect.set(0, h - dp(120), dp(40), h); + rightExclRect.set(w - dp(40), h - dp(120), w, h); + setSystemGestureExclusionRects(Arrays.asList(leftExclRect, rightExclRect)); + } + } }); + containerView.addView(flashViews.foregroundView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + blurManager = new BlurringShader.BlurManager(previewContainer); containerView.addView(actionBarContainer = new FrameLayout(context)); // 150dp containerView.addView(controlContainer = new FrameLayout(context)); // 220dp @@ -1782,7 +1831,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg captionContainer.addView(videoTimelineContainerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80 + 25, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM, 0, 0, 0, 68)); captionContainer.addView(captionEdit, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM, 0, 200, 0, 0)); - backButton = new ImageView(context); + backButton = new FlashViews.ImageViewInvertable(context); backButton.setContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); backButton.setScaleType(ImageView.ScaleType.CENTER); backButton.setImageResource(R.drawable.msg_photo_back); @@ -1795,6 +1844,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg onBackPressed(); }); actionBarContainer.addView(backButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.LEFT)); + flashViews.add(backButton); titleTextView = new SimpleTextView(context); titleTextView.setTextSize(20); @@ -1859,28 +1909,60 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg }); actionBarContainer.addView(playButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT, 0, 0, 48 + 48, 0)); - flashButton = new ImageView(context); - flashButton.setScaleType(ImageView.ScaleType.CENTER); - flashButton.setColorFilter(new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY)); + flashButton = new ToggleButton2(context); flashButton.setBackground(Theme.createSelectorDrawable(0x20ffffff)); flashButton.setOnClickListener(e -> { if (cameraView == null || awaitingPlayer) { return; } - CameraSession cameraSession = cameraView.getCameraSession(); - if (cameraSession == null) { + String current = getCurrentFlashMode(); + String next = getNextFlashMode(); + if (current == null || current.equals(next)) { return; } - String current = cameraSession.getCurrentFlashMode(); - String next = cameraSession.getNextFlashMode(); - if (current.equals(next)) { - return; - } - cameraView.getCameraSession().setCurrentFlashMode(next); + setCurrentFlashMode(next); setCameraFlashModeIcon(next, true); }); + flashButton.setOnLongClickListener(e -> { + if (cameraView == null || !cameraView.isFrontface()) { + return false; + } + + checkFrontfaceFlashModes(); + flashButton.setSelected(true); + flashViews.previewStart(); + ItemOptions.makeOptions(containerView, resourcesProvider, flashButton) + .addView( + new SliderView(getContext(), SliderView.TYPE_WARMTH) + .setValue(flashViews.warmth) + .setOnValueChange(v -> { + flashViews.setWarmth(v); + }) + ) + .addSpaceGap() + .addView( + new SliderView(getContext(), SliderView.TYPE_INTENSITY) + .setMinMax(.65f, 1f) + .setValue(flashViews.intensity) + .setOnValueChange(v -> { + flashViews.setIntensity(v); + }) + ) + .setOnDismiss(() -> { + saveFrontFaceFlashMode(); + flashViews.previewEnd(); + flashButton.setSelected(false); + }) + .setDimAlpha(0) + .setGravity(Gravity.RIGHT) + .translate(dp(46), -dp(4)) + .setBackgroundColor(0xbb1b1b1b) + .show(); + return true; + }); flashButton.setVisibility(View.GONE); flashButton.setAlpha(0f); + flashViews.add(flashButton); actionBarContainer.addView(flashButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT)); dualButton = new ToggleButton(context, R.drawable.media_dual_camera2_shadow, R.drawable.media_dual_camera2); @@ -1899,6 +1981,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg savedDualHint.hide(); }); dualButton.setVisibility(DualCameraView.dualAvailableStatic(context) ? View.VISIBLE : View.GONE); + flashViews.add(dualButton); actionBarContainer.addView(dualButton, LayoutHelper.createFrame(56, 56, Gravity.TOP | Gravity.RIGHT)); dualHint = new HintView2(activity, HintView2.DIRECTION_TOP) @@ -1919,6 +2002,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg videoTimerView = new VideoTimerView(context); showVideoTimer(false, false); actionBarContainer.addView(videoTimerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 45, Gravity.TOP | Gravity.FILL_HORIZONTAL, 56, 0, 56, 0)); + flashViews.add(videoTimerView); if (Build.VERSION.SDK_INT >= 21) { MediaController.loadGalleryPhotosAlbums(0); @@ -1928,6 +2012,8 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg recordControl.setDelegate(recordControlDelegate); recordControl.startAsVideo(isVideo); controlContainer.addView(recordControl, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 100, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + flashViews.add(recordControl); + cameraHint = new HintView2(activity, HintView2.DIRECTION_BOTTOM) .setMultilineText(true) .setText(LocaleController.getString(R.string.StoryCameraHint2)) @@ -1963,9 +2049,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg recordControl.startAsVideoT(t); }); navbarContainer.addView(modeSwitcherView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + flashViews.add(modeSwitcherView); hintTextView = new HintTextView(context); navbarContainer.addView(hintTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER, 8, 0, 8, 8)); + flashViews.add(hintTextView); previewButtons = new PreviewButtons(context); previewButtons.setVisibility(View.GONE); @@ -2369,11 +2457,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg flashButton.setContentDescription(LocaleController.getString("AccDescrCameraFlashOff", R.string.AccDescrCameraFlashOff)); break; } - if (animated && flashButtonResId != resId) { - AndroidUtilities.updateImageViewImageAnimated(flashButton, flashButtonResId = resId); - } else { - flashButton.setImageResource(flashButtonResId = resId); - } + flashButton.setIcon(flashButtonResId = resId, animated && flashButtonResId != resId); flashButton.setVisibility(View.VISIBLE); if (animated) { flashButton.animate().alpha(1f).start(); @@ -2401,10 +2485,25 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg outputFile = null; } outputFile = StoryEntry.makeCacheFile(currentAccount, false); - cameraView.startTakePictureAnimation(); + takingPhoto = true; + checkFrontfaceFlashModes(); + isDark = false; + if (cameraView.isFrontface() && frontfaceFlashMode == 1) { + checkIsDark(); + } + if (useDisplayFlashlight()) { + flashViews.flash(this::takePicture); + } else { + takePicture(null); + } + } + + private void takePicture(Utilities.Callback done) { boolean savedFromTextureView = false; + if (!useDisplayFlashlight()) { + cameraView.startTakePictureAnimation(true); + } if (cameraView.isDual() && TextUtils.equals(cameraView.getCameraSession().getCurrentFlashMode(), Camera.Parameters.FLASH_MODE_OFF)) { - takingPhoto = true; cameraView.pauseAsTakingPicture(); final Bitmap bitmap = cameraView.getTextureView().getBitmap(); try (FileOutputStream out = new FileOutputStream(outputFile.getAbsoluteFile())) { @@ -2418,6 +2517,11 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg if (!savedFromTextureView) { final CameraSession cameraSession = cameraView.getCameraSession(); takingPhoto = CameraController.getInstance().takePicture(outputFile, true, cameraSession, (orientation) -> { + if (useDisplayFlashlight()) { + try { + windowView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } takingPhoto = false; if (outputFile == null) { return; @@ -2439,14 +2543,24 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg outputEntry = StoryEntry.fromPhotoShoot(outputFile, rotate); StoryPrivacySelector.applySaved(currentAccount, outputEntry); fromGallery = false; - navigateTo(PAGE_PREVIEW, true); + + if (done != null) { + done.run(() -> navigateTo(PAGE_PREVIEW, true)); + } else { + navigateTo(PAGE_PREVIEW, true); + } }); } else { takingPhoto = false; outputEntry = StoryEntry.fromPhotoShoot(outputFile, 0); StoryPrivacySelector.applySaved(currentAccount, outputEntry); fromGallery = false; - navigateTo(PAGE_PREVIEW, true); + + if (done != null) { + done.run(() -> navigateTo(PAGE_PREVIEW, true)); + } else { + navigateTo(PAGE_PREVIEW, true); + } } } @@ -2470,10 +2584,26 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg outputFile = null; } outputFile = StoryEntry.makeCacheFile(currentAccount, true); + checkFrontfaceFlashModes(); + isDark = false; + if (cameraView.isFrontface() && frontfaceFlashMode == 1) { + checkIsDark(); + } + if (useDisplayFlashlight()) { + flashViews.flashIn(() -> startRecording(byLongPress, whenStarted)); + } else { + startRecording(byLongPress, whenStarted); + } + } + + private void startRecording(boolean byLongPress, Runnable whenStarted) { CameraController.getInstance().recordVideo(cameraView.getCameraSession(), outputFile, false, (thumbPath, duration) -> { if (recordControl != null) { recordControl.stopRecordingLoading(true); } + if (useDisplayFlashlight()) { + flashViews.flashOut(); + } if (outputFile == null || cameraView == null) { return; } @@ -2575,7 +2705,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg @Override public void onGalleryClick() { - if (currentPage == PAGE_CAMERA && requestGalleryPermission()) { + if (currentPage == PAGE_CAMERA && !takingPhoto && !takingVideo && requestGalleryPermission()) { animateGalleryListView(true); } } @@ -2588,8 +2718,18 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg if (savedDualHint != null) { savedDualHint.hide(); } + if (useDisplayFlashlight() && frontfaceFlashModes != null && !frontfaceFlashModes.isEmpty()) { + final String mode = frontfaceFlashModes.get(frontfaceFlashMode); + SharedPreferences sharedPreferences = ApplicationLoader.applicationContext.getSharedPreferences("camera", Activity.MODE_PRIVATE); + sharedPreferences.edit().putString("flashMode", mode).commit(); + } cameraView.switchCamera(); saveCameraFace(cameraView.isFrontface()); + if (useDisplayFlashlight()) { + flashViews.flashIn(null); + } else { + flashViews.flashOut(); + } } @Override @@ -2686,6 +2826,34 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } } + private boolean isDark; + private void checkIsDark() { + if (cameraView == null || cameraView.getTextureView() == null) { + isDark = false; + return; + } + final Bitmap bitmap = cameraView.getTextureView().getBitmap(); + if (bitmap == null) { + isDark = false; + return; + } + float l = 0; + final int sx = bitmap.getWidth() / 12; + final int sy = bitmap.getHeight() / 12; + for (int x = 0; x < 10; ++x) { + for (int y = 0; y < 10; ++y) { + l += AndroidUtilities.computePerceivedBrightness(bitmap.getPixel((1 + x) * sx, (1 + y) * sy)); + } + } + l /= 100; + bitmap.recycle(); + isDark = l < .22f; + } + + private boolean useDisplayFlashlight() { + return (takingPhoto || takingVideo) && (cameraView != null && cameraView.isFrontface()) && (frontfaceFlashMode == 2 || frontfaceFlashMode == 1 && isDark); + } + private boolean videoTimerShown = true; private void showVideoTimer(boolean show, boolean animated) { if (videoTimerShown == show) { @@ -4091,7 +4259,7 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg super.toggleDual(); dualButton.setValue(isDual()); // recordControl.setDual(isDual()); - setCameraFlashModeIcon(isDual() || getCameraSession() == null || isFrontface() ? null : getCameraSession().getCurrentFlashMode(), true); + setCameraFlashModeIcon(getCurrentFlashMode(), true); } @Override @@ -4117,8 +4285,8 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg cameraView.setThumbDrawable(getCameraThumb()); cameraView.initTexture(); cameraView.setDelegate(() -> { - String currentFlashMode = cameraView.getCameraSession().getCurrentFlashMode(); - if (TextUtils.equals(currentFlashMode, cameraView.getCameraSession().getNextFlashMode())) { + String currentFlashMode = getCurrentFlashMode(); + if (TextUtils.equals(currentFlashMode, getNextFlashMode())) { currentFlashMode = null; } setCameraFlashModeIcon(currentPage == PAGE_CAMERA ? currentFlashMode : null, true); @@ -4137,6 +4305,67 @@ public class StoryRecorder implements NotificationCenter.NotificationCenterDeleg } } + private int frontfaceFlashMode = -1; + private ArrayList frontfaceFlashModes; + private void checkFrontfaceFlashModes() { + if (frontfaceFlashMode < 0) { + frontfaceFlashMode = MessagesController.getGlobalMainSettings().getInt("frontflash", 1); + frontfaceFlashModes = new ArrayList<>(); + frontfaceFlashModes.add(Camera.Parameters.FLASH_MODE_OFF); + frontfaceFlashModes.add(Camera.Parameters.FLASH_MODE_AUTO); + frontfaceFlashModes.add(Camera.Parameters.FLASH_MODE_ON); + + flashViews.setWarmth(MessagesController.getGlobalMainSettings().getFloat("frontflash_warmth", .9f)); + flashViews.setIntensity(MessagesController.getGlobalMainSettings().getFloat("frontflash_intensity", 1)); + } + } + private void saveFrontFaceFlashMode() { + if (frontfaceFlashMode >= 0) { + MessagesController.getGlobalMainSettings().edit() + .putFloat("frontflash_warmth", flashViews.warmth) + .putFloat("frontflash_intensity", flashViews.intensity) + .apply(); + } + } + + private String getCurrentFlashMode() { + if (cameraView == null || cameraView.getCameraSession() == null) { + return null; + } + if (cameraView.isFrontface() && cameraView.getCameraSession().availableFlashModes.isEmpty()) { + checkFrontfaceFlashModes(); + return frontfaceFlashModes.get(frontfaceFlashMode); + } + return cameraView.getCameraSession().getCurrentFlashMode(); + } + + private String getNextFlashMode() { + if (cameraView == null || cameraView.getCameraSession() == null) { + return null; + } + if (cameraView.isFrontface() && cameraView.getCameraSession().availableFlashModes.isEmpty()) { + checkFrontfaceFlashModes(); + return frontfaceFlashModes.get(frontfaceFlashMode + 1 >= frontfaceFlashModes.size() ? 0 : frontfaceFlashMode + 1); + } + return cameraView.getCameraSession().getNextFlashMode(); + } + + private void setCurrentFlashMode(String mode) { + if (cameraView == null || cameraView.getCameraSession() == null) { + return; + } + if (cameraView.isFrontface() && cameraView.getCameraSession().availableFlashModes.isEmpty()) { + int index = frontfaceFlashModes.indexOf(mode); + if (index >= 0) { + frontfaceFlashMode = index; + MessagesController.getGlobalMainSettings().edit().putInt("frontflash", frontfaceFlashMode).apply(); + } + return; + } + cameraView.getCameraSession().setCurrentFlashMode(mode); + } + + private Drawable getCameraThumb() { Bitmap bitmap = null; try { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TimelineView.java index 54f0ef781..e80473070 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TimelineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/TimelineView.java @@ -28,7 +28,6 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -192,9 +191,10 @@ public class TimelineView extends View { onLongPress = () -> { if (!pressVideo && hasAudio) { - VolumeSliderView slider = - new VolumeSliderView(getContext()) - .setVolume(audioVolume) + SliderView slider = + new SliderView(getContext(), SliderView.TYPE_VOLUME) + .setValue(audioVolume) + .setMinMax(0, 1.5f) .setOnValueChange(volume -> { audioVolume = volume; if (delegate != null) { @@ -641,7 +641,7 @@ public class TimelineView extends View { delegate.onProgressDragChange(true); } } - if (!hasVideo && (progress / (float) audioDuration < audioLeft || progress / (float) audioDuration > audioRight)) { + if (!hasVideo) { progress = (long) (audioLeft * audioDuration); if (delegate != null) { delegate.onProgressDragChange(true); @@ -703,17 +703,23 @@ public class TimelineView extends View { scroller.fling(wasScrollX = scrollX, 0, -velocity, 0, px, maxScrollX, 0, 0); scrollStopped = false; } - } else if ((pressHandle == HANDLE_AUDIO_SCROLL || pressHandle == HANDLE_AUDIO_REGION && !dragged) && hasVideo && audioSelected && velocityTracker != null) { - velocityTracker.computeCurrentVelocity(1000); + } else if ((pressHandle == HANDLE_AUDIO_SCROLL || pressHandle == HANDLE_AUDIO_REGION && !dragged) && audioSelected && velocityTracker != null) { + velocityTracker.computeCurrentVelocity(hasVideo ? 1000 : 1500); final int velocity = (int) velocityTracker.getXVelocity(); scrollingVideo = false; if (Math.abs(velocity) > dp(100)) { final long videoScrollDuration = Math.min(getBaseDuration(), MAX_SCROLL_DURATION); final int scrollX = (int) (px + ph + audioOffset / (float) videoScrollDuration * sw); - final long mx = (long) Math.max(getBaseDuration(), audioDuration); - final long mn = (long) Math.min(getBaseDuration(), audioDuration); + final long mx, mn; + if (hasVideo) { + mx = (long) ((videoRight * videoDuration) - (0 * audioDuration)); + mn = (long) ((videoLeft * videoDuration) - (1 * audioDuration)); + } else { + mx = 0; + mn = (long) -(audioDuration - Math.min(getBaseDuration(), MAX_SCROLL_DURATION)); + } scrolling = true; - scroller.fling(wasScrollX = scrollX, 0, velocity, 0, (int) (px + ph + (long) ((videoLeft * videoDuration) - (1 * audioDuration)) / (float) videoScrollDuration * sw), (int) (px + ph + (long) ((videoRight * videoDuration) - (0 * audioDuration)) / (float) videoScrollDuration * sw), 0, 0); + scroller.fling(wasScrollX = scrollX, 0, velocity, 0, (int) (px + ph + mn / (float) videoScrollDuration * sw), (int) (px + ph + mx / (float) videoScrollDuration * sw), 0, 0); scrollStopped = false; } } @@ -739,13 +745,21 @@ public class TimelineView extends View { } private long minAudioSelect() { - return (long) Math.max(MIN_SELECT_DURATION, Math.min(videoDuration, MAX_SELECT_DURATION) * 0.15f); + return (long) Math.max(MIN_SELECT_DURATION, Math.min(hasVideo ? videoDuration : audioDuration, MAX_SELECT_DURATION) * 0.15f); } private void moveAudioOffset(final float d) { final long videoScrollDuration = Math.min(getBaseDuration(), MAX_SCROLL_DURATION); if (!hasVideo) { + long wasAudioOffset = audioOffset; audioOffset = Utilities.clamp(audioOffset + (long) d, 0, (long) -(audioDuration - Math.min(getBaseDuration(), MAX_SCROLL_DURATION))); + long rd = audioOffset - wasAudioOffset; + audioLeft = Utilities.clamp(audioLeft - (float) rd / audioDuration, 1, 0); + audioRight = Utilities.clamp(audioRight - (float) rd / audioDuration, 1, 0); + if (delegate != null) { + delegate.onAudioLeftChange(audioLeft); + delegate.onAudioRightChange(audioRight); + } } else if (audioSelected) { long mx = (long) ((videoRight * videoDuration) - (audioRight * audioDuration)); long mn = (long) ((videoLeft * videoDuration) - (audioLeft * audioDuration)); @@ -786,12 +800,6 @@ public class TimelineView extends View { } else { audioOffset = Utilities.clamp(audioOffset + (long) d, (long) (getBaseDuration() - audioDuration * audioRight), (long) (-audioLeft * audioDuration)); } - if (!hasVideo && (progress / (float) audioDuration < audioLeft || progress / (float) audioDuration > audioRight)) { - progress = (long) (audioLeft * audioDuration); - if (delegate != null) { - delegate.onProgressChange(progress, false); - } - } invalidate(); if (delegate != null) { delegate.onAudioOffsetChange(audioOffset + (long) (audioLeft * audioDuration)); @@ -799,16 +807,23 @@ public class TimelineView extends View { if (!dragged && delegate != null) { delegate.onProgressDragChange(true); + long progressToStart; if (hasVideo) { - long progressToStart = Utilities.clamp(audioOffset + (long) (audioLeft * audioDuration), (long) (videoRight * videoDuration), (long) (videoLeft * videoDuration)); - if (Math.abs(progress - progressToStart) > 400) { - loopProgressFrom = progress; - loopProgress.set(1, true); - } - delegate.onProgressChange(progress = progressToStart, false); + progressToStart = Utilities.clamp(audioOffset + (long) (audioLeft * audioDuration), (long) (videoRight * videoDuration), (long) (videoLeft * videoDuration)); + } else { + progressToStart = Utilities.clamp((long) (audioLeft * audioDuration), audioDuration, 0); + } + if (hasVideo && Math.abs(progress - progressToStart) > 400) { + loopProgressFrom = progress; + loopProgress.set(1, true); + } + delegate.onProgressChange(progress = progressToStart, false); + } else if (dragged || scrolling) { + if (hasVideo) { + progress = Utilities.clamp(audioOffset + (long) (audioLeft * audioDuration), (long) (videoRight * videoDuration), (long) (videoLeft * videoDuration)); + } else { + progress = Utilities.clamp((long) (audioLeft * audioDuration), audioDuration, 0); } - } else if ((dragged || scrolling) && hasVideo) { - progress = Utilities.clamp(audioOffset + (long) (audioLeft * audioDuration), (long) (videoRight * videoDuration), (long) (videoLeft * videoDuration)); if (delegate != null) { delegate.onProgressChange(progress, false); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton.java index 852798a9f..2f4c6bbf9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton.java @@ -6,6 +6,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; +import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; @@ -16,13 +17,15 @@ import android.graphics.Xfermode; import android.graphics.drawable.Drawable; import android.view.View; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.R; import org.telegram.messenger.Utilities; import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.CubicBezierInterpolator; -public class ToggleButton extends View { +public class ToggleButton extends View implements FlashViews.Invertable { private Drawable drawable; @@ -58,6 +61,7 @@ public class ToggleButton extends View { super.onDetachedFromWindow(); if (activeBitmap != null) { activeBitmap.recycle(); + activeBitmap = null; } } @@ -71,6 +75,11 @@ public class ToggleButton extends View { private final Path clipPath = new Path(); + public void setInvert(float invert) { + drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(0xFFFFFFFF, 0xFF000000, invert), PorterDuff.Mode.MULTIPLY)); + activePaint.setColor(ColorUtils.blendARGB(0xFFFFFFFF, 0xFF000000, invert)); + } + @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton2.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton2.java new file mode 100644 index 000000000..8046c11a5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/ToggleButton2.java @@ -0,0 +1,155 @@ +package org.telegram.ui.Stories.recorder; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; +import android.graphics.Region; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.Components.AnimatedFloat; +import org.telegram.ui.Components.CubicBezierInterpolator; + +import java.util.concurrent.atomic.AtomicBoolean; + +public class ToggleButton2 extends View implements FlashViews.Invertable { + + private final Path clipPath = new Path(); + private final Paint activePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private final Paint activeBitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); + + public ToggleButton2(Context context) { + super(context); + activePaint.setColor(0xFFFFFFFF); + activeBitmapPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); + } + + private boolean selected; + private AnimatedFloat animatedSelected = new AnimatedFloat(this, 0, 380, CubicBezierInterpolator.EASE_OUT_QUINT); + + private Drawable drawable; + private Bitmap activeBitmap; + + private int currentIcon; + private float scale = 1f; + private ValueAnimator animator; + + public void setIcon(int iconRes, boolean animated) { + if (currentIcon == iconRes) { + return; + } + + if (animator != null) { + animator.cancel(); + animator = null; + } + + if (animated) { + animator = ValueAnimator.ofFloat(0, 1).setDuration(150); + AtomicBoolean changed = new AtomicBoolean(); + animator.addUpdateListener(animation -> { + float val = (float) animation.getAnimatedValue(); + this.scale = 0.5f + Math.abs(val - 0.5f); + if (val >= 0.5f && !changed.get()) { + changed.set(true); + setDrawable(iconRes); + } + }); + animator.start(); + } else { + scale = 1f; + setDrawable(iconRes); + } + } + + public void setSelected(boolean selected) { + this.selected = selected; + invalidate(); + } + + @Override + public void setInvert(float invert) { + if (drawable != null) { + drawable.setColorFilter(new PorterDuffColorFilter(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert), PorterDuff.Mode.MULTIPLY)); + } + activePaint.setColor(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert)); + invalidate(); + } + + private void setDrawable(int iconRes) { + drawable = getContext().getResources().getDrawable(iconRes).mutate(); + if (activeBitmap != null) { + activeBitmap.recycle(); + activeBitmap = null; + } + if (activeBitmap == null && iconRes != 0) { + activeBitmap = BitmapFactory.decodeResource(getResources(), iconRes); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (drawable == null) { + return; + } + + float t = animatedSelected.set(selected); + + final int w = drawable.getIntrinsicWidth(), h = drawable.getIntrinsicHeight(); + + AndroidUtilities.rectTmp2.set((getWidth() - w) / 2, (getHeight() - h) / 2, (getWidth() + w) / 2, (getHeight() + h) / 2); + if (t <= 0) { + drawable.setBounds(AndroidUtilities.rectTmp2); + drawable.draw(canvas); + } else if (t < 1) { + canvas.save(); + clipPath.rewind(); + clipPath.addCircle(getWidth() / 2f, getHeight() / 2f, dp(16) * t, Path.Direction.CW); + canvas.clipPath(clipPath, Region.Op.DIFFERENCE); + drawable.setBounds(AndroidUtilities.rectTmp2); + drawable.draw(canvas); + canvas.restore(); + } + + if (t > 0) { + canvas.saveLayerAlpha(0, 0, getWidth(), getHeight(), 0xFF, Canvas.ALL_SAVE_FLAG); + canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, dp(16) * t, activePaint); + canvas.save(); + if (activeBitmap != null) { + canvas.drawBitmap(activeBitmap, null, AndroidUtilities.rectTmp2, activeBitmapPaint); + } + canvas.restore(); + canvas.restore(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (activeBitmap == null && currentIcon != 0) { + activeBitmap = BitmapFactory.decodeResource(getResources(), currentIcon); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (activeBitmap != null) { + activeBitmap.recycle(); + activeBitmap = null; + } + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VideoTimerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VideoTimerView.java index 29f8fbcaa..fe4446677 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VideoTimerView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Stories/recorder/VideoTimerView.java @@ -8,6 +8,7 @@ import android.view.Gravity; import android.view.View; import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; @@ -16,7 +17,7 @@ import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.CubicBezierInterpolator; -public class VideoTimerView extends View { +public class VideoTimerView extends View implements FlashViews.Invertable { private Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint recordPaint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -100,4 +101,9 @@ public class VideoTimerView extends View { textDrawable.draw(canvas); } + public void setInvert(float invert) { + backgroundPaint.setColor(ColorUtils.blendARGB(0x3f000000, 0x10000000, invert)); + textDrawable.setTextColor(ColorUtils.blendARGB(0xffffffff, 0xff000000, invert)); + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java b/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java index 25df99281..b30028cd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TextMessageEnterTransition.java @@ -12,7 +12,9 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; +import android.graphics.RectF; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Build; @@ -22,6 +24,7 @@ import android.text.SpannableString; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Log; import android.view.View; import android.view.animation.LinearInterpolator; @@ -44,6 +47,7 @@ import org.telegram.ui.Components.ChatActivityEnterView; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EmptyStubSpan; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ReplyMessageLine; import org.telegram.ui.Components.spoilers.SpoilerEffect; public class TextMessageEnterTransition implements MessageEnterTransitionContainer.Transition { @@ -60,6 +64,7 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain boolean initBitmaps = false; float replyFromStartX; + float replyFromStartWidth; float replyFromStartY; float replyFromObjectStartY; int replayFromColor; @@ -105,7 +110,6 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain float textY; float replyNameDx; - float replyMessageDx; int fromColor; int toColor; @@ -331,6 +335,7 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain if (hasReply) { SimpleTextView replyNameTextView = chatActivity.getReplyNameTextView(); replyFromStartX = replyNameTextView.getX() + ((View) replyNameTextView.getParent()).getX(); + replyFromStartWidth = ((View) replyNameTextView.getParent()).getWidth(); replyFromStartY = replyNameTextView.getY() + ((View) replyNameTextView.getParent().getParent()).getY() + ((View) replyNameTextView.getParent().getParent().getParent()).getY(); replyNameTextView = chatActivity.getReplyObjectTextView(); replyFromObjectStartY = replyNameTextView.getY() + ((View) replyNameTextView.getParent().getParent()).getY() + ((View) replyNameTextView.getParent().getParent().getParent()).getY(); @@ -357,11 +362,6 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain replyNameDx = messageView.replyNameLayout.getWidth() - messageView.replyNameLayout.getLineWidth(0); } } - if (messageView.replyTextLayout != null && messageView.replyTextLayout.getText().length() >= 1) { - if (messageView.replyTextLayout.getPrimaryHorizontal(0) != 0) { - replyMessageDx = messageView.replyTextLayout.getWidth() - messageView.replyTextLayout.getLineWidth(0); - } - } animator = ValueAnimator.ofFloat(0f, 1f); animator.addUpdateListener(valueAnimator -> { @@ -413,6 +413,8 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain float lastMessageX; float lastMessageY; + private final RectF replySelectorRect = new RectF(); + private final RectF messageReplySelectorRect = new RectF(); private Path replyRoundRect; private float[] roundRectRadii; @@ -424,7 +426,7 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain if (messageView.animatedEmojiStack != null) { messageView.animatedEmojiStack.clearPositions(); } - messageView.drawMessageText(bitmapCanvas, messageView.getMessageObject().textLayoutBlocks, messageView.getMessageObject().textXOffset, true, 1f, true); + messageView.drawMessageText(bitmapCanvas, messageView.getMessageObject().textLayoutBlocks, true, 1f, true); messageView.drawAnimatedEmojis(bitmapCanvas, 1f); } float listViewBottom = listView.getY() - container.getY() + listView.getMeasuredHeight(); @@ -532,24 +534,30 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain chatActivity.getReplyNameTextView().setAlpha(0f); chatActivity.getReplyObjectTextView().setAlpha(0f); - float replyHeight = AndroidUtilities.lerp(AndroidUtilities.dp(35), AndroidUtilities.dp(7) + Theme.chat_replyNamePaint.getTextSize() + Theme.chat_replyTextPaint.getTextSize(), progressX); - int offset = (int) Math.min(AndroidUtilities.dp(10), (replyHeight - AndroidUtilities.dp(35)) / 1.5f + AndroidUtilities.dp(10)); + float replyHeight = AndroidUtilities.lerp(AndroidUtilities.dp(35), messageView.replyHeight, progressX); + int offset = AndroidUtilities.dp(10); float fromReplayX = replyFromStartX - container.getX(); float fromReplayY = replyFromStartY - container.getY(); float toReplayX = messageViewX + messageView.replyStartX; float toReplayY = messageViewY + messageView.replyStartY; + if (messageView.replyLine == null) { + messageView.replyLine = new ReplyMessageLine(messageView); + } + messageView.replyLine.check(messageView.getMessageObject(), messageView.getCurrentUser(), messageView.getCurrentChat(), resourcesProvider, true); + int replyMessageColor; int replyOwnerMessageColor; int replyLineColor; - if (currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) { - replyMessageColor = getThemedColor(Theme.key_chat_outReplyMessageText); - } else { - replyMessageColor = getThemedColor(Theme.key_chat_outReplyMediaMessageText); - } - if (currentMessageObject.isOutOwner()) { + if (currentMessageObject.shouldDrawWithoutBackground()) { + replyOwnerMessageColor = getThemedColor(Theme.key_chat_stickerReplyNameText); + replyLineColor = getThemedColor(Theme.key_chat_stickerReplyLine); + } else if (messageView.replyLine != null) { + replyOwnerMessageColor = messageView.replyLine.nameColorAnimated.get(); + replyLineColor = messageView.replyLine.getColor(); + } else if (currentMessageObject.isOutOwner()) { replyOwnerMessageColor = getThemedColor(Theme.key_chat_outReplyNameText); replyLineColor = getThemedColor(Theme.key_chat_outReplyLine); } else { @@ -557,58 +565,133 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain replyLineColor = getThemedColor(Theme.key_chat_inReplyLine); } + if (!currentMessageObject.shouldDrawWithoutBackground()) { + if (currentMessageObject.isOutOwner()) { + if (currentMessageObject.isReplyToStory()) { + replyMessageColor = replyOwnerMessageColor; + } else { + float blendPressed = 0; + int color = getThemedColor(Theme.key_chat_outReplyMessageText); + if (!currentMessageObject.forceAvatar && !(currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) || messageView.isReplyQuote)) { + color = getThemedColor(Theme.key_chat_outReplyMediaMessageText); + blendPressed = .6f + (blendPressed * .4f); + } + replyMessageColor = ColorUtils.blendARGB(color, Theme.adaptHue(color, replyOwnerMessageColor), blendPressed); + } + } else { + if (currentMessageObject.isReplyToStory()) { + replyMessageColor = replyOwnerMessageColor; + } else { + float blendPressed = 0; + int color = getThemedColor(Theme.key_chat_inReplyMessageText); + if (!currentMessageObject.forceAvatar && !(currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaGame || MessageObject.getMedia(currentMessageObject.replyMessageObject.messageOwner) instanceof TLRPC.TL_messageMediaInvoice) || messageView.isReplyQuote)) { + color = getThemedColor(Theme.key_chat_inReplyMediaMessageText); + blendPressed = .6f + (blendPressed * .4f); + } + replyMessageColor = ColorUtils.blendARGB(color, Theme.adaptHue(color, replyOwnerMessageColor), blendPressed); + } + } + } else if (messageView.replyLine != null) { + replyMessageColor = messageView.replyLine.nameColorAnimated.get(); + } else if (currentMessageObject.hasValidReplyMessageObject() && (currentMessageObject.replyMessageObject.type == MessageObject.TYPE_TEXT || !TextUtils.isEmpty(currentMessageObject.replyMessageObject.caption)) && !(currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame || currentMessageObject.replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice)) { + replyMessageColor = getThemedColor(Theme.key_chat_outReplyMessageText); + } else { + replyMessageColor = getThemedColor(Theme.key_chat_outReplyMediaMessageText); + } + Theme.chat_replyTextPaint.setColor(ColorUtils.blendARGB(replayObjectFromColor, replyMessageColor, progress)); Theme.chat_replyNamePaint.setColor(ColorUtils.blendARGB(replayFromColor, replyOwnerMessageColor, progress)); if (messageView.needReplyImage) { fromReplayX -= AndroidUtilities.dp(44); } - float replyX = fromReplayX * (1f - progressX) + toReplayX * progressX; - float replyY = (fromReplayY + AndroidUtilities.dp(12) * progress) * (1f - progress) + toReplayY * progress; + float replyX = AndroidUtilities.lerp(fromReplayX, toReplayX, progressX); + float replyY = AndroidUtilities.lerp(fromReplayY + AndroidUtilities.dp(12) * progress, toReplayY, progress); - if (replyRoundRect == null) { - replyRoundRect = new Path(); - } else { - replyRoundRect.rewind(); - } if (roundRectRadii == null) { roundRectRadii = new float[8]; - roundRectRadii[0] = roundRectRadii[1] = roundRectRadii[6] = roundRectRadii[7] = AndroidUtilities.dp(2); // left - roundRectRadii[2] = roundRectRadii[3] = roundRectRadii[4] = roundRectRadii[5] = AndroidUtilities.dp(1); // right + roundRectRadii[0] = roundRectRadii[1] = roundRectRadii[6] = roundRectRadii[7] = AndroidUtilities.dp(4); // left + roundRectRadii[2] = roundRectRadii[3] = roundRectRadii[4] = roundRectRadii[5] = 0; // right + } + + AndroidUtilities.rectTmp.set( + fromReplayX, fromReplayY, + fromReplayX + replyFromStartWidth, + fromReplayY + AndroidUtilities.dp(35) + ); + AndroidUtilities.rectTmp.offset(0, + AndroidUtilities.dp(12) * progress); + messageReplySelectorRect.set(messageView.replySelectorRect); + messageReplySelectorRect.offset(messageViewX, messageViewY + (fromY - toY) * (1f - progress)); + AndroidUtilities.lerp( + AndroidUtilities.rectTmp, + messageReplySelectorRect, + progressX, + replySelectorRect + ); + + messageView.replyLine.drawBackground(canvas, replySelectorRect, alphaProgress, messageView.isReplyQuote, messageView.getMessageObject().shouldDrawWithoutBackground()); + messageView.replyLine.drawLine(canvas, replySelectorRect, alphaProgress); + + float replyImageSz = 0; + if (messageView.needReplyImage) { + canvas.save(); + final float sz = Math.min(replySelectorRect.height() - AndroidUtilities.dp(10), AndroidUtilities.dp(33)); + replyImageSz = AndroidUtilities.lerp(AndroidUtilities.dp(35), sz, progressX); + messageView.replyImageReceiver.setImageCoords( + AndroidUtilities.lerp(replyX, replySelectorRect.left + AndroidUtilities.dp(8), progressX), + AndroidUtilities.lerp(replyY, replySelectorRect.top + AndroidUtilities.dp(5), progressX), + replyImageSz, replyImageSz + ); + messageView.replyImageReceiver.draw(canvas); + canvas.restore(); } - AndroidUtilities.rectTmp.set(replyX, replyY, replyX + AndroidUtilities.dp(3), replyY + AndroidUtilities.lerp(AndroidUtilities.dp(35), messageView.replyHeight, progressX)); - replyRoundRect.addRoundRect(AndroidUtilities.rectTmp, roundRectRadii, Path.Direction.CW); - Theme.chat_replyLinePaint.setColor(ColorUtils.setAlphaComponent(replyLineColor, (int) (Color.alpha(replyLineColor) * progressX))); - canvas.drawPath(replyRoundRect, Theme.chat_replyLinePaint); canvas.save(); canvas.translate(offset * progressX, 0); - if (messageView.needReplyImage) { - canvas.save(); - messageView.replyImageReceiver.setImageCoords(replyX, replyY, replyHeight, replyHeight); - messageView.replyImageReceiver.draw(canvas); - canvas.translate(replyX, replyY); - canvas.restore(); - canvas.translate(offset - AndroidUtilities.dp(1) + replyHeight, 0); - } + final float offsetX = currentMessageObject != null && currentMessageObject.shouldDrawWithoutBackground() ? -AndroidUtilities.dp(6) : -AndroidUtilities.dp(1); + final float offsetY = currentMessageObject != null && currentMessageObject.shouldDrawWithoutBackground() ? AndroidUtilities.dp(1) : AndroidUtilities.dp(3); - float replyToMessageX = toReplayX - replyMessageDx; - float replyToNameX = toReplayX - replyNameDx; + float replyToMessageX = toReplayX - messageView.replyTextOffset + offsetX; + float replyToNameX = toReplayX - replyNameDx + offsetX; - float replyMessageX =(fromReplayX - replyMessageDx) * (1f - progressX) + replyToMessageX * progressX; - float replyNameX = fromReplayX * (1f - progressX) + replyToNameX * progressX; + float replyMessageX = AndroidUtilities.lerp(fromReplayX - messageView.replyTextOffset, replyToMessageX, progressX); + float replyNameX = AndroidUtilities.lerp(fromReplayX, replyToNameX, progressX) + (messageView.needReplyImage ? replyImageSz + AndroidUtilities.dp(3) : 0); if (messageView.replyNameLayout != null) { canvas.save(); - canvas.translate(replyNameX, replyY); + canvas.translate(replyNameX, replyY + offsetY * progressX); + int wasAlpha = Theme.chat_replyNamePaint.getAlpha(); + Theme.chat_replyNamePaint.setAlpha((int) (wasAlpha * progressX)); messageView.replyNameLayout.draw(canvas); + Theme.chat_replyNamePaint.setAlpha(wasAlpha); + final SimpleTextView uiText = chatActivity.getReplyNameTextView(); + canvas.saveLayerAlpha(0, 0, uiText.getWidth(), uiText.getHeight(), (int) (0xFF * (1f - progressX)), Canvas.ALL_SAVE_FLAG); + uiText.setAlpha(1f); + uiText.draw(canvas); + uiText.setAlpha(0f); canvas.restore(); + canvas.restore(); + } + + if (messageView.isReplyQuote && messageView.replyQuoteDrawable != null) { + if (messageView.replyLine.getColor() != messageView.replyQuoteDrawableColor) { + messageView.replyQuoteDrawable.setColorFilter(new PorterDuffColorFilter(messageView.replyQuoteDrawableColor = messageView.replyLine.getColor(), PorterDuff.Mode.SRC_IN)); + } + messageView.replyQuoteDrawable.setBounds( + (int) (replySelectorRect.right - offset * progressX - AndroidUtilities.dp(2 + (!messageView.drawPinnedTop ? 1 : 0)) - messageView.replyQuoteDrawable.getIntrinsicWidth()), + (int) (replySelectorRect.top + AndroidUtilities.dp(2 + (!messageView.drawPinnedTop ? 1 : 0))), + (int) (replySelectorRect.right - offset * progressX - AndroidUtilities.dp(2 + (!messageView.drawPinnedTop ? 1 : 0))), + (int) (replySelectorRect.top + AndroidUtilities.dp(2 + (!messageView.drawPinnedTop ? 1 : 0)) + messageView.replyQuoteDrawable.getIntrinsicHeight()) + ); + messageView.replyQuoteDrawable.setAlpha((int) (0xFF * progressX)); + messageView.replyQuoteDrawable.draw(canvas); } if (messageView.replyTextLayout != null) { canvas.save(); - canvas.translate(replyMessageX, replyY + AndroidUtilities.lerp(AndroidUtilities.dp(19), Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(5), progressX)); + final float offsetX2 = (messageView.needReplyImage && (!messageView.isReplyQuote || messageView.replyTextRTL) ? replyImageSz + AndroidUtilities.dp(3) : 0) + AndroidUtilities.dp(messageView.isReplyQuote && messageView.needReplyImage ? -2 : 0); + canvas.translate(replyMessageX + offsetX2, replyY + AndroidUtilities.lerp(AndroidUtilities.dp(19), Theme.chat_replyNamePaint.getTextSize() + AndroidUtilities.dp(4) + offsetY, progressX)); canvas.save(); SpoilerEffect.clipOutCanvas(canvas, messageView.replySpoilers); @@ -711,7 +794,7 @@ public class TextMessageEnterTransition implements MessageEnterTransitionContain } else { int oldColor = Theme.chat_msgTextPaint.getColor(); Theme.chat_msgTextPaint.setColor(toColor); - messageView.drawMessageText(canvas, messageView.getMessageObject().textLayoutBlocks, false, alphaProgress, true); + messageView.drawMessageText(canvas, messageView.getMessageObject().textLayoutBlocks, true, alphaProgress, true); messageView.drawAnimatedEmojis(canvas, alphaProgress); if (Theme.chat_msgTextPaint.getColor() != oldColor) { Theme.chat_msgTextPaint.setColor(oldColor); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index d54ddc0bc..1c5ab42f4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.Manifest; import android.animation.ObjectAnimator; import android.app.Activity; @@ -20,6 +22,8 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.location.Address; import android.location.Geocoder; @@ -50,6 +54,7 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; @@ -58,8 +63,10 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.messenger.time.SunDate; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -86,6 +93,7 @@ import org.telegram.ui.Cells.ThemePreviewMessagesCell; import org.telegram.ui.Cells.ThemeTypeCell; import org.telegram.ui.Cells.ThemesHorizontalListCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieDrawable; @@ -94,6 +102,7 @@ import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SimpleThemeDescription; import org.telegram.ui.Components.SwipeGestureSettingsView; +import org.telegram.ui.Components.Text; import org.telegram.ui.Components.ThemeEditorView; import java.io.File; @@ -146,6 +155,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int bluetoothScoRow; private int enableAnimationsRow; private int settings2Row; + private int changeUserColor; private int contactsReimportRow; private int contactsSortRow; @@ -271,7 +281,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No setWillNotDraw(false); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - textPaint.setTextSize(AndroidUtilities.dp(16)); + textPaint.setTextSize(dp(16)); sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); @@ -309,7 +319,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override protected void onDraw(Canvas canvas) { textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); - canvas.drawText("" + SharedConfig.fontSize, getMeasuredWidth() - AndroidUtilities.dp(39), AndroidUtilities.dp(28), textPaint); + canvas.drawText("" + SharedConfig.fontSize, getMeasuredWidth() - dp(39), dp(28), textPaint); } @Override @@ -355,7 +365,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No setWillNotDraw(false); textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - textPaint.setTextSize(AndroidUtilities.dp(16)); + textPaint.setTextSize(dp(16)); sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); @@ -387,7 +397,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override protected void onDraw(Canvas canvas) { textPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); - canvas.drawText("" + SharedConfig.bubbleRadius, getMeasuredWidth() - AndroidUtilities.dp(39), AndroidUtilities.dp(28), textPaint); + canvas.drawText("" + SharedConfig.bubbleRadius, getMeasuredWidth() - dp(39), dp(28), textPaint); } @Override @@ -539,6 +549,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No textSizeRow = -1; backgroundRow = -1; + changeUserColor = -1; settingsRow = -1; customTabsRow = -1; directShareRow = -1; @@ -613,6 +624,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No textSizeHeaderRow = rowCount++; textSizeRow = rowCount++; backgroundRow = rowCount++; + changeUserColor = rowCount++; newThemeInfoRow = rowCount++; themeHeaderRow = rowCount++; @@ -884,7 +896,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No if (currentType == THEME_TYPE_THEMES_BROWSER) { actionBar.setTitle(LocaleController.getString("BrowseThemes", R.string.BrowseThemes)); ActionBarMenu menu = actionBar.createMenu(); - sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); + sunDrawable = new RLottieDrawable(R.raw.sun, "" + R.raw.sun, dp(28), dp(28), true, null); if (lastIsDarkTheme) { sunDrawable.setCurrentFrame(sunDrawable.getFramesCount() - 1); } else { @@ -1039,6 +1051,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } } else if (position == backgroundRow) { presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL)); + } else if (position == changeUserColor) { + presentFragment(new PeerColorActivity(0).setOnApplied(this)); } else if (position == sendByEnterRow) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); boolean send = preferences.getBoolean("send_by_enter", false); @@ -1100,7 +1114,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No for (int i = 0; i < items.length; ++i) { final int index = i; RadioColorCell cell = new RadioColorCell(getParentActivity()); - cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setPadding(dp(4), 0, dp(4), 0); cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); cell.setTextAndValue(items[index], index == SharedConfig.distanceSystemType); cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); @@ -1133,7 +1147,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No linearLayout.setOrientation(LinearLayout.VERTICAL); RadioColorCell cell = new RadioColorCell(getParentActivity()); - cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setPadding(dp(4), 0, dp(4), 0); cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); cell.setTextAndValue(LocaleController.getString(R.string.MicrophoneForVoiceMessagesBuiltIn), !SharedConfig.recordViaSco); cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); @@ -1151,7 +1165,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No }); cell = new RadioColorCell(getParentActivity()); - cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); + cell.setPadding(dp(4), 0, dp(4), 0); cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); cell.setTextAndText2AndValue(LocaleController.getString(R.string.MicrophoneForVoiceMessagesScoIfConnected), LocaleController.getString(R.string.MicrophoneForVoiceMessagesScoHint), SharedConfig.recordViaSco); cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); @@ -1214,7 +1228,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No ((TextCheckCell) view).setChecked(SharedConfig.chatBlurEnabled()); } } else if (position == nightThemeRow) { - if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { + if (LocaleController.isRTL && x <= dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - dp(76)) { NotificationsCheckCell checkCell = (NotificationsCheckCell) view; if (Theme.selectedAutoNightType == Theme.AUTO_NIGHT_TYPE_NONE) { Theme.selectedAutoNightType = Theme.AUTO_NIGHT_TYPE_AUTOMATIC; @@ -1578,37 +1592,37 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY)); + super.onMeasure(MeasureSpec.makeMeasureSpec(dp(62), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(dp(62), MeasureSpec.EXACTLY)); } @Override protected void onDraw(Canvas canvas) { - float radius = AndroidUtilities.dp(20); + float radius = dp(20); float cx = 0.5f * getMeasuredWidth(); float cy = 0.5f * getMeasuredHeight(); paint.setColor(currentAccent.accentColor); paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(AndroidUtilities.dp(3)); + paint.setStrokeWidth(dp(3)); paint.setAlpha(Math.round(255f * checkedState)); canvas.drawCircle(cx, cy, radius - 0.5f * paint.getStrokeWidth(), paint); paint.setAlpha(255); paint.setStyle(Paint.Style.FILL); - canvas.drawCircle(cx, cy, radius - AndroidUtilities.dp(5) * checkedState, paint); + canvas.drawCircle(cx, cy, radius - dp(5) * checkedState, paint); if (checkedState != 0) { paint.setColor(0xffffffff); paint.setAlpha(Math.round(255f * checkedState)); - canvas.drawCircle(cx, cy, AndroidUtilities.dp(2), paint); - canvas.drawCircle(cx - AndroidUtilities.dp(7) * checkedState, cy, AndroidUtilities.dp(2), paint); - canvas.drawCircle(cx + AndroidUtilities.dp(7) * checkedState, cy, AndroidUtilities.dp(2), paint); + canvas.drawCircle(cx, cy, dp(2), paint); + canvas.drawCircle(cx - dp(7) * checkedState, cy, dp(2), paint); + canvas.drawCircle(cx + dp(7) * checkedState, cy, dp(2), paint); } if (currentAccent.myMessagesAccentColor != 0 && checkedState != 1) { paint.setColor(currentAccent.myMessagesAccentColor); - canvas.drawCircle(cx, cy, AndroidUtilities.dp(8) * (1.0f - checkedState), paint); + canvas.drawCircle(cx, cy, dp(8) * (1.0f - checkedState), paint); } } @@ -1642,8 +1656,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(62), MeasureSpec.EXACTLY) + MeasureSpec.makeMeasureSpec(dp(62), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(62), MeasureSpec.EXACTLY) ); } @@ -1652,8 +1666,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No float centerX = 0.5f * getMeasuredWidth(); float centerY = 0.5f * getMeasuredHeight(); - float radSmall = AndroidUtilities.dp(5); - float radRing = AndroidUtilities.dp(20) - radSmall; + float radSmall = dp(5); + float radRing = dp(20) - radSmall; paint.setStyle(Paint.Style.FILL); @@ -1768,6 +1782,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private final static int TYPE_DEFAULT_THEMES_PREVIEW = 17; private final static int TYPE_SAVE_TO_GALLERY = 19; private final static int TYPE_APP_ICON = 20; + private final static int TYPE_CHOOSE_COLOR = 21; private Context mContext; private boolean first = true; @@ -1786,7 +1801,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No int type = holder.getItemViewType(); return type == 0 || type == TYPE_TEXT_SETTING || type == TYPE_THEME_TYPE || type == TYPE_TEXT_CHECK || type == TYPE_NIGHT_THEME || type == TYPE_THEME_LIST || type == TYPE_THEME_ACCENT_LIST || - type == TYPE_TEXT_PREFERENCE || type == 18 || type == TYPE_APP_ICON; + type == TYPE_TEXT_PREFERENCE || type == 18 || type == TYPE_APP_ICON || type == TYPE_CHOOSE_COLOR; } private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { @@ -2008,7 +2023,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No themesHorizontalListCell.setDrawDivider(hasThemeAccents); themesHorizontalListCell.setFocusable(false); view = themesHorizontalListCell; - view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(148))); + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(148))); break; case TYPE_THEME_ACCENT_LIST: { RecyclerListView accentsListView = new TintRecyclerListView(mContext) { @@ -2024,7 +2039,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No accentsListView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); accentsListView.setItemAnimator(null); accentsListView.setLayoutAnimation(null); - accentsListView.setPadding(AndroidUtilities.dp(11), 0, AndroidUtilities.dp(11), 0); + accentsListView.setPadding(dp(11), 0, dp(11), 0); accentsListView.setClipToPadding(false); LinearLayoutManager accentsLayoutManager = new LinearLayoutManager(mContext); accentsLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); @@ -2053,7 +2068,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No int left = view1.getLeft(); int right = view1.getRight(); - int extra = AndroidUtilities.dp(52); + int extra = dp(52); if (left - extra < 0) { accentsListView.smoothScrollBy(left - extra, 0); } else if (right + extra > accentsListView.getMeasuredWidth()) { @@ -2134,7 +2149,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No }); view = accentsListView; - view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(62))); + view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, dp(62))); break; } case TYPE_BUBBLE_RADIUS: @@ -2150,7 +2165,15 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No view = new SwipeGestureSettingsView(mContext, currentAccount); break; case TYPE_THEME_PREVIEW: - ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(mContext, parentLayout, 0); + ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(mContext, parentLayout, 0) { + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (getParent() != null && getParent().getParent() != null) { + getParent().getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1)); + } + return super.onInterceptTouchEvent(e); + } + }; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } @@ -2168,6 +2191,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No case TYPE_APP_ICON: view = new AppIconsSelectorCell(mContext, ThemeActivity.this, currentAccount); break; + case TYPE_CHOOSE_COLOR: + view = new PeerColorActivity.ChangeNameColorCell(false, mContext, getResourceProvider()); + break; } return new RecyclerListView.Holder(view); } @@ -2367,7 +2393,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No pos = adapter.getItemCount() - 1; } if (pos != -1) { - ((LinearLayoutManager) accentsList.getLayoutManager()).scrollToPositionWithOffset(pos, listView.getMeasuredWidth() / 2 - AndroidUtilities.dp(42)); + ((LinearLayoutManager) accentsList.getLayoutManager()).scrollToPositionWithOffset(pos, listView.getMeasuredWidth() / 2 - dp(42)); } break; } @@ -2377,7 +2403,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No if (position == backgroundRow) { cell.setSubtitle(null); cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); - cell.setTextAndIcon(LocaleController.getString("ChangeChatBackground", R.string.ChangeChatBackground), R.drawable.msg_background, false); + cell.setTextAndIcon(LocaleController.getString(R.string.ChangeChatBackground), R.drawable.msg_background, changeUserColor >= 0); } else if (position == editThemeRow) { cell.setSubtitle(null); cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); @@ -2418,6 +2444,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No break; } + case TYPE_CHOOSE_COLOR: { + PeerColorActivity.ChangeNameColorCell cell = (PeerColorActivity.ChangeNameColorCell) holder.itemView; + cell.set(getUserConfig().getCurrentUser()); + } } } @@ -2485,6 +2515,8 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No return TYPE_SAVE_TO_GALLERY; } else if (position == appIconSelectorRow) { return TYPE_APP_ICON; + } else if (position == changeUserColor) { + return TYPE_CHOOSE_COLOR; } return TYPE_TEXT_SETTING; } @@ -2500,7 +2532,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, TextSizeCell.class, BubbleRadiusCell.class, ChatListCell.class, NotificationsCheckCell.class, ThemesHorizontalListCell.class, TintRecyclerListView.class, TextCell.class, SwipeGestureSettingsView.class, DefaultThemesPreviewCell.class, AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{TextSettingsCell.class, TextCheckCell.class, HeaderCell.class, BrightnessControlCell.class, ThemeTypeCell.class, TextSizeCell.class, BubbleRadiusCell.class, ChatListCell.class, NotificationsCheckCell.class, ThemesHorizontalListCell.class, TintRecyclerListView.class, TextCell.class, PeerColorActivity.ChangeNameColorCell.class, SwipeGestureSettingsView.class, DefaultThemesPreviewCell.class, AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); themeDescriptions.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundGray)); themeDescriptions.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); @@ -2594,24 +2626,32 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No View ch = listView.getChildAt(i); if (ch instanceof AppIconsSelectorCell) { ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } else if (ch instanceof PeerColorActivity.ChangeNameColorCell) { + ((PeerColorActivity.ChangeNameColorCell) ch).updateColors(); } } for (int i = 0; i < listView.getCachedChildCount(); i++) { View ch = listView.getCachedChildAt(i); if (ch instanceof AppIconsSelectorCell) { ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } else if (ch instanceof PeerColorActivity.ChangeNameColorCell) { + ((PeerColorActivity.ChangeNameColorCell) ch).updateColors(); } } for (int i = 0; i < listView.getHiddenChildCount(); i++) { View ch = listView.getHiddenChildAt(i); if (ch instanceof AppIconsSelectorCell) { ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } else if (ch instanceof PeerColorActivity.ChangeNameColorCell) { + ((PeerColorActivity.ChangeNameColorCell) ch).updateColors(); } } for (int i = 0; i < listView.getAttachedScrapChildCount(); i++) { View ch = listView.getAttachedScrapChildAt(i); if (ch instanceof AppIconsSelectorCell) { ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } else if (ch instanceof PeerColorActivity.ChangeNameColorCell) { + ((PeerColorActivity.ChangeNameColorCell) ch).updateColors(); } } }, Theme.key_windowBackgroundWhiteHintText, Theme.key_windowBackgroundWhiteBlackText, Theme.key_windowBackgroundWhiteValueText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index cae833713..d6b8fbafa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -2471,7 +2471,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro }); } - if (screenType == SCREEN_TYPE_ACCENT_COLOR && !Theme.hasCustomWallpaper() && accent.backgroundOverrideColor != 0x100000000L) { + if (screenType == SCREEN_TYPE_ACCENT_COLOR && !Theme.hasCustomWallpaper() && accent != null && accent.backgroundOverrideColor != 0x100000000L) { selectColorType(2); } @@ -2524,7 +2524,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro backgroundRotation -= 360; } setBackgroundColor(backgroundColor, 0, true, true); - } else { + } else if (accent != null) { accent.backgroundRotation += 45; while (accent.backgroundRotation >= 360) { accent.backgroundRotation -= 360; @@ -2538,10 +2538,10 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro } private void selectColorType(int id, boolean ask) { - if (getParentActivity() == null || colorType == id || patternViewAnimation != null) { + if (getParentActivity() == null || colorType == id || patternViewAnimation != null || accent != null) { return; } - if (ask && id == 2 && (Theme.hasCustomWallpaper() || accent.backgroundOverrideColor == 0x100000000L)) { + if (ask && id == 2 && (Theme.hasCustomWallpaper() || accent.backgroundOverrideColor == 0x100000000L)) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("ChangeChatBackground", R.string.ChangeChatBackground)); if (!Theme.hasCustomWallpaper() || Theme.isCustomWallpaperColor()) { @@ -4604,6 +4604,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro message.from_id = new TLRPC.TL_peerUser(); message.id = 1; message.reply_to = new TLRPC.TL_messageReplyHeader(); + message.reply_to.flags |= 16; message.reply_to.reply_to_msg_id = 5; message.media = new TLRPC.TL_messageMediaEmpty(); message.out = false; @@ -4764,6 +4765,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro message.from_id = new TLRPC.TL_peerUser(); message.id = 1; message.reply_to = new TLRPC.TL_messageReplyHeader(); + message.reply_to.flags |= 16; message.reply_to.reply_to_msg_id = 5; message.media = new TLRPC.TL_messageMediaEmpty(); message.out = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java index 6c1bf20df..0150e223c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TopicCreateFragment.java @@ -443,7 +443,7 @@ public class TopicCreateFragment extends BaseFragment { selectAnimatedEmojiDialog.setClipChildren(false); emojiContainer.addView(selectAnimatedEmojiDialog, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 12, 12, 12, 12)); - Drawable drawable = ForumUtilities.createTopicDrawable("", iconColor); + Drawable drawable = ForumUtilities.createTopicDrawable("", iconColor, false); CombinedDrawable topicCombinedDrawable = (CombinedDrawable) drawable; forumBubbleDrawable = (ForumBubbleDrawable) topicCombinedDrawable.getBackgroundDrawable(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java index 376b9cb2e..9acb80739 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TopicsFragment.java @@ -235,6 +235,8 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N public boolean searching; private boolean opnendForSelect; private boolean openedForForward; + private boolean openedForQuote; + private boolean openedForReply; HashSet excludeTopics; private boolean mute = false; @@ -282,6 +284,8 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N chatId = arguments.getLong("chat_id", 0); opnendForSelect = arguments.getBoolean("for_select", false); openedForForward = arguments.getBoolean("forward_to", false); + openedForQuote = arguments.getBoolean("quote", false); + openedForReply = arguments.getBoolean("reply_to", false); topicsController = getMessagesController().getTopicsController(); canShowProgress = !getUserConfig().getPreferences().getBoolean("topics_end_reached_" + chatId, false); } @@ -726,7 +730,7 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N } }; SpannableString generalIcon = new SpannableString("#"); - Drawable generalIconDrawable = ForumUtilities.createGeneralTopicDrawable(getContext(), .85f, Color.WHITE); + Drawable generalIconDrawable = ForumUtilities.createGeneralTopicDrawable(getContext(), .85f, Color.WHITE, false); generalIconDrawable.setBounds(0, AndroidUtilities.dp(2), AndroidUtilities.dp(16), AndroidUtilities.dp(18)); generalIcon.setSpan(new ImageSpan(generalIconDrawable, DynamicDrawableSpan.ALIGN_CENTER), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); pullForegroundDrawable = new PullForegroundDrawable( @@ -2369,7 +2373,11 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N } updateSubtitle(); } else { - if (openedForForward) { + if (openedForReply) { + avatarContainer.setTitle(LocaleController.getString(R.string.ReplyToDialog)); + } else if (openedForQuote) { + avatarContainer.setTitle(LocaleController.getString("QuoteTo", R.string.QuoteTo)); + } else if (openedForForward) { avatarContainer.setTitle(LocaleController.getString("ForwardTo", R.string.ForwardTo)); } else { avatarContainer.setTitle(LocaleController.getString("SelectTopic", R.string.SelectTopic)); @@ -2970,7 +2978,7 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N } if (topic != null && topic.id == 1) { setAnimatedEmojiDrawable(null); - setForumIcon(ForumUtilities.createGeneralTopicDrawable(getContext(), 1f, getThemedColor(Theme.key_chat_inMenu))); + setForumIcon(ForumUtilities.createGeneralTopicDrawable(getContext(), 1f, getThemedColor(Theme.key_chat_inMenu), false)); } else if (topic != null && topic.icon_emoji_id != 0) { setForumIcon(null); if (animatedEmojiDrawable == null || animatedEmojiDrawable.getDocumentId() != topic.icon_emoji_id) { @@ -2978,7 +2986,7 @@ public class TopicsFragment extends BaseFragment implements NotificationCenter.N } } else { setAnimatedEmojiDrawable(null); - setForumIcon(ForumUtilities.createTopicDrawable(topic)); + setForumIcon(ForumUtilities.createTopicDrawable(topic, false)); } updateHidden(topic != null && topic.hidden, true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java index 4c569c5d3..ce21bfd2c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoIPFragment.java @@ -29,6 +29,7 @@ import android.transition.TransitionManager; import android.transition.TransitionSet; import android.transition.TransitionValues; import android.transition.Visibility; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -2033,7 +2034,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent speakerPhoneIcon.animate().alpha(0).start(); } setVideoAction(bottomButtons[1], service, animated); - setMicrohoneAction(bottomButtons[2], service, animated); + setMicrophoneAction(bottomButtons[2], service, animated); } else { bottomButtons[0].setVisibility(View.GONE); bottomButtons[1].setVisibility(View.GONE); @@ -2056,7 +2057,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent speakerPhoneIcon.animate().alpha(0f).start(); } setVideoAction(bottomButtons[1], service, animated); - setMicrohoneAction(bottomButtons[2], service, animated); + setMicrophoneAction(bottomButtons[2], service, animated); bottomButtons[3].setData(R.drawable.calls_decline, Color.WHITE, 0xFFF01D2C, LocaleController.getString("VoipEndCall", R.string.VoipEndCall), false, animated); bottomButtons[3].setOnClickListener(view -> { @@ -2076,7 +2077,7 @@ public class VoIPFragment implements VoIPService.StateListener, NotificationCent updateSpeakerPhoneIcon(); } - private void setMicrohoneAction(VoIPToggleButton bottomButton, VoIPService service, boolean animated) { + private void setMicrophoneAction(VoIPToggleButton bottomButton, VoIPService service, boolean animated) { if (service.isMicMute()) { bottomButton.setData(R.drawable.calls_unmute, Color.BLACK, Color.WHITE, LocaleController.getString("VoipUnmute", R.string.VoipUnmute), true, animated); } else { diff --git a/TMessagesProj/src/main/java/org/webrtc/OrientationHelper.java b/TMessagesProj/src/main/java/org/webrtc/OrientationHelper.java index 976dda797..e65d584db 100644 --- a/TMessagesProj/src/main/java/org/webrtc/OrientationHelper.java +++ b/TMessagesProj/src/main/java/org/webrtc/OrientationHelper.java @@ -10,6 +10,7 @@ public class OrientationHelper { private OrientationEventListener orientationEventListener; private int rotation; + public static volatile boolean cameraRotationDisabled; public static volatile int cameraRotation; public static volatile int cameraOrientation; @@ -64,6 +65,9 @@ public class OrientationHelper { } public int getOrientation() { + if (cameraRotationDisabled) { + return 0; + } return rotation; } } diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_boost_counter.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_boost_counter.png new file mode 100644 index 000000000..24aa0a88f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_boost_counter.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_forward.png new file mode 100644 index 000000000..1ba4cf37a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_gift_premium.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_gift_premium.png new file mode 100644 index 000000000..a280b1a78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_gift_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_link.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_link.png new file mode 100644 index 000000000..278c510a3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply.png new file mode 100644 index 000000000..1cc143522 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_quote.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_quote.png new file mode 100644 index 000000000..96391d595 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_settings.png new file mode 100644 index 000000000..a5cdda021 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_reply_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_share.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_share.png new file mode 100644 index 000000000..67c8649dc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_unclaimed.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_unclaimed.png new file mode 100644 index 000000000..aed8a880f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_unclaimed.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/filled_unknown.png b/TMessagesProj/src/main/res/drawable-hdpi/filled_unknown.png new file mode 100644 index 000000000..43408185f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/filled_unknown.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_delete_quote.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_delete_quote.png new file mode 100644 index 000000000..9cbc5948a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_delete_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quote.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote.png new file mode 100644 index 000000000..81709dac5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_delete.png new file mode 100644 index 000000000..becddb26e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_select.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_select.png new file mode 100644 index 000000000..d4a358ad5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_specific.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_specific.png new file mode 100644 index 000000000..ab482f232 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_quote_specific.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_select_quote.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_select_quote.png new file mode 100644 index 000000000..b66246d6e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_select_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_badge.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_badge.png new file mode 100644 index 000000000..8b66194ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_button.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_button.png new file mode 100644 index 000000000..a7b1e5d4b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_button.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_remove.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_remove.png new file mode 100644 index 000000000..0ccee741c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_boost_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_gift.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_gift.png new file mode 100644 index 000000000..c7b422d2d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_gift.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_giveaway.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_giveaway.png new file mode 100644 index 000000000..67314a38f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_giveaway.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_quote.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_quote.png new file mode 100644 index 000000000..2fc9ff155 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/mini_reply_user.png b/TMessagesProj/src/main/res/drawable-hdpi/mini_reply_user.png new file mode 100644 index 000000000..3e6c43aac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/mini_reply_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_boost_counter.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_boost_counter.png new file mode 100644 index 000000000..e5b648e9b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_boost_counter.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_forward.png new file mode 100644 index 000000000..26568658b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_gift_premium.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_gift_premium.png new file mode 100644 index 000000000..61b34b6b2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_gift_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_link.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_link.png new file mode 100644 index 000000000..2a620770c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply.png new file mode 100644 index 000000000..2819b5b51 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_quote.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_quote.png new file mode 100644 index 000000000..112328be7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_settings.png new file mode 100644 index 000000000..63afc7ded Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_reply_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_share.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_share.png new file mode 100644 index 000000000..d5bdcb92a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_unclaimed.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_unclaimed.png new file mode 100644 index 000000000..bbf06f2cf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_unclaimed.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/filled_unknown.png b/TMessagesProj/src/main/res/drawable-mdpi/filled_unknown.png new file mode 100644 index 000000000..1bd0f15d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/filled_unknown.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_delete_quote.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_delete_quote.png new file mode 100644 index 000000000..e43d7e33c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_delete_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quote.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote.png new file mode 100644 index 000000000..4e1f8fe8f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_delete.png new file mode 100644 index 000000000..de19b6090 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_select.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_select.png new file mode 100644 index 000000000..3b8bbe803 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_specific.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_specific.png new file mode 100644 index 000000000..e7474a5a3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_quote_specific.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_select_quote.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_select_quote.png new file mode 100644 index 000000000..8ecbb19f5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_select_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_badge.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_badge.png new file mode 100644 index 000000000..b11159828 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_button.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_button.png new file mode 100644 index 000000000..ac0461a64 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_button.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_remove.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_remove.png new file mode 100644 index 000000000..c04306002 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_boost_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_gift.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_gift.png new file mode 100644 index 000000000..8fe56b467 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_gift.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_giveaway.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_giveaway.png new file mode 100644 index 000000000..9a37d58c8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_giveaway.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_quote.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_quote.png new file mode 100644 index 000000000..d67840d3c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/mini_reply_user.png b/TMessagesProj/src/main/res/drawable-mdpi/mini_reply_user.png new file mode 100644 index 000000000..33d004f94 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/mini_reply_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_boost_counter.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_boost_counter.png new file mode 100644 index 000000000..fbfacf24f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_boost_counter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_forward.png new file mode 100644 index 000000000..4d1f57ea4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_gift_premium.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_gift_premium.png new file mode 100644 index 000000000..8613cb0fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_gift_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_link.png new file mode 100644 index 000000000..dce945995 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply.png new file mode 100644 index 000000000..b5daf3d0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_quote.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_quote.png new file mode 100644 index 000000000..dcb4aea4b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_settings.png new file mode 100644 index 000000000..838a0acd9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_reply_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_share.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_share.png new file mode 100644 index 000000000..13221af07 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_unclaimed.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_unclaimed.png new file mode 100644 index 000000000..e83fa5573 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_unclaimed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/filled_unknown.png b/TMessagesProj/src/main/res/drawable-xhdpi/filled_unknown.png new file mode 100644 index 000000000..780b44634 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/filled_unknown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_delete_quote.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_delete_quote.png new file mode 100644 index 000000000..3feea67fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_delete_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote.png new file mode 100644 index 000000000..1bab268b1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_delete.png new file mode 100644 index 000000000..4b58a477f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_select.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_select.png new file mode 100644 index 000000000..8b2efd4c5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_specific.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_specific.png new file mode 100644 index 000000000..1ed26f4e3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_quote_specific.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_select_quote.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_select_quote.png new file mode 100644 index 000000000..cb8767be4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_select_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_badge.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_badge.png new file mode 100644 index 000000000..072c7609c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_button.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_button.png new file mode 100644 index 000000000..b2ae96ea2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_button.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_remove.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_remove.png new file mode 100644 index 000000000..5a87e9dfb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_boost_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_gift.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_gift.png new file mode 100644 index 000000000..0935d6f04 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_gift.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_giveaway.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_giveaway.png new file mode 100644 index 000000000..98c4c579f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_giveaway.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_quote.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_quote.png new file mode 100644 index 000000000..8d689530c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/mini_reply_user.png b/TMessagesProj/src/main/res/drawable-xhdpi/mini_reply_user.png new file mode 100644 index 000000000..c3b1ae334 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/mini_reply_user.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_boost_counter.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_boost_counter.png new file mode 100644 index 000000000..6f06fcfa6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_boost_counter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_forward.png new file mode 100644 index 000000000..b24050fee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_gift_premium.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_gift_premium.png new file mode 100644 index 000000000..f3cf4d97a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_gift_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_link.png new file mode 100644 index 000000000..edb56d8d9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply.png new file mode 100644 index 000000000..33dd04be9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_quote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_quote.png new file mode 100644 index 000000000..74cca5e5d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_settings.png new file mode 100644 index 000000000..ae79901ea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_reply_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_share.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_share.png new file mode 100644 index 000000000..c1de1fe9f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unclaimed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unclaimed.png new file mode 100644 index 000000000..168505080 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unclaimed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unknown.png b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unknown.png new file mode 100644 index 000000000..af1edcda4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/filled_unknown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_delete_quote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_delete_quote.png new file mode 100644 index 000000000..757a55312 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_delete_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote.png new file mode 100644 index 000000000..5c4aa1469 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_delete.png new file mode 100644 index 000000000..f7e9f67bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_select.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_select.png new file mode 100644 index 000000000..a1047dc75 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_specific.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_specific.png new file mode 100644 index 000000000..0fd2dc3f6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_quote_specific.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_select_quote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_select_quote.png new file mode 100644 index 000000000..5d115361d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_select_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_badge.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_badge.png new file mode 100644 index 000000000..69164fbe0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_button.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_button.png new file mode 100644 index 000000000..837742de4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_button.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_remove.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_remove.png new file mode 100644 index 000000000..fad01ed0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_boost_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_gift.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_gift.png new file mode 100644 index 000000000..fd71fa6d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_gift.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_giveaway.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_giveaway.png new file mode 100644 index 000000000..80fa00634 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_giveaway.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_quote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_quote.png new file mode 100644 index 000000000..7c9267787 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_quote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/mini_reply_user.png b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_reply_user.png new file mode 100644 index 000000000..b27691228 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/mini_reply_user.png differ diff --git a/TMessagesProj/src/main/res/raw/caption_hide.json b/TMessagesProj/src/main/res/raw/caption_hide.json new file mode 100644 index 000000000..cb76d2e6c --- /dev/null +++ b/TMessagesProj/src/main/res/raw/caption_hide.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"caption_hide","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.384,1.288,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-59.384,-56.65],[59.386,56.65]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 3","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.717,1.415,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[109.842,109.842,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-59.384,-56.65],[59.386,56.65]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape","parent":4,"tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,13],[60,18],[55,23],[-53,23],[-58,18],[-53,13]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,45],[60,50],[55,55],[-53,55],[-58,50],[-53,45]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,-19],[60,-14],[55,-9],[11,-9],[6,-14],[11,-19]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,-51],[60,-46],[55,-41],[11,-41],[6,-46],[11,-51]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,-8.8],[0,0],[8.8,0],[0,0],[0,8.8],[0,0],[-8.8,0]],"o":[[8.8,0],[0,0],[0,8.8],[0,0],[-8.8,0],[0,0],[0,-8.8],[0,0]],"v":[[-23.94,-55],[-8,-39.06],[-8,-18.94],[-23.94,-3],[-44.06,-3],[-60,-18.94],[-60,-39.06],[-44.06,-55]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[3.28,0],[0,0],[0,-3.28],[0,0],[-3.28,0],[0,0],[0,3.28],[0,0]],"o":[[0,0],[-3.28,0],[0,0],[0,3.28],[0,0],[3.28,0],[0,0],[0,-3.28]],"v":[[-23.94,-45],[-44.06,-45],[-50,-39.06],[-50,-18.94],[-44.06,-13],[-23.94,-13],[-18,-18.94],[-18,-39.06]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":8,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/caption_show.json b/TMessagesProj/src/main/res/raw/caption_show.json new file mode 100644 index 000000000..22193f89b --- /dev/null +++ b/TMessagesProj/src/main/res/raw/caption_show.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"caption_show","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.384,1.288,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-59.384,-56.65],[59.386,56.65]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 3","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-3.717,1.415,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[109.842,109.842,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-59.384,-56.65],[59.386,56.65]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":26,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape","parent":4,"tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-1,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,13],[60,18],[55,23],[-53,23],[-58,18],[-53,13]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,45],[60,50],[55,55],[-53,55],[-58,50],[-53,45]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,-19],[60,-14],[55,-9],[11,-9],[6,-14],[11,-19]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[0,0],[0,-2.76],[2.76,0],[0,0],[0,2.76],[-2.76,0]],"o":[[2.76,0],[0,2.76],[0,0],[-2.76,0],[0,-2.76],[0,0]],"v":[[55,-51],[60,-46],[55,-41],[11,-41],[6,-46],[11,-51]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ind":4,"ty":"sh","ix":5,"ks":{"a":0,"k":{"i":[[0,0],[0,-8.8],[0,0],[8.8,0],[0,0],[0,8.8],[0,0],[-8.8,0]],"o":[[8.8,0],[0,0],[0,8.8],[0,0],[-8.8,0],[0,0],[0,-8.8],[0,0]],"v":[[-23.94,-55],[-8,-39.06],[-8,-18.94],[-23.94,-3],[-44.06,-3],[-60,-18.94],[-60,-39.06],[-44.06,-55]],"c":true},"ix":2},"nm":"Path 5","mn":"ADBE Vector Shape - Group","hd":false},{"ind":5,"ty":"sh","ix":6,"ks":{"a":0,"k":{"i":[[3.28,0],[0,0],[0,-3.28],[0,0],[-3.28,0],[0,0],[0,3.28],[0,0]],"o":[[0,0],[-3.28,0],[0,0],[0,3.28],[0,0],[3.28,0],[0,0],[0,-3.28]],"v":[[-23.94,-45],[-44.06,-45],[-50,-39.06],[-50,-18.94],[-44.06,-13],[-23.94,-13],[-18,-18.94],[-18,-39.06]],"c":true},"ix":2},"nm":"Path 6","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":8,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/media_enlarge.json b/TMessagesProj/src/main/res/raw/media_enlarge.json new file mode 100644 index 000000000..7ab051e06 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/media_enlarge.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"media_large","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Arrow 2","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-23.088,23.088,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":7,"s":[-20.31,20.31,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[-23.088,23.088,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.111,111.111,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-0.04,-0.435],[0,0]],"o":[[0,0],[0.444,0.003],[0,0],[0,0]],"v":[[29.504,-50.033],[48.995,-50.173],[49.929,-49.651],[49.807,-29.168]],"c":false}]},{"t":10,"s":[{"i":[[0,0],[0,0],[-0.451,-0.027],[0,0]],"o":[[0,0],[0.007,0.348],[0,0],[0,0]],"v":[[28.767,-51.234],[28.934,-29.558],[29.298,-29.089],[50.831,-28.855]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0.112,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line 2","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.873,-20.123,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-12.002,11.998],[15.734,-15.349]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[2]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":10,"s":[31]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[78]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":10,"s":[88]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Line 1","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-19.377,19.377,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[11.373,-11.377],[-12.252,12.248]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":10,"s":[6]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":10,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Arrow 1","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.865},"o":{"x":0.333,"y":0},"t":0,"s":[-19.588,19.588,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.444},"t":7,"s":[-24.956,24.956,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[-23.088,23.088,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.111,111.111,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-0.55,0],[0,0]],"o":[[0,0],[0,0.55],[0,0],[0,0]],"v":[[-11.271,-8.971],[-11.221,10.099],[-10.231,11.099],[9.307,11.268]],"c":false}]},{"t":10,"s":[{"i":[[0,0],[0,0],[0.01,-0.535],[0,0]],"o":[[0,0],[0.375,0.09],[0,0],[0,0]],"v":[[-8.606,-12.84],[12.217,-12.838],[12.769,-11.901],[12.837,8.178]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Path","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-16.02],[0,0],[16.02,0],[0,0],[0,16.02],[0,0],[-16.02,0]],"o":[[16.02,0],[0,0],[0,16.02],[0,0],[-16.02,0],[0,0],[0,-16.02],[0,0]],"v":[[32,-61],[61,-32],[61,32],[32,61],[-32,61],[-61,32],[-61,-32],[-32,-61]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[10.49,0],[0,0],[0,-10.49],[0,0],[-10.49,0],[0,0],[0,10.49],[0,0]],"o":[[0,0],[-10.49,0],[0,0],[0,10.49],[0,0],[10.49,0],[0,0],[0,-10.49]],"v":[[32,-51],[-32,-51],[-51,-32],[-51,32],[-32,51],[32,51],[51,32],[51,-32]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/media_shrink.json b/TMessagesProj/src/main/res/raw/media_shrink.json new file mode 100644 index 000000000..b41780c57 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/media_shrink.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"media_small","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Arrow 2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-23.088,23.088,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":4,"s":[-28.969,28.969,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[-23.088,23.088,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.111,111.111,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":2,"s":[{"i":[[0,0],[0,0],[-0.451,-0.027],[0,0]],"o":[[0,0],[0.007,0.348],[0,0],[0,0]],"v":[[28.767,-51.234],[28.934,-29.558],[29.298,-29.089],[50.831,-28.855]],"c":false}]},{"t":10,"s":[{"i":[[0,0],[0,0],[-0.04,-0.435],[0,0]],"o":[[0,0],[0.444,0.003],[0,0],[0,0]],"v":[[29.504,-50.033],[48.995,-50.173],[49.929,-49.651],[49.807,-29.168]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0.112,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Line 2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[19.873,-20.123,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-12.002,11.998],[15.734,-15.349]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.569],"y":[1.135]},"o":{"x":[0.203],"y":[0]},"t":0,"s":[31]},{"i":{"x":[0.703],"y":[1]},"o":{"x":[0.317],"y":[0.117]},"t":2,"s":[16.593]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":11,"s":[2]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.569],"y":[0.514]},"o":{"x":[0.203],"y":[0]},"t":0,"s":[88]},{"i":{"x":[0.703],"y":[1]},"o":{"x":[0.317],"y":[0.479]},"t":2,"s":[69.115]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":11,"s":[78]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Line 1","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-19.377,19.377,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[11.373,-11.377],[-12.252,12.248]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.569],"y":[2.139]},"o":{"x":[0.203],"y":[0]},"t":0,"s":[6]},{"i":{"x":[0.658],"y":[-7.905]},"o":{"x":[0.312],"y":[4.949]},"t":2,"s":[0]},{"i":{"x":[0.698],"y":[1]},"o":{"x":[0.351],"y":[0.223]},"t":4,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":11,"s":[1]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.569],"y":[0.628]},"o":{"x":[0.203],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.703],"y":[1]},"o":{"x":[0.317],"y":[0.604]},"t":2,"s":[69]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[41]},{"t":11,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Arrow 1","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":0.921},"o":{"x":0.333,"y":0},"t":0,"s":[-19.588,19.588,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0.134},"t":4,"s":[-13.921,13.921,0],"to":[0,0,0],"ti":[0,0,0]},{"t":15,"s":[-23.088,23.088,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[111.111,111.111,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":2,"s":[{"i":[[0,0],[0,0],[0.01,-0.535],[0,0]],"o":[[0,0],[0.375,0.09],[0,0],[0,0]],"v":[[-8.606,-12.84],[12.217,-12.838],[12.769,-11.901],[12.837,8.178]],"c":false}]},{"t":10,"s":[{"i":[[0,0],[0,0],[-0.55,0],[0,0]],"o":[[0,0],[0,0.55],[0,0],[0,0]],"v":[[-11.271,-8.971],[-11.221,10.099],[-10.231,11.099],[9.307,11.268]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Path","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,-16.02],[0,0],[16.02,0],[0,0],[0,16.02],[0,0],[-16.02,0]],"o":[[16.02,0],[0,0],[0,16.02],[0,0],[-16.02,0],[0,0],[0,-16.02],[0,0]],"v":[[32,-61],[61,-32],[61,32],[32,61],[-32,61],[-61,32],[-61,-32],[-32,-61]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[10.49,0],[0,0],[0,-10.49],[0,0],[-10.49,0],[0,0],[0,10.49],[0,0]],"o":[[0,0],[-10.49,0],[0,0],[0,10.49],[0,0],[10.49,0],[0,0],[0,-10.49]],"v":[[32,-51],[-32,-51],[-51,-32],[-51,32],[-32,51],[32,51],[51,32],[51,-32]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/name_hide.json b/TMessagesProj/src/main/res/raw/name_hide.json new file mode 100644 index 000000000..6a9282a19 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/name_hide.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"name_hide","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.034,2.81,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-57.895,-51.798],[57.895,51.802]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 2","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.034,2.81,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-57.895,-51.798],[57.895,51.802]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":32,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":10,"s":[0]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape","parent":4,"tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-2.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-15.46,0],[0,-15.46],[15.46,0],[0,15.46]],"o":[[15.46,0],[0,15.46],[-15.46,0],[0,-15.46]],"v":[[0,-57.5],[28,-29.5],[0,-1.5],[-28,-29.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[9.94,0],[0,-9.94],[-9.94,0],[0,9.94]],"o":[[-9.94,0],[0,9.94],[9.94,0],[0,-9.94]],"v":[[0,-47.5],[-18,-29.5],[0,-11.5],[18,-29.5]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-0.33,-19.87],[0,0],[6.81,0],[0,0],[0.15,6.38],[0,0],[-20.07,0]],"o":[[19.86,0],[0,0],[0,6.55],[0,0],[-7.11,0],[0,0],[0,-20.07],[0,0]],"v":[[14.63,9.5],[51,45.31],[51,45.87],[39.3,57.5],[-39.33,57.5],[-51,46.1],[-51,45.84],[-14.66,9.5]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[14.4,0],[0,0],[0,-14.49],[0,0],[-1.31,0],[0,0],[0,1.07],[0,0]],"o":[[0,0],[-14.55,0],[0,0],[0.03,1.2],[0,0],[1.2,0],[0,0],[-0.24,-14.38]],"v":[[14.63,19.5],[-14.66,19.5],[-41,45.78],[-41,45.92],[-39.33,47.5],[39.3,47.5],[41,45.91],[41,45.43]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/name_show.json b/TMessagesProj/src/main/res/raw/name_show.json new file mode 100644 index 000000000..7bb609916 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/name_show.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"name_show","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path","parent":4,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.034,2.81,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-57.895,-51.798],[57.895,51.802]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path 2","parent":4,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.034,2.81,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-57.895,-51.798],[57.895,51.802]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":32,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape","parent":4,"tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-2.5,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-15.46,0],[0,-15.46],[15.46,0],[0,15.46]],"o":[[15.46,0],[0,15.46],[-15.46,0],[0,-15.46]],"v":[[0,-57.5],[28,-29.5],[0,-1.5],[-28,-29.5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[9.94,0],[0,-9.94],[-9.94,0],[0,9.94]],"o":[[-9.94,0],[0,9.94],[9.94,0],[0,-9.94]],"v":[[0,-47.5],[-18,-29.5],[0,-11.5],[18,-29.5]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[0,0],[-0.33,-19.87],[0,0],[6.81,0],[0,0],[0.15,6.38],[0,0],[-20.07,0]],"o":[[19.86,0],[0,0],[0,6.55],[0,0],[-7.11,0],[0,0],[0,-20.07],[0,0]],"v":[[14.63,9.5],[51,45.31],[51,45.87],[39.3,57.5],[-39.33,57.5],[-51,46.1],[-51,45.84],[-14.66,9.5]],"c":true},"ix":2},"nm":"Path 3","mn":"ADBE Vector Shape - Group","hd":false},{"ind":3,"ty":"sh","ix":4,"ks":{"a":0,"k":{"i":[[14.4,0],[0,0],[0,-14.49],[0,0],[-1.31,0],[0,0],[0,1.07],[0,0]],"o":[[0,0],[-14.55,0],[0,0],[0.03,1.2],[0,0],[1.2,0],[0,0],[-0.24,-14.38]],"v":[[14.63,19.5],[-14.66,19.5],[-41,45.78],[-41,45.92],[-39.33,47.5],[39.3,47.5],[41,45.91],[41,45.43]],"c":true},"ix":2},"nm":"Path 4","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape","np":6,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/position_above.json b/TMessagesProj/src/main/res/raw/position_above.json new file mode 100644 index 000000000..c3a6df6d8 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/position_above.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"position_above","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path Copy 2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,-15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,-43,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[47]},{"t":12,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path Copy 3","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,13,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,-15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[66]},{"t":12,"s":[65]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path Copy 4","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,41,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,13,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[43]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Path Copy","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.357,-0.027,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[101.051,101.051,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,49.03],[0,-49.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[42]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":2,"s":[57.667]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[48]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[40]},{"t":12,"s":[58]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":2,"s":[91]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":4,"s":[48]},{"i":{"x":[0.667],"y":[0.5]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[40]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0.607]},"t":9,"s":[23]},{"t":12,"s":[2]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Path","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34,-43.693,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-0.84,-0.83],[0,0]],"o":[[0,0],[0.84,-0.83],[0,0],[0,0]],"v":[[-24,11.431],[-1.52,-10.809],[1.52,-10.809],[24,11.431]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[-0.889,-0.008],[0,0]],"o":[[0,0],[0.877,0.055],[0,0],[0,0]],"v":[[-9.312,44.015],[-1.53,44.128],[1.51,44.128],[8.71,44.057]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[0,0],[-0.938,0.814],[0,0]],"o":[[0,0],[0.915,0.939],[0,0],[0,0]],"v":[[-24,75.806],[-1.54,99.066],[1.5,99.066],[24,76.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":-0.022,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/position_below.json b/TMessagesProj/src/main/res/raw/position_below.json new file mode 100644 index 000000000..3f26da654 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/position_below.json @@ -0,0 +1 @@ +{"v":"5.9.6","fr":60,"ip":0,"op":20,"w":144,"h":144,"nm":"position_below","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Path Copy 2","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,-43,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,-15,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 2","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[100]},{"t":12,"s":[47]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Path Copy 3","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,-15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,13,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 3","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[65]},{"t":12,"s":[66]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Path Copy 4","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[-2,13,0],"to":[0,0,0],"ti":[0,0,0]},{"t":12,"s":[-2,41,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-46,0],[46,0]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[43]},{"t":12,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Path Copy","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34.357,-0.027,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[101.051,101.051,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,49.03],[0,-49.5]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path Copy","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.615],"y":[0.802]},"o":{"x":[0.17],"y":[0]},"t":0,"s":[58]},{"i":{"x":[0.69],"y":[1]},"o":{"x":[0.351],"y":[-0.232]},"t":4,"s":[35.635]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[40]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[48]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[48]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[57.667]},{"t":12,"s":[42]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.593],"y":[0.665]},"o":{"x":[0.175],"y":[0]},"t":0,"s":[2]},{"i":{"x":[0.698],"y":[1.797]},"o":{"x":[0.351],"y":[0.605]},"t":2,"s":[22.177]},{"i":{"x":[0.667],"y":[0.582]},"o":{"x":[0.333],"y":[-0.412]},"t":3,"s":[27]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[1.605]},"t":4,"s":[37.312]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":5,"s":[40]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":6,"s":[48]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":7,"s":[48]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[83]},{"t":12,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Path","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[34,-43.693,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[-0.938,0.814],[0,0]],"o":[[0,0],[0.915,0.939],[0,0],[0,0]],"v":[[-24,75.806],[-1.54,99.066],[1.5,99.066],[24,76.056]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[-0.889,-0.008],[0,0]],"o":[[0,0],[0.877,0.055],[0,0],[0,0]],"v":[[-9.312,44.015],[-1.53,44.128],[1.51,44.128],[8.71,44.057]],"c":false}]},{"t":12,"s":[{"i":[[0,0],[0,0],[-0.84,-0.83],[0,0]],"o":[[0,0],[0.84,-0.83],[0,0],[0,0]],"v":[[-24,11.431],[-1.52,-10.809],[1.52,-10.809],[24,11.431]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":-0.022,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Path","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"ct":1,"bm":0},{"ddd":0,"ind":6,"ty":3,"nm":"Rectangle 222","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[72,72,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":10,"s":[90,90,100]},{"t":20,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":20,"st":0,"ct":1,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/star_premium_2.json b/TMessagesProj/src/main/res/raw/star_premium_2.json new file mode 100644 index 000000000..333652f41 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/star_premium_2.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":50,"w":512,"h":512,"nm":"Star Premium 2","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":0,"k":[256,256,0]},"s":{"a":0,"k":[90,90,100]}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Lines","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[0.05,0.05,0]},"a":{"a":0,"k":[0.05,0.05,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[286.963,71.213],[31.05,2.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[259.849,288.269],[41.05,17.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0.702,294.1],[0.8,43.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-264.799,287.248],[-24.95,30.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-282.446,73.448],[-26.95,5.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-298.969,-160.205],[0.05,0.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[125.429,-292],[14.05,-46.95]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-113.946,-280.214],[-10.95,-43.95]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 10","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[297.969,-194.45],[0.05,0.05]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"t":29,"s":[10]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 9","bm":0,"hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":15,"s":[100]},{"t":30,"s":[0]}]},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":14,"s":[100]},{"t":29,"s":[0]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":17,"op":31,"st":-28,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Circle","parent":1,"sr":1,"ks":{"a":{"a":0,"k":[27,-21,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":0.937},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[-23.196,0],[0,-23.196],[23.196,0],[0,23.196]],"o":[[23.196,0],[0,23.196],[-23.196,0],[0,-23.196]],"v":[[0,-42],[42,0],[0,42],[-42,0]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.064,"y":0.006},"t":16,"s":[{"i":[[-149.117,0],[0,-149.117],[149.117,0],[0,149.117]],"o":[[149.117,0],[0,149.117],[-149.117,0],[0,-149.117]],"v":[[0,-270],[270,0],[0,270],[-270,0]],"c":true}]},{"t":22,"s":[{"i":[[-155.867,0],[0,-155.867],[155.867,0],[0,155.867]],"o":[[155.867,0],[0,155.867],[-155.867,0],[0,-155.867]],"v":[[0,-282.222],[282.222,0],[0,282.222],[-282.222,0]],"c":true}]}]},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":6,"s":[{"i":[[-0.276,0],[0,0.276],[0.276,0],[0,-0.276]],"o":[[0.276,0],[0,-0.276],[-0.276,0],[0,0.276]],"v":[[0,0.5],[0.5,0],[0,-0.5],[-0.5,0]],"c":true}]},{"t":22,"s":[{"i":[[154.64,0],[0,-154.64],[-154.64,0],[0,154.64]],"o":[[-154.64,0],[0,154.64],[154.64,0],[0,-154.64]],"v":[[0,-280],[-280,0],[0,280],[280,0]],"c":true}]}]},"nm":"Path 2","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[27,-21]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Ellipse 1","bm":0,"hd":false}],"ip":1,"op":20,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Star","parent":1,"sr":1,"ks":{"p":{"a":0,"k":[1.049,-1.084,0]},"a":{"a":0,"k":[1.049,-1.084,0]},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.1,0.1,0.1],"y":[0,0,0]},"t":19,"s":[20,20,100]},{"i":{"x":[0.7,0.7,0.7],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":33,"s":[116,116,100]},{"i":{"x":[0.5,0.5,0.5],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":41,"s":[89,89,100]},{"t":49,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[6.768,-4.255],[0,0],[6.115,9.726],[-1.358,5.485],[0,0],[-18.409,9.56],[0,0],[2.45,4.717],[4.09,-0.647],[0,0],[17.857,15.358],[0,0],[-7.491,8.71],[-5.463,0.439],[0,0],[-2.949,7.305],[0,0],[-10.653,-4.3],[-2.114,-5.237],[0,0],[-7.853,-0.631],[0,0],[0.92,-11.451],[4.078,-3.568],[0,0],[-1.757,-7.49],[0,0],[11.185,-2.623],[4.709,2.96],[0,0]],"o":[[0,0],[-9.726,6.115],[-3.008,-4.784],[0,0],[4.985,-20.136],[0,0],[4.717,-2.45],[-1.909,-3.675],[0,0],[-23.264,3.679],[0,0],[-8.71,-7.491],[3.574,-4.155],[0,0],[7.853,-0.631],[0,0],[4.3,-10.653],[5.237,2.114],[0,0],[2.949,7.305],[0,0],[11.451,0.92],[-0.434,5.402],[0,0],[-5.79,5.066],[0,0],[2.623,11.185],[-5.415,1.27],[0,0],[-6.768,-4.255]],"v":[[-10.317,141.124],[-103.919,199.974],[-132.6,193.436],[-135.182,177.366],[-120.015,116.098],[-83.215,69.384],[4.209,23.985],[8.315,11.009],[-1.73,5.938],[-99.135,21.343],[-163.96,2.932],[-201.443,-29.307],[-203.65,-58.641],[-189.545,-65.811],[-78.588,-74.723],[-60.965,-87.672],[-18.534,-192.792],[8.541,-204.295],[20.044,-192.792],[62.474,-87.672],[80.098,-74.723],[191.642,-65.764],[210.711,-43.364],[203.674,-29.375],[117.813,45.75],[111.259,66.154],[137.513,178.093],[122.012,203.095],[106.19,200.453],[11.827,141.124]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Star","bm":0,"hd":false}],"ip":19,"op":119,"st":-1,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/stories_intro_go_back.json b/TMessagesProj/src/main/res/raw/stories_intro_go_back.json new file mode 100644 index 000000000..276b86f07 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/stories_intro_go_back.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":40,"w":512,"h":512,"nm":"Go Back","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL DROPS","sr":1,"ks":{"o":{"a":0,"k":0},"r":{"a":0,"k":-35},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[166.208,167.406,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[174.568,153.346,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[158.529,152.64,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":0.4},"o":{"x":0.2,"y":0.2},"t":31,"s":[166.208,167.406,0],"to":[0,0,0],"ti":[0,0,0]},{"t":39,"s":[166.208,167.406,0]}]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[57,57,100]},{"i":{"x":[0.6,0.6,0.6],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[110,110,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.4,0.4,0.4],"y":[0,0,0]},"t":31,"s":[95,95,100]},{"t":39,"s":[100,100,100]}]}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Group 1","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-72.346,32.835,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.064},"t":11,"s":[8.11,11.801,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[3.092,-27.691,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-66.577,42.835,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[-72.346,32.835,0]}]},"a":{"a":0,"k":[-94.346,-93.165,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.62,-4.212],[4.212,1.62],[-1.62,4.212],[-4.212,-1.62]],"o":[[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212],[4.212,1.62]],"v":[[-86.719,-90.232],[-97.279,-85.538],[-101.973,-96.098],[-91.413,-100.792]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Group 2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-73.36,-6.38,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.052},"t":11,"s":[4.552,8.64,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[-0.553,-29.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-72.975,0.928,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[-73.36,-6.38,0]}]},"a":{"a":0,"k":[-95.36,-132.38,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.509,-2.838],[2.838,3.509],[-3.509,2.838],[-2.838,-3.509]],"o":[[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838],[2.838,3.509]],"v":[[-90.221,-126.026],[-101.713,-127.241],[-100.499,-138.733],[-89.006,-137.518]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Group 3","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-54.63,-40.848,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.04},"t":11,"s":[7.163,3.439,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[1.51,-33.83,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-60.784,-33.925,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[-54.63,-40.848,0]}]},"a":{"a":0,"k":[-76.63,-166.848,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.458,-0.703],[0.703,4.458],[-4.458,0.703],[-0.703,-4.458]],"o":[[-4.458,0.703],[-0.703,-4.458],[4.458,-0.703],[0.703,4.458]],"v":[[-75.357,-158.776],[-84.702,-165.574],[-77.904,-174.92],[-68.558,-168.121]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Group 4","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-21.176,-61.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.024},"t":11,"s":[10.502,-1.352,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[3.824,-38.088,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-29.637,-60.179,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[-21.176,-61.333,0]}]},"a":{"a":0,"k":[-43.176,-187.333,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.212,1.62],[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212]],"o":[[-4.212,-1.62],[1.62,-4.212],[4.212,1.62],[-1.62,4.212]],"v":[[-46.109,-179.706],[-50.803,-190.266],[-40.243,-194.96],[-35.549,-184.4]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Group 5","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[18.039,-62.347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.021},"t":11,"s":[14.935,2.3,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[7.074,-34.277,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[16.116,-62.347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[18.039,-62.347,0]}]},"a":{"a":0,"k":[-3.961,-188.347,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.838,3.509],[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838]],"o":[[-2.838,-3.509],[3.509,-2.838],[2.838,3.509],[-3.509,2.838]],"v":[[-10.314,-183.208],[-9.099,-194.7],[2.393,-193.486],[1.178,-181.993]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Group 6","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[52.507,-43.617,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.032},"t":11,"s":[15.894,3.639,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[6.893,-33.529,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[56.738,-39.771,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[52.507,-43.617,0]}]},"a":{"a":0,"k":[30.507,-169.617,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.703,4.458],[-4.458,0.703],[-0.703,-4.458],[4.458,-0.703]],"o":[[-0.703,-4.458],[4.458,-0.703],[0.703,4.458],[-4.458,0.703]],"v":[[22.436,-168.344],[29.234,-177.689],[38.579,-170.891],[31.781,-161.545]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Group 7","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[72.993,-10.163,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.047},"t":11,"s":[14.747,9.522,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[5.01,-28.584,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[73.762,-4.394,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[72.993,-10.163,0]}]},"a":{"a":0,"k":[50.993,-136.163,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212],[4.212,1.62]],"o":[[1.62,-4.212],[4.212,1.62],[-1.62,4.212],[-4.212,-1.62]],"v":[[43.366,-139.096],[53.926,-143.79],[58.62,-133.23],[48.06,-128.536]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Group 8","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":15,"s":[0]},{"t":20,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[74.007,29.052,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.06},"t":11,"s":[13.216,8.017,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":16,"s":[3.392,-31.474,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[70.16,32.514,0],"to":[0,0,0],"ti":[0,0,0]},{"t":31,"s":[74.007,29.052,0]}]},"a":{"a":0,"k":[52.007,-96.948,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":16,"s":[600,600,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[70,70,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838],[2.838,3.509]],"o":[[3.509,-2.838],[2.838,3.509],[-3.509,2.838],[-2.838,-3.509]],"v":[[46.868,-103.301],[58.36,-102.087],[57.145,-90.594],[45.653,-91.809]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger 2","parent":11,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":9,"s":[3]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":20,"s":[-4]},{"t":37,"s":[0]}]},"p":{"a":0,"k":[-18.5,36.537,0]},"a":{"a":0,"k":[-18.5,36.537,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.6,"y":0},"t":9,"s":[{"i":[[0,0],[-0.346,24.046],[0,0],[-9.202,-25.328],[-1.098,-24.859],[0,0]],"o":[[0,0],[0.213,-14.846],[-6.846,-27.519],[0,0],[1.095,24.8],[0,0]],"v":[[-42.122,74.94],[-37.299,-31.67],[-51.383,-87.595],[-10.511,-97.777],[7.58,-39.153],[5.855,17.136]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":20,"s":[{"i":[[-4.088,9.534],[-5.177,79.73],[0,0],[8.6,-27.85],[0.979,-24.038],[0,0]],"o":[[8.122,-18.94],[1.832,-28.211],[6.45,-23.131],[0,0],[-1.179,28.956],[0,0]],"v":[[-46.827,64.355],[-41.157,-74.325],[-33.111,-116.823],[6.301,-103.185],[3.533,-64.461],[6.915,7.869]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Hand 2","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[-35]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":10,"s":[-20]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":20,"s":[-45]},{"t":37,"s":[-35]}]},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[338.249,325.933,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.6,"y":0},"t":9,"s":[354.111,348.828,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":20,"s":[337.969,263.868,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[338.249,325.933,0]}]},"a":{"a":0,"k":[28,102.537,0]},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.5,0.5,0.5],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":10,"s":[107,107,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.5],"y":[0,0,0]},"t":20,"s":[92,92,100]},{"t":34,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.3,"y":0},"t":9,"s":[{"i":[[0,0],[0,0],[-1.78,-29.177],[5.86,-32.177],[67.329,0.109],[12.187,19.221],[-14.163,41.622],[-14.7,-21.86],[-1.782,-7.759]],"o":[[0,0],[0.662,-27.555],[1.369,3.499],[-4.356,25.922],[-53.507,-0.096],[-20.587,-31.797],[6.699,-22.594],[3.45,16.135],[0,0]],"v":[[91.276,43.443],[91.953,13.857],[133.756,17.313],[131.634,119.667],[36.922,202.939],[-63.676,143.664],[-90.659,26.805],[-42.147,25.138],[-42.485,72.616]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":20,"s":[{"i":[[0,0],[0,0],[-11.786,-32.04],[13.326,-50.937],[69.886,-1.133],[16.408,44.906],[-27.224,20.199],[-2.287,-0.383],[7.921,-14.798]],"o":[[0,0],[2.535,-16.526],[6.464,17.572],[-6.659,25.455],[-53.502,0.867],[-11.91,-32.595],[5.638,-4.183],[1.812,23.929],[0,0]],"v":[[103.086,29.669],[96.137,2.758],[139.168,25.141],[132.333,121.479],[36.922,202.939],[-81.134,95.727],[-68.861,14.458],[-44.312,9.071],[-44.421,63.798]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[0,0],[0,0],[-1.78,-29.177],[5.86,-32.177],[67.329,0.109],[12.187,19.221],[14.229,49.701],[-21.585,-15.101],[-4.318,-9.495]],"o":[[0,0],[0.662,-27.555],[1.369,3.499],[-4.356,25.922],[-53.507,-0.096],[-20.587,-31.797],[-8.087,-22.277],[21.081,18.933],[0,0]],"v":[[91.276,43.443],[91.953,13.857],[133.756,17.313],[131.634,119.667],[36.922,202.939],[-60.86,145.533],[-110.627,32.289],[-69.263,13.802],[-42.485,72.616]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.3,"y":0},"t":9,"s":[{"i":[[0,0],[0,0],[-0.861,-30.119],[0,0]],"o":[[0,0],[-0.376,-28.79],[0,0],[0,0]],"v":[[45.179,33.141],[45.482,2.731],[91.928,3.006],[91.371,42.024]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":20,"s":[{"i":[[0,0],[0,0],[-4.407,-29.87],[0,0]],"o":[[0,0],[-2.286,-24.055],[0,0],[0,0]],"v":[[52.657,18.68],[48.169,0.276],[95.112,0.495],[102.22,25.89]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[0,0],[0,0],[-0.861,-30.119],[0,0]],"o":[[0,0],[-0.376,-28.79],[0,0],[0,0]],"v":[[45.179,33.141],[45.482,2.731],[91.928,3.006],[91.371,42.024]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.3,"y":0},"t":9,"s":[{"i":[[0,0],[0,0],[-1.403,-28.322],[0,0]],"o":[[0,0],[-1.163,-21.954],[0,0],[0,0]],"v":[[6.569,22.091],[11.851,-16.256],[45.253,-9.411],[45.103,33.19]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":20,"s":[{"i":[[0,0],[0,0],[-7.106,-26.835],[0,0]],"o":[[0,0],[-1.195,-22.395],[0,0],[0,0]],"v":[[4.701,4.504],[2.792,-11.488],[46.861,-4.507],[52.327,18.897]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[0,0],[0,0],[-1.403,-28.322],[0,0]],"o":[[0,0],[-1.163,-21.954],[0,0],[0,0]],"v":[[6.569,22.091],[5.237,-15.834],[45.253,-9.411],[45.103,33.19]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"Line","sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":1,"s":[62.458,256,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.6,"y":0},"t":10,"s":[41.458,255,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":20,"s":[77.458,256,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[62.458,256,0]}]},"a":{"a":0,"k":[-188.542,0,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":3,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-188.542,-196.721],[-188.542,-16.768],[-188.542,196.721]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.6,"y":0},"t":12,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-188.542,-182.99],[-188.542,-15.597],[-188.542,182.99]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":22,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-188.542,-218],[-188.542,-18.581],[-188.542,218]],"c":false}]},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-188.542,-196.721],[-188.542,-16.768],[-188.542,196.721]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/stories_intro_go_forward.json b/TMessagesProj/src/main/res/raw/stories_intro_go_forward.json new file mode 100644 index 000000000..03ab793bd --- /dev/null +++ b/TMessagesProj/src/main/res/raw/stories_intro_go_forward.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":38,"w":512,"h":512,"nm":"Go Forward","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"NULL DROPS","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.2,"y":0},"t":0,"s":[234,130,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[239,120,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[236.179,113.5,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[234,130,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[234,130,0]}]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[57,57,100]},{"i":{"x":[0.8,0.8,0.8],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[130,130,100]},{"i":{"x":[0.6,0.6,0.6],"y":[1,1,1]},"o":{"x":[0.2,0.2,0.2],"y":[0,0,0]},"t":31,"s":[95,95,100]},{"t":37,"s":[100,100,100]}]}},"ao":0,"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Group 1","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-72.346,32.835,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.051},"t":11,"s":[8.11,11.801,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[3.092,-27.691,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-66.577,42.835,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[-72.346,32.835,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[-72.346,32.835,0]}]},"a":{"a":0,"k":[-94.346,-93.165,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[1.62,-4.212],[4.212,1.62],[-1.62,4.212],[-4.212,-1.62]],"o":[[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212],[4.212,1.62]],"v":[[-86.719,-90.232],[-97.279,-85.538],[-101.973,-96.098],[-91.413,-100.792]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Group 2","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-73.36,-6.38,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.042},"t":11,"s":[4.552,8.64,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[-0.553,-29.625,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-72.975,0.928,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[-73.36,-6.38,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[-73.36,-6.38,0]}]},"a":{"a":0,"k":[-95.36,-132.38,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[3.509,-2.838],[2.838,3.509],[-3.509,2.838],[-2.838,-3.509]],"o":[[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838],[2.838,3.509]],"v":[[-90.221,-126.026],[-101.713,-127.241],[-100.499,-138.733],[-89.006,-137.518]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Group 3","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-54.63,-40.848,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.032},"t":11,"s":[7.163,3.439,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[1.51,-33.83,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-60.784,-33.925,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[-54.63,-40.848,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[-54.63,-40.848,0]}]},"a":{"a":0,"k":[-76.63,-166.848,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.458,-0.703],[0.703,4.458],[-4.458,0.703],[-0.703,-4.458]],"o":[[-4.458,0.703],[-0.703,-4.458],[4.458,-0.703],[0.703,4.458]],"v":[[-75.357,-158.776],[-84.702,-165.574],[-77.904,-174.92],[-68.558,-168.121]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Group 4","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[-21.176,-61.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.019},"t":11,"s":[10.502,-1.352,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[3.824,-38.088,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[-29.637,-60.179,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[-21.176,-61.333,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[-21.176,-61.333,0]}]},"a":{"a":0,"k":[-43.176,-187.333,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[4.212,1.62],[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212]],"o":[[-4.212,-1.62],[1.62,-4.212],[4.212,1.62],[-1.62,4.212]],"v":[[-46.109,-179.706],[-50.803,-190.266],[-40.243,-194.96],[-35.549,-184.4]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Group 5","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[18.039,-62.347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.017},"t":11,"s":[14.935,2.3,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[7.074,-34.277,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[16.116,-62.347,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":1},"o":{"x":0.2,"y":0},"t":31,"s":[18.039,-62.347,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[18.039,-62.347,0]}]},"a":{"a":0,"k":[-3.961,-188.347,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.838,3.509],[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838]],"o":[[-2.838,-3.509],[3.509,-2.838],[2.838,3.509],[-3.509,2.838]],"v":[[-10.314,-183.208],[-9.099,-194.7],[2.393,-193.486],[1.178,-181.993]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 5","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Group 6","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[52.507,-43.617,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.026},"t":11,"s":[15.894,3.639,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[6.893,-33.529,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[56.738,-39.771,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[52.507,-43.617,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[52.507,-43.617,0]}]},"a":{"a":0,"k":[30.507,-169.617,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.703,4.458],[-4.458,0.703],[-0.703,-4.458],[4.458,-0.703]],"o":[[-0.703,-4.458],[4.458,-0.703],[0.703,4.458],[-4.458,0.703]],"v":[[22.436,-168.344],[29.234,-177.689],[38.579,-170.891],[31.781,-161.545]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 6","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Group 7","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[72.993,-10.163,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.038},"t":11,"s":[14.747,9.522,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[5.01,-28.584,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[73.762,-4.394,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[72.993,-10.163,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[72.993,-10.163,0]}]},"a":{"a":0,"k":[50.993,-136.163,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-1.62,4.212],[-4.212,-1.62],[1.62,-4.212],[4.212,1.62]],"o":[[1.62,-4.212],[4.212,1.62],[-1.62,4.212],[-4.212,-1.62]],"v":[[43.366,-139.096],[53.926,-143.79],[58.62,-133.23],[48.06,-128.536]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 7","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Group 8","parent":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.9],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":11,"s":[0]},{"i":{"x":[0],"y":[1]},"o":{"x":[0.1],"y":[0]},"t":14,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.1,"y":1},"o":{"x":0.25,"y":0},"t":0,"s":[74.007,29.052,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.619,"y":1},"o":{"x":0.288,"y":0.048},"t":11,"s":[13.216,8.017,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.1,"y":1},"o":{"x":0.05,"y":0},"t":15,"s":[3.392,-31.474,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.52,"y":0},"t":23,"s":[70.16,32.514,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":0.6},"o":{"x":0.2,"y":0.2},"t":31,"s":[74.007,29.052,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[74.007,29.052,0]}]},"a":{"a":0,"k":[52.007,-96.948,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":11,"s":[100,100,100]},{"i":{"x":[0.1,0.1,0.1],"y":[1,1,1]},"o":{"x":[0.05,0.05,0.05],"y":[0,0,0]},"t":15,"s":[500,500,100]},{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.52,0.52,0.52],"y":[0,0,0]},"t":23,"s":[60,60,100]},{"t":31,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-3.509,2.838],[-2.838,-3.509],[3.509,-2.838],[2.838,3.509]],"o":[[3.509,-2.838],[2.838,3.509],[-3.509,2.838],[-2.838,-3.509]],"v":[[46.868,-103.301],[58.36,-102.087],[57.145,-90.594],[45.653,-91.809]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 8","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger 2","parent":11,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":7,"s":[3]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":17,"s":[-4]},{"t":36,"s":[0]}]},"p":{"a":0,"k":[-18.5,36.537,0]},"a":{"a":0,"k":[-18.5,36.537,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.7,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.3,"y":0},"t":7,"s":[{"i":[[0,0],[-0.346,24.046],[0,0],[-9.202,-25.328],[-1.098,-24.859],[0,0]],"o":[[0,0],[0.213,-14.846],[-6.846,-27.519],[0,0],[1.095,24.8],[0,0]],"v":[[-42.122,74.94],[-37.299,-31.67],[-51.383,-87.595],[-10.511,-97.777],[7.58,-39.153],[5.855,17.136]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":17,"s":[{"i":[[-4.088,9.534],[-5.177,79.73],[0,0],[5.691,-28.586],[0.979,-24.038],[0,0]],"o":[[8.122,-18.94],[1.832,-28.211],[4.038,-23.672],[0,0],[-1.179,28.956],[0,0]],"v":[[-46.827,64.355],[-39.556,-74.99],[-33.972,-115.073],[5.007,-106.161],[3.533,-64.461],[7.786,15.745]],"c":false}]},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Hand 2","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":7,"s":[8]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":17,"s":[-6]},{"t":36,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[284,358.537,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.5,"y":1},"o":{"x":0.6,"y":0},"t":7,"s":[285.5,387.537,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.5,"y":0},"t":17,"s":[307,302.537,0],"to":[0,0,0],"ti":[0,0,0]},{"t":36,"s":[284,358.537,0]}]},"a":{"a":0,"k":[28,102.537,0]},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.5,0.5,0.5],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":8,"s":[106,106,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.5,0.5,0.5],"y":[0,0,0]},"t":15,"s":[89,89,100]},{"t":33,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,0],[0,0],[-1.78,-29.177],[5.86,-32.177],[67.329,0.109],[12.187,19.221],[29.323,34.648],[-25.031,-8.211],[-4.318,-9.495]],"o":[[0,0],[0.662,-27.555],[1.369,3.499],[-4.356,25.922],[-53.507,-0.096],[-20.587,-31.797],[-14.186,-18.985],[25.656,12.025],[0,0]],"v":[[91.276,43.443],[91.953,13.857],[133.756,17.313],[131.634,119.667],[36.922,202.939],[-55.694,146.569],[-114.612,45.421],[-80.365,15.758],[-42.485,72.616]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":17,"s":[{"i":[[0,0],[0,0],[-9.631,-24.611],[13.326,-50.937],[69.886,-1.133],[16.408,44.906],[-27.224,20.199],[-2.287,-0.383],[7.921,-14.798]],"o":[[0,0],[2.535,-16.526],[6.823,17.436],[-6.659,25.455],[-53.502,0.867],[-11.91,-32.595],[5.638,-4.183],[1.812,23.929],[0,0]],"v":[[104.559,34.357],[96.137,2.758],[137.614,18.924],[129.614,121.091],[36.922,202.939],[-81.134,95.727],[-68.861,14.458],[-44.312,9.071],[-44.421,63.798]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":25,"s":[{"i":[[0,0],[0,0],[-1.78,-29.177],[5.86,-32.177],[67.329,0.109],[12.187,19.221],[29.323,34.648],[-25.031,-8.211],[-4.318,-9.495]],"o":[[0,0],[0.662,-27.555],[1.369,3.499],[-4.356,25.922],[-53.507,-0.096],[-20.587,-31.797],[-14.186,-18.985],[25.656,12.025],[0,0]],"v":[[91.276,43.443],[91.953,13.857],[133.756,17.313],[131.634,119.667],[36.922,202.939],[-55.694,146.569],[-114.612,45.421],[-80.365,15.758],[-42.485,72.616]],"c":false}]},{"t":36,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,0],[0,0],[-0.861,-30.119],[0,0]],"o":[[0,0],[-0.376,-28.79],[0,0],[0,0]],"v":[[45.179,33.141],[45.482,2.731],[91.928,3.006],[91.371,42.024]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":17,"s":[{"i":[[0,0],[0,0],[-4.407,-29.87],[0,0]],"o":[[0,0],[-2.286,-24.055],[0,0],[0,0]],"v":[[54.539,22.21],[48.169,0.276],[95.112,0.495],[103.693,30.578]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":25,"s":[{"i":[[0,0],[0,0],[-0.861,-30.119],[0,0]],"o":[[0,0],[-0.376,-28.79],[0,0],[0,0]],"v":[[45.179,33.141],[45.482,2.731],[91.928,3.006],[91.371,42.024]],"c":false}]},{"t":36,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]},{"i":{"x":0.5,"y":1},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,0],[0,0],[-1.403,-28.322],[0,0]],"o":[[0,0],[-1.163,-21.954],[0,0],[0,0]],"v":[[6.569,22.091],[11.851,-16.256],[45.253,-9.411],[45.103,33.19]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.5,"y":0},"t":17,"s":[{"i":[[0,0],[0,0],[-7.106,-26.835],[0,0]],"o":[[0,0],[-1.195,-22.395],[0,0],[0,0]],"v":[[6.541,10.365],[2.792,-11.488],[46.861,-4.507],[54.208,22.427]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":25,"s":[{"i":[[0,0],[0,0],[-1.403,-28.322],[0,0]],"o":[[0,0],[-1.163,-21.954],[0,0],[0,0]],"v":[[6.569,22.091],[8.316,-16.264],[45.253,-9.411],[45.103,33.19]],"c":false}]},{"t":36,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/stories_intro_go_to_next.json b/TMessagesProj/src/main/res/raw/stories_intro_go_to_next.json new file mode 100644 index 000000000..8445bf840 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/stories_intro_go_to_next.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":39,"w":512,"h":512,"nm":"Move between stories","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"L 2","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.6],"y":[0]},"t":10,"s":[0]},{"t":18,"s":[100]}]},"p":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":10,"s":[18.324,121.326,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":25,"s":[139.324,121.326,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[106.324,121.326,0]}]},"a":{"a":0,"k":[-149.676,-134.674,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-146.5,-113.848],[-129.25,-133.123],[-146.003,-155.5]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-107,-90.586],[-180.85,-131.391],[-109.128,-178.762]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-118.501,-90.586],[-180.85,-131.391],[-120.298,-178.762]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":10,"op":180,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"L","sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[106.324,121.326,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":10,"s":[94.324,121.326,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":25,"s":[312.324,119.326,0],"to":[0,0,0],"ti":[0,0,0]},{"t":37,"s":[275.324,119.326,0]}]},"a":{"a":0,"k":[-149.676,-134.674,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-118.501,-90.586],[-180.85,-131.391],[-120.298,-178.762]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-118.501,-90.586],[-180.85,-131.391],[-120.298,-178.762]],"c":false}]},{"i":{"x":0.647,"y":1},"o":{"x":0.167,"y":0.167},"t":20,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-104.329,-104.074],[-102.535,-136.095],[-104.938,-167.302]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-94.887,-92.586],[-44,-139.782],[-95.5,-180.262]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-111.751,-92.586],[-51,-139.641],[-112.6,-180.262]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"R","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":18,"s":[100]},{"t":25,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[342.867,117.741,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":10,"s":[330.867,117.741,0],"to":[0,0,0],"ti":[0,0,0]},{"t":25,"s":[455.867,113.741,0]}]},"a":{"a":0,"k":[86.867,-138.259,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[55.693,-182.347],[118.041,-141.542],[57.489,-94.171]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":10,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[55.693,-182.347],[118.041,-141.542],[57.489,-94.171]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":19,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[81.583,-164.679],[89.485,-139.61],[81.832,-110.584]],"c":false}]},{"i":{"x":0.8,"y":1},"o":{"x":0.167,"y":0.167},"t":21,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[81.807,-157.27],[72.456,-138.259],[81.956,-117.121]],"c":false}]},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[85.99,-146.065],[80.274,-137.134],[86,-126.935]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":26,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Finger","parent":5,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":11,"s":[-9]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":26,"s":[4]},{"t":38,"s":[0]}]},"p":{"a":0,"k":[-18.5,36.537,0]},"a":{"a":0,"k":[-18.5,36.537,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]},{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":11,"s":[{"i":[[-2.092,10.16],[-5.177,79.73],[0,0],[5.691,-28.586],[0.979,-24.038],[0,0]],"o":[[4.328,-21.016],[1.832,-28.211],[7.3,-23.082],[0,0],[-1.179,28.956],[0,0]],"v":[[-43.668,53.071],[-42.051,-75.618],[-33.972,-115.073],[5.007,-106.161],[3.533,-64.461],[7.786,15.745]],"c":false}]},{"i":{"x":0.8,"y":1},"o":{"x":0.2,"y":0},"t":19,"s":[{"i":[[-3.071,9.909],[8.504,79.444],[0.57,10.213],[-7.08,-16.453],[-3.6,-22.061],[0,0]],"o":[[5.474,-17.664],[-1.318,-12.309],[-1.745,-31.265],[5.46,12.688],[5.795,35.511],[0,0]],"v":[[-42.743,52.948],[-43.879,-74.602],[-47.579,-105.62],[-4.387,-112.049],[5.866,-65.354],[7.786,15.745]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":26,"s":[{"i":[[0.753,10.346],[-7.829,79.513],[0,0],[6.64,-28.381],[1.341,-24.021],[0,0]],"o":[[-2.145,-29.468],[2.77,-28.134],[4.823,-23.524],[0,0],[-1.739,31.148],[0,0]],"v":[[-44.856,60.991],[-39.277,-75.736],[-32.362,-115.611],[11.396,-106.027],[7.002,-64.366],[2.412,15.349]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Hand","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.3],"y":[0]},"t":1,"s":[-17]},{"i":{"x":[0.8],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":10,"s":[-27]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.2],"y":[0]},"t":25,"s":[-2]},{"t":37,"s":[-17]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[331.157,340.048,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.8,"y":1},"o":{"x":0.7,"y":0},"t":8,"s":[314.157,376.048,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.2,"y":0},"t":23,"s":[352.157,343.048,0],"to":[0,0,0],"ti":[0,0,0]},{"t":35,"s":[331.157,340.048,0]}]},"a":{"a":0,"k":[28,102.537,0]},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.3],"y":[1,1,1]},"o":{"x":[0.3,0.3,0.3],"y":[0,0,0]},"t":0,"s":[100,100,100]},{"i":{"x":[0.8,0.8,0.8],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.7],"y":[0,0,0]},"t":7,"s":[106,106,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.2,0.2,0.2],"y":[0,0,0]},"t":19,"s":[90,90,100]},{"t":32,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":8,"s":[{"i":[[0,0],[0,0],[-9.631,-24.611],[13.326,-50.937],[69.886,-1.133],[12.597,46.12],[11.013,20.741],[-15.894,-10.516],[-1.068,-16.09]],"o":[[0,0],[2.536,-16.526],[6.823,17.436],[-6.659,25.455],[-53.502,0.867],[-11.012,-40.316],[-13.07,-25.36],[22.214,14.945],[0,0]],"v":[[104.559,34.357],[96.137,2.758],[137.615,18.924],[134.473,115.606],[36.922,202.939],[-81.134,95.727],[-112.647,27.616],[-76.042,6.465],[-40.636,58.339]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":26,"s":[{"i":[[0,0],[0,0],[-2.545,-28.732],[6.588,-34.006],[67.579,-0.012],[12.05,25.204],[35.745,26.327],[-25.416,-6.308],[-5.629,-10.372]],"o":[[0,0],[0.844,-26.479],[1.901,4.858],[-4.581,25.876],[-53.506,-0.002],[-18.533,-33.604],[-20.1,-17.415],[28.249,7.714],[0,0]],"v":[[94.565,44.045],[92.361,12.775],[134.132,17.47],[131.437,119.806],[36.922,202.939],[-61.743,137.016],[-121.118,66.328],[-91.793,32.008],[-41.619,70.235]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":8,"s":[{"i":[[0,0],[0,0],[-4.407,-29.87],[0,0]],"o":[[0,0],[-2.286,-24.055],[0,0],[0,0]],"v":[[54.539,22.21],[48.169,0.276],[95.112,0.495],[103.693,30.578]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":26,"s":[{"i":[[0,0],[0,0],[-1.09,-30.103],[0,0]],"o":[[0,0],[-0.5,-28.483],[0,0],[0,0]],"v":[[47.278,32.979],[47.953,2.683],[92.134,2.843],[94.324,42.992]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.3,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":8,"s":[{"i":[[0,0],[0,0],[-7.106,-26.835],[0,0]],"o":[[0,0],[-1.195,-22.395],[0,0],[0,0]],"v":[[6.541,10.365],[2.792,-11.488],[46.861,-4.507],[54.208,22.427]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":26,"s":[{"i":[[0,0],[0,0],[-1.772,-28.226],[0,0]],"o":[[0,0],[0.283,-23.334],[0,0],[0,0]],"v":[[3.129,24.028],[8.692,-22.43],[47.908,-8.97],[47.186,33.04]],"c":false}]},{"t":37,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/stories_intro_pause.json b/TMessagesProj/src/main/res/raw/stories_intro_pause.json new file mode 100644 index 000000000..565bec213 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/stories_intro_pause.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":46,"w":512,"h":512,"nm":"Pause","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Line 1","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.852]},"o":{"x":[0.9],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[1],"y":[0]},"t":8,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":16,"s":[0]},{"t":24,"s":[100]}]},"p":{"a":0,"k":[234.206,153.434,0]},"a":{"a":0,"k":[-21.794,-102.566,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,-54.502],[54.502,0],[0,54.502],[-54.502,0]],"o":[[0,54.502],[-54.502,0],[0,-54.502],[54.502,0]],"v":[[76.64,-104.816],[-22.044,-6.132],[-120.728,-104.816],[-22.044,-203.5]],"c":true}]},{"i":{"x":0.2,"y":1},"o":{"x":0.253,"y":0},"t":17,"s":[{"i":[[-3.764,-13.031],[13.031,-3.764],[3.764,13.031],[-13.031,3.764]],"o":[[3.764,13.031],[-13.031,3.764],[-3.764,-13.031],[13.031,-3.764]],"v":[[3.175,-115.632],[-13.604,-85.222],[-44.014,-102],[-27.235,-132.41]],"c":true}]},{"i":{"x":0.7,"y":1},"o":{"x":0.5,"y":0},"t":32,"s":[{"i":[[0,-61.681],[61.681,0],[0,61.681],[-61.681,0]],"o":[[0,61.681],[-61.681,0],[0,-61.681],[61.681,0]],"v":[[89.64,-104.816],[-22.044,6.868],[-133.728,-104.816],[-22.044,-216.5]],"c":true}]},{"t":45,"s":[{"i":[[0,-54.502],[54.502,0],[0,54.502],[-54.502,0]],"o":[[0,54.502],[-54.502,0],[0,-54.502],[54.502,0]],"v":[[76.64,-104.816],[-22.044,-6.132],[-120.728,-104.816],[-22.044,-203.5]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[14]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[4]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[0]},{"i":{"x":[0],"y":[1.168]},"o":{"x":[0.036],"y":[0.02]},"t":17,"s":[8.252]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":32,"s":[13]},{"t":45,"s":[14]}]},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[84]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[82]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[80]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":7,"s":[100]},{"i":{"x":[0.31],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[70]},{"i":{"x":[0.7],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":32,"s":[85]},{"t":45,"s":[84]}]},"o":{"a":0,"k":-277},"m":1,"nm":"Trim Paths 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":191,"st":11,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Line 3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.9],"y":[0]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":9,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":21,"s":[0]},{"t":29,"s":[100]}]},"p":{"a":0,"k":[234.206,153.434,0]},"a":{"a":0,"k":[-21.794,-102.566,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,-34.953],[34.953,0],[0,34.953],[-34.953,0]],"o":[[0,34.953],[-34.953,0],[0,-34.953],[34.953,0]],"v":[[41.494,-102.566],[-21.794,-39.277],[-85.083,-102.566],[-21.794,-165.855]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":17,"s":[{"i":[[-4.07,-13.156],[13.156,-4.07],[4.07,13.156],[-13.156,4.07]],"o":[[4.07,13.156],[-13.156,4.07],[-4.07,-13.156],[13.156,-4.07]],"v":[[3.666,-115.935],[-12.786,-84.746],[-43.975,-101.197],[-27.524,-132.386]],"c":true}]},{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":22,"s":[{"i":[[0,-13.771],[13.771,0],[0,13.771],[-13.771,0]],"o":[[0,13.771],[-13.771,0],[0,-13.771],[13.771,0]],"v":[[4.779,-108.566],[-20.155,-83.632],[-45.089,-108.566],[-20.155,-133.5]],"c":true}]},{"i":{"x":0.7,"y":1},"o":{"x":0.49,"y":0},"t":38,"s":[{"i":[[0,-37.592],[37.592,0],[0,37.592],[-37.592,0]],"o":[[0,37.592],[-37.592,0],[0,-37.592],[37.592,0]],"v":[[46.272,-102.566],[-21.794,-34.5],[-89.86,-102.566],[-21.794,-170.632]],"c":true}]},{"t":45,"s":[{"i":[[0,-34.953],[34.953,0],[0,34.953],[-34.953,0]],"o":[[0,34.953],[-34.953,0],[0,-34.953],[34.953,0]],"v":[[41.494,-102.566],[-21.794,-39.277],[-85.083,-102.566],[-21.794,-165.855]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[18]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[7]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[1]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":6,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[22]},{"t":38,"s":[18]}]},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[82]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":4,"s":[79]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":5,"s":[83.25]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":6,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":17,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":22,"s":[72]},{"t":38,"s":[82]}]},"o":{"a":0,"k":-277},"m":1,"nm":"Trim Paths 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false}],"ip":0,"op":201,"st":21,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Finger","parent":4,"sr":1,"ks":{"p":{"a":0,"k":[-18.5,36.537,0]},"a":{"a":0,"k":[-18.5,36.537,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]},{"i":{"x":0.6,"y":1},"o":{"x":0.7,"y":0},"t":6,"s":[{"i":[[-7.8,1.437],[3.081,17.286],[0,0],[-20.884,-29.621],[-2.133,-16.56],[0,0]],"o":[[11.66,-2.149],[-3.081,-17.287],[-17.012,-40.384],[0,0],[3.035,23.558],[0,0]],"v":[[-42.122,74.94],[-33.175,-23.495],[-43.361,-57.296],[-7.626,-88.68],[15.363,-36.072],[15.527,17.249]],"c":false}]},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0.184,-29.147],[0,0],[0,0]],"o":[[0,0],[0,0],[0.179,-28.358],[0,0],[0,0],[0,0]],"v":[[-42.122,74.94],[-42.656,-41.628],[-42.954,-106.447],[2.666,-106.159],[2.179,-28.956],[1.885,17.624]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 4","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Hand","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.3],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":2,"s":[0]},{"i":{"x":[0.6],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":11,"s":[14]},{"t":24,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[284,358.537,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.6,"y":1},"o":{"x":0.7,"y":0},"t":8,"s":[312,386.537,0],"to":[0,0,0],"ti":[0,0,0]},{"t":22,"s":[284,358.537,0]}]},"a":{"a":0,"k":[28,102.537,0]},"s":{"a":1,"k":[{"i":{"x":[0.3,0.3,0.3],"y":[1,1,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,-0.152]},"t":2,"s":[100,100,100]},{"i":{"x":[0.6,0.6,0.6],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.7],"y":[0,0,0]},"t":11,"s":[109,109,100]},{"t":25,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]},{"i":{"x":0.6,"y":1},"o":{"x":0.7,"y":0},"t":9,"s":[{"i":[[-2.761,-1.894],[0,0],[-2.312,-24.788],[4.577,-31.317],[66.688,0.421],[14.618,14.824],[35.595,50.913],[-24.528,-30.75],[-12.852,9.371]],"o":[[0.332,-13.797],[18.044,-3.258],[1.521,16.304],[-3.805,26.035],[-53.508,-0.338],[-25.21,-25.566],[-16.843,-24.091],[13.343,16.728],[0,0]],"v":[[91.053,49.756],[87.731,16.733],[122.404,59.983],[122.458,120.363],[36.922,202.939],[-60.929,156.915],[-127.906,56.569],[-78.283,44.09],[-41.999,74.829]],"c":false}]},{"t":23,"s":[{"i":[[0,0],[0,0],[0.191,-30.324],[3.985,-27.467],[66.688,0.421],[11.838,17.125],[45.297,28.484],[-29.093,-4.682],[-7.391,-8.163]],"o":[[0,0],[0.191,-30.324],[0,0],[-3.778,26.039],[-53.508,-0.338],[-21.438,-31.012],[-22.816,-14.347],[30.58,4.921],[0,0]],"v":[[90.706,47.786],[90.902,16.644],[132.787,16.908],[132.141,119.309],[36.922,202.939],[-54.092,149.617],[-124.228,77.933],[-97.877,41.873],[-41.999,74.829]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]},{"i":{"x":0.6,"y":1},"o":{"x":0.7,"y":0},"t":9,"s":[{"i":[[4.034,-5.2],[0,0],[0.281,-20.185],[0,0]],"o":[[4.865,-21.734],[18.88,-2.079],[0,0],[0,0]],"v":[[57.462,38.822],[57.089,-2.813],[90.197,33.844],[91.053,49.756]],"c":false}]},{"t":23,"s":[{"i":[[0,0],[0,0],[0.19,-30.193],[0,0]],"o":[[0,0],[0.19,-30.193],[0,0],[0,0]],"v":[[44.474,37.139],[44.686,3.459],[90.983,3.751],[90.706,47.786]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.3,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]},{"i":{"x":0.6,"y":1},"o":{"x":0.7,"y":0},"t":9,"s":[{"i":[[0,0],[0,0],[2.373,-29.033],[0,0]],"o":[[0,0],[17.766,-5.161],[0,0],[0,0]],"v":[[15.512,26.381],[18.69,-23.708],[59.379,16.938],[57.462,38.822]],"c":false}]},{"t":23,"s":[{"i":[[0,0],[0,0],[0.288,-28.763],[0,0]],"o":[[0,0],[0.181,-28.763],[0,0],[0,0]],"v":[[1.812,29.305],[2.067,-11.134],[44.776,-10.865],[44.474,37.139]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":14},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 3","bm":0,"hd":false}],"ip":0,"op":180,"st":0,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml index 09132f967..6fabeb56a 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -1129,7 +1129,6 @@ 📅 تذكير نتيجة واحدة جودة المقطع المرئي أقل مما ينبغي لتغيير إعدادات الضغط. - اضغط باستمرار على **كلمة** ما، ثم حرّك المؤشر لتحديد المزيد والنسخ. تم نسخ رقم البطاقة للحافظة نسخ أرسل الرمز التعبيري **🎲** لرمي حجر النرد. diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index a0e907222..6083f2ead 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -1129,7 +1129,6 @@ 📅 Erinnerung 1 Ergebnis Die Videoqualität ist zu niedrig, um die Komprimierung zu ändern. - **Wort** gedrückt halten und Cursor bewegen, um noch mehr Text zu markieren. Kartennummer in Zwischenablage kopiert Kopieren **:würfel:**-Emoji senden, um zu würfeln diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 1b7dc9c8a..b846baa26 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -1129,7 +1129,6 @@ 📅 Recordatorio 1 resultado La calidad del video es demasiado baja para cambiar los ajustes de compresión. - Mantén pulsada una **palabra**, luego mueve el cursor para seleccionar más texto para copiar. Número de tarjeta copiado al portapapeles Copiar Puedes tirar un :dado: enviando su emoji en cualquier chat. diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index 0a6d1d15a..c5b706a02 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -1129,7 +1129,6 @@ 📅 Promemoria 1 risultato Qualità video troppo bassa per cambiare le impostazioni di compressione. - Premi la **parola**, quindi muovi il cursore per selezionare altro testo da copiare. Numero carta copiato negli appunti Copia Invia l\'emoji **:dado:** in qualsiasi chat per lanciare un dado. diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 3ea761c0a..2baf44ae1 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -1129,7 +1129,6 @@ 📅 알림 1건의 결과 압축 설정을 바꾸기엔 동영상 품질이 너무 낮습니다. - **낱말**을 꾹 잡고선, 커서를 움직여 복사할 글을 조정하세요. 카드 번호가 클립보드에 복사되었습니다 복사 대화방에 **:dice:**를 보내어 주사위를 굴리세요. diff --git a/TMessagesProj/src/main/res/values-night/styles.xml b/TMessagesProj/src/main/res/values-night/styles.xml index 85bbd39fd..4d619334d 100644 --- a/TMessagesProj/src/main/res/values-night/styles.xml +++ b/TMessagesProj/src/main/res/values-night/styles.xml @@ -12,6 +12,8 @@ + + + + + + + + + + + +