diff --git a/TMessagesProj/build.gradle b/TMessagesProj/build.gradle index 21e53e335..11861d05d 100644 --- a/TMessagesProj/build.gradle +++ b/TMessagesProj/build.gradle @@ -10,8 +10,8 @@ if (System.getenv("DEBUG_BUILD") == "true") { verName += "-" + RuntimeUtil.execForStr("git log --pretty=format:'%h' -n 1").trim() } -def officialVer = "8.7.4" -def officialCode = 2636 +def officialVer = "8.8.3" +def officialCode = 2705 def serviceAccountCredentialsFile = rootProject.file("service_account_credentials.json") diff --git a/TMessagesProj/jni/audio.c b/TMessagesProj/jni/audio.c index 7dc36e45c..445b78895 100644 --- a/TMessagesProj/jni/audio.c +++ b/TMessagesProj/jni/audio.c @@ -219,7 +219,7 @@ static int writeOggPage(ogg_page *page, FILE *os) { return written; } -const opus_int32 bitrate = 30 * 1024; +const opus_int32 bitrate = OPUS_BITRATE_MAX; const opus_int32 frame_size = 960; const int with_cvbr = 1; const int max_ogg_delay = 0; @@ -322,7 +322,7 @@ int initRecorder(const char *path, opus_int32 sampleRate) { header.nb_streams = 1; int result = OPUS_OK; - _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_AUDIO, &result); + _encoder = opus_encoder_create(coding_rate, 1, OPUS_APPLICATION_VOIP, &result); if (result != OPUS_OK) { LOGE("Error cannot create encoder: %s", opus_strerror(result)); return 0; diff --git a/TMessagesProj/jni/lottie.cpp b/TMessagesProj/jni/lottie.cpp index 1a6f45cc9..9169dde5f 100644 --- a/TMessagesProj/jni/lottie.cpp +++ b/TMessagesProj/jni/lottie.cpp @@ -39,6 +39,7 @@ typedef struct LottieInfo { volatile uint32_t maxFrameSize = 0; uint32_t imageSize = 0; uint32_t fileOffset = 0; + uint32_t fileFrame = 0; bool nextFrameIsCacheFrame = false; FILE *precacheFile = nullptr; @@ -146,6 +147,7 @@ JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_create(JNIEnv *e info->maxFrameSize = maxFrameSize; fread(&(info->imageSize), sizeof(uint32_t), 1, precacheFile); info->fileOffset = 9; + info->fileFrame = 0; utimensat(0, info->cacheFile.c_str(), nullptr, 0); } fclose(precacheFile); @@ -162,6 +164,18 @@ JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_create(JNIEnv *e return (jlong) (intptr_t) info; } +JNIEXPORT jstring Java_org_telegram_ui_Components_RLottieDrawable_getCacheFile(JNIEnv *env, jclass clazz, jlong ptr) { + if (!ptr) { + return NULL; + } + auto info = (LottieInfo *) (intptr_t) ptr; + if (info->precache) { + return env->NewStringUTF(info->cacheFile.c_str()); + } + return NULL; +} + + JNIEXPORT jlong Java_org_telegram_ui_Components_RLottieDrawable_createWithJson(JNIEnv *env, jclass clazz, jstring json, jstring name, jintArray data, jintArray colorReplacement) { std::map *colors = nullptr; if (colorReplacement != nullptr) { @@ -271,6 +285,7 @@ void CacheWriteThreadProc() { if (task->firstFrame) { task->firstFrameSize = size; task->fileOffset = 9 + sizeof(uint32_t) + task->firstFrameSize; + task->fileFrame = 1; } task->maxFrameSize = MAX(task->maxFrameSize, size); fwrite(&size, sizeof(uint32_t), 1, task->precacheFile); @@ -310,6 +325,7 @@ JNIEXPORT void Java_org_telegram_ui_Components_RLottieDrawable_createCache(JNIEn info->precacheFile = fopen(info->cacheFile.c_str(), "w+"); if (info->precacheFile != nullptr) { fseek(info->precacheFile, info->fileOffset = 9, SEEK_SET); + info->fileFrame = 0; info->maxFrameSize = 0; info->bufferSize = w * h * 4; info->imageSize = (uint32_t) w * h * 4; @@ -393,18 +409,32 @@ JNIEXPORT jint Java_org_telegram_ui_Components_RLottieDrawable_getFrame(JNIEnv * } info->decompressBuffer = new uint8_t[info->decompressBufferSize]; } + int currentFrame = frame / framesPerUpdate; + if (info->fileFrame != frame) { + info->fileOffset = 9; + info->fileFrame = 0; + while (info->fileFrame != currentFrame) { + fseek(precacheFile, info->fileOffset, SEEK_SET); + uint32_t frameSize; + fread(&frameSize, sizeof(uint32_t), 1, precacheFile); + info->fileOffset += 4 + frameSize; + info->fileFrame++; + } + } fseek(precacheFile, info->fileOffset, SEEK_SET); uint32_t frameSize; fread(&frameSize, sizeof(uint32_t), 1, precacheFile); if (frameSize > 0 && frameSize <= info->decompressBufferSize) { fread(info->decompressBuffer, sizeof(uint8_t), frameSize, precacheFile); info->fileOffset += 4 + frameSize; + info->fileFrame = currentFrame + 1; LZ4_decompress_safe((const char *) info->decompressBuffer, (char *) pixels, frameSize, w * h * 4); loadedFromCache = true; } fclose(precacheFile); if (frame + framesPerUpdate >= info->frameCount) { info->fileOffset = 9; + info->fileFrame = 0; } } } diff --git a/TMessagesProj/jni/tgnet/ApiScheme.cpp b/TMessagesProj/jni/tgnet/ApiScheme.cpp index 337e6a7aa..6a8b48dde 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.cpp +++ b/TMessagesProj/jni/tgnet/ApiScheme.cpp @@ -55,6 +55,7 @@ void TL_dcOption::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool tcpo_only = (flags & 4) != 0; cdn = (flags & 8) != 0; isStatic = (flags & 16) != 0; + thisPortOnly = (flags & 32) != 0; id = stream->readInt32(&error); ip_address = stream->readString(&error); port = stream->readInt32(&error); @@ -70,6 +71,7 @@ void TL_dcOption::serializeToStream(NativeByteBuffer *stream) { flags = tcpo_only ? (flags | 4) : (flags &~ 4); flags = cdn ? (flags | 8) : (flags &~ 8); flags = isStatic ? (flags | 16) : (flags &~ 16); + flags = thisPortOnly ? (flags | 32) : (flags &~ 32); stream->writeInt32(flags); stream->writeInt32(id); stream->writeString(ip_address); diff --git a/TMessagesProj/jni/tgnet/ApiScheme.h b/TMessagesProj/jni/tgnet/ApiScheme.h index 9ec65bb9e..dfa30e2ce 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.h +++ b/TMessagesProj/jni/tgnet/ApiScheme.h @@ -49,6 +49,7 @@ public: bool tcpo_only; bool cdn; bool isStatic; + bool thisPortOnly; int32_t id; std::string ip_address; int32_t port; diff --git a/TMessagesProj/jni/tgnet/Connection.cpp b/TMessagesProj/jni/tgnet/Connection.cpp index 001e6acac..ee7b3ff5d 100644 --- a/TMessagesProj/jni/tgnet/Connection.cpp +++ b/TMessagesProj/jni/tgnet/Connection.cpp @@ -699,6 +699,10 @@ void Connection::onDisconnectedInternal(int32_t reason, int32_t error) { isTryingNextPort = true; if (failedConnectionCount > willRetryConnectCount || switchToNextPort) { currentDatacenter->nextAddressOrPort(currentAddressFlags); + if (currentDatacenter->isRepeatCheckingAddresses() && (ConnectionsManager::getInstance(currentDatacenter->instanceNum).getIpStratagy() == USE_IPV4_ONLY || ConnectionsManager::getInstance(currentDatacenter->instanceNum).getIpStratagy() == USE_IPV6_ONLY)) { + if (LOGS_ENABLED) DEBUG_D("started retrying connection, set ipv4 ipv6 random strategy"); + ConnectionsManager::getInstance(currentDatacenter->instanceNum).setIpStrategy(USE_IPV4_IPV6_RANDOM); + } failedConnectionCount = 0; } } diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index f39f60e5b..317e83918 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -3009,8 +3009,13 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) { if (dcOption->secret != nullptr) { secret = std::string((const char *) dcOption->secret->bytes, dcOption->secret->length); } - if (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has secret = %d[%d]", dcOption->ip_address.c_str(), dcOption->port, dcOption->id, dcOption->flags, dcOption->secret != nullptr ? 1 : 0, dcOption->secret != nullptr ? dcOption->secret->length : 0); - addresses->push_back(TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret)); + if (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has_secret = %d[%d], try_this_port_only = %d", dcOption->ip_address.c_str(), dcOption->port, dcOption->id, dcOption->flags, dcOption->secret != nullptr ? 1 : 0, dcOption->secret != nullptr ? dcOption->secret->length : 0, dcOption->thisPortOnly ? 1 : 0); + if (dcOption->thisPortOnly) { + addresses->insert(addresses->begin(), TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret)); + } else { + addresses->push_back(TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret)); + } + } }; diff --git a/TMessagesProj/jni/tgnet/Datacenter.cpp b/TMessagesProj/jni/tgnet/Datacenter.cpp index 37f84d3c6..8b8211c8c 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.cpp +++ b/TMessagesProj/jni/tgnet/Datacenter.cpp @@ -414,6 +414,7 @@ void Datacenter::nextAddressOrPort(uint32_t flags) { if (currentAddressNum + 1 < addresses->size()) { currentAddressNum++; } else { + repeatCheckingAddresses = true; currentAddressNum = 0; } currentPortNum = 0; @@ -1477,6 +1478,12 @@ void Datacenter::resetInitVersion() { lastInitMediaVersion = 0; } +bool Datacenter::isRepeatCheckingAddresses() { + bool b = repeatCheckingAddresses; + repeatCheckingAddresses = false; + return b; +} + TL_help_configSimple *Datacenter::decodeSimpleConfig(NativeByteBuffer *buffer) { TL_help_configSimple *result = nullptr; diff --git a/TMessagesProj/jni/tgnet/Datacenter.h b/TMessagesProj/jni/tgnet/Datacenter.h index b4c19d5d2..8d10580b8 100644 --- a/TMessagesProj/jni/tgnet/Datacenter.h +++ b/TMessagesProj/jni/tgnet/Datacenter.h @@ -58,6 +58,7 @@ public: bool isExportingAuthorization(); bool hasMediaAddress(); void resetInitVersion(); + bool isRepeatCheckingAddresses(); Connection *getDownloadConnection(uint8_t num, bool create); Connection *getProxyConnection(uint8_t num, bool create, bool connect); @@ -121,6 +122,7 @@ private: int64_t authKeyMediaTempId = 0; Config *config = nullptr; bool isCdnDatacenter = false; + bool repeatCheckingAddresses = false; std::vector> handshakes; diff --git a/TMessagesProj/jni/tgnet/Defines.h b/TMessagesProj/jni/tgnet/Defines.h index 3eb348793..6a8ec7eea 100644 --- a/TMessagesProj/jni/tgnet/Defines.h +++ b/TMessagesProj/jni/tgnet/Defines.h @@ -39,13 +39,9 @@ #define NETWORK_TYPE_ROAMING 2 class TLObject; - class TL_error; - class Request; - class TL_message; - class TL_config; class NativeByteBuffer; class Handshake; diff --git a/TMessagesProj/jni/voip/CMakeLists.txt b/TMessagesProj/jni/voip/CMakeLists.txt index 5f9b8a4cc..be045d0c0 100644 --- a/TMessagesProj/jni/voip/CMakeLists.txt +++ b/TMessagesProj/jni/voip/CMakeLists.txt @@ -41,7 +41,7 @@ target_compile_options(tgvoip PUBLIC set_target_properties(tgvoip PROPERTIES ANDROID_ARM_MODE arm) target_compile_definitions(tgvoip PUBLIC - HAVE_PTHREAD __STDC_LIMIT_MACROS BSD=1 USE_KISS_FFT TGVOIP_NO_VIDEO NULL=0 SOCKLEN_T=socklen_t LOCALE_NOT_USED _LARGEFILE_SOURCE=1 _FILE_OFFSET_BITS=64 restrict= __EMX__ OPUS_BUILD FIXED_POINT USE_ALLOCA HAVE_LRINT HAVE_LRINTF) + HAVE_PTHREAD __STDC_LIMIT_MACROS BSD=1 USE_KISS_FFT TGVOIP_NO_VIDEO NULL=0 SOCKLEN_T=socklen_t LOCALE_NOT_USED _LARGEFILE_SOURCE=1 _FILE_OFFSET_BITS=64 restrict= __EMX__ OPUS_BUILD FIXED_POINT USE_ALLOCA HAVE_LRINT HAVE_LRINTF TGVOIP_NO_DSP) target_compile_definitions(tgvoip PUBLIC RTC_DISABLE_TRACE_EVENTS WEBRTC_OPUS_SUPPORT_120MS_PTIME=1 BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=0 ABSL_ALLOCATOR_NOTHROW=1 RTC_ENABLE_VP9 WEBRTC_POSIX WEBRTC_LINUX WEBRTC_ANDROID WEBRTC_USE_H264 NDEBUG WEBRTC_HAVE_USRSCTP WEBRTC_HAVE_SCTP WEBRTC_APM_DEBUG_DUMP=0 WEBRTC_USE_BUILTIN_ISAC_FLOAT WEBRTC_OPUS_VARIABLE_COMPLEXITY=0 HAVE_NETINET_IN_H WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE __Userspace__ SCTP_SIMPLE_ALLOCATOR SCTP_PROCESS_LEVEL_LOCKS __Userspace_os_Linux) target_include_directories(tgvoip PUBLIC @@ -404,7 +404,7 @@ target_compile_options(tgcalls_tp PUBLIC set_target_properties(tgcalls_tp PROPERTIES ANDROID_ARM_MODE arm) target_compile_definitions(tgcalls_tp PUBLIC - RTC_DISABLE_TRACE_EVENTS WEBRTC_OPUS_SUPPORT_120MS_PTIME=1 BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=0 ABSL_ALLOCATOR_NOTHROW=1 HAVE_PTHREAD RTC_ENABLE_VP9 WEBRTC_POSIX WEBRTC_LINUX WEBRTC_ANDROID WEBRTC_USE_H264 NDEBUG WEBRTC_HAVE_USRSCTP WEBRTC_HAVE_SCTP WEBRTC_APM_DEBUG_DUMP=0 WEBRTC_USE_BUILTIN_ISAC_FLOAT WEBRTC_OPUS_VARIABLE_COMPLEXITY=0 HAVE_NETINET_IN_H WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE __Userspace__ SCTP_SIMPLE_ALLOCATOR SCTP_PROCESS_LEVEL_LOCKS __Userspace_os_Linux HAVE_WEBRTC_VIDEO __ANDROID__) + RTC_DISABLE_TRACE_EVENTS WEBRTC_OPUS_SUPPORT_120MS_PTIME=1 BWE_TEST_LOGGING_COMPILE_TIME_ENABLE=0 ABSL_ALLOCATOR_NOTHROW=1 HAVE_PTHREAD RTC_ENABLE_VP9 WEBRTC_POSIX WEBRTC_LINUX WEBRTC_ANDROID WEBRTC_USE_H264 NDEBUG WEBRTC_HAVE_USRSCTP WEBRTC_HAVE_SCTP WEBRTC_APM_DEBUG_DUMP=0 WEBRTC_USE_BUILTIN_ISAC_FLOAT WEBRTC_OPUS_VARIABLE_COMPLEXITY=0 HAVE_NETINET_IN_H WEBRTC_INCLUDE_INTERNAL_AUDIO_DEVICE __Userspace__ SCTP_SIMPLE_ALLOCATOR SCTP_PROCESS_LEVEL_LOCKS __Userspace_os_Linux HAVE_WEBRTC_VIDEO __ANDROID__ TGVOIP_NO_DSP) target_include_directories(tgcalls_tp PUBLIC ./ voip diff --git a/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java b/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java index 96d2a44d0..d0ae2f4fa 100644 --- a/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java +++ b/TMessagesProj/src/gservcies/java/org/telegram/messenger/GcmPushListenerService.java @@ -371,7 +371,12 @@ public class GcmPushListenerService extends FirebaseMessagingService { if (loc_key.startsWith("REACT_") || loc_key.startsWith("CHAT_REACT_")) { messageText = getReactedText(loc_key, args); } else {switch (loc_key) { - case "MESSAGE_TEXT": + case "MESSAGE_RECURRING_PAY": { + messageText = LocaleController.formatString("NotificationMessageRecurringPay", R.string.NotificationMessageRecurringPay, args[0], args[1]); + message1 = LocaleController.getString("PaymentInvoice", R.string.PaymentInvoice); + break; + } + case "MESSAGE_TEXT": case "CHANNEL_MESSAGE_TEXT": { messageText = LocaleController.formatString("NotificationMessageText", R.string.NotificationMessageText, args[0], args[1]); message1 = args[1]; diff --git a/TMessagesProj/src/main/AndroidManifest.xml b/TMessagesProj/src/main/AndroidManifest.xml index e82ff21b8..5096f1f38 100644 --- a/TMessagesProj/src/main/AndroidManifest.xml +++ b/TMessagesProj/src/main/AndroidManifest.xml @@ -97,6 +97,7 @@ + @@ -119,6 +120,94 @@ android:allowAudioPlaybackCapture="true" tools:replace="android:supportsRtl"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - diff --git a/TMessagesProj/src/main/assets/currencies.json b/TMessagesProj/src/main/assets/currencies.json new file mode 100644 index 000000000..732c551bf --- /dev/null +++ b/TMessagesProj/src/main/assets/currencies.json @@ -0,0 +1 @@ +{"AED":{"code":"AED","title":"United Arab Emirates Dirham","symbol":"AED","native":"د.إ.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"367","max_amount":"3673104"},"AFN":{"code":"AFN","title":"Afghan Afghani","symbol":"AFN","native":"؋","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"8943","max_amount":"89437089"},"ALL":{"code":"ALL","title":"Albanian Lek","symbol":"ALL","native":"Lek","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":false,"exp":2,"min_amount":"11415","max_amount":"114153729"},"AMD":{"code":"AMD","title":"Armenian Dram","symbol":"AMD","native":"դր.","thousands_sep":",","decimal_sep":".","symbol_left":false,"space_between":true,"exp":2,"min_amount":"42405","max_amount":"424059434"},"ARS":{"code":"ARS","title":"Argentine Peso","symbol":"ARS","native":"$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"12287","max_amount":"122871702"},"AUD":{"code":"AUD","title":"Australian Dollar","symbol":"AU$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"144","max_amount":"1442793"},"AZN":{"code":"AZN","title":"Azerbaijani Manat","symbol":"AZN","native":"ман.","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"170","max_amount":"1703970"},"BAM":{"code":"BAM","title":"Bosnia & Herzegovina Convertible Mark","symbol":"BAM","native":"KM","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"186","max_amount":"1862873"},"BDT":{"code":"BDT","title":"Bangladeshi Taka","symbol":"BDT","native":"৳","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"9313","max_amount":"93138585"},"BGN":{"code":"BGN","title":"Bulgarian Lev","symbol":"BGN","native":"лв.","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"186","max_amount":"1862844"},"BND":{"code":"BND","title":"Brunei Dollar","symbol":"BND","native":"$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":false,"exp":2,"min_amount":"138","max_amount":"1388608"},"BOB":{"code":"BOB","title":"Bolivian Boliviano","symbol":"BOB","native":"Bs","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"689","max_amount":"6898943"},"BRL":{"code":"BRL","title":"Brazilian Real","symbol":"R$","native":"R$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"515","max_amount":"5153919"},"CAD":{"code":"CAD","title":"Canadian Dollar","symbol":"CA$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"130","max_amount":"1303495"},"CHF":{"code":"CHF","title":"Swiss Franc","symbol":"CHF","native":"CHF","thousands_sep":"'","decimal_sep":".","symbol_left":false,"space_between":true,"exp":2,"min_amount":"97","max_amount":"970848"},"CLP":{"code":"CLP","title":"Chilean Peso","symbol":"CLP","native":"$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":0,"min_amount":"876","max_amount":"8768039"},"CNY":{"code":"CNY","title":"Chinese Renminbi Yuan","symbol":"CN¥","native":"CN¥","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"671","max_amount":"6716704"},"COP":{"code":"COP","title":"Colombian Peso","symbol":"COP","native":"$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"390589","max_amount":"3905895800"},"CRC":{"code":"CRC","title":"Costa Rican Colón","symbol":"CRC","native":"₡","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":false,"exp":2,"min_amount":"68499","max_amount":"684998571"},"CZK":{"code":"CZK","title":"Czech Koruna","symbol":"CZK","native":"Kč","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"2355","max_amount":"23555404"},"DKK":{"code":"DKK","title":"Danish Krone","symbol":"DKK","native":"kr","thousands_sep":"","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"708","max_amount":"7087040"},"DOP":{"code":"DOP","title":"Dominican Peso","symbol":"DOP","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"5485","max_amount":"54850938"},"DZD":{"code":"DZD","title":"Algerian Dinar","symbol":"DZD","native":"د.ج.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"14626","max_amount":"146263454"},"EGP":{"code":"EGP","title":"Egyptian Pound","symbol":"EGP","native":"ج.م.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"1874","max_amount":"18741785"},"EUR":{"code":"EUR","title":"Euro","symbol":"€","native":"€","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"95","max_amount":"952804"},"GBP":{"code":"GBP","title":"British Pound","symbol":"£","native":"£","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"81","max_amount":"817962"},"GEL":{"code":"GEL","title":"Georgian Lari","symbol":"GEL","native":"GEL","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"292","max_amount":"2925040"},"GTQ":{"code":"GTQ","title":"Guatemalan Quetzal","symbol":"GTQ","native":"Q","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"775","max_amount":"7750738"},"HKD":{"code":"HKD","title":"Hong Kong Dollar","symbol":"HK$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"785","max_amount":"7850055"},"HNL":{"code":"HNL","title":"Honduran Lempira","symbol":"HNL","native":"L","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"2461","max_amount":"24617583"},"HRK":{"code":"HRK","title":"Croatian Kuna","symbol":"HRK","native":"kn","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"716","max_amount":"7164904"},"HUF":{"code":"HUF","title":"Hungarian Forint","symbol":"HUF","native":"Ft","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"38098","max_amount":"380982504"},"IDR":{"code":"IDR","title":"Indonesian Rupiah","symbol":"IDR","native":"Rp","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":false,"exp":2,"min_amount":"1483885","max_amount":"14838850000"},"ILS":{"code":"ILS","title":"Israeli New Sheqel","symbol":"₪","native":"₪","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"346","max_amount":"3462015"},"INR":{"code":"INR","title":"Indian Rupee","symbol":"₹","native":"₹","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"7795","max_amount":"77951504"},"ISK":{"code":"ISK","title":"Icelandic Króna","symbol":"ISK","native":"kr","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":0,"min_amount":"131","max_amount":"1311903"},"JMD":{"code":"JMD","title":"Jamaican Dollar","symbol":"JMD","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"15254","max_amount":"152544052"},"JPY":{"code":"JPY","title":"Japanese Yen","symbol":"¥","native":"¥","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":0,"min_amount":"134","max_amount":"1349925"},"KES":{"code":"KES","title":"Kenyan Shilling","symbol":"KES","native":"Ksh","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"11763","max_amount":"117638156"},"KGS":{"code":"KGS","title":"Kyrgyzstani Som","symbol":"KGS","native":"KGS","thousands_sep":" ","decimal_sep":"-","symbol_left":false,"space_between":true,"exp":2,"min_amount":"7950","max_amount":"79501104"},"KRW":{"code":"KRW","title":"South Korean Won","symbol":"₩","native":"₩","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":0,"min_amount":"1291","max_amount":"12915037"},"KZT":{"code":"KZT","title":"Kazakhstani Tenge","symbol":"KZT","native":"₸","thousands_sep":" ","decimal_sep":"-","symbol_left":true,"space_between":false,"exp":2,"min_amount":"44915","max_amount":"449157063"},"LBP":{"code":"LBP","title":"Lebanese Pound","symbol":"LBP","native":"ل.ل.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"151528","max_amount":"1515287170"},"LKR":{"code":"LKR","title":"Sri Lankan Rupee","symbol":"LKR","native":"රු.","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"35972","max_amount":"359728355"},"MAD":{"code":"MAD","title":"Moroccan Dirham","symbol":"MAD","native":"د.م.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"1009","max_amount":"10093437"},"MDL":{"code":"MDL","title":"Moldovan Leu","symbol":"MDL","native":"MDL","thousands_sep":",","decimal_sep":".","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1928","max_amount":"19284027"},"MNT":{"code":"MNT","title":"Mongolian Tögrög","symbol":"MNT","native":"MNT","thousands_sep":" ","decimal_sep":",","symbol_left":true,"space_between":false,"exp":2,"min_amount":"311718","max_amount":"3117185198"},"MUR":{"code":"MUR","title":"Mauritian Rupee","symbol":"MUR","native":"MUR","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"4495","max_amount":"44956663"},"MVR":{"code":"MVR","title":"Maldivian Rufiyaa","symbol":"MVR","native":"MVR","thousands_sep":",","decimal_sep":".","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1540","max_amount":"15403741"},"MXN":{"code":"MXN","title":"Mexican Peso","symbol":"MX$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"2033","max_amount":"20338950"},"MYR":{"code":"MYR","title":"Malaysian Ringgit","symbol":"MYR","native":"RM","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"440","max_amount":"4402039"},"MZN":{"code":"MZN","title":"Mozambican Metical","symbol":"MZN","native":"MTn","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"6383","max_amount":"63830377"},"NGN":{"code":"NGN","title":"Nigerian Naira","symbol":"NGN","native":"₦","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"41537","max_amount":"415370377"},"NIO":{"code":"NIO","title":"Nicaraguan Córdoba","symbol":"NIO","native":"C$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"3592","max_amount":"35928184"},"NOK":{"code":"NOK","title":"Norwegian Krone","symbol":"NOK","native":"kr","thousands_sep":" ","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"1001","max_amount":"10013205"},"NPR":{"code":"NPR","title":"Nepalese Rupee","symbol":"NPR","native":"नेरू","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"12511","max_amount":"125113820"},"NZD":{"code":"NZD","title":"New Zealand Dollar","symbol":"NZ$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"158","max_amount":"1585666"},"PAB":{"code":"PAB","title":"Panamanian Balboa","symbol":"PAB","native":"B\/.","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"100","max_amount":"1002000"},"PEN":{"code":"PEN","title":"Peruvian Nuevo Sol","symbol":"PEN","native":"S\/.","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"371","max_amount":"3718830"},"PHP":{"code":"PHP","title":"Philippine Peso","symbol":"PHP","native":"₱","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"5376","max_amount":"53760375"},"PKR":{"code":"PKR","title":"Pakistani Rupee","symbol":"PKR","native":"₨","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"20967","max_amount":"209674540"},"PLN":{"code":"PLN","title":"Polish Złoty","symbol":"PLN","native":"zł","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"445","max_amount":"4457704"},"PYG":{"code":"PYG","title":"Paraguayan Guaraní","symbol":"PYG","native":"₲","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":0,"min_amount":"6873","max_amount":"68730355"},"QAR":{"code":"QAR","title":"Qatari Riyal","symbol":"QAR","native":"ر.ق.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"364","max_amount":"3641038"},"RON":{"code":"RON","title":"Romanian Leu","symbol":"RON","native":"RON","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"471","max_amount":"4711804"},"RSD":{"code":"RSD","title":"Serbian Dinar","symbol":"RSD","native":"дин.","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"11195","max_amount":"111950662"},"RUB":{"code":"RUB","title":"Russian Ruble","symbol":"RUB","native":"руб.","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"5749","max_amount":"57499904"},"SAR":{"code":"SAR","title":"Saudi Riyal","symbol":"SAR","native":"ر.س.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"375","max_amount":"3751352"},"SEK":{"code":"SEK","title":"Swedish Krona","symbol":"SEK","native":"kr","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1022","max_amount":"10229465"},"SGD":{"code":"SGD","title":"Singapore Dollar","symbol":"SGD","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"139","max_amount":"1390604"},"THB":{"code":"THB","title":"Thai Baht","symbol":"฿","native":"฿","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"3523","max_amount":"35232038"},"TJS":{"code":"TJS","title":"Tajikistani Somoni","symbol":"TJS","native":"TJS","thousands_sep":" ","decimal_sep":";","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1106","max_amount":"11060101"},"TRY":{"code":"TRY","title":"Turkish Lira","symbol":"TRY","native":"TL","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1732","max_amount":"17328404"},"TTD":{"code":"TTD","title":"Trinidad and Tobago Dollar","symbol":"TTD","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"680","max_amount":"6808077"},"TWD":{"code":"TWD","title":"New Taiwan Dollar","symbol":"NT$","native":"NT$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"2971","max_amount":"29716504"},"TZS":{"code":"TZS","title":"Tanzanian Shilling","symbol":"TZS","native":"TSh","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"233672","max_amount":"2336727307"},"UAH":{"code":"UAH","title":"Ukrainian Hryvnia","symbol":"UAH","native":"₴","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":false,"exp":2,"min_amount":"2960","max_amount":"29603677"},"UGX":{"code":"UGX","title":"Ugandan Shilling","symbol":"UGX","native":"USh","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":0,"min_amount":"3747","max_amount":"37475950"},"USD":{"code":"USD","title":"United States Dollar","symbol":"$","native":"$","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":false,"exp":2,"min_amount":"100","max_amount":1000000},"UYU":{"code":"UYU","title":"Uruguayan Peso","symbol":"UYU","native":"$","thousands_sep":".","decimal_sep":",","symbol_left":true,"space_between":true,"exp":2,"min_amount":"4018","max_amount":"40180970"},"UZS":{"code":"UZS","title":"Uzbekistani Som","symbol":"UZS","native":"UZS","thousands_sep":" ","decimal_sep":",","symbol_left":false,"space_between":true,"exp":2,"min_amount":"1099173","max_amount":"10991732546"},"VND":{"code":"VND","title":"Vietnamese Đồng","symbol":"₫","native":"₫","thousands_sep":".","decimal_sep":",","symbol_left":false,"space_between":true,"exp":0,"min_amount":"23230","max_amount":"232300000"},"YER":{"code":"YER","title":"Yemeni Rial","symbol":"YER","native":"ر.ي.‏","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"25025","max_amount":"250250364"},"ZAR":{"code":"ZAR","title":"South African Rand","symbol":"ZAR","native":"R","thousands_sep":",","decimal_sep":".","symbol_left":true,"space_between":true,"exp":2,"min_amount":"1602","max_amount":"16028160"}} \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/darkblue.attheme b/TMessagesProj/src/main/assets/darkblue.attheme index 53855489c..1556b190f 100644 --- a/TMessagesProj/src/main/assets/darkblue.attheme +++ b/TMessagesProj/src/main/assets/darkblue.attheme @@ -26,6 +26,7 @@ chat_inPreviewInstantSelectedText=-5648402 chat_attachAudioBackground=-626837 location_sendLocationBackground=-9919529 actionBarDefaultSubmenuBackground=-14075831 +actionBarDefaultSubmenuSeparator=-14733761 switchTrackBlueThumb=-14866637 avatar_nameInMessageViolet=-6643205 emptyListPlaceholder=-8549479 diff --git a/TMessagesProj/src/main/assets/flecks.png b/TMessagesProj/src/main/assets/flecks.png new file mode 100644 index 000000000..8c61be7bb Binary files /dev/null and b/TMessagesProj/src/main/assets/flecks.png differ diff --git a/TMessagesProj/src/main/assets/fonts/courier_new_bold.ttf b/TMessagesProj/src/main/assets/fonts/courier_new_bold.ttf new file mode 100644 index 000000000..b6e60d917 Binary files /dev/null and b/TMessagesProj/src/main/assets/fonts/courier_new_bold.ttf differ diff --git a/TMessagesProj/src/main/assets/models/star.binobj b/TMessagesProj/src/main/assets/models/star.binobj new file mode 100644 index 000000000..4b0823820 Binary files /dev/null and b/TMessagesProj/src/main/assets/models/star.binobj differ diff --git a/TMessagesProj/src/main/assets/night.attheme b/TMessagesProj/src/main/assets/night.attheme index a0a26e615..cdaeaf07d 100644 --- a/TMessagesProj/src/main/assets/night.attheme +++ b/TMessagesProj/src/main/assets/night.attheme @@ -33,7 +33,7 @@ chat_inAudioSelectedProgress=-1 chats_nameMessage=-1315861 chat_messagePanelShadow=2030043136 chat_inMediaIcon=-1 -actionBarDefaultArchived=-14145495 +actionBarDefaultArchived=-13882323 avatar_subtitleInProfileViolet=-7628894 chat_messagePanelCancelInlineBot=1694498815 dialogSearchBackground=-13816531 @@ -107,6 +107,7 @@ dialogInputField=-8553091 windowBackgroundWhiteInputFieldActivated=-9522449 chat_attachGalleryBackground=-11692299 chat_outInstantSelected=-1 +actionBarDefaultSubmenuSeparator=-14803425 chat_outSentCheck=-506859265 key_graySectionText=-8158332 player_placeholder=-10197916 @@ -116,7 +117,7 @@ groupcreate_spanBackground=-13816531 dialogButton=-10177041 contextProgressInner1=1526726655 chat_inLoaderPhotoIconSelected=-1 -actionBarDefaultSubtitle=1693643506 +actionBarDefaultSubtitle=1945301746 chat_inContactPhoneText=-8486783 chat_inlineResultIcon=-8796932 chat_outBubbleGradientSelectedOverlay=352321535 @@ -197,7 +198,7 @@ statisticChartSignatureAlpha=-1946157057 chat_emojiSearchIcon=-9211020 chat_emojiPanelTrendingDescription=-8553090 calls_callReceivedGreenIcon=-12001930 -chats_pinnedOverlay=16777215 +chats_pinnedOverlay=201326591 windowBackgroundWhiteInputField=-11513776 avatar_backgroundRed=-2326437 statisticChartLine_green=-12729793 @@ -266,7 +267,13 @@ chat_outAudioDurationSelectedText=-7023626 avatar_backgroundArchivedHidden=-12279320 chat_attachCameraIcon1=-32171 undo_background=-181917656 +premiumGradientBackground3=-16777216 +premiumGradientBackground4=-16777216 +premiumGradientBackground1=-16578545 avatar_actionBarSelectorPink=-12758164 +premiumGradientBackground2=-16645625 +premiumStarGradient1=-2342678 +premiumStarGradient2=-9992961 dialogTextHint=-8553091 statisticChartLine_orange=-1457126 chat_topPanelTitle=-10440716 @@ -324,7 +331,7 @@ avatar_actionBarSelectorViolet=-12758164 chat_attachPollBackground=-2183099 avatar_nameInMessageBlue=-8796932 dialogTextBlack=-592138 -actionBarDefault=-14671838 +actionBarDefault=-14474458 location_placeLocationBackground=-9919529 profile_actionIcon=-1 windowBackgroundUnchecked=-14803424 @@ -344,6 +351,7 @@ chat_goDownButtonCounter=-1 switchTrackBlueSelectorChecked=848091135 chat_outFileBackground=520093695 chats_name=-921103 +premiumStartSmallStarsColor=-8290049 switchTrackBlueSelector=431611386 dialogBadgeBackground=-10177041 chat_outBubbleSelected=-11829841 @@ -494,4 +502,4 @@ chat_topPanelBackground=-15066597 chat_outSentClock=-6698513 dialogBackgroundGray=-14013910 chat_searchPanelText=-10767620 -chat_inContactIcon=-1 +chat_inContactIcon=-1 \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/shaders/fragment2.glsl b/TMessagesProj/src/main/assets/shaders/fragment2.glsl new file mode 100644 index 000000000..ee3dda066 --- /dev/null +++ b/TMessagesProj/src/main/assets/shaders/fragment2.glsl @@ -0,0 +1,68 @@ +precision highp float; + +uniform sampler2D u_Texture; +uniform sampler2D u_NormalMap; +uniform sampler2D u_BackgroundTexture; +uniform float f_xOffset; +uniform float f_alpha; +uniform mat4 world; +uniform vec3 modelViewVertex; + +varying vec3 vNormal; +varying vec2 vUV; + +vec3 cameraPosition = vec3(0, 0, 100); + +vec4 a_Color = vec4(1); +uniform float spec1; +uniform float spec2; +uniform float u_diffuse; +uniform float normalSpec; +uniform vec3 gradientColor1; +uniform vec3 gradientColor2; +uniform vec3 normalSpecColor; +uniform vec3 specColor; +uniform vec2 resolution; +uniform vec4 gradientPosition; + +void main() { + vec3 vLightPosition2 = vec3(-400,400,400); + vec3 vLightPosition3 = vec3(0,200,400); + vec3 vLightPosition4 = vec3(100,-200,400); + + vec3 vNormalW = normalize(vec3(world * vec4(vNormal, 0.0))); + vec3 vTextureNormal = normalize(texture2D(u_NormalMap, vUV + vec2(-f_xOffset, f_xOffset)).xyz * 2.0 - 1.0); + + vec3 finalNormal = normalize(vNormalW + vTextureNormal); + + vec3 color = texture2D(u_Texture, vUV * vec2(0.8, 0.8) + vec2(0.2 * f_xOffset, 0)).xyz; + vec3 viewDirectionW = normalize(cameraPosition - modelViewVertex); + + vec3 angleW = normalize(viewDirectionW + vLightPosition2); + float specComp2 = max(0., dot(vNormalW, angleW)); + specComp2 = pow(specComp2, max(1., 128.)) * spec1; + + angleW = normalize(viewDirectionW + vLightPosition4); + float specComp3 = max(0., dot(vNormalW, angleW)); + specComp3 = pow(specComp3, max(1., 128.)) * spec2; + + float diffuse = max(dot(vNormalW, viewDirectionW), (1.0 - u_diffuse)); + + float mixValue = distance(vUV,vec2(1,0)); + vec4 gradientColorFinal = vec4(mix(gradientColor1,gradientColor2,mixValue), 1.0); + + angleW = normalize(viewDirectionW + vLightPosition4); + float normalSpecComp = max(0., dot(finalNormal, angleW)); + normalSpecComp = pow(normalSpecComp, max(1., 128.)) * normalSpec; + + angleW = normalize(viewDirectionW + vLightPosition2); + float normalSpecComp2 = max(0., dot(finalNormal, angleW)); + normalSpecComp2 = pow(normalSpecComp2, max(1., 128.)) * normalSpec; + + vec4 normalSpecFinal = vec4(normalSpecColor, 0.0) * (normalSpecComp + normalSpecComp2); + vec4 specFinal = vec4(specColor, 0.0) * (specComp2 + specComp3); + + vec4 fragColor = gradientColorFinal + specFinal + normalSpecFinal; + vec4 backgroundColor = texture2D(u_BackgroundTexture, vec2(gradientPosition.x + (gl_FragCoord.x / resolution.x) * gradientPosition.y, gradientPosition.z + (1.0 - (gl_FragCoord.y / resolution.y)) * gradientPosition.w)); + gl_FragColor = mix(backgroundColor, fragColor, diffuse) * f_alpha; +} \ No newline at end of file diff --git a/TMessagesProj/src/main/assets/shaders/vertex2.glsl b/TMessagesProj/src/main/assets/shaders/vertex2.glsl new file mode 100644 index 000000000..8a3bb36af --- /dev/null +++ b/TMessagesProj/src/main/assets/shaders/vertex2.glsl @@ -0,0 +1,16 @@ +uniform mat4 uMVPMatrix; + +attribute vec2 a_TexCoordinate; +attribute vec3 a_Normal; +attribute vec4 vPosition; + +varying vec3 vNormal; +varying vec2 vUV; +varying vec3 modelViewVertex; + +void main() { + modelViewVertex = vec3(uMVPMatrix * vPosition); + vUV = a_TexCoordinate; + vNormal = a_Normal; + gl_Position = uMVPMatrix * vPosition; +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java index a41729d5a..a2f937dc4 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/ChatListItemAnimator.java @@ -761,6 +761,13 @@ public class ChatListItemAnimator extends DefaultItemAnimator { recyclerListView.invalidate(); ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0); + if (moveInfoExtended.animateBackgroundOnly) { + params.toDeltaLeft = -moveInfoExtended.deltaLeft; + params.toDeltaRight = -moveInfoExtended.deltaRight; + } else { + params.toDeltaLeft = -moveInfoExtended.deltaLeft - chatMessageCell.getAnimationOffsetX(); + params.toDeltaRight = -moveInfoExtended.deltaRight - chatMessageCell.getAnimationOffsetX(); + } valueAnimator.addUpdateListener(animation -> { float v = (float) animation.getAnimatedValue(); if (moveInfoExtended.animateBackgroundOnly) { @@ -777,6 +784,9 @@ public class ChatListItemAnimator extends DefaultItemAnimator { chatMessageCell.invalidate(); }); animatorSet.playTogether(valueAnimator); + } else { + params.toDeltaLeft = 0; + params.toDeltaRight = 0; } MessageObject.GroupedMessages group = chatMessageCell.getCurrentMessagesGroup(); diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java index 9d45b4015..545f96120 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/DefaultItemAnimator.java @@ -21,6 +21,7 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.os.Build; import android.view.View; +import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.view.animation.Interpolator; @@ -223,7 +224,11 @@ public class DefaultItemAnimator extends SimpleItemAnimator { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mRemoveAnimations.add(holder); - animation.setDuration(getRemoveDuration()).alpha(0).setListener( + if (getRemoveDelay() > 0) { + // wanted to achieve an effect of next items covering current + ((ViewGroup) view.getParent()).bringChildToFront(view); + } + animation.setDuration(getRemoveDuration()).setStartDelay(getRemoveDelay()).alpha(0).setListener( new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { @@ -256,7 +261,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { final View view = holder.itemView; final ViewPropertyAnimator animation = view.animate(); mAddAnimations.add(holder); - animation.alpha(1).setDuration(getAddDuration()) + animation.alpha(1).setDuration(getAddDuration()).setStartDelay(getAddDelay()) .setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { @@ -331,30 +336,35 @@ public class DefaultItemAnimator extends SimpleItemAnimator { if (translationInterpolator != null) { animation.setInterpolator(translationInterpolator); } - animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animator) { - dispatchMoveStarting(holder); - } - - @Override - public void onAnimationCancel(Animator animator) { - if (deltaX != 0) { - view.setTranslationX(0); + animation + .setDuration(getMoveDuration()) + .setStartDelay(getMoveDelay()) + .setInterpolator(getMoveInterpolator()) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + dispatchMoveStarting(holder); } - if (deltaY != 0) { - view.setTranslationY(0); - } - } - @Override - public void onAnimationEnd(Animator animator) { - animation.setListener(null); - dispatchMoveFinished(holder); - mMoveAnimations.remove(holder); - dispatchFinishedWhenDone(); - } - }).start(); + @Override + public void onAnimationCancel(Animator animator) { + if (deltaX != 0) { + view.setTranslationX(0); + } + if (deltaY != 0) { + view.setTranslationY(0); + } + } + + @Override + public void onAnimationEnd(Animator animator) { + animation.setListener(null); + dispatchMoveFinished(holder); + mMoveAnimations.remove(holder); + dispatchFinishedWhenDone(); + } + }) + .start(); } @Override @@ -393,8 +403,7 @@ public class DefaultItemAnimator extends SimpleItemAnimator { final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; final View newView = newHolder != null ? newHolder.itemView : null; if (view != null) { - final ViewPropertyAnimator oldViewAnim = view.animate().setDuration( - getChangeDuration()); + final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(getChangeRemoveDuration()).setStartDelay(getChangeDelay()); mChangeAnimations.add(changeInfo.oldHolder); oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); @@ -419,7 +428,8 @@ public class DefaultItemAnimator extends SimpleItemAnimator { if (newView != null) { final ViewPropertyAnimator newViewAnimation = newView.animate(); mChangeAnimations.add(changeInfo.newHolder); - newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()) + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeAddDuration()) + .setStartDelay(getChangeDelay() + (getChangeDuration() - getChangeAddDuration())) .alpha(1).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { @@ -713,6 +723,14 @@ public class DefaultItemAnimator extends SimpleItemAnimator { } } + public boolean isHolderRemoving(RecyclerView.ViewHolder holder) { + return mRemoveAnimations.contains(holder); + } + + public boolean isHolderAdding(RecyclerView.ViewHolder holder) { + return mAddAnimations.contains(holder); + } + /** * {@inheritDoc} *

diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java index 0ac777d20..c89753e40 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/GapWorker.java @@ -21,6 +21,9 @@ import android.view.View; import androidx.annotation.Nullable; import androidx.core.os.TraceCompat; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -274,6 +277,7 @@ final class GapWorker implements Runnable { return false; } + @SuppressLint("NotifyDataSetChanged") private RecyclerView.ViewHolder prefetchPositionWithDeadline(RecyclerView view, int position, long deadlineNs) { if (isPrefetchPositionAttached(view, position)) { @@ -301,6 +305,14 @@ final class GapWorker implements Runnable { recycler.addViewHolderToRecycledViewPool(holder, false); } } + } catch (Exception e) { + FileLog.e(e); + AndroidUtilities.runOnUIThread(() -> { + if (view.getAdapter() != null) { + view.getAdapter().notifyDataSetChanged(); + } + }); + return null; } finally { view.onExitLayoutOrScroll(false); } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java index a8a8085bb..fab3e6e7f 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java @@ -22,6 +22,7 @@ import static androidx.core.view.ViewCompat.TYPE_NON_TOUCH; import static androidx.core.view.ViewCompat.TYPE_TOUCH; import android.animation.LayoutTransition; +import android.animation.TimeInterpolator; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.Resources; @@ -12720,7 +12721,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView, private long mAddDuration = 120; private long mRemoveDuration = 120; private long mMoveDuration = 250; - private long mChangeDuration = 250; + private long mChangeAddDuration = 250; + private long mChangeRemoveDuration = 250; + + private TimeInterpolator mMoveInterpolator = null; + + private long mAddDelay = 0; + private long mRemoveDelay = 0; + private long mMoveDelay = 0; + private long mDelay = 0; + private long mChangeDelay = 0; /** * Gets the current duration for which all move animations will run. @@ -12776,13 +12786,31 @@ public class RecyclerView extends ViewGroup implements ScrollingView, mRemoveDuration = removeDuration; } + /** + * Gets the current duration for which all change animations of item appearance + * + * @return The current change duration + */ + public long getChangeAddDuration() { + return mChangeAddDuration; + } + /** * Gets the current duration for which all change animations will run. * * @return The current change duration */ public long getChangeDuration() { - return mChangeDuration; + return Math.max(mChangeAddDuration, mChangeRemoveDuration); + } + + /** + * Gets the current duration for which all change animations of item disappearance + * + * @return The current change duration + */ + public long getChangeRemoveDuration() { + return mChangeRemoveDuration; } /** @@ -12791,7 +12819,68 @@ public class RecyclerView extends ViewGroup implements ScrollingView, * @param changeDuration The change duration */ public void setChangeDuration(long changeDuration) { - mChangeDuration = changeDuration; + mChangeAddDuration = changeDuration; + mChangeRemoveDuration = changeDuration; + } + + /** + * Sets the duration for which all change animations will run. + * + * @param changeNewDuration The duration of showing new view of change + * @param changeOldDuration The duration of hiding old view of change + */ + public void setChangeDuration(long changeNewDuration, long changeOldDuration) { + mChangeAddDuration = changeNewDuration; + mChangeRemoveDuration = changeOldDuration; + } + + + public void setAddDelay(long addDelay) { + mAddDelay = addDelay; + } + + public void setRemoveDelay(long removeDelay) { + mRemoveDelay = removeDelay; + } + + public void setMoveDelay(long moveDelay) { + mMoveDelay = moveDelay; + } + + public void setChangeDelay(long changeDelay) { + mChangeDelay = changeDelay; + } + + public long getAddDelay() { + return mAddDelay; + } + + public long getRemoveDelay() { + return mRemoveDelay; + } + + public long getMoveDelay() { + return mMoveDelay; + } + + public long getChangeDelay() { + return mChangeDelay; + } + + public void setDurations(long duration) { + mAddDuration = duration; + mMoveDuration = duration; + mRemoveDuration = duration; + mChangeAddDuration = duration; + mChangeRemoveDuration = duration; + } + + public void setMoveInterpolator(TimeInterpolator interpolator) { + mMoveInterpolator = interpolator; + } + + public TimeInterpolator getMoveInterpolator() { + return mMoveInterpolator; } /** diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java index dee9cfb9b..6ebcae4db 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/SimpleItemAnimator.java @@ -40,6 +40,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { boolean mSupportsChangeAnimations = true; protected boolean alwaysCreateMoveAnimationIfPossible; + protected boolean disabledMoveAnimations; /** * Returns whether this ItemAnimator supports animations of change events. @@ -93,7 +94,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { View disappearingItemView = viewHolder.itemView; int newLeft = postLayoutInfo == null ? disappearingItemView.getLeft() : postLayoutInfo.left; int newTop = postLayoutInfo == null ? disappearingItemView.getTop() : postLayoutInfo.top; - if (!viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) { + if (!disabledMoveAnimations && !viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) { disappearingItemView.layout(newLeft, newTop, newLeft + disappearingItemView.getWidth(), newTop + disappearingItemView.getHeight()); @@ -114,7 +115,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { @Override public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) { - if (preLayoutInfo != null && ((preLayoutInfo.left != postLayoutInfo.left + if (!disabledMoveAnimations && preLayoutInfo != null && ((preLayoutInfo.left != postLayoutInfo.left || preLayoutInfo.top != postLayoutInfo.top) || alwaysCreateMoveAnimationIfPossible)) { // slide items in if before/after locations differ if (DEBUG) { @@ -133,7 +134,7 @@ public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { @Override public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) { - if (preInfo.left != postInfo.left || preInfo.top != postInfo.top) { + if (!disabledMoveAnimations && (preInfo.left != postInfo.left || preInfo.top != postInfo.top)) { if (DEBUG) { Log.d(TAG, "PERSISTENT: " + viewHolder + " with view " + viewHolder.itemView); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index ddd125d1e..884342f5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -49,6 +49,7 @@ import android.os.Build; import android.os.Environment; import android.os.PowerManager; import android.os.SystemClock; +import android.os.Vibrator; import android.provider.CallLog; import android.provider.DocumentsContract; import android.provider.MediaStore; @@ -76,6 +77,7 @@ import android.view.MotionEvent; import android.view.Surface; import android.view.TextureView; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.Window; import android.view.WindowInsets; @@ -90,12 +92,14 @@ import android.view.inputmethod.InputMethodSubtype; import android.webkit.MimeTypeMap; import android.widget.EdgeEffect; import android.widget.HorizontalScrollView; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; @@ -162,6 +166,7 @@ import java.util.Hashtable; import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -187,7 +192,10 @@ import static com.v2ray.ang.V2RayConfig.WS_PROTOCOL; public class AndroidUtilities { public final static int LIGHT_STATUS_BAR_OVERLAY = 0x0f000000, DARK_STATUS_BAR_OVERLAY = 0x33000000; + public final static String TYPEFACE_ROBOTO_MEDIUM = "fonts/rmedium.ttf"; + private static final Hashtable typefaceCache = new Hashtable<>(); + public static float touchSlop; private static int prevOrientation = -10; private static boolean waitingForSms = false; private static boolean waitingForCall = false; @@ -215,6 +223,7 @@ public class AndroidUtilities { public static OvershootInterpolator overshootInterpolator = new OvershootInterpolator(); private static AccessibilityManager accessibilityManager; + private static Vibrator vibrator; private static Boolean isTablet = null, isSmallScreen = null; private static int adjustOwnerClassGuid = 0; @@ -453,6 +462,23 @@ public class AndroidUtilities { return spannableStringBuilder; } + public static void recycleBitmaps(ArrayList bitmapToRecycle) { + if (bitmapToRecycle != null && !bitmapToRecycle.isEmpty()) { + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getInstance(UserConfig.selectedAccount).doOnIdle(() -> { + for (int i = 0; i < bitmapToRecycle.size(); i++) { + Bitmap bitmap = bitmapToRecycle.get(i); + if (bitmap != null && !bitmap.isRecycled()) { + try { + bitmap.recycle(); + } catch (Exception e) { + FileLog.e(e); + } + } + } + }), 36); + } + } + private static class LinkSpec { String url; int start; @@ -572,7 +598,7 @@ public class AndroidUtilities { Linkify.addLinks(text, Linkify.PHONE_NUMBERS); } if ((mask & Linkify.WEB_URLS) != 0) { - gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://"}, sUrlMatchFilter, internalOnly); + gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "tg://"}, sUrlMatchFilter, internalOnly); } pruneOverlaps(links); if (links.size() == 0) { @@ -904,10 +930,17 @@ public class AndroidUtilities { } public static void requestAdjustResize(Activity activity, int classGuid) { - if (activity == null || isTablet()) { + if (activity == null) { return; } - activity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); + requestAdjustResize(activity.getWindow(), classGuid); + } + + public static void requestAdjustResize(Window window, int classGuid) { + if (window == null || isTablet()) { + return; + } + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); adjustOwnerClassGuid = classGuid; } @@ -1846,6 +1879,8 @@ public class AndroidUtilities { } FileLog.e("density = " + density + " display size = " + displaySize.x + " " + displaySize.y + " " + displayMetrics.xdpi + "x" + displayMetrics.ydpi + ", screen layout: " + configuration.screenLayout + ", statusbar height: " + statusBarHeight + ", navbar height: " + navigationBarHeight); } + ViewConfiguration vc = ViewConfiguration.get(context); + touchSlop = vc.getScaledTouchSlop(); } catch (Exception e) { FileLog.e(e); } @@ -2638,8 +2673,13 @@ public class AndroidUtilities { public static File generatePicturePath(boolean secretChat, String ext) { try { - File storageDir = ApplicationLoader.applicationContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES); - return new File(storageDir, generateFileName(0, ext)); + File publicDir = FileLoader.getDirectory(FileLoader.MEDIA_DIR_IMAGE_PUBLIC); + if (secretChat || publicDir == null) { + File storageDir = ApplicationLoader.applicationContext.getExternalFilesDir(Environment.DIRECTORY_PICTURES); + return new File(storageDir, generateFileName(0, ext)); + } else { + return new File(publicDir, generateFileName(0, ext)); + } } catch (Exception e) { FileLog.e(e); } @@ -2765,11 +2805,11 @@ public class AndroidUtilities { return String.format("%.1f MB", value); } } else { - float value = size / 1024.0f / 1024.0f / 1024.0f; + float value = (int) (size / 1024L / 1024L) / 1000.0f; if (removeZero && (value - (int) value) * 10 == 0) { return String.format("%d GB", (int) value); } else { - return String.format("%.1f GB", value); + return String.format("%.2f GB", value); } } } @@ -3013,7 +3053,7 @@ public class AndroidUtilities { f = new File(message.messageOwner.attachPath); } if (f == null || f != null && !f.exists()) { - f = FileLoader.getPathToMessage(message.messageOwner); + f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToMessage(message.messageOwner); } if (f != null && f.exists()) { if (parentFragment != null && f.getName().toLowerCase().endsWith("attheme")) { @@ -3136,7 +3176,7 @@ public class AndroidUtilities { f = new File(message.messageOwner.attachPath); } if (f == null || !f.exists()) { - f = FileLoader.getPathToMessage(message.messageOwner); + f = FileLoader.getInstance(message.currentAccount).getPathToMessage(message.messageOwner); } String mimeType = message.type == 9 || message.type == 0 ? message.getMimeType() : null; return openForView(f, message.getFileName(), mimeType, activity, resourcesProvider); @@ -3144,7 +3184,7 @@ public class AndroidUtilities { public static boolean openForView(TLRPC.Document document, boolean forceCache, Activity activity) { String fileName = FileLoader.getAttachFileName(document); - File f = FileLoader.getPathToAttach(document, true); + File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); return openForView(f, fileName, document.mime_type, activity, null); } @@ -3225,7 +3265,7 @@ public class AndroidUtilities { return false; } String fileName = FileLoader.getAttachFileName(media); - File f = FileLoader.getPathToAttach(media, true); + File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(media, true); if (f != null && f.exists()) { String realMimeType = null; Intent intent = new Intent(Intent.ACTION_VIEW); @@ -3331,6 +3371,13 @@ public class AndroidUtilities { } } + public static Vibrator getVibrator() { + if (vibrator == null) { + vibrator = (Vibrator) ApplicationLoader.applicationContext.getSystemService(Context.VIBRATOR_SERVICE); + } + return vibrator; + } + public static boolean isAccessibilityTouchExplorationEnabled() { if (accessibilityManager == null) { accessibilityManager = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); @@ -4414,6 +4461,10 @@ public class AndroidUtilities { } } + public static float computeDampingRatio(float tension /* stiffness */, float friction /* damping */, float mass) { + return friction / (2f * (float) Math.sqrt(mass * tension)); + } + private static WeakReference flagSecureFragment; public static boolean hasFlagSecureFragment() { @@ -4763,11 +4814,34 @@ public class AndroidUtilities { } } + public static void updateImageViewImageAnimated(ImageView imageView, int newIcon) { + updateImageViewImageAnimated(imageView, ContextCompat.getDrawable(imageView.getContext(), newIcon)); + } + + public static void updateImageViewImageAnimated(ImageView imageView, Drawable newIcon) { + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(150); + AtomicBoolean changed = new AtomicBoolean(); + animator.addUpdateListener(animation -> { + float val = (float) animation.getAnimatedValue(); + float scale = 0.5f + Math.abs(val - 0.5f); + imageView.setScaleX(scale); + imageView.setScaleY(scale); + if (val >= 0.5f && !changed.get()) { + changed.set(true); + imageView.setImageDrawable(newIcon); + } + }); + animator.start(); + } + public static void updateViewVisibilityAnimated(View view, boolean show) { updateViewVisibilityAnimated(view, show, 1f, true); } public static void updateViewVisibilityAnimated(View view, boolean show, float scaleFactor, boolean animated) { + if (view == null) { + return; + } if (view.getParent() == null) { animated = false; } @@ -4883,4 +4957,14 @@ public class AndroidUtilities { return false; } } + + public static boolean isAccessibilityScreenReaderEnabled() { + return false; +// try { +// AccessibilityManager am = (AccessibilityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACCESSIBILITY_SERVICE); +// return (am != null && am.isEnabled() && !am.isTouchExplorationEnabled()); +// } catch (Exception ignroe) { +// return false; +// } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java index f112cd774..1e0841698 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AnimatedFileDrawableStream.java @@ -14,7 +14,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { private int currentAccount; private volatile boolean canceled; private final Object sync = new Object(); - private int lastOffset; + private long lastOffset; private boolean waitingForLoad; private boolean preview; private boolean finishedLoadingFile; @@ -48,10 +48,10 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { if (readLength == 0) { return 0; } else { - int availableLength = 0; + long availableLength = 0; try { while (availableLength == 0) { - int[] result = loadOperation.getDownloadedLengthFromOffset(offset, readLength); + long[] result = loadOperation.getDownloadedLengthFromOffset(offset, readLength); availableLength = result[0]; if (!finishedLoadingFile && result[1] != 0) { finishedLoadingFile = true; @@ -79,7 +79,7 @@ public class AnimatedFileDrawableStream implements FileLoadOperationStream { } catch (Exception e) { FileLog.e(e, false); } - return availableLength; + return (int) availableLength; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java index 6cf07df7a..505cffa04 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java @@ -41,6 +41,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.ForegroundDetector; +import org.telegram.ui.LauncherIconController; import java.io.File; import java.lang.reflect.Method; @@ -388,7 +389,7 @@ public class ApplicationLoader extends Application { org.osmdroid.config.Configuration.getInstance().setOsmdroidBasePath(new File(ApplicationLoader.applicationContext.getCacheDir(), "osmdroid")); startPushService(); - +LauncherIconController.tryFixLauncherIconIfNeeded(); } public static void startPushService() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java b/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java index 069396e19..1affa94f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BaseController.java @@ -4,7 +4,7 @@ import org.telegram.tgnet.ConnectionsManager; public class BaseController { - public int currentAccount; + protected final int currentAccount; private AccountInstance parentAccountInstance; public BaseController(int num) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BotWebViewVibrationEffect.java b/TMessagesProj/src/main/java/org/telegram/messenger/BotWebViewVibrationEffect.java new file mode 100644 index 000000000..3c2bced83 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BotWebViewVibrationEffect.java @@ -0,0 +1,42 @@ +package org.telegram.messenger; + +import android.os.Build; +import android.os.VibrationEffect; + +import androidx.annotation.RequiresApi; + +public enum BotWebViewVibrationEffect { + IMPACT_LIGHT(new long[] {7}, new int[] {65}, new long[] {50}), + IMPACT_MEDIUM(new long[] {7}, new int[] {145}, new long[] {50}), + IMPACT_HEAVY(new long[] {7}, new int[] {255}, new long[] {50}), + IMPACT_RIGID(new long[] {3}, new int[] {225}, new long[] {50}), + IMPACT_SOFT(new long[] {10}, new int[] {175}, new long[] {50}), + NOTIFICATION_ERROR(new long[] {14,48,14,48,14,48,20}, new int[] {200,0,200,0,255,0,145}, new long[] {50}), + NOTIFICATION_SUCCESS(new long[] {14,65,14}, new int[] {175,0,255}, new long[] {50}), + NOTIFICATION_WARNING(new long[] {14,64,14}, new int[] {225,0,175}, new long[] {50}), + SELECTION_CHANGE(new long[] {1}, new int[] {65}, new long[] {50}); + + public final long[] timings; + public final int[] amplitudes; + public final long[] fallbackTimings; + private Object vibrationEffect; + + BotWebViewVibrationEffect(long[] timings, int[] amplitudes, long[] fallbackTimings) { + this.timings = timings; + this.amplitudes = amplitudes; + this.fallbackTimings = fallbackTimings; + } + + @RequiresApi(Build.VERSION_CODES.O) + public VibrationEffect getVibrationEffectForOreo() { + if (vibrationEffect == null) { + if (!AndroidUtilities.getVibrator().hasAmplitudeControl()) { + vibrationEffect = VibrationEffect.createWaveform(fallbackTimings, -1); + } else { + vibrationEffect = VibrationEffect.createWaveform(timings, amplitudes, -1); + } + } + + return (VibrationEffect) vibrationEffect; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 018c1ae99..8847c74f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -17,6 +17,7 @@ import android.os.Build; @SuppressWarnings("ConstantConditions") public class BuildVars { + public static final boolean IS_BILLING_UNAVAILABLE = false; public static boolean DEBUG_VERSION = BuildConfig.BUILD_TYPE.equals("debug"); public static boolean DEBUG_PRIVATE_VERSION = DEBUG_VERSION; public static boolean LOGS_ENABLED = DEBUG_PRIVATE_VERSION; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java index e3b0ef2f5..049df5404 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ChatsWidgetService.java @@ -21,6 +21,8 @@ import android.view.View; import android.widget.RemoteViews; import android.widget.RemoteViewsService; +import androidx.collection.LongSparseArray; + import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AvatarDrawable; @@ -30,8 +32,6 @@ import org.telegram.ui.EditWidgetActivity; import java.io.File; import java.util.ArrayList; -import androidx.collection.LongSparseArray; - public class ChatsWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { @@ -132,7 +132,7 @@ class ChatsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory { try { Bitmap bitmap = null; if (photoPath != null) { - File path = FileLoader.getPathToAttach(photoPath, true); + File path = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoPath, true); bitmap = BitmapFactory.decodeFile(path.toString()); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsWidgetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsWidgetService.java index 2a618dbbe..41dd23557 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsWidgetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsWidgetService.java @@ -18,6 +18,8 @@ import android.view.View; import android.widget.RemoteViews; import android.widget.RemoteViewsService; +import androidx.collection.LongSparseArray; + import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.AvatarDrawable; @@ -26,8 +28,6 @@ import org.telegram.ui.EditWidgetActivity; import java.io.File; import java.util.ArrayList; -import androidx.collection.LongSparseArray; - public class ContactsWidgetService extends RemoteViewsService { @Override public RemoteViewsFactory onGetViewFactory(Intent intent) { @@ -135,7 +135,7 @@ class ContactsRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactor try { Bitmap bitmap = null; if (photoPath != null) { - File path = FileLoader.getPathToAttach(photoPath, true); + File path = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoPath, true); bitmap = BitmapFactory.decodeFile(path.toString()); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java index 0713aa91c..d57bdaa58 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueue.java @@ -52,7 +52,7 @@ public class DispatchQueue extends Thread { syncLatch.await(); handler.removeCallbacks(runnable); } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } } @@ -63,7 +63,7 @@ public class DispatchQueue extends Thread { handler.removeCallbacks(runnables[i]); } } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } } @@ -76,7 +76,7 @@ public class DispatchQueue extends Thread { try { syncLatch.await(); } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } if (delay <= 0) { return handler.post(runnable); @@ -90,7 +90,7 @@ public class DispatchQueue extends Thread { syncLatch.await(); handler.removeCallbacksAndMessages(null); } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } } @@ -109,12 +109,10 @@ public class DispatchQueue extends Thread { @Override public void run() { Looper.prepare(); - handler = new Handler() { - @Override - public void handleMessage(Message msg) { - DispatchQueue.this.handleMessage(msg); - } - }; + handler = new Handler(Looper.myLooper(), msg -> { + DispatchQueue.this.handleMessage(msg); + return true; + }); syncLatch.countDown(); Looper.loop(); } @@ -122,4 +120,8 @@ public class DispatchQueue extends Thread { public boolean isReady() { return syncLatch.getCount() == 0; } + + public Handler getHandler() { + return handler; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueueMainThreadSync.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueueMainThreadSync.java new file mode 100644 index 000000000..7d9e310a0 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueueMainThreadSync.java @@ -0,0 +1,169 @@ +package org.telegram.messenger; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.SystemClock; + +import java.util.ArrayList; + +public class DispatchQueueMainThreadSync extends Thread { + + private volatile Handler handler = null; + private boolean isRunning; + private boolean isRecycled; + private long lastTaskTime; + private static int indexPointer = 0; + public final int index = indexPointer++; + private ArrayList postponedTasks = new ArrayList<>(); + + public DispatchQueueMainThreadSync(final String threadName) { + this(threadName, true); + } + + public DispatchQueueMainThreadSync(final String threadName, boolean start) { + setName(threadName); + if (start) { + start(); + } + } + + public void sendMessage(Message msg, int delay) { + checkThread(); + if (isRecycled) { + return; + } + if (!isRunning) { + postponedTasks.add(new PostponedTask(msg, delay)); + return; + } + if (delay <= 0) { + handler.sendMessage(msg); + } else { + handler.sendMessageDelayed(msg, delay); + } + } + + private void checkThread() { + if (BuildVars.DEBUG_PRIVATE_VERSION && Thread.currentThread() != ApplicationLoader.applicationHandler.getLooper().getThread()) { + throw new IllegalStateException("Disaptch thread"); + } + } + + public void cancelRunnable(Runnable runnable) { + checkThread(); + if (isRunning) { + handler.removeCallbacks(runnable); + } else { + for (int i = 0; i < postponedTasks.size(); i++) { + if (postponedTasks.get(i).runnable == runnable) { + postponedTasks.remove(i); + i--; + } + } + } + } + + public void cancelRunnables(Runnable[] runnables) { + checkThread(); + for (int i = 0; i < runnables.length; i++) { + cancelRunnable(runnables[i]); + } + } + + public boolean postRunnable(Runnable runnable) { + checkThread(); + lastTaskTime = SystemClock.elapsedRealtime(); + return postRunnable(runnable, 0); + } + + public boolean postRunnable(Runnable runnable, long delay) { + checkThread(); + if (isRecycled) { + return false; + } + if (!isRunning) { + postponedTasks.add(new PostponedTask(runnable, delay)); + return true; + } + if (delay <= 0) { + return handler.post(runnable); + } else { + return handler.postDelayed(runnable, delay); + } + } + + public void cleanupQueue() { + checkThread(); + postponedTasks.clear(); + handler.removeCallbacksAndMessages(null); + } + + public void handleMessage(Message inputMessage) { + + } + + public long getLastTaskTime() { + return lastTaskTime; + } + + public void recycle() { + checkThread(); + postRunnable(() -> { + handler.getLooper().quit(); + }); + isRecycled = true; + } + + @Override + public void run() { + Looper.prepare(); + handler = new Handler(Looper.myLooper(), msg -> { + DispatchQueueMainThreadSync.this.handleMessage(msg); + return true; + }); + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + isRunning = true; + for (int i = 0; i < postponedTasks.size(); i++) { + postponedTasks.get(i).run(); + } + postponedTasks.clear(); + } + }); + Looper.loop(); + } + + public boolean isReady() { + return isRunning; + } + + public Handler getHandler() { + return handler; + } + + private class PostponedTask { + Message message; + Runnable runnable; + long delay; + + public PostponedTask(Message msg, int delay) { + this.message = msg; + this.delay = delay; + } + + public PostponedTask(Runnable runnable, long delay) { + this.runnable = runnable; + this.delay = delay; + } + + public void run() { + if (runnable != null) { + postRunnable(runnable, delay); + } else { + sendMessage(message, (int) delay); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolMainThreadSync.java b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolMainThreadSync.java new file mode 100644 index 000000000..6f0a924ae --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DispatchQueuePoolMainThreadSync.java @@ -0,0 +1,86 @@ +package org.telegram.messenger; + +import android.os.SystemClock; +import android.util.SparseIntArray; + +import androidx.annotation.UiThread; + +import java.util.LinkedList; + +public class DispatchQueuePoolMainThreadSync { + + private LinkedList queues = new LinkedList<>(); + private SparseIntArray busyQueuesMap = new SparseIntArray(); + private LinkedList busyQueues = new LinkedList<>(); + private int maxCount; + private int createdCount; + private int guid; + private int totalTasksCount; + private boolean cleanupScheduled; + + private Runnable cleanupRunnable = new Runnable() { + @Override + public void run() { + if (!queues.isEmpty()) { + long currentTime = SystemClock.elapsedRealtime(); + for (int a = 0, N = queues.size(); a < N; a++) { + DispatchQueueMainThreadSync queue = queues.get(a); + if (queue.getLastTaskTime() < currentTime - 30000) { + queue.recycle(); + queues.remove(a); + createdCount--; + a--; + N--; + } + } + } + if (!queues.isEmpty() || !busyQueues.isEmpty()) { + AndroidUtilities.runOnUIThread(this, 30000); + cleanupScheduled = true; + } else { + cleanupScheduled = false; + } + } + }; + + public DispatchQueuePoolMainThreadSync(int count) { + maxCount = count; + guid = Utilities.random.nextInt(); + } + + @UiThread + public void execute(Runnable runnable) { + DispatchQueueMainThreadSync queue; + if (!busyQueues.isEmpty() && (totalTasksCount / 2 <= busyQueues.size() || queues.isEmpty() && createdCount >= maxCount)) { + queue = busyQueues.remove(0); + } else if (queues.isEmpty()) { + queue = new DispatchQueueMainThreadSync("DispatchQueuePool" + guid + "_" + Utilities.random.nextInt()); + queue.setPriority(Thread.MAX_PRIORITY); + createdCount++; + } else { + queue = queues.remove(0); + } + if (!cleanupScheduled) { + AndroidUtilities.runOnUIThread(cleanupRunnable, 30000); + cleanupScheduled = true; + } + totalTasksCount++; + busyQueues.add(queue); + int count = busyQueuesMap.get(queue.index, 0); + busyQueuesMap.put(queue.index, count + 1); + queue.postRunnable(() -> { + runnable.run(); + AndroidUtilities.runOnUIThread(() -> { + totalTasksCount--; + int remainingTasksCount = busyQueuesMap.get(queue.index) - 1; + if (remainingTasksCount == 0) { + busyQueuesMap.delete(queue.index); + busyQueues.remove(queue); + queues.add(queue); + } else { + busyQueuesMap.put(queue.index, remainingTasksCount); + } + }); + }); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java index 2380061f2..035925401 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DownloadController.java @@ -85,14 +85,14 @@ public class DownloadController extends BaseController implements NotificationCe public static class Preset { public int[] mask = new int[4]; - public int[] sizes = new int[4]; + public long[] sizes = new long[4]; public boolean preloadVideo; public boolean preloadMusic; public boolean lessCallData; public boolean enabled; public int maxVideoBitrate; - public Preset(int[] m, int p, int v, int f, boolean pv, boolean pm, boolean e, boolean l, int bitrate) { + public Preset(int[] m, long p, long v, long f, boolean pv, boolean pm, boolean e, boolean l, int bitrate) { System.arraycopy(m, 0, mask, 0, mask.length); sizes[PRESET_SIZE_NUM_PHOTO] = p; sizes[PRESET_SIZE_NUM_VIDEO] = v; @@ -261,9 +261,9 @@ public class DownloadController extends BaseController implements NotificationCe int[] mobileDataDownloadMask = new int[4]; int[] wifiDownloadMask = new int[4]; int[] roamingDownloadMask = new int[4]; - int[] mobileMaxFileSize = new int[7]; - int[] wifiMaxFileSize = new int[7]; - int[] roamingMaxFileSize = new int[7]; + long[] mobileMaxFileSize = new long[7]; + long[] wifiMaxFileSize = new long[7]; + long[] roamingMaxFileSize = new long[7]; for (int a = 0; a < 4; a++) { String key = "mobileDataDownloadMask" + (a == 0 ? "" : a); @@ -278,12 +278,12 @@ public class DownloadController extends BaseController implements NotificationCe } } - mobileMaxFileSize[2] = preferences.getInt("mobileMaxDownloadSize" + 2, mediumPreset.sizes[PRESET_SIZE_NUM_VIDEO]); - mobileMaxFileSize[3] = preferences.getInt("mobileMaxDownloadSize" + 3, mediumPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); - wifiMaxFileSize[2] = preferences.getInt("wifiMaxDownloadSize" + 2, highPreset.sizes[PRESET_SIZE_NUM_VIDEO]); - wifiMaxFileSize[3] = preferences.getInt("wifiMaxDownloadSize" + 3, highPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); - roamingMaxFileSize[2] = preferences.getInt("roamingMaxDownloadSize" + 2, lowPreset.sizes[PRESET_SIZE_NUM_VIDEO]); - roamingMaxFileSize[3] = preferences.getInt("roamingMaxDownloadSize" + 3, lowPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); + mobileMaxFileSize[2] = preferences.getLong("mobileMaxDownloadSize" + 2, mediumPreset.sizes[PRESET_SIZE_NUM_VIDEO]); + mobileMaxFileSize[3] = preferences.getLong("mobileMaxDownloadSize" + 3, mediumPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); + wifiMaxFileSize[2] = preferences.getLong("wifiMaxDownloadSize" + 2, highPreset.sizes[PRESET_SIZE_NUM_VIDEO]); + wifiMaxFileSize[3] = preferences.getLong("wifiMaxDownloadSize" + 3, highPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); + roamingMaxFileSize[2] = preferences.getLong("roamingMaxDownloadSize" + 2, lowPreset.sizes[PRESET_SIZE_NUM_VIDEO]); + roamingMaxFileSize[3] = preferences.getLong("roamingMaxDownloadSize" + 3, lowPreset.sizes[PRESET_SIZE_NUM_DOCUMENT]); boolean globalAutodownloadEnabled = preferences.getBoolean("globalAutodownloadEnabled", true); mobilePreset = new Preset(mobileDataDownloadMask, mediumPreset.sizes[PRESET_SIZE_NUM_PHOTO], mobileMaxFileSize[2], mobileMaxFileSize[3], true, true, globalAutodownloadEnabled, false, 100); @@ -596,7 +596,7 @@ public class DownloadController extends BaseController implements NotificationCe return canDownloadMedia(messageObject.messageOwner) == 1; } - public boolean canDownloadMedia(int type, int size) { + public boolean canDownloadMedia(int type, long size) { Preset preset; int networkType = ApplicationLoader.getAutodownloadNetworkType(); if (networkType == StatsController.TYPE_WIFI) { @@ -617,7 +617,7 @@ public class DownloadController extends BaseController implements NotificationCe preset = getCurrentMobilePreset(); } int mask = preset.mask[1]; - int maxSize = preset.sizes[typeToIndex(type)]; + long maxSize = preset.sizes[typeToIndex(type)]; return (type == AUTODOWNLOAD_TYPE_PHOTO || size != 0 && size <= maxSize) && (type == AUTODOWNLOAD_TYPE_AUDIO || (mask & type) != 0); } @@ -688,13 +688,13 @@ public class DownloadController extends BaseController implements NotificationCe preset = getCurrentMobilePreset(); } int mask = preset.mask[index]; - int maxSize; + long maxSize; if (type == AUTODOWNLOAD_TYPE_AUDIO) { maxSize = Math.max(512 * 1024, preset.sizes[typeToIndex(type)]); } else { maxSize = preset.sizes[typeToIndex(type)]; } - int size = MessageObject.getMessageSize(message); + long size = MessageObject.getMessageSize(message); if (isVideo && preset.preloadVideo && size > maxSize && maxSize > 2 * 1024 * 1024) { return (mask & type) != 0 ? 2 : 0; } else { @@ -782,7 +782,7 @@ public class DownloadController extends BaseController implements NotificationCe break; } } - req.settings.photo_size_max = photo ? preset.sizes[PRESET_SIZE_NUM_PHOTO] : 0; + req.settings.photo_size_max = photo ? (int) preset.sizes[PRESET_SIZE_NUM_PHOTO] : 0; req.settings.video_size_max = video ? preset.sizes[PRESET_SIZE_NUM_VIDEO] : 0; req.settings.file_size_max = document ? preset.sizes[PRESET_SIZE_NUM_DOCUMENT] : 0; getConnectionsManager().sendRequest(req, (response, error) -> { @@ -1128,7 +1128,7 @@ public class DownloadController extends BaseController implements NotificationCe boolean contains = false; for (int i = 0; i < recentDownloadingFiles.size(); i++) { - if (recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) { + if (recentDownloadingFiles.get(i).getDocument() != null && recentDownloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) { contains = true; break; } @@ -1136,7 +1136,7 @@ public class DownloadController extends BaseController implements NotificationCe if (!contains) { for (int i = 0; i < downloadingFiles.size(); i++) { - if (downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) { + if (downloadingFiles.get(i).getDocument() != null && downloadingFiles.get(i).getDocument().id == parentObject.getDocument().id) { contains = true; break; } @@ -1318,7 +1318,7 @@ public class DownloadController extends BaseController implements NotificationCe getMessagesStorage().getStorageQueue().postRunnable(() -> { ArrayList downloadingMessages = new ArrayList<>(); ArrayList recentlyDownloadedMessages = new ArrayList<>(); - + ArrayList newMessages = new ArrayList<>(); try { SQLiteCursor cursor2 = getMessagesStorage().getDatabase().queryFinalized("SELECT data, state FROM downloading_documents ORDER BY date DESC"); while (cursor2.next()) { @@ -1328,10 +1328,11 @@ public class DownloadController extends BaseController implements NotificationCe TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false); if (message != null) { message.readAttachPath(data, UserConfig.getInstance(currentAccount).clientUserId); - MessageObject messageObject = new MessageObject(currentAccount, message, false, true); + MessageObject messageObject = new MessageObject(currentAccount, message, false, false); + newMessages.add(messageObject); if (state == 0) { downloadingMessages.add(messageObject); - } else if (messageObject.mediaExists) { + } else { recentlyDownloadedMessages.add(messageObject); } } @@ -1343,6 +1344,9 @@ public class DownloadController extends BaseController implements NotificationCe FileLog.e(e); } + getFileLoader().checkMediaExistance(downloadingMessages); + getFileLoader().checkMediaExistance(recentlyDownloadedMessages); + AndroidUtilities.runOnUIThread(() -> { downloadingFiles.clear(); downloadingFiles.addAll(downloadingMessages); @@ -1400,7 +1404,7 @@ public class DownloadController extends BaseController implements NotificationCe state.step(); try { - File file = FileLoader.getPathToMessage(messageObjects.get(i).messageOwner); + File file = FileLoader.getInstance(currentAccount).getPathToMessage(messageObjects.get(i).messageOwner); file.delete(); } catch (Exception e) { FileLog.e(e); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java index 1dbcf26bf..a4150bd4e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Emoji.java @@ -30,10 +30,12 @@ import android.widget.TextView; import java.io.File; import java.io.InputStream; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Locale; +import java.util.concurrent.atomic.AtomicReference; import java.io.File; import java.io.FileInputStream; @@ -121,20 +123,6 @@ public class Emoji { scale = 2.0f; } - String imageName; - File imageFile; - - try { - for (int a = 13; a < 16; a++) { - imageName = String.format(Locale.US, "v%d_emoji%.01fx_%d.png", a, scale, page); - imageFile = ApplicationLoader.applicationContext.getFileStreamPath(imageName); - if (imageFile.exists()) { - imageFile.delete(); - } - } - } catch (Exception e) { - FileLog.e(e); - } Bitmap bitmap = null; try { InputStream is; @@ -262,9 +250,10 @@ public class Emoji { public static class EmojiDrawable extends Drawable { private DrawableInfo info; private boolean fullSize = false; - private static Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); - private static Rect rect = new Rect(); - private static TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + private static final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); + private static final Rect rect = new Rect(); + private static final TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + public int placeholderColor = 0x20000000; public EmojiDrawable(DrawableInfo i) { info = i; @@ -288,7 +277,9 @@ public class Emoji { public void draw(Canvas canvas) { if (!isLoaded()) { loadEmoji(info.page, info.page2); - canvas.drawRect(getBounds(), placeholderPaint); + placeholderPaint.setColor(placeholderColor); + Rect bounds = getBounds(); + canvas.drawCircle(bounds.centerX(), bounds.centerY(), bounds.width() * .4f, placeholderPaint); return; } @@ -377,37 +368,41 @@ public class Emoji { return false; } - public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew) { - return replaceEmoji(cs, fontMetrics, size, createNew, null); + public static class EmojiSpanRange { + public EmojiSpanRange(int start, int end, CharSequence code) { + this.start = start; + this.end = end; + this.code = code; + } + int start; + int end; + CharSequence code; } - public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly) { - if (cs == null || cs.length() == 0) { - return cs; - } - Spannable s; - if (!createNew && cs instanceof Spannable) { - s = (Spannable) cs; - } else { - s = Spannable.Factory.getInstance().newSpannable(cs.toString()); + public static boolean fullyConsistsOfEmojis(CharSequence cs) { + int[] emojiOnly = new int[1]; + parseEmojis(cs, emojiOnly); + return emojiOnly[0] > 0; + } + + public static ArrayList parseEmojis(CharSequence cs) { + return parseEmojis(cs, null); + } + + public static ArrayList parseEmojis(CharSequence cs, int[] emojiOnly) { + ArrayList emojis = new ArrayList<>(); + if (cs == null || cs.length() <= 0) { + return emojis; } long buf = 0; - int emojiCount = 0; char c; int startIndex = -1; int startLength = 0; int previousGoodIndex = 0; StringBuilder emojiCode = new StringBuilder(16); - StringBuilder addionalCode = new StringBuilder(2); - boolean nextIsSkinTone; - EmojiDrawable drawable; - EmojiSpan span; int length = cs.length(); boolean doneEmoji = false; - int nextValidLength; - boolean nextValid; boolean notOnlyEmoji; - //s.setSpansCount(emojiCount); try { for (int i = 0; i < length; i++) { @@ -520,29 +515,65 @@ public class Emoji { if (emojiOnly != null) { emojiOnly[0]++; } - CharSequence code = emojiCode.subSequence(0, emojiCode.length()); - drawable = Emoji.getEmojiDrawable(code); - if (drawable != null) { - span = new EmojiSpan(drawable, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); - s.setSpan(span, startIndex, startIndex + startLength, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - emojiCount++; - } + emojis.add(new EmojiSpanRange(startIndex, startIndex + startLength, emojiCode.subSequence(0, emojiCode.length()))); startLength = 0; startIndex = -1; emojiCode.setLength(0); doneEmoji = false; } - if ((Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29) && !BuildVars.DEBUG_PRIVATE_VERSION && emojiCount >= 50) { - break; - } } } catch (Exception e) { FileLog.e(e); - return cs; } if (emojiOnly != null && emojiCode.length() != 0) { emojiOnly[0] = 0; } + return emojis; + } + + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew) { + return replaceEmoji(cs, fontMetrics, size, createNew, null, false, null); + } + + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, boolean allowAnimated, AtomicReference> viewRef) { + return replaceEmoji(cs, fontMetrics, size, createNew, null, allowAnimated, viewRef); + } + + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly) { + return replaceEmoji(cs, fontMetrics, size, createNew, emojiOnly, false, null); + } + + public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly, boolean allowAnimated, AtomicReference> viewRef) { + allowAnimated = false; + if (NekoConfig.useSystemEmoji.Bool() || cs == null || cs.length() == 0) { + return cs; + } + Spannable s; + if (!createNew && cs instanceof Spannable) { + s = (Spannable) cs; + } else { + s = Spannable.Factory.getInstance().newSpannable(cs.toString()); + } + ArrayList emojis = parseEmojis(s, emojiOnly); + + EmojiSpan span; + Drawable drawable; + for (int i = 0; i < emojis.size(); ++i) { + EmojiSpanRange emojiRange = emojis.get(i); + + try { + drawable = Emoji.getEmojiDrawable(emojiRange.code); + if (drawable != null) { + span = new EmojiSpan(drawable, DynamicDrawableSpan.ALIGN_BOTTOM, size, fontMetrics); + s.setSpan(span, emojiRange.start, emojiRange.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } catch (Exception e) { + FileLog.e(e); + } + if ((Build.VERSION.SDK_INT < 23 || Build.VERSION.SDK_INT >= 29) && !BuildVars.DEBUG_PRIVATE_VERSION && (i + 1) >= 50) { + break; + } + } return s; } @@ -550,7 +581,7 @@ public class Emoji { private Paint.FontMetricsInt fontMetrics; private int size = AndroidUtilities.dp(20); - public EmojiSpan(EmojiDrawable d, int verticalAlignment, int s, Paint.FontMetricsInt original) { + public EmojiSpan(Drawable d, int verticalAlignment, int s, Paint.FontMetricsInt original) { super(d, verticalAlignment); fontMetrics = original; if (original != null) { @@ -620,6 +651,14 @@ public class Emoji { getDrawable().setAlpha(255); } } + + @Override + public void updateDrawState(TextPaint ds) { + if (getDrawable() instanceof EmojiDrawable) { + ((EmojiDrawable) getDrawable()).placeholderColor = 0x20ffffff & ds.getColor(); + } + super.updateDrawState(ds); + } } public static void addRecentEmoji(String code) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FeedWidgetService.java b/TMessagesProj/src/main/java/org/telegram/messenger/FeedWidgetService.java index 6a73597fd..f64f41f9f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FeedWidgetService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FeedWidgetService.java @@ -94,7 +94,7 @@ class FeedRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory, N rv.setViewVisibility(R.id.feed_widget_item_image, View.GONE); } else { TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - File f = FileLoader.getPathToAttach(size); + File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(size); if (f.exists()) { rv.setViewVisibility(R.id.feed_widget_item_image, View.VISIBLE); Uri uri = FileProvider.getUriForFile(mContext, BuildConfig.APPLICATION_ID + ".provider", f); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index 2dcf2c6b8..39f31b419 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -8,9 +8,6 @@ package org.telegram.messenger; -import android.util.SparseArray; -import android.util.SparseIntArray; - import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.TLObject; @@ -23,6 +20,7 @@ import java.nio.channels.FileChannel; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.Scanner; import java.util.concurrent.CountDownLatch; import java.util.zip.GZIPInputStream; @@ -32,27 +30,27 @@ public class FileLoadOperation { protected static class RequestInfo { private int requestToken; - private int offset; + private long offset; private TLRPC.TL_upload_file response; private TLRPC.TL_upload_webFile responseWeb; private TLRPC.TL_upload_cdnFile responseCdn; } public static class Range { - private int start; - private int end; + private long start; + private long end; - private Range(int s, int e) { + private Range(long s, long e) { start = s; end = e; } } private static class PreloadRange { - private int fileOffset; - private int length; + private long fileOffset; + private long length; - private PreloadRange(int o, int l) { + private PreloadRange(long o, long l) { fileOffset = o; length = l; } @@ -65,21 +63,22 @@ public class FileLoadOperation { private final static int stateFailed = 2; private final static int stateFinished = 3; - private final static int downloadChunkSize = 1024 * 32; - private final static int downloadChunkSizeBig = 1024 * 128; - private final static int cdnChunkCheckSize = 1024 * 128; - private final static int maxDownloadRequests = BuildVars.DEBUG_PRIVATE_VERSION ? 8 : 4; - private final static int maxDownloadRequestsBig = BuildVars.DEBUG_PRIVATE_VERSION ? 8 : 4; - private final static int bigFileSizeFrom = 1024 * 1024; - private final static int maxCdnParts = (int) (FileLoader.MAX_FILE_SIZE / downloadChunkSizeBig); + private int downloadChunkSize = 1024 * 32; + private int downloadChunkSizeBig = 1024 * 128; + private int cdnChunkCheckSize = 1024 * 128; + private int maxDownloadRequests = 4; + private int maxDownloadRequestsBig = 4; + private int bigFileSizeFrom = 1024 * 1024; + private int maxCdnParts = (int) (FileLoader.DEFAULT_MAX_FILE_SIZE / downloadChunkSizeBig); private final static int preloadMaxBytes = 2 * 1024 * 1024; private String fileName; + private String storeFileName; private int currentQueueType; - private SparseArray preloadedBytesRanges; - private SparseIntArray requestedPreloadedBytesRanges; + private HashMap preloadedBytesRanges; + private HashMap requestedPreloadedBytesRanges; private RandomAccessFile preloadStream; private int preloadStreamFileOffset; private int totalPreloadedBytes; @@ -87,12 +86,12 @@ public class FileLoadOperation { private boolean preloadFinished; private File cacheFilePreload; private boolean supportsPreloading; - private int nextPreloadDownloadOffset; - private int nextAtomOffset; - private int foundMoovSize; - private int preloadNotRequestedBytesCount; + private long nextPreloadDownloadOffset; + private long nextAtomOffset; + private long foundMoovSize; + private long preloadNotRequestedBytesCount; private int moovFound; - private byte[] preloadTempBuffer = new byte[16]; + private byte[] preloadTempBuffer = new byte[24]; private int preloadTempBufferCount; private boolean nextPartWasPreloaded; @@ -103,7 +102,7 @@ public class FileLoadOperation { private volatile ArrayList notLoadedBytesRangesCopy; private ArrayList notRequestedBytesRanges; private ArrayList notCheckedCdnRanges; - private int requestedBytesCount; + private long requestedBytesCount; private int currentAccount; private boolean started; @@ -114,11 +113,11 @@ public class FileLoadOperation { private WebFile webFile; private volatile int state = stateIdle; private volatile boolean paused; - private int downloadedBytes; - private int totalBytesCount; - private int bytesCountPadding; - private int streamStartOffset; - private int streamPriorityStartOffset; + private long downloadedBytes; + private long totalBytesCount; + private long bytesCountPadding; + private long streamStartOffset; + private long streamPriorityStartOffset; private RequestInfo priorityRequestInfo; private FileLoadOperationDelegate delegate; private byte[] key; @@ -133,7 +132,7 @@ public class FileLoadOperation { public Object parentObject; - private SparseArray cdnHashes; + private HashMap cdnHashes; private boolean forceBig; @@ -172,14 +171,30 @@ public class FileLoadOperation { private boolean ungzip; private int currentType; + public FilePathDatabase.PathData pathSaveData; public interface FileLoadOperationDelegate { void didFinishLoadingFile(FileLoadOperation operation, File finalFile); void didFailedLoadingFile(FileLoadOperation operation, int state); void didChangedLoadProgress(FileLoadOperation operation, long uploadedSize, long totalSize); + void saveFilePath(FilePathDatabase.PathData pathSaveData, File cacheFileFinal); } - public FileLoadOperation(ImageLocation imageLocation, Object parent, String extension, int size) { + private void updateParams() { + if (MessagesController.getInstance(currentAccount).getfileExperimentalParams) { + downloadChunkSizeBig = 1024 * 512; + maxDownloadRequests = 8; + maxDownloadRequestsBig = 8; + } else { + downloadChunkSizeBig = 1024 * 128; + maxDownloadRequests = 4; + maxDownloadRequestsBig = 4; + } + maxCdnParts = (int) (FileLoader.DEFAULT_MAX_FILE_SIZE / downloadChunkSizeBig); + } + + public FileLoadOperation(ImageLocation imageLocation, Object parent, String extension, long size) { + updateParams(); parentObject = parent; forceBig = imageLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION; if (imageLocation.isEncrypted()) { @@ -251,6 +266,7 @@ public class FileLoadOperation { } public FileLoadOperation(SecureDocument secureDocument) { + updateParams(); location = new TLRPC.TL_inputSecureFileLocation(); location.id = secureDocument.secureFile.id; location.access_hash = secureDocument.secureFile.access_hash; @@ -262,6 +278,7 @@ public class FileLoadOperation { } public FileLoadOperation(int instance, WebFile webDocument) { + updateParams(); currentAccount = instance; webFile = webDocument; webLocation = webDocument.location; @@ -282,6 +299,7 @@ public class FileLoadOperation { } public FileLoadOperation(TLRPC.Document documentLocation, Object parent) { + updateParams(); try { parentObject = parent; if (documentLocation instanceof TLRPC.TL_documentEncrypted) { @@ -369,11 +387,12 @@ public class FileLoadOperation { return priority; } - public void setPaths(int instance, String name, int queueType, File store, File temp) { + public void setPaths(int instance, String name, int queueType, File store, File temp, String finalName) { storePath = store; tempPath = temp; currentAccount = instance; fileName = name; + storeFileName = finalName; currentQueueType = queueType; } @@ -389,7 +408,7 @@ public class FileLoadOperation { return currentType; } - private void removePart(ArrayList ranges, int start, int end) { + private void removePart(ArrayList ranges, long start, long end) { if (ranges == null || end < start) { return; } @@ -430,7 +449,7 @@ public class FileLoadOperation { } } - private void addPart(ArrayList ranges, int start, int end, boolean save) { + private void addPart(ArrayList ranges, long start, long end, boolean save) { if (ranges == null || end < start) { return; } @@ -471,18 +490,13 @@ public class FileLoadOperation { filePartsStream.writeInt(count); for (int a = 0; a < count; a++) { range = ranges.get(a); - filePartsStream.writeInt(range.start); - filePartsStream.writeInt(range.end); + filePartsStream.writeLong(range.start); + filePartsStream.writeLong(range.end); } } catch (Exception e) { FileLog.e(e); } - if (streamListeners != null) { - count = streamListeners.size(); - for (int a = 0; a < count; a++) { - streamListeners.get(a).newDataAvailable(); - } - } + notifyStreamListeners(); } else { if (BuildVars.LOGS_ENABLED) { FileLog.e(cacheFileFinal + " downloaded duplicate file part " + start + " - " + end); @@ -491,6 +505,15 @@ public class FileLoadOperation { } } + private void notifyStreamListeners() { + if (streamListeners != null) { + int count = streamListeners.size(); + for (int a = 0; a < count; a++) { + streamListeners.get(a).newDataAvailable(); + } + } + } + protected File getCacheFileFinal() { return cacheFileFinal; } @@ -514,10 +537,13 @@ public class FileLoadOperation { return result[0]; } - private int getDownloadedLengthFromOffsetInternal(ArrayList ranges, final int offset, final int length) { + private long getDownloadedLengthFromOffsetInternal(ArrayList ranges, final long offset, final long length) { if (ranges == null || state == stateFinished || ranges.isEmpty()) { - if (downloadedBytes == 0) { + if (state == stateFinished) { return length; + } + if (downloadedBytes == 0) { + return 0; } else { return Math.min(length, Math.max(downloadedBytes - offset, 0)); } @@ -525,7 +551,7 @@ public class FileLoadOperation { int count = ranges.size(); Range range; Range minRange = null; - int availableLength = length; + long availableLength = length; for (int a = 0; a < count; a++) { range = ranges.get(a); if (offset <= range.start && (minRange == null || range.start < minRange.start)) { @@ -554,9 +580,9 @@ public class FileLoadOperation { return progress + getDownloadedLengthFromOffsetInternal(ranges, (int) (totalBytesCount * progress), totalBytesCount) / (float) totalBytesCount; } - protected int[] getDownloadedLengthFromOffset(final int offset, final int length) { + protected long[] getDownloadedLengthFromOffset(final int offset, final long length) { final CountDownLatch countDownLatch = new CountDownLatch(1); - final int[] result = new int[2]; + final long[] result = new long[2]; Utilities.stageQueue.postRunnable(() -> { result[0] = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, offset, length); if (state == stateFinished) { @@ -603,7 +629,8 @@ public class FileLoadOperation { return start(null, 0, false); } - public boolean start(final FileLoadOperationStream stream, final int streamOffset, final boolean steamPriority) { + public boolean start(final FileLoadOperationStream stream, final long streamOffset, final boolean steamPriority) { + updateParams(); if (currentDownloadChunkSize == 0) { currentDownloadChunkSize = totalBytesCount >= bigFileSizeFrom || forceBig ? downloadChunkSizeBig : downloadChunkSize; currentMaxDownloadRequests = totalBytesCount >= bigFileSizeFrom || forceBig ? maxDownloadRequestsBig : maxDownloadRequests; @@ -617,7 +644,7 @@ public class FileLoadOperation { streamListeners = new ArrayList<>(); } if (steamPriority) { - int offset = streamOffset / currentDownloadChunkSize * currentDownloadChunkSize; + long offset = (streamOffset / (long) currentDownloadChunkSize) * (long) currentDownloadChunkSize; if (priorityRequestInfo != null && priorityRequestInfo.offset != offset) { requestInfos.remove(priorityRequestInfo); requestedBytesCount -= currentDownloadChunkSize; @@ -677,13 +704,13 @@ public class FileLoadOperation { fileNameTemp = md5 + ".temp.enc"; fileNameFinal = md5 + "." + ext + ".enc"; if (key != null) { - fileNameIv = md5 + ".iv.enc"; + fileNameIv = md5 + "_64.iv.enc"; } } else { fileNameTemp = md5 + ".temp"; fileNameFinal = md5 + "." + ext; if (key != null) { - fileNameIv = md5 + ".iv"; + fileNameIv = md5 + "_64.iv"; } } } else { @@ -697,18 +724,18 @@ public class FileLoadOperation { fileNameTemp = location.volume_id + "_" + location.local_id + ".temp.enc"; fileNameFinal = location.volume_id + "_" + location.local_id + "." + ext + ".enc"; if (key != null) { - fileNameIv = location.volume_id + "_" + location.local_id + ".iv.enc"; + fileNameIv = location.volume_id + "_" + location.local_id + "_64.iv.enc"; } } else { fileNameTemp = location.volume_id + "_" + location.local_id + ".temp"; fileNameFinal = location.volume_id + "_" + location.local_id + "." + ext; if (key != null) { - fileNameIv = location.volume_id + "_" + location.local_id + ".iv"; + fileNameIv = location.volume_id + "_" + location.local_id + "_64.iv"; } if (notLoadedBytesRanges != null) { - fileNameParts = location.volume_id + "_" + location.local_id + ".pt"; + fileNameParts = location.volume_id + "_" + location.local_id + "_64.pt"; } - fileNamePreload = location.volume_id + "_" + location.local_id + ".preload"; + fileNamePreload = location.volume_id + "_" + location.local_id + "_64.preload"; } } else { if (datacenterId == 0 || location.id == 0) { @@ -719,18 +746,18 @@ public class FileLoadOperation { fileNameTemp = datacenterId + "_" + location.id + ".temp.enc"; fileNameFinal = datacenterId + "_" + location.id + ext + ".enc"; if (key != null) { - fileNameIv = datacenterId + "_" + location.id + ".iv.enc"; + fileNameIv = datacenterId + "_" + location.id + "_64.iv.enc"; } } else { fileNameTemp = datacenterId + "_" + location.id + ".temp"; fileNameFinal = datacenterId + "_" + location.id + ext; if (key != null) { - fileNameIv = datacenterId + "_" + location.id + ".iv"; + fileNameIv = datacenterId + "_" + location.id + "_64.iv"; } if (notLoadedBytesRanges != null) { - fileNameParts = datacenterId + "_" + location.id + ".pt"; + fileNameParts = datacenterId + "_" + location.id + "_64.pt"; } - fileNamePreload = datacenterId + "_" + location.id + ".preload"; + fileNamePreload = datacenterId + "_" + location.id + "_64.preload"; } } } @@ -745,7 +772,7 @@ public class FileLoadOperation { } else if (fileName != null && !encryptFile) { cacheFileFinal = new File(storePath, fileName); } else { - cacheFileFinal = new File(storePath, fileNameFinal); + cacheFileFinal = new File(storePath, storeFileName); } boolean finalFileExist = cacheFileFinal.exists(); if (finalFileExist && (parentObject instanceof TLRPC.TL_theme || totalBytesCount != 0 && totalBytesCount != cacheFileFinal.length())) { @@ -795,51 +822,51 @@ public class FileLoadOperation { try { preloadStream = new RandomAccessFile(cacheFilePreload, "rws"); long len = preloadStream.length(); - int readOffset = 0; + long readOffset = 0; preloadStreamFileOffset = 1; if (len - readOffset > 1) { preloaded[0] = preloadStream.readByte() != 0; readOffset += 1; while (readOffset < len) { - if (len - readOffset < 4) { + if (len - readOffset < 8) { break; } - int offset = preloadStream.readInt(); - readOffset += 4; - if (len - readOffset < 4 || offset < 0 || offset > totalBytesCount) { + long offset = preloadStream.readLong(); + readOffset += 8; + if (len - readOffset < 8 || offset < 0 || offset > totalBytesCount) { break; } - int size = preloadStream.readInt(); - readOffset += 4; + long size = preloadStream.readLong(); + readOffset += 8; if (len - readOffset < size || size > currentDownloadChunkSize) { break; } PreloadRange range = new PreloadRange(readOffset, size); readOffset += size; preloadStream.seek(readOffset); - if (len - readOffset < 12) { + if (len - readOffset < 24) { break; } - foundMoovSize = preloadStream.readInt(); + foundMoovSize = preloadStream.readLong(); if (foundMoovSize != 0) { moovFound = nextPreloadDownloadOffset > totalBytesCount / 2 ? 2 : 1; preloadNotRequestedBytesCount = foundMoovSize; } - nextPreloadDownloadOffset = preloadStream.readInt(); - nextAtomOffset = preloadStream.readInt(); - readOffset += 12; + nextPreloadDownloadOffset = preloadStream.readLong(); + nextAtomOffset = preloadStream.readLong(); + readOffset += 24; if (preloadedBytesRanges == null) { - preloadedBytesRanges = new SparseArray<>(); + preloadedBytesRanges = new HashMap<>(); } if (requestedPreloadedBytesRanges == null) { - requestedPreloadedBytesRanges = new SparseIntArray(); + requestedPreloadedBytesRanges = new HashMap<>(); } preloadedBytesRanges.put(offset, range); requestedPreloadedBytesRanges.put(offset, 1); totalPreloadedBytes += size; - preloadStreamFileOffset += 20 + size; + preloadStreamFileOffset += 36 + size; } } preloadStream.seek(preloadStreamFileOffset); @@ -874,8 +901,8 @@ public class FileLoadOperation { int count = filePartsStream.readInt(); if (count <= len / 2) { for (int a = 0; a < count; a++) { - int start = filePartsStream.readInt(); - int end = filePartsStream.readInt(); + long start = filePartsStream.readLong(); + long end = filePartsStream.readLong(); notLoadedBytesRanges.add(new Range(start, end)); notRequestedBytesRanges.add(new Range(start, end)); } @@ -892,9 +919,9 @@ public class FileLoadOperation { } else { long totalDownloadedLen = cacheFileTemp.length(); if (fileNameIv != null && (totalDownloadedLen % currentDownloadChunkSize) != 0) { - requestedBytesCount = downloadedBytes = 0; + requestedBytesCount = 0; } else { - requestedBytesCount = downloadedBytes = ((int) cacheFileTemp.length()) / currentDownloadChunkSize * currentDownloadChunkSize; + requestedBytesCount = downloadedBytes = (cacheFileTemp.length()) / ((long) currentDownloadChunkSize) * currentDownloadChunkSize; } if (notLoadedBytesRanges != null && notLoadedBytesRanges.isEmpty()) { notLoadedBytesRanges.add(new Range(downloadedBytes, totalBytesCount)); @@ -930,8 +957,8 @@ public class FileLoadOperation { fiv = new RandomAccessFile(cacheIvTemp, "rws"); if (downloadedBytes != 0 && !newKeyGenerated) { long len = cacheIvTemp.length(); - if (len > 0 && len % 32 == 0) { - fiv.read(iv, 0, 32); + if (len > 0 && len % 64 == 0) { + fiv.read(iv, 0, 64); } else { requestedBytesCount = downloadedBytes = 0; } @@ -951,7 +978,7 @@ public class FileLoadOperation { fileOutputStream.seek(downloadedBytes); } } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } if (fileOutputStream == null) { onFail(true, 0); @@ -973,6 +1000,9 @@ public class FileLoadOperation { started = true; try { onFinishLoadingFile(false); + if (pathSaveData != null) { + delegate.saveFilePath(pathSaveData, null); + } } catch (Exception e) { onFail(true, 0); } @@ -1175,6 +1205,7 @@ public class FileLoadOperation { return; } state = stateFinished; + notifyStreamListeners(); cleanup(); if (isPreloadVideoOperation) { preloadFinished = true; @@ -1223,6 +1254,21 @@ public class FileLoadOperation { } } else { try { + if (pathSaveData != null) { + cacheFileFinal = new File(storePath, storeFileName); + int count = 1; + while (cacheFileFinal.exists()) { + int lastDotIndex = storeFileName.lastIndexOf('.'); + String newFileName; + if (lastDotIndex > 0) { + newFileName = storeFileName.substring(0, lastDotIndex) + " (" + count + ")" + storeFileName.substring(lastDotIndex); + } else { + newFileName = storeFileName + " (" + count + ")"; + } + cacheFileFinal = new File(storePath, newFileName); + count++; + } + } renameResult = cacheFileTemp.renameTo(cacheFileFinal); } catch (Exception e) { renameResult = false; @@ -1251,6 +1297,9 @@ public class FileLoadOperation { onFail(false, 0); return; } + if (pathSaveData != null && cacheFileFinal.exists()) { + delegate.saveFilePath(pathSaveData, cacheFileFinal); + } } if (BuildVars.LOGS_ENABLED) { FileLog.d("finished downloading file to " + cacheFileFinal); @@ -1281,15 +1330,21 @@ public class FileLoadOperation { } } - private int findNextPreloadDownloadOffset(int atomOffset, int partOffset, NativeByteBuffer partBuffer) { + private long findNextPreloadDownloadOffset(long atomOffset, long partOffset, NativeByteBuffer partBuffer) { int partSize = partBuffer.limit(); while (true) { if (atomOffset < partOffset - (preloadTempBuffer != null ? 16 : 0) || atomOffset >= partOffset + partSize) { return 0; } if (atomOffset >= partOffset + partSize - 16) { - preloadTempBufferCount = partOffset + partSize - atomOffset; - partBuffer.position(partBuffer.limit() - preloadTempBufferCount); + long count = partOffset + partSize - atomOffset; + if (count > Integer.MAX_VALUE) { + throw new RuntimeException("!!!"); + } + preloadTempBufferCount = (int) count; + long position = partBuffer.limit() - preloadTempBufferCount; + + partBuffer.position((int) position); partBuffer.readBytes(preloadTempBuffer, 0, preloadTempBufferCount, false); return partOffset + partSize; } @@ -1298,10 +1353,15 @@ public class FileLoadOperation { partBuffer.readBytes(preloadTempBuffer, preloadTempBufferCount, 16 - preloadTempBufferCount, false); preloadTempBufferCount = 0; } else { - partBuffer.position(atomOffset - partOffset); + long count = atomOffset - partOffset; + if (count > Integer.MAX_VALUE) { + throw new RuntimeException("!!!"); + } + partBuffer.position((int) count); partBuffer.readBytes(preloadTempBuffer, 0, 16, false); } int atomSize = (((int) preloadTempBuffer[0] & 0xFF) << 24) + (((int) preloadTempBuffer[1] & 0xFF) << 16) + (((int) preloadTempBuffer[2] & 0xFF) << 8) + ((int) preloadTempBuffer[3] & 0xFF); + if (atomSize == 0) { return 0; } else if (atomSize == 1) { @@ -1317,7 +1377,7 @@ public class FileLoadOperation { } } - private void requestFileOffsets(int offset) { + private void requestFileOffsets(long offset) { if (requestingCdnOffsets) { return; } @@ -1333,7 +1393,7 @@ public class FileLoadOperation { TLRPC.Vector vector = (TLRPC.Vector) response; if (!vector.objects.isEmpty()) { if (cdnHashes == null) { - cdnHashes = new SparseArray<>(); + cdnHashes = new HashMap<>(); } for (int a = 0; a < vector.objects.size(); a++) { TLRPC.TL_fileHash hash = (TLRPC.TL_fileHash) vector.objects.get(a); @@ -1393,8 +1453,8 @@ public class FileLoadOperation { } int currentBytesSize = bytes.limit(); if (isCdn) { - int cdnCheckPart = requestInfo.offset / cdnChunkCheckSize; - int fileOffset = cdnCheckPart * cdnChunkCheckSize; + long cdnCheckPart = requestInfo.offset / cdnChunkCheckSize; + long fileOffset = cdnCheckPart * cdnChunkCheckSize; TLRPC.TL_fileHash hash = cdnHashes != null ? cdnHashes.get(fileOffset) : null; if (hash == null) { delayRequestInfo(requestInfo); @@ -1404,7 +1464,7 @@ public class FileLoadOperation { } if (requestInfo.responseCdn != null) { - int offset = requestInfo.offset / 16; + long offset = requestInfo.offset / 16; cdnIv[15] = (byte) (offset & 0xff); cdnIv[14] = (byte) ((offset >> 8) & 0xff); cdnIv[13] = (byte) ((offset >> 16) & 0xff); @@ -1414,16 +1474,16 @@ public class FileLoadOperation { boolean finishedDownloading; if (isPreloadVideoOperation) { - preloadStream.writeInt(requestInfo.offset); - preloadStream.writeInt(currentBytesSize); - preloadStreamFileOffset += 8; + preloadStream.writeLong(requestInfo.offset); + preloadStream.writeLong(currentBytesSize); + preloadStreamFileOffset += 16; FileChannel channel = preloadStream.getChannel(); channel.write(bytes.buffer); if (BuildVars.DEBUG_VERSION) { FileLog.d("save preload file part " + cacheFilePreload + " offset " + requestInfo.offset + " size " + currentBytesSize); } if (preloadedBytesRanges == null) { - preloadedBytesRanges = new SparseArray<>(); + preloadedBytesRanges = new HashMap<>(); } preloadedBytesRanges.put(requestInfo.offset, new PreloadRange(preloadStreamFileOffset, currentBytesSize)); @@ -1431,7 +1491,7 @@ public class FileLoadOperation { preloadStreamFileOffset += currentBytesSize; if (moovFound == 0) { - int offset = findNextPreloadDownloadOffset(nextAtomOffset, requestInfo.offset, bytes); + long offset = findNextPreloadDownloadOffset(nextAtomOffset, requestInfo.offset, bytes); if (offset < 0) { offset *= -1; nextPreloadDownloadOffset += currentDownloadChunkSize; @@ -1444,14 +1504,14 @@ public class FileLoadOperation { } nextPreloadDownloadOffset = -1; } else { - nextPreloadDownloadOffset = offset / currentDownloadChunkSize * currentDownloadChunkSize; + nextPreloadDownloadOffset += currentDownloadChunkSize; } nextAtomOffset = offset; } - preloadStream.writeInt(foundMoovSize); - preloadStream.writeInt(nextPreloadDownloadOffset); - preloadStream.writeInt(nextAtomOffset); - preloadStreamFileOffset += 12; + preloadStream.writeLong(foundMoovSize); + preloadStream.writeLong(nextPreloadDownloadOffset); + preloadStream.writeLong(nextAtomOffset); + preloadStreamFileOffset += 24; finishedDownloading = nextPreloadDownloadOffset == 0 || moovFound != 0 && foundMoovSize < 0 || totalPreloadedBytes > preloadMaxBytes || nextPreloadDownloadOffset >= totalBytesCount; if (finishedDownloading) { preloadStream.seek(0); @@ -1469,11 +1529,15 @@ public class FileLoadOperation { if (key != null) { Utilities.aesIgeEncryption(bytes.buffer, key, iv, false, true, 0, bytes.limit()); if (finishedDownloading && bytesCountPadding != 0) { - bytes.limit(bytes.limit() - bytesCountPadding); + long limit = bytes.limit() - bytesCountPadding; + if (BuildVars.DEBUG_VERSION && limit > Integer.MAX_VALUE) { + throw new RuntimeException("Out of limit" + limit); + } + bytes.limit((int) (limit)); } } if (encryptFile) { - int offset = requestInfo.offset / 16; + long offset = requestInfo.offset / 16; encryptIv[15] = (byte) (offset & 0xff); encryptIv[14] = (byte) ((offset >> 8) & 0xff); encryptIv[13] = (byte) ((offset >> 16) & 0xff); @@ -1491,7 +1555,7 @@ public class FileLoadOperation { channel.write(bytes.buffer); addPart(notLoadedBytesRanges, requestInfo.offset, requestInfo.offset + currentBytesSize, true); if (isCdn) { - int cdnCheckPart = requestInfo.offset / cdnChunkCheckSize; + long cdnCheckPart = requestInfo.offset / cdnChunkCheckSize; int size = notCheckedCdnRanges.size(); Range range; @@ -1504,8 +1568,8 @@ public class FileLoadOperation { } } if (!checked) { - int fileOffset = cdnCheckPart * cdnChunkCheckSize; - int availableSize = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, fileOffset, cdnChunkCheckSize); + long fileOffset = cdnCheckPart * cdnChunkCheckSize; + long availableSize = getDownloadedLengthFromOffsetInternal(notLoadedBytesRanges, fileOffset, cdnChunkCheckSize); if (availableSize != 0 && (availableSize == cdnChunkCheckSize || totalBytesCount > 0 && availableSize == totalBytesCount - fileOffset || totalBytesCount <= 0 && finishedDownloading)) { TLRPC.TL_fileHash hash = cdnHashes.get(fileOffset); if (fileReadStream == null) { @@ -1513,10 +1577,13 @@ public class FileLoadOperation { fileReadStream = new RandomAccessFile(cacheFileTemp, "r"); } fileReadStream.seek(fileOffset); - fileReadStream.readFully(cdnCheckBytes, 0, availableSize); + if (BuildVars.DEBUG_VERSION && availableSize > Integer.MAX_VALUE) { + throw new RuntimeException("!!!"); + } + fileReadStream.readFully(cdnCheckBytes, 0, (int) availableSize); if (encryptFile) { - int offset = fileOffset / 16; + long offset = fileOffset / 16; encryptIv[15] = (byte) (offset & 0xff); encryptIv[14] = (byte) ((offset >> 8) & 0xff); encryptIv[13] = (byte) ((offset >> 16) & 0xff); @@ -1639,12 +1706,12 @@ public class FileLoadOperation { } private void clearOperaion(RequestInfo currentInfo, boolean preloadChanged) { - int minOffset = Integer.MAX_VALUE; + long minOffset = Long.MAX_VALUE; for (int a = 0; a < requestInfos.size(); a++) { RequestInfo info = requestInfos.get(a); minOffset = Math.min(info.offset, minOffset); if (isPreloadVideoOperation) { - requestedPreloadedBytesRanges.delete(info.offset); + requestedPreloadedBytesRanges.remove(info.offset); } else { removePart(notRequestedBytesRanges, info.offset, info.offset + currentDownloadChunkSize); } @@ -1659,7 +1726,7 @@ public class FileLoadOperation { for (int a = 0; a < delayedRequestInfos.size(); a++) { RequestInfo info = delayedRequestInfos.get(a); if (isPreloadVideoOperation) { - requestedPreloadedBytesRanges.delete(info.offset); + requestedPreloadedBytesRanges.remove(info.offset); } else { removePart(notRequestedBytesRanges, info.offset, info.offset + currentDownloadChunkSize); } @@ -1713,7 +1780,7 @@ public class FileLoadOperation { } for (int a = 0; a < count; a++) { - int downloadOffset; + long downloadOffset; if (isPreloadVideoOperation) { if (moovFound != 0 && preloadNotRequestedBytesCount <= 0) { return; @@ -1723,7 +1790,7 @@ public class FileLoadOperation { boolean found = false; int tries = preloadMaxBytes / currentDownloadChunkSize + 2; while (tries != 0) { - if (requestedPreloadedBytesRanges.get(downloadOffset, 0) == 0) { + if (!requestedPreloadedBytesRanges.containsKey(downloadOffset)) { found = true; break; } @@ -1743,7 +1810,7 @@ public class FileLoadOperation { downloadOffset = nextPreloadDownloadOffset; } if (requestedPreloadedBytesRanges == null) { - requestedPreloadedBytesRanges = new SparseIntArray(); + requestedPreloadedBytesRanges = new HashMap<>(); } requestedPreloadedBytesRanges.put(downloadOffset, 1); if (BuildVars.DEBUG_VERSION) { @@ -1752,27 +1819,27 @@ public class FileLoadOperation { preloadNotRequestedBytesCount -= currentDownloadChunkSize; } else { if (notRequestedBytesRanges != null) { - int sreamOffset = streamPriorityStartOffset != 0 ? streamPriorityStartOffset : streamStartOffset; + long streamOffset = streamPriorityStartOffset != 0 ? streamPriorityStartOffset : streamStartOffset; int size = notRequestedBytesRanges.size(); - int minStart = Integer.MAX_VALUE; - int minStreamStart = Integer.MAX_VALUE; + long minStart = Long.MAX_VALUE; + long minStreamStart = Long.MAX_VALUE; for (int b = 0; b < size; b++) { Range range = notRequestedBytesRanges.get(b); - if (sreamOffset != 0) { - if (range.start <= sreamOffset && range.end > sreamOffset) { - minStreamStart = sreamOffset; - minStart = Integer.MAX_VALUE; + if (streamOffset != 0) { + if (range.start <= streamOffset && range.end > streamOffset) { + minStreamStart = streamOffset; + minStart = Long.MAX_VALUE; break; } - if (sreamOffset < range.start && range.start < minStreamStart) { + if (streamOffset < range.start && range.start < minStreamStart) { minStreamStart = range.start; } } minStart = Math.min(minStart, range.start); } - if (minStreamStart != Integer.MAX_VALUE) { + if (minStreamStart != Long.MAX_VALUE) { downloadOffset = minStreamStart; - } else if (minStart != Integer.MAX_VALUE) { + } else if (minStart != Long.MAX_VALUE) { downloadOffset = minStart; } else { break; @@ -1803,7 +1870,7 @@ public class FileLoadOperation { if (webLocation != null) { TLRPC.TL_upload_getWebFile req = new TLRPC.TL_upload_getWebFile(); req.location = webLocation; - req.offset = downloadOffset; + req.offset = (int) downloadOffset; req.limit = currentDownloadChunkSize; request = req; } else { @@ -1825,7 +1892,10 @@ public class FileLoadOperation { if (range != null) { requestInfo.response = new TLRPC.TL_upload_file(); try { - NativeByteBuffer buffer = new NativeByteBuffer(range.length); + if (BuildVars.DEBUG_VERSION && range.length > Integer.MAX_VALUE) { + throw new RuntimeException("cast long to integer"); + } + NativeByteBuffer buffer = new NativeByteBuffer((int) range.length); preloadStream.seek(range.fileOffset); preloadStream.getChannel().read(buffer.buffer); buffer.buffer.position(0); @@ -1840,6 +1910,7 @@ public class FileLoadOperation { } } } + if (streamPriorityStartOffset != 0) { if (BuildVars.DEBUG_VERSION) { FileLog.d("frame get offset = " + streamPriorityStartOffset); @@ -1882,7 +1953,7 @@ public class FileLoadOperation { TLRPC.TL_upload_fileCdnRedirect res = (TLRPC.TL_upload_fileCdnRedirect) response; if (!res.file_hashes.isEmpty()) { if (cdnHashes == null) { - cdnHashes = new SparseArray<>(); + cdnHashes = new HashMap<>(); } for (int a1 = 0; a1 < res.file_hashes.size(); a1++) { TLRPC.TL_fileHash hash = res.file_hashes.get(a1); @@ -1921,7 +1992,7 @@ public class FileLoadOperation { TLRPC.Vector vector = (TLRPC.Vector) response1; if (!vector.objects.isEmpty()) { if (cdnHashes == null) { - cdnHashes = new SparseArray<>(); + cdnHashes = new HashMap<>(); } for (int a1 = 0; a1 < vector.objects.size(); a1++) { TLRPC.TL_fileHash hash = (TLRPC.TL_fileHash) vector.objects.get(a1); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index f65a70a27..6c46ec4b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -30,10 +30,15 @@ public class FileLoader extends BaseController { public interface FileLoaderDelegate { void fileUploadProgressChanged(FileUploadOperation operation, String location, long uploadedSize, long totalSize, boolean isEncrypted); + void fileDidUploaded(String location, TLRPC.InputFile inputFile, TLRPC.InputEncryptedFile inputEncryptedFile, byte[] key, byte[] iv, long totalFileSize); + void fileDidFailedUpload(String location, boolean isEncrypted); + void fileDidLoaded(String location, File finalFile, Object parentObject, int type); + void fileDidFailedLoad(String location, int state); + void fileLoadProgressChanged(FileLoadOperation operation, String location, long uploadedSize, long totalSize); } @@ -42,6 +47,7 @@ public class FileLoader extends BaseController { public static final int MEDIA_DIR_VIDEO = 2; public static final int MEDIA_DIR_DOCUMENT = 3; public static final int MEDIA_DIR_CACHE = 4; + public static final int MEDIA_DIR_FILES = 5; public static final int MEDIA_DIR_IMAGE_PUBLIC = 100; public static final int MEDIA_DIR_VIDEO_PUBLIC = 101; @@ -55,10 +61,15 @@ public class FileLoader extends BaseController { public static final int QUEUE_TYPE_FILE = 0; public static final int QUEUE_TYPE_IMAGE = 1; public static final int QUEUE_TYPE_AUDIO = 2; + public static final int QUEUE_TYPE_PRELOAD = 3; - public final static long MAX_FILE_SIZE = 1024L * 1024L * 2000L; + public final static long DEFAULT_MAX_FILE_SIZE = 1024L * 1024L * 2000L; + public final static long DEFAULT_MAX_FILE_SIZE_PREMIUM = DEFAULT_MAX_FILE_SIZE * 2L; + + public final static int PRELOAD_CACHE_TYPE = 11; private volatile static DispatchQueue fileLoaderQueue = new DispatchQueue("fileUploadQueue"); + private final FilePathDatabase filePathDatabase; private LinkedList uploadOperationQueue = new LinkedList<>(); private LinkedList uploadSmallOperationQueue = new LinkedList<>(); @@ -70,9 +81,11 @@ public class FileLoader extends BaseController { private SparseArray> fileLoadOperationQueues = new SparseArray<>(); private SparseArray> audioLoadOperationQueues = new SparseArray<>(); private SparseArray> imageLoadOperationQueues = new SparseArray<>(); + private SparseArray> preloadingLoadOperationQueues = new SparseArray<>(); private SparseIntArray fileLoadOperationsCount = new SparseIntArray(); private SparseIntArray audioLoadOperationsCount = new SparseIntArray(); private SparseIntArray imageLoadOperationsCount = new SparseIntArray(); + private SparseIntArray preloadingLoadOperationsCount = new SparseIntArray(); private ConcurrentHashMap loadOperationPaths = new ConcurrentHashMap<>(); private ArrayList activeFileLoadOperation = new ArrayList<>(); @@ -116,6 +129,7 @@ public class FileLoader extends BaseController { public FileLoader(int instance) { super(instance); + filePathDatabase = new FilePathDatabase(instance); } public static void setMediaDirs(SparseArray dirs) { @@ -255,7 +269,7 @@ public class FileLoader extends BaseController { uploadFile(location, encrypted, small, 0, type, false); } - public void uploadFile(final String location, final boolean encrypted, final boolean small, final int estimatedSize, final int type, boolean forceSmallFile) { + public void uploadFile(final String location, final boolean encrypted, final boolean small, final long estimatedSize, final int type, boolean forceSmallFile) { if (location == null) { return; } @@ -269,7 +283,7 @@ public class FileLoader extends BaseController { return; } } - int esimated = estimatedSize; + long esimated = estimatedSize; if (esimated != 0) { Long finalSize = uploadSizes.get(location); if (finalSize != null) { @@ -383,7 +397,9 @@ public class FileLoader extends BaseController { private LinkedList getLoadOperationQueue(int datacenterId, int type) { SparseArray> queues; - if (type == QUEUE_TYPE_AUDIO) { + if (type == QUEUE_TYPE_PRELOAD) { + queues = preloadingLoadOperationQueues; + } else if (type == QUEUE_TYPE_AUDIO) { queues = audioLoadOperationQueues; } else if (type == QUEUE_TYPE_IMAGE) { queues = imageLoadOperationQueues; @@ -400,7 +416,9 @@ public class FileLoader extends BaseController { private SparseIntArray getLoadOperationCount(int type) { SparseArray> queues; - if (type == QUEUE_TYPE_AUDIO) { + if (type == QUEUE_TYPE_PRELOAD) { + return preloadingLoadOperationsCount; + } else if (type == QUEUE_TYPE_AUDIO) { return audioLoadOperationsCount; } else if (type == QUEUE_TYPE_IMAGE) { return imageLoadOperationsCount; @@ -597,7 +615,7 @@ public class FileLoader extends BaseController { } } - private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, Object parentObject, final String locationExt, final int locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, boolean streamPriority, final int cacheType) { + private FileLoadOperation loadFileInternal(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, Object parentObject, final String locationExt, final long locationSize, final int priority, final FileLoadOperationStream stream, final int streamOffset, boolean streamPriority, final int cacheType) { String fileName; if (location != null) { fileName = getAttachFileName(location, locationExt); @@ -617,7 +635,7 @@ public class FileLoader extends BaseController { loadOperationPathsUI.put(fileName, true); } - if (document != null && parentObject instanceof MessageObject && ((MessageObject) parentObject).putInDownloadsStore) { + if (document != null && parentObject instanceof MessageObject && ((MessageObject) parentObject).putInDownloadsStore && !((MessageObject) parentObject).isAnyKindOfSticker()) { getDownloadController().startDownloadFile(document, (MessageObject) parentObject); } @@ -666,15 +684,22 @@ public class FileLoader extends BaseController { File tempDir = getDirectory(MEDIA_DIR_CACHE); File storeDir = tempDir; int type = MEDIA_DIR_CACHE; + long documentId = 0; + int dcId = 0; + String lastKnownPath = null; if (secureDocument != null) { operation = new FileLoadOperation(secureDocument); type = MEDIA_DIR_DOCUMENT; } else if (location != null) { + documentId = location.volume_id; + dcId = location.dc_id; operation = new FileLoadOperation(imageLocation, parentObject, locationExt, locationSize); type = MEDIA_DIR_IMAGE; } else if (document != null) { operation = new FileLoadOperation(document, parentObject); + documentId = document.id; + dcId = document.dc_id; if (MessageObject.isVoiceDocument(document)) { type = MEDIA_DIR_AUDIO; } else if (MessageObject.isVideoDocument(document) || MessageObject.isGifDocument(document)) { @@ -699,19 +724,67 @@ public class FileLoader extends BaseController { } } int queueType; - if (type == MEDIA_DIR_AUDIO) { + if (cacheType == PRELOAD_CACHE_TYPE) { + queueType = QUEUE_TYPE_PRELOAD; + } else if (type == MEDIA_DIR_AUDIO) { queueType = QUEUE_TYPE_AUDIO; - } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument)) { + } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument) || MessageObject.isStickerDocument(document)) { queueType = QUEUE_TYPE_IMAGE; } else { queueType = QUEUE_TYPE_FILE; } + + String storeFileName = fileName; + if (cacheType == 0 || cacheType == 10) { - storeDir = getDirectory(type); + if (documentId != 0) { + String path = getFileDatabase().getPath(documentId, dcId, type, true); + boolean customPath = false; + if (path != null) { + File file = new File(path); + if (file.exists()) { + customPath = true; + storeFileName = file.getName(); + storeDir = file.getParentFile(); + } + } + if (!customPath) { + storeFileName = fileName; + storeDir = getDirectory(type); + boolean saveCustomPath = false; + + + if ((type == MEDIA_DIR_IMAGE || type == MEDIA_DIR_VIDEO) && canSaveToPublicStorage(parentObject)) { + File newDir; + if (type == MEDIA_DIR_IMAGE) { + newDir = getDirectory(MEDIA_DIR_IMAGE_PUBLIC); + } else { + newDir = getDirectory(MEDIA_DIR_VIDEO_PUBLIC); + } + if (newDir != null) { + storeDir = newDir; + saveCustomPath = true; + } + } else if (!TextUtils.isEmpty(getDocumentFileName(document)) && canSaveAsFile(parentObject)) { + storeFileName = getDocumentFileName(document); + File newDir = getDirectory(MEDIA_DIR_FILES); + if (newDir != null) { + storeDir = newDir; + saveCustomPath = true; + } + } + + if (saveCustomPath) { + operation.pathSaveData = new FilePathDatabase.PathData(documentId, dcId, type); + } + } + } else { + storeDir = getDirectory(type); + } } else if (cacheType == 2) { operation.setEncryptFile(true); } - operation.setPaths(currentAccount, fileName, queueType, storeDir, tempDir); + operation.setPaths(currentAccount, fileName, queueType, storeDir, tempDir, storeFileName); if (cacheType == 10) { operation.setIsPreloadVideoOperation(true); } @@ -757,6 +830,11 @@ public class FileLoader extends BaseController { delegate.fileLoadProgressChanged(operation, fileName, uploadedSize, totalSize); } } + + @Override + public void saveFilePath(FilePathDatabase.PathData pathSaveData, File cacheFileFinal) { + getFileDatabase().putPath(pathSaveData.id, pathSaveData.dc, pathSaveData.type, cacheFileFinal != null ? cacheFileFinal.toString() : null); + } }; operation.setDelegate(fileLoadOperationDelegate); @@ -766,7 +844,15 @@ public class FileLoader extends BaseController { operation.setPriority(priority); boolean started; - if (queueType == QUEUE_TYPE_AUDIO) { + if (queueType == QUEUE_TYPE_PRELOAD) { + int maxCount = priority > 0 ? 6 : 2; + int count = preloadingLoadOperationsCount.get(datacenterId); + if (started = (stream != null || count < maxCount)) { + if (operation.start(stream, streamOffset, streamPriority)) { + preloadingLoadOperationsCount.put(datacenterId, count + 1); + } + } + } else if (queueType == QUEUE_TYPE_AUDIO) { int maxCount = priority > 0 ? 3 : 1; int count = audioLoadOperationsCount.get(datacenterId); if (started = (stream != null || count < maxCount)) { @@ -801,6 +887,45 @@ public class FileLoader extends BaseController { return operation; } + private boolean canSaveAsFile(Object parentObject) { + if (parentObject instanceof MessageObject) { + MessageObject messageObject = (MessageObject) parentObject; + if (!messageObject.isDocument()) { + return false; + } + return true; + } + return false; + } + + private boolean canSaveToPublicStorage(Object parentObject) { + if (SharedConfig.saveToGalleryFlags == 0 || BuildVars.NO_SCOPED_STORAGE) { + return false; + } + if (parentObject instanceof MessageObject) { + MessageObject messageObject = (MessageObject) parentObject; + int flag; + long dialogId = messageObject.getDialogId(); + if (messageObject.isAnyKindOfSticker() || getMessagesController().isChatNoForwards(getMessagesController().getChat(-dialogId)) || messageObject.messageOwner.noforwards) { + return false; + } + if (dialogId >= 0) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_PEER; + } else { + if (ChatObject.isChannelAndNotMegaGroup(getMessagesController().getChat(-dialogId))) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_CHANNELS; + } else { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_GROUP; + } + } + + if ((SharedConfig.saveToGalleryFlags & flag) != 0) { + return true; + } + } + return false; + } + private void addOperationToQueue(FileLoadOperation operation, LinkedList queue) { int priority = operation.getPriority(); if (priority > 0) { @@ -818,7 +943,7 @@ public class FileLoader extends BaseController { } } - private void loadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, final Object parentObject, final String locationExt, final int locationSize, final int priority, final int cacheType) { + private void loadFile(final TLRPC.Document document, final SecureDocument secureDocument, final WebFile webDocument, TLRPC.TL_fileLocationToBeDeprecated location, final ImageLocation imageLocation, final Object parentObject, final String locationExt, final long locationSize, final int priority, final int cacheType) { String fileName; if (location != null) { fileName = getAttachFileName(location, locationExt); @@ -845,7 +970,7 @@ public class FileLoader extends BaseController { try { semaphore.await(); } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } return result[0]; } @@ -870,7 +995,9 @@ public class FileLoader extends BaseController { while (!queue.isEmpty()) { operation = queue.get(0); int maxCount; - if (queueType == QUEUE_TYPE_AUDIO) { + if (queueType == QUEUE_TYPE_PRELOAD) { + maxCount = operation.getPriority() != 0 ? 6 : 2; + } else if (queueType == QUEUE_TYPE_AUDIO) { maxCount = operation.getPriority() != 0 ? 3 : 1; } else if (queueType == QUEUE_TYPE_IMAGE) { maxCount = operation.getPriority() != 0 ? 6 : 2; @@ -942,7 +1069,11 @@ public class FileLoader extends BaseController { return ""; } - public static File getPathToMessage(TLRPC.Message message) { + public File getPathToMessage(TLRPC.Message message) { + return getPathToMessage(message, true); + } + + public File getPathToMessage(TLRPC.Message message, boolean useFileDatabaseQueue) { if (message == null) { return new File(""); } @@ -952,75 +1083,91 @@ public class FileLoader extends BaseController { if (sizes.size() > 0) { TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize()); if (sizeFull != null) { - return getPathToAttach(sizeFull); + return getPathToAttach(sizeFull, null, false, useFileDatabaseQueue); } } } } else { if (message.media instanceof TLRPC.TL_messageMediaDocument) { - return getPathToAttach(message.media.document, message.media.ttl_seconds != 0); + return getPathToAttach(message.media.document, null, message.media.ttl_seconds != 0, useFileDatabaseQueue); } else if (message.media instanceof TLRPC.TL_messageMediaPhoto) { ArrayList sizes = message.media.photo.sizes; if (sizes.size() > 0) { TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize(), false, null, true); if (sizeFull != null) { - return getPathToAttach(sizeFull, message.media.ttl_seconds != 0); + return getPathToAttach(sizeFull, null, message.media.ttl_seconds != 0, useFileDatabaseQueue); } } } else if (message.media instanceof TLRPC.TL_messageMediaWebPage) { if (message.media.webpage.document != null) { - return getPathToAttach(message.media.webpage.document); + return getPathToAttach(message.media.webpage.document, null, false, useFileDatabaseQueue); } else if (message.media.webpage.photo != null) { ArrayList sizes = message.media.webpage.photo.sizes; if (sizes.size() > 0) { TLRPC.PhotoSize sizeFull = getClosestPhotoSizeWithSize(sizes, AndroidUtilities.getPhotoSize()); if (sizeFull != null) { - return getPathToAttach(sizeFull); + return getPathToAttach(sizeFull, null, false, useFileDatabaseQueue); } } } } else if (message.media instanceof TLRPC.TL_messageMediaInvoice) { - return getPathToAttach(((TLRPC.TL_messageMediaInvoice) message.media).photo, true); + return getPathToAttach(((TLRPC.TL_messageMediaInvoice) message.media).photo, null, true, useFileDatabaseQueue); } } return new File(""); } - public static File getPathToAttach(TLObject attach) { + public File getPathToAttach(TLObject attach) { return getPathToAttach(attach, null, false); } - public static File getPathToAttach(TLObject attach, boolean forceCache) { + public File getPathToAttach(TLObject attach, boolean forceCache) { return getPathToAttach(attach, null, forceCache); } - public static File getPathToAttach(TLObject attach, String ext, boolean forceCache) { - return getPathToAttach(attach, null, ext, forceCache); + public File getPathToAttach(TLObject attach, String ext, boolean forceCache) { + return getPathToAttach(attach, null, ext, forceCache, true); } - public static File getPathToAttach(TLObject attach, String size, String ext, boolean forceCache) { + public File getPathToAttach(TLObject attach, String ext, boolean forceCache, boolean useFileDatabaseQueue) { + 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) { File dir = null; + long documentId = 0; + int dcId = 0; + int type = 0; if (forceCache) { dir = getDirectory(MEDIA_DIR_CACHE); } else { if (attach instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) attach; + if (!TextUtils.isEmpty(document.localPath)) { + return new File(document.localPath); + } if (document.key != null) { - dir = getDirectory(MEDIA_DIR_CACHE); + type = MEDIA_DIR_CACHE; } else { if (MessageObject.isVoiceDocument(document)) { - dir = getDirectory(MEDIA_DIR_AUDIO); + type = MEDIA_DIR_AUDIO; } else if (MessageObject.isVideoDocument(document) || MessageObject.isGifDocument(document)) { - dir = getDirectory(MEDIA_DIR_VIDEO); + type = MEDIA_DIR_VIDEO; } else if (MessageObject.isStickerDocument(document)) { dir = getDirectory(MEDIA_DIR_CACHE); } else { - dir = getDirectory(MEDIA_DIR_DOCUMENT); + type = MEDIA_DIR_DOCUMENT; } } + documentId = document.id; + dcId = document.dc_id; + dir = getDirectory(type); } else if (attach instanceof TLRPC.Photo) { TLRPC.PhotoSize photoSize = getClosestPhotoSizeWithSize(((TLRPC.Photo) attach).sizes, AndroidUtilities.getPhotoSize()); - return getPathToAttach(photoSize, ext, false); + return getPathToAttach(photoSize, ext, false, useFileDatabaseQueue); } else if (attach instanceof TLRPC.PhotoSize) { TLRPC.PhotoSize photoSize = (TLRPC.PhotoSize) attach; if (photoSize instanceof TLRPC.TL_photoStrippedSize || photoSize instanceof TLRPC.TL_photoPathSize) { @@ -1042,7 +1189,9 @@ public class FileLoader extends BaseController { if (fileLocation.key != null || fileLocation.volume_id == Integer.MIN_VALUE && fileLocation.local_id < 0) { dir = getDirectory(MEDIA_DIR_CACHE); } else { - dir = getDirectory(MEDIA_DIR_IMAGE); + documentId = fileLocation.volume_id; + dcId = fileLocation.dc_id; + dir = getDirectory(type = MEDIA_DIR_IMAGE); } } else if (attach instanceof TLRPC.UserProfilePhoto || attach instanceof TLRPC.ChatPhoto) { if (size == null) { @@ -1071,9 +1220,19 @@ public class FileLoader extends BaseController { if (dir == null) { return new File(""); } + if (documentId != 0) { + String path = getInstance(UserConfig.selectedAccount).getFileDatabase().getPath(documentId, dcId, type, useFileDatabaseQueue); + if (path != null) { + return new File(path); + } + } return new File(dir, getAttachFileName(attach, ext)); } + private FilePathDatabase getFileDatabase() { + return filePathDatabase; + } + public static TLRPC.PhotoSize getClosestPhotoSizeWithSize(ArrayList sizes, int side) { return getClosestPhotoSizeWithSize(sizes, side, false); } @@ -1215,6 +1374,9 @@ public class FileLoader extends BaseController { return getAttachFileName(attach, null, ext); } + /** + * file hash. contains docId, dcId, ext. + */ public static String getAttachFileName(TLObject attach, String size, String ext) { if (attach instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) attach; @@ -1441,7 +1603,7 @@ public class FileLoader extends BaseController { public void checkCurrentDownloadsFiles() { ArrayList messagesToRemove = new ArrayList<>(); ArrayList messageObjects = new ArrayList<>(getDownloadController().recentDownloadingFiles); - for (int i = 0 ; i < messageObjects.size(); i++) { + for (int i = 0; i < messageObjects.size(); i++) { messageObjects.get(i).checkMediaExistance(); if (messageObjects.get(i).mediaExists) { messagesToRemove.add(messageObjects.get(i)); @@ -1453,10 +1615,28 @@ public class FileLoader extends BaseController { getNotificationCenter().postNotificationName(NotificationCenter.onDownloadingFilesChanged); }); } + } + /** + * optimezed for bulk messages + */ + public void checkMediaExistance(ArrayList messageObjects) { + getFileDatabase().checkMediaExistance(messageObjects); + } + + public interface FileResolver { + File getFile(); } public void clearRecentDownloadedFiles() { getDownloadController().clearRecentDownloadedFiles(); } + + public static boolean checkUploadFileSize(int currentAccount, long length) { + boolean premium = AccountInstance.getInstance(currentAccount).getUserConfig().isPremium(); + if (length < DEFAULT_MAX_FILE_SIZE || (length < DEFAULT_MAX_FILE_SIZE_PREMIUM && premium)) { + return true; + } + return false; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java new file mode 100644 index 000000000..de5ae346a --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java @@ -0,0 +1,238 @@ +package org.telegram.messenger; + +import android.os.Looper; + +import org.telegram.SQLite.SQLiteCursor; +import org.telegram.SQLite.SQLiteDatabase; +import org.telegram.SQLite.SQLiteException; +import org.telegram.SQLite.SQLitePreparedStatement; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; + +public class FilePathDatabase { + + private final DispatchQueue dispatchQueue; + private final int currentAccount; + + private SQLiteDatabase database; + private File cacheFile; + private File shmCacheFile; + + private final static int LAST_DB_VERSION = 1; + + private final static String DATABASE_NAME = "file_to_path"; + private final static String DATABASE_BACKUP_NAME = "file_to_path_backup"; + + public FilePathDatabase(int currentAccount) { + this.currentAccount = currentAccount; + dispatchQueue = new DispatchQueue("files_database_queue_" + currentAccount); + dispatchQueue.postRunnable(() -> { + createDatabase(0, false); + }); + } + + public void createDatabase(int tryCount, boolean fromBackup) { + File filesDir = ApplicationLoader.getFilesDirFixed(); + if (currentAccount != 0) { + filesDir = new File(filesDir, "account" + currentAccount + "/"); + filesDir.mkdirs(); + } + cacheFile = new File(filesDir, DATABASE_NAME + ".db"); + shmCacheFile = new File(filesDir, DATABASE_NAME + ".db-shm"); + + + boolean createTable = false; + + + if (!cacheFile.exists()) { + createTable = true; + } + try { + database = new SQLiteDatabase(cacheFile.getPath()); + database.executeFast("PRAGMA secure_delete = ON").stepThis().dispose(); + database.executeFast("PRAGMA temp_store = MEMORY").stepThis().dispose(); + + if (createTable) { + database.executeFast("CREATE TABLE paths(document_id INTEGER, dc_id INTEGER, type INTEGER, path TEXT, PRIMARY KEY(document_id, dc_id, type));").stepThis().dispose(); + database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose(); + } else { + int version = database.executeInt("PRAGMA user_version"); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("current db version = " + version); + } + if (version == 0) { + throw new Exception("malformed"); + } + //migration + } + if (!fromBackup) { + createBackup(); + } + FileLog.d("files db created from_backup= " + fromBackup); + } catch (Exception e) { + if (tryCount < 4) { + if (!fromBackup && restoreBackup()) { + createDatabase(tryCount + 1, true); + return; + } else { + cacheFile.delete(); + shmCacheFile.delete(); + createDatabase(tryCount + 1, false); + } + } + if (BuildVars.DEBUG_VERSION) { + FileLog.e(e); + } + } + } + + private void createBackup() { + File filesDir = ApplicationLoader.getFilesDirFixed(); + if (currentAccount != 0) { + filesDir = new File(filesDir, "account" + currentAccount + "/"); + filesDir.mkdirs(); + } + File backupCacheFile = new File(filesDir, DATABASE_BACKUP_NAME + ".db"); + try { + AndroidUtilities.copyFile(cacheFile, backupCacheFile); + FileLog.d("file db backup created " + backupCacheFile.getAbsolutePath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private boolean restoreBackup() { + File filesDir = ApplicationLoader.getFilesDirFixed(); + if (currentAccount != 0) { + filesDir = new File(filesDir, "account" + currentAccount + "/"); + filesDir.mkdirs(); + } + File backupCacheFile = new File(filesDir, DATABASE_BACKUP_NAME + ".db"); + if (!backupCacheFile.exists()) { + return false; + } + try { + return AndroidUtilities.copyFile(backupCacheFile, cacheFile); + } catch (IOException e) { + FileLog.e(e); + } + return false; + } + + public String getPath(long documentId, int dc, int type, boolean useQueue) { + if (useQueue) { + if (BuildVars.DEBUG_VERSION) { + if (dispatchQueue.getHandler() != null && Thread.currentThread() == dispatchQueue.getHandler().getLooper().getThread()) { + throw new RuntimeException("Error, lead to infinity loop"); + } + } + + CountDownLatch syncLatch = new CountDownLatch(1); + String[] res = new String[1]; + long time = System.currentTimeMillis(); + + dispatchQueue.postRunnable(() -> { + SQLiteCursor cursor = null; + try { + cursor = database.queryFinalized("SELECT path FROM paths WHERE document_id = " + documentId + " AND dc_id = " + dc + " AND type = " + type); + if (cursor.next()) { + res[0] = cursor.stringValue(0); + } + cursor.dispose(); + } catch (SQLiteException e) { + FileLog.e(e); + } + syncLatch.countDown(); + }); + try { + syncLatch.await(); + } catch (Exception ignore) { + } + return res[0]; + } else { + SQLiteCursor cursor = null; + String res = null; + try { + cursor = database.queryFinalized("SELECT path FROM paths WHERE document_id = " + documentId + " AND dc_id = " + dc + " AND type = " + type); + if (cursor.next()) { + res = cursor.stringValue(0); + } + cursor.dispose(); + } catch (SQLiteException e) { + FileLog.e(e); + } + return res; + } + } + + public void putPath(long id, int dc, int type, String path) { + dispatchQueue.postRunnable(() -> { + SQLitePreparedStatement state = null; + try { + if (path != null) { + state = database.executeFast("REPLACE INTO paths VALUES(?, ?, ?, ?)"); + state.requery(); + state.bindLong(1, id); + state.bindInteger(2, dc); + state.bindInteger(3, type); + state.bindString(4, path); + state.step(); + } else { + database.executeFast("DELETE FROM paths WHERE document_id = " + id + " AND dc_id = " + dc + " AND type = " + type).stepThis().dispose(); + } + } catch (SQLiteException e) { + FileLog.e(e); + } + }); + } + + public void checkMediaExistance(ArrayList messageObjects) { + if (messageObjects.isEmpty()) { + return; + } + ArrayList arrayListFinal = new ArrayList<>(messageObjects); + + CountDownLatch syncLatch = new CountDownLatch(1); + long time = System.currentTimeMillis(); + dispatchQueue.postRunnable(() -> { + try { + for (int i = 0; i < arrayListFinal.size(); i++) { + MessageObject messageObject = arrayListFinal.get(i); + messageObject.checkMediaExistance(false); + } + } catch (Exception e) { + e.printStackTrace(); + } + syncLatch.countDown(); + }); + + try { + syncLatch.await(); + } catch (InterruptedException e) { + FileLog.e(e); + } + + FileLog.d("checkMediaExistance size=" + messageObjects.size() + " time=" + (System.currentTimeMillis() - time)); + + if (BuildVars.DEBUG_VERSION) { + if (Thread.currentThread() == Looper.getMainLooper().getThread()) { + FileLog.e(new Exception("warning, not allowed in main thread")); + } + } + } + + public static class PathData { + public final long id; + public final int dc; + public final int type; + + public PathData(long documentId, int dcId, int type) { + this.id = documentId; + this.dc = dcId; + this.type = type; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index 65e07a2f4..adeaf8c7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -70,7 +70,16 @@ public class FileRefController extends BaseController { } public static String getKeyForParentObject(Object parentObject) { - if (parentObject instanceof MessageObject) { + if (parentObject instanceof TLRPC.TL_availableReaction) { + return "available_reaction_" + ((TLRPC.TL_availableReaction) parentObject).reaction; + } else if (parentObject instanceof TLRPC.BotInfo) { + TLRPC.BotInfo botInfo = (TLRPC.BotInfo) parentObject; + return "bot_info_" + botInfo.user_id; + } else if (parentObject instanceof TLRPC.TL_attachMenuBot) { + TLRPC.TL_attachMenuBot bot = (TLRPC.TL_attachMenuBot) parentObject; + long botId = bot.bot_id; + return "attach_menu_bot_" + botId; + } else if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; long channelId = messageObject.getChannelId(); return "message" + messageObject.getRealId() + "_" + channelId + "_" + messageObject.scheduled; @@ -309,7 +318,21 @@ public class FileRefController extends BaseController { } private void requestReferenceFromServer(Object parentObject, String locationKey, String parentKey, Object[] args) { - if (parentObject instanceof MessageObject) { + if (parentObject instanceof TLRPC.TL_availableReaction) { + TLRPC.TL_messages_getAvailableReactions req = new TLRPC.TL_messages_getAvailableReactions(); + req.hash = 0; + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + } else if (parentObject instanceof TLRPC.BotInfo) { + TLRPC.BotInfo botInfo = (TLRPC.BotInfo) parentObject; + TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser(); + req.id = getMessagesController().getInputUser(botInfo.user_id); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + } else if (parentObject instanceof TLRPC.TL_attachMenuBot) { + TLRPC.TL_attachMenuBot bot = (TLRPC.TL_attachMenuBot) parentObject; + TLRPC.TL_messages_getAttachMenuBot req = new TLRPC.TL_messages_getAttachMenuBot(); + req.bot = getMessagesController().getInputUser(bot.bot_id); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + } else if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; long channelId = messageObject.getChannelId(); if (messageObject.scheduled) { @@ -726,12 +749,84 @@ public class FileRefController extends BaseController { } } if (result == null) { - getMessagesStorage().replaceMessageIfExists(res.messages.get(0), res.users, res.chats,true); + getMessagesStorage().replaceMessageIfExists(res.messages.get(0), res.users, res.chats, true); if (BuildVars.DEBUG_VERSION) { FileLog.d("file ref not found in messages, replacing message"); } } } + } else if (response instanceof TLRPC.TL_messages_availableReactions) { + TLRPC.TL_messages_availableReactions availableReactions = (TLRPC.TL_messages_availableReactions) response; + getMediaDataController().processLoadedReactions(availableReactions.reactions, availableReactions.hash, (int) (System.currentTimeMillis() / 1000), false); + + for (TLRPC.TL_availableReaction reaction : availableReactions.reactions) { + result = getFileReference(reaction.static_icon, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.appear_animation, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.select_animation, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.activate_animation, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.effect_animation, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.around_animation, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + result = getFileReference(reaction.center_icon, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + } + } else if (response instanceof TLRPC.TL_users_userFull) { + TLRPC.TL_users_userFull usersFull = (TLRPC.TL_users_userFull) response; + getMessagesController().putUsers(usersFull.users, false); + getMessagesController().putChats(usersFull.chats, false); + TLRPC.UserFull userFull = usersFull.full_user; + TLRPC.BotInfo botInfo = userFull.bot_info; + if (botInfo != null) { + getMessagesStorage().updateUserInfo(userFull, true); + + result = getFileReference(botInfo.description_document, requester.location, needReplacement, locationReplacement); + + if (result != null) { + continue; + } + + result = getFileReference(botInfo.description_photo, requester.location, needReplacement, locationReplacement); + } + } else if (response instanceof TLRPC.TL_attachMenuBotsBot) { + TLRPC.TL_attachMenuBot bot = ((TLRPC.TL_attachMenuBotsBot) response).bot; + for (TLRPC.TL_attachMenuBotIcon icon : bot.icons) { + result = getFileReference(icon.icon, requester.location, needReplacement, locationReplacement); + if (result != null) { + break; + } + } + if (cache) { + TLRPC.TL_attachMenuBots bots = getMediaDataController().getAttachMenuBots(); + ArrayList newBotsList = new ArrayList<>(bots.bots); + for (int i = 0; i < newBotsList.size(); i++) { + TLRPC.TL_attachMenuBot wasBot = newBotsList.get(i); + if (wasBot.bot_id == bot.bot_id) { + newBotsList.set(i, bot); + break; + } + } + bots.bots = newBotsList; + getMediaDataController().processLoadedMenuBots(bots, bots.hash, (int) (System.currentTimeMillis() / 1000), false); + } } else if (response instanceof TLRPC.TL_help_appUpdate) { TLRPC.TL_help_appUpdate appUpdate = (TLRPC.TL_help_appUpdate) response; result = getFileReference(appUpdate.document, requester.location, needReplacement, locationReplacement); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java index 55ab9f99f..864a83383 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileStreamLoadOperation.java @@ -57,7 +57,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO document = new TLRPC.TL_document(); document.access_hash = Utilities.parseLong(uri.getQueryParameter("hash")); document.id = Utilities.parseLong(uri.getQueryParameter("id")); - document.size = Utilities.parseInt(uri.getQueryParameter("size")); + document.size = Utilities.parseLong(uri.getQueryParameter("size")); document.dc_id = Utilities.parseInt(uri.getQueryParameter("dc")); document.mime_type = uri.getQueryParameter("mime"); document.file_reference = Utilities.hexToBytes(uri.getQueryParameter("reference")); @@ -96,7 +96,7 @@ public class FileStreamLoadOperation extends BaseDataSource implements FileLoadO readLength = (int) bytesRemaining; } while (availableLength == 0 && opened) { - availableLength = loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength)[0]; + availableLength = (int) loadOperation.getDownloadedLengthFromOffset(currentOffset, readLength)[0]; if (availableLength == 0) { FileLoader.getInstance(currentAccount).loadStreamFile(this, document, null, parentObject, currentOffset, false); countDownLatch = new CountDownLatch(1); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java index 7ee6834b1..59248efbb 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileUploadOperation.java @@ -43,7 +43,7 @@ public class FileUploadOperation { private static final int initialRequestsSlowNetworkCount = 1; private static final int maxUploadingKBytes = 1024 * 2; private static final int maxUploadingSlowNetworkKBytes = 32; - private static final int maxUploadParts = (int) (FileLoader.MAX_FILE_SIZE / 1024 / 512); + private int maxRequestsCount; private int uploadChunkSize = 64 * 1024; private boolean slowNetwork; @@ -69,7 +69,7 @@ public class FileUploadOperation { private boolean isBigFile; private boolean forceSmallFile; private String fileKey; - private int estimatedSize; + private long estimatedSize; private int uploadStartTime; private RandomAccessFile stream; private boolean started; @@ -88,7 +88,7 @@ public class FileUploadOperation { void didChangedUploadProgress(FileUploadOperation operation, long uploadedSize, long totalSize); } - public FileUploadOperation(int instance, String location, boolean encrypted, int estimated, int type) { + public FileUploadOperation(int instance, String location, boolean encrypted, long estimated, int type) { currentAccount = instance; uploadingFilePath = location; isEncrypted = encrypted; @@ -229,12 +229,12 @@ public class FileUploadOperation { private void calcTotalPartsCount() { if (uploadFirstPartLater) { if (isBigFile) { - totalPartsCount = 1 + (int) ((totalFileSize - uploadChunkSize) + uploadChunkSize - 1) / uploadChunkSize; + totalPartsCount = 1 + (int) (((totalFileSize - uploadChunkSize) + uploadChunkSize - 1) / uploadChunkSize); } else { - totalPartsCount = 1 + (int) ((totalFileSize - 1024) + uploadChunkSize - 1) / uploadChunkSize; + totalPartsCount = 1 + (int) (((totalFileSize - 1024) + uploadChunkSize - 1) / uploadChunkSize); } } else { - totalPartsCount = (int) (totalFileSize + uploadChunkSize - 1) / uploadChunkSize; + totalPartsCount = (int) ((totalFileSize + uploadChunkSize - 1) / uploadChunkSize); } } @@ -279,7 +279,11 @@ public class FileUploadOperation { isBigFile = true; } - uploadChunkSize = (int) Math.max(slowNetwork ? minUploadChunkSlowNetworkSize : minUploadChunkSize, (totalFileSize + 1024 * maxUploadParts - 1) / (1024 * maxUploadParts)); + long maxUploadParts = MessagesController.getInstance(currentAccount).uploadMaxFileParts; + if (AccountInstance.getInstance(currentAccount).getUserConfig().isPremium() && totalFileSize > FileLoader.DEFAULT_MAX_FILE_SIZE) { + maxUploadParts = MessagesController.getInstance(currentAccount).uploadMaxFilePartsPremium; + } + uploadChunkSize = (int) Math.max(slowNetwork ? minUploadChunkSlowNetworkSize : minUploadChunkSize, (totalFileSize + 1024L * maxUploadParts - 1) / (1024L * maxUploadParts)); if (1024 % uploadChunkSize != 0) { int chunkSize = 64; while (uploadChunkSize > chunkSize) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FilesMigrationService.java b/TMessagesProj/src/main/java/org/telegram/messenger/FilesMigrationService.java new file mode 100644 index 000000000..e69de29bb diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index 16d887549..5977df01c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -94,6 +94,7 @@ public class ImageLoader { private LruCache memCache; private LruCache wallpaperMemCache; private LruCache lottieMemCache; + ArrayList cachedAnimatedFileDrawables = new ArrayList<>(); private HashMap imageLoadingByUrl = new HashMap<>(); private HashMap imageLoadingByKeys = new HashMap<>(); private SparseArray imageLoadingByTag = new SparseArray<>(); @@ -460,13 +461,13 @@ public class ImageLoader { private CacheImage cacheImage; private RandomAccessFile fileOutputStream; - private int imageSize; + private long imageSize; private long lastProgressTime; private boolean canRetry = true; private String overrideUrl; private HttpURLConnection httpConnection; - public HttpImageTask(CacheImage cacheImage, int size) { + public HttpImageTask(CacheImage cacheImage, long size) { this.cacheImage = cacheImage; imageSize = size; } @@ -812,7 +813,7 @@ public class ImageLoader { if (cacheImage.imageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize) { TLRPC.TL_photoStrippedSize photoSize = (TLRPC.TL_photoStrippedSize) cacheImage.imageLocation.photoSize; - Bitmap bitmap = getStrippedPhotoBitmap(photoSize.bytes, cacheImage.filter); + Bitmap bitmap = getStrippedPhotoBitmap(photoSize.bytes, "b"); onPostExecute(bitmap != null ? new BitmapDrawable(bitmap) : null); } else if (cacheImage.imageType == FileLoader.IMAGE_TYPE_THEME_PREVIEW) { BitmapDrawable bitmapDrawable = null; @@ -823,8 +824,8 @@ public class ImageLoader { } onPostExecute(bitmapDrawable); } else if (cacheImage.imageType == FileLoader.IMAGE_TYPE_SVG || cacheImage.imageType == FileLoader.IMAGE_TYPE_SVG_WHITE) { - int w = AndroidUtilities.dp(360); - int h = AndroidUtilities.dp(640); + int w = AndroidUtilities.displaySize.x; + int h = AndroidUtilities.displaySize.y; if (cacheImage.filter != null) { String[] args = cacheImage.filter.split("_"); if (args.length >= 2) { @@ -957,10 +958,22 @@ public class ImageLoader { } else { seekTo = 0; } - if (AUTOPLAY_FILTER.equals(cacheImage.filter) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted)) { + boolean limitFps = false; + if (cacheImage.filter != null) { + String[] args = cacheImage.filter.split("_"); + if (args.length >= 2) { + float w_filter = Float.parseFloat(args[0]); + float h_filter = Float.parseFloat(args[1]); + if (w_filter <= 90 && h_filter <= 90 && !cacheImage.filter.contains("nolimit")) { + limitFps = true; + } + } + } + if ((isAnimatedAvatar(cacheImage.filter) || AUTOPLAY_FILTER.equals(cacheImage.filter)) && !(cacheImage.imageLocation.document instanceof TLRPC.TL_documentEncrypted)) { TLRPC.Document document = cacheImage.imageLocation.document instanceof TLRPC.Document ? cacheImage.imageLocation.document : null; - int size = document != null ? cacheImage.size : cacheImage.imageLocation.currentSize; + long size = document != null ? cacheImage.size : cacheImage.imageLocation.currentSize; fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, false, size, document, document == null ? cacheImage.imageLocation : null, cacheImage.parentObject, seekTo, cacheImage.currentAccount, false); + fileDrawable.setIsWebmSticker(MessageObject.isWebM(document) || MessageObject.isVideoSticker(document) || isAnimatedAvatar(cacheImage.filter)); } else { int w = 0; @@ -974,8 +987,10 @@ public class ImageLoader { h = (int) (h_filter * AndroidUtilities.density); } } - fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, "d".equals(cacheImage.filter), 0, cacheImage.imageLocation.document, null, null, seekTo, cacheImage.currentAccount, false , w, h); + fileDrawable = new AnimatedFileDrawable(cacheImage.finalFilePath, "d".equals(cacheImage.filter), 0, cacheImage.imageLocation.document, null, null, seekTo, cacheImage.currentAccount, false, w, h); + fileDrawable.setIsWebmSticker(MessageObject.isWebM(cacheImage.imageLocation.document) || MessageObject.isVideoSticker(cacheImage.imageLocation.document) || isAnimatedAvatar(cacheImage.filter)); } + fileDrawable.setLimitFps(limitFps); Thread.interrupted(); onPostExecute(fileDrawable); } else { @@ -985,7 +1000,7 @@ public class ImageLoader { boolean needInvert = false; int orientation = 0; File cacheFileFinal = cacheImage.finalFilePath; - boolean inEncryptedFile = cacheImage.secureDocument != null || cacheImage.encryptionKeyPath != null && cacheFileFinal != null && cacheFileFinal.getAbsolutePath().endsWith(".enc"); + boolean inEncryptedFile = cacheImage.secureDocument != null || cacheImage.encryptionKeyPath != null && cacheFileFinal != null && (cacheFileFinal.getAbsolutePath().endsWith(".enc") || cacheFileFinal.getAbsolutePath().endsWith(".64enc")); SecureDocumentKey secureDocumentKey; byte[] secureDocumentHash; if (cacheImage.secureDocument != null) { @@ -1502,7 +1517,7 @@ public class ImageLoader { } else if (drawable instanceof AnimatedFileDrawable) { AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; if (animatedFileDrawable.isWebmSticker) { - toSet = getFromLottieCahce(cacheImage.key); + toSet = getFromLottieCache(cacheImage.key); if (toSet == null) { lottieMemCache.put(cacheImage.key, animatedFileDrawable); toSet = animatedFileDrawable; @@ -1557,6 +1572,10 @@ public class ImageLoader { } } + private boolean isAnimatedAvatar(String filter) { + return filter != null && filter.endsWith("avatar"); + } + private BitmapDrawable getFromMemCache(String key) { BitmapDrawable drawable = memCache.get(key); if (drawable == null) { @@ -1566,7 +1585,7 @@ public class ImageLoader { drawable = wallpaperMemCache.get(key); } if (drawable == null) { - drawable = getFromLottieCahce(key); + drawable = getFromLottieCache(key); } return drawable; } @@ -1602,7 +1621,7 @@ public class ImageLoader { protected SecureDocument secureDocument; protected ImageLocation imageLocation; protected Object parentObject; - protected int size; + protected long size; protected int imageType; protected int type; @@ -1728,7 +1747,7 @@ public class ImageLoader { AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) image; for (int a = 0; a < finalImageReceiverArray.size(); a++) { ImageReceiver imgView = finalImageReceiverArray.get(a); - AnimatedFileDrawable toSet = (a == 0 ? fileDrawable : fileDrawable.makeCopy()); + AnimatedFileDrawable toSet = fileDrawable; if (imgView.setImageBitmapByKey(toSet, key, type, false, finalImageReceiverGuidsArray.get(a))) { if (toSet == fileDrawable) { imageSet = true; @@ -1813,7 +1832,9 @@ public class ImageLoader { if (count == null || count == 0) { Bitmap b = oldValue.getBitmap(); if (!b.isRecycled()) { - b.recycle(); + ArrayList bitmapToRecycle = new ArrayList<>(); + bitmapToRecycle.add(b); + AndroidUtilities.recycleBitmaps(bitmapToRecycle); } } } @@ -1833,7 +1854,9 @@ public class ImageLoader { if (count == null || count == 0) { Bitmap b = oldValue.getBitmap(); if (!b.isRecycled()) { - b.recycle(); + ArrayList bitmapToRecycle = new ArrayList<>(); + bitmapToRecycle.add(b); + AndroidUtilities.recycleBitmaps(bitmapToRecycle); } } } @@ -1846,14 +1869,26 @@ public class ImageLoader { }; lottieMemCache = new LruCache(512 * 512 * 2 * 4 * 5) { + @Override protected int sizeOf(String key, BitmapDrawable value) { return value.getIntrinsicWidth() * value.getIntrinsicHeight() * 4 * 2; } + @Override + public BitmapDrawable put(String key, BitmapDrawable value) { + if (value instanceof AnimatedFileDrawable) { + cachedAnimatedFileDrawables.add((AnimatedFileDrawable) value); + } + return super.put(key, value); + } + @Override protected void entryRemoved(boolean evicted, String key, final BitmapDrawable oldValue, BitmapDrawable newValue) { final Integer count = bitmapUseCounts.get(key); + if (oldValue instanceof AnimatedFileDrawable) { + cachedAnimatedFileDrawables.remove((AnimatedFileDrawable) oldValue); + } if (count == null || count == 0) { if (oldValue instanceof AnimatedFileDrawable) { ((AnimatedFileDrawable) oldValue).recycle(); @@ -1911,11 +1946,22 @@ public class ImageLoader { public void fileDidLoaded(final String location, final File finalFile, Object parentObject, final int type) { fileProgresses.remove(location); AndroidUtilities.runOnUIThread(() -> { - if (SharedConfig.saveToGallery && finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) { + if (SharedConfig.saveToGalleryFlags != 0 && finalFile != null && (location.endsWith(".mp4") || location.endsWith(".jpg"))) { if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; - // test add only for peer dialogs - if (messageObject.getDialogId() >= 0) { + + long dialogId = messageObject.getDialogId(); + int flag; + if (dialogId >= 0) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_PEER; + } else { + if (ChatObject.isChannelAndNotMegaGroup(MessagesController.getInstance(currentAccount).getChat(-dialogId))) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_CHANNELS; + } else { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_GROUP; + } + } + if ((SharedConfig.saveToGalleryFlags & flag) != 0) { AndroidUtilities.addMediaToGallery(finalFile.toString()); } } @@ -2094,7 +2140,7 @@ public class ImageLoader { if (type == FileLoader.MEDIA_DIR_IMAGE) { srcFile = new File(from, "000000000_999999_temp.f"); dstFile = new File(to, "000000000_999999.f"); - } else if (type == FileLoader.MEDIA_DIR_DOCUMENT) { + } else if (type == FileLoader.MEDIA_DIR_DOCUMENT || type == FileLoader.MEDIA_DIR_FILES) { srcFile = new File(from, "000000000_999999_temp.f"); dstFile = new File(to, "000000000_999999.f"); } else if (type == FileLoader.MEDIA_DIR_AUDIO) { @@ -2223,7 +2269,7 @@ public class ImageLoader { public boolean isInMemCache(String key, boolean animated) { if (animated) { - return getFromLottieCahce(key) != null; + return getFromLottieCache(key) != null; } else { return getFromMemCache(key) != null; } @@ -2382,7 +2428,7 @@ public class ImageLoader { imageLoadQueue.postRunnable(() -> forceLoadingImages.remove(key)); } - private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final ImageLocation imageLocation, final String filter, final int size, final int cacheType, final int type, final int thumb, int guid) { + private void createLoadOperationForImageReceiver(final ImageReceiver imageReceiver, final String key, final String url, final String ext, final ImageLocation imageLocation, final String filter, final long size, final int cacheType, final int type, final int thumb, int guid) { if (imageReceiver == null || url == null || key == null || imageLocation == null) { return; } @@ -2398,7 +2444,7 @@ public class ImageLoader { final int finalTag = TAG; final boolean finalIsNeedsQualityThumb = imageReceiver.isNeedsQualityThumb(); final Object parentObject = imageReceiver.getParentObject(); - final TLRPC.Document qualityDocument = imageReceiver.getQulityThumbDocument(); + final TLRPC.Document qualityDocument = imageReceiver.getQualityThumbDocument(); final boolean shouldGenerateQualityThumb = imageReceiver.isShouldGenerateQualityThumb(); final int currentAccount = imageReceiver.getCurrentAccount(); final boolean currentKeyQuality = type == ImageReceiver.TYPE_IMAGE && imageReceiver.isCurrentKeyQuality(); @@ -2470,12 +2516,12 @@ public class ImageLoader { MessageObject parentMessageObject = (MessageObject) parentObject; parentDocument = parentMessageObject.getDocument(); localPath = parentMessageObject.messageOwner.attachPath; - cachePath = FileLoader.getPathToMessage(parentMessageObject.messageOwner); + cachePath = FileLoader.getInstance(currentAccount).getPathToMessage(parentMessageObject.messageOwner); mediaType = parentMessageObject.getMediaType(); bigThumb = false; } else if (qualityDocument != null) { parentDocument = qualityDocument; - cachePath = FileLoader.getPathToAttach(parentDocument, true); + cachePath = FileLoader.getInstance(currentAccount).getPathToAttach(parentDocument, true); if (MessageObject.isVideoDocument(parentDocument)) { mediaType = FileLoader.MEDIA_DIR_VIDEO; } else { @@ -2554,14 +2600,14 @@ public class ImageLoader { } if (cacheFile == null) { - int fileSize = 0; + long fileSize = 0; if (imageLocation.photoSize instanceof TLRPC.TL_photoStrippedSize || imageLocation.photoSize instanceof TLRPC.TL_photoPathSize) { onlyCache = true; } else if (imageLocation.secureDocument != null) { img.secureDocument = imageLocation.secureDocument; onlyCache = img.secureDocument.secureFile.dc_id == Integer.MIN_VALUE; cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); - } else if (!AUTOPLAY_FILTER.equals(filter) && (cacheType != 0 || size <= 0 || imageLocation.path != null || isEncrypted)) { + } else if (!(AUTOPLAY_FILTER.equals(filter) || isAnimatedAvatar(filter)) && (cacheType != 0 || size <= 0 || imageLocation.path != null || isEncrypted)) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), url); if (cacheFile.exists()) { cacheFileExists = true; @@ -2600,7 +2646,7 @@ public class ImageLoader { } else { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), url); } - if (AUTOPLAY_FILTER.equals(filter) && !cacheFile.exists()) { + if ((isAnimatedAvatar(filter) || AUTOPLAY_FILTER.equals(filter)) && !cacheFile.exists()) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), document.dc_id + "_" + document.id + ".temp"); } if (document instanceof DocumentObject.ThemeDocument) { @@ -2631,11 +2677,11 @@ public class ImageLoader { } else { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_IMAGE), url); } - if (AUTOPLAY_FILTER.equals(filter) && imageLocation.location != null && !cacheFile.exists()) { + if (isAnimatedAvatar(filter) || AUTOPLAY_FILTER.equals(filter) && imageLocation.location != null && !cacheFile.exists()) { cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), imageLocation.location.volume_id + "_" + imageLocation.location.local_id + ".temp"); } } - if (AUTOPLAY_FILTER.equals(filter)) { + if (AUTOPLAY_FILTER.equals(filter) || isAnimatedAvatar(filter)) { img.imageType = FileLoader.IMAGE_TYPE_ANIMATION; img.size = fileSize; onlyCache = true; @@ -2752,8 +2798,8 @@ public class ImageLoader { if (mediaKey != null) { ImageLocation mediaLocation = imageReceiver.getMediaLocation(); Drawable drawable; - if (useLottieMemChache(mediaLocation)) { - drawable = getFromLottieCahce(mediaKey); + if (useLottieMemCache(mediaLocation, mediaKey)) { + drawable = getFromLottieCache(mediaKey); } else { drawable = memCache.get(mediaKey); if (drawable != null) { @@ -2785,8 +2831,8 @@ public class ImageLoader { if (!imageSet && imageKey != null) { ImageLocation imageLocation = imageReceiver.getImageLocation(); Drawable drawable = null; - if (useLottieMemChache(imageLocation)) { - drawable = getFromLottieCahce(imageKey); + if (useLottieMemCache(imageLocation, imageKey)) { + drawable = getFromLottieCache(imageKey); } if (drawable == null) { drawable = memCache.get(imageKey); @@ -2820,8 +2866,8 @@ public class ImageLoader { if (thumbKey != null) { ImageLocation thumbLocation = imageReceiver.getThumbLocation(); Drawable drawable; - if (useLottieMemChache(thumbLocation)) { - drawable = getFromLottieCahce(thumbKey); + if (useLottieMemCache(thumbLocation, thumbKey)) { + drawable = getFromLottieCache(thumbKey); } else { drawable = memCache.get(thumbKey); if (drawable != null) { @@ -2852,7 +2898,7 @@ public class ImageLoader { boolean qualityThumb = false; Object parentObject = imageReceiver.getParentObject(); - TLRPC.Document qualityDocument = imageReceiver.getQulityThumbDocument(); + TLRPC.Document qualityDocument = imageReceiver.getQualityThumbDocument(); ImageLocation thumbLocation = imageReceiver.getThumbLocation(); String thumbFilter = imageReceiver.getThumbFilter(); ImageLocation mediaLocation = imageReceiver.getMediaLocation(); @@ -3034,7 +3080,7 @@ public class ImageLoader { } } - private BitmapDrawable getFromLottieCahce(String imageKey) { + private BitmapDrawable getFromLottieCache(String imageKey) { BitmapDrawable drawable = lottieMemCache.get(imageKey); if (drawable instanceof AnimatedFileDrawable) { if (((AnimatedFileDrawable) drawable).isRecycled()) { @@ -3045,8 +3091,8 @@ public class ImageLoader { return drawable; } - private boolean useLottieMemChache(ImageLocation imageLocation) { - return imageLocation != null && (MessageObject.isAnimatedStickerDocument(imageLocation.document, true) || imageLocation.imageType == FileLoader.IMAGE_TYPE_LOTTIE || MessageObject.isVideoSticker(imageLocation.document)); + private boolean useLottieMemCache(ImageLocation imageLocation, String key) { + return imageLocation != null && (MessageObject.isAnimatedStickerDocument(imageLocation.document, true) || imageLocation.imageType == FileLoader.IMAGE_TYPE_LOTTIE || MessageObject.isVideoSticker(imageLocation.document)) || isAnimatedAvatar(key); } private void httpFileLoadError(final String location) { @@ -3434,7 +3480,7 @@ public class ImageLoader { if (photoSize == null || photoSize.bytes != null && photoSize.bytes.length != 0) { return; } - File file = FileLoader.getPathToAttach(photoSize, true); + File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoSize, true); try { RandomAccessFile f = new RandomAccessFile(file, "r"); int len = (int) f.length(); @@ -3491,16 +3537,17 @@ public class ImageLoader { fileDir = location.volume_id != Integer.MIN_VALUE ? FileLoader.getDirectory(FileLoader.MEDIA_DIR_IMAGE) : FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE); } final File cacheFile = new File(fileDir, fileName); - if (compressFormat == Bitmap.CompressFormat.JPEG && progressive && BuildVars.DEBUG_VERSION) { - photoSize.size = Utilities.saveProgressiveJpeg(scaledBitmap, scaledBitmap.getWidth(), scaledBitmap.getHeight(), scaledBitmap.getRowBytes(), quality, cacheFile.getAbsolutePath()); - } else { - FileOutputStream stream = new FileOutputStream(cacheFile); - scaledBitmap.compress(compressFormat, quality, stream); - if (!cache) { - photoSize.size = (int) stream.getChannel().size(); - } - stream.close(); + //TODO was crash in DEBUG_PRIVATE +// if (compressFormat == Bitmap.CompressFormat.JPEG && progressive && BuildVars.DEBUG_VERSION) { +// photoSize.size = Utilities.saveProgressiveJpeg(scaledBitmap, scaledBitmap.getWidth(), scaledBitmap.getHeight(), scaledBitmap.getRowBytes(), quality, cacheFile.getAbsolutePath()); +// } else { + FileOutputStream stream = new FileOutputStream(cacheFile); + scaledBitmap.compress(compressFormat, quality, stream); + if (!cache) { + photoSize.size = (int) stream.getChannel().size(); } + stream.close(); + // } if (cache) { ByteArrayOutputStream stream2 = new ByteArrayOutputStream(); scaledBitmap.compress(compressFormat, quality, stream2); @@ -3604,7 +3651,7 @@ public class ImageLoader { photoSize.location.volume_id = Integer.MIN_VALUE; photoSize.location.local_id = SharedConfig.getLastLocalId(); } - File file = FileLoader.getPathToAttach(photoSize, true); + File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoSize, true); boolean isEncrypted = false; if (MessageObject.shouldEncryptPhotoOrVideo(message)) { file = new File(file.getAbsolutePath() + ".enc"); @@ -3718,7 +3765,7 @@ public class ImageLoader { TLRPC.PhotoSize photoSize = findPhotoCachedSize(message); if (photoSize != null && photoSize.bytes != null && photoSize.bytes.length != 0) { - File file = FileLoader.getPathToAttach(photoSize, true); + File file = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoSize, true); TLRPC.TL_photoSize newPhotoSize = new TLRPC.TL_photoSize_layer127(); newPhotoSize.w = photoSize.w; @@ -3767,7 +3814,7 @@ public class ImageLoader { } Point point = ChatMessageCell.getMessageSize(w, h); - String key = String.format(Locale.US, "%s_false@%d_%d_b", ImageLocation.getStippedKey(message, message, size), (int) (point.x / AndroidUtilities.density), (int) (point.y / AndroidUtilities.density)); + String key = String.format(Locale.US, "%s_false@%d_%d_b", ImageLocation.getStrippedKey(message, message, size), (int) (point.x / AndroidUtilities.density), (int) (point.y / AndroidUtilities.density)); if (!getInstance().isInMemCache(key, false)) { Bitmap b = getStrippedPhotoBitmap(size.bytes, null); if (b != null) { @@ -3786,6 +3833,12 @@ public class ImageLoader { return null; } + public void onFragmentStackChanged() { + for (int i = 0; i < cachedAnimatedFileDrawables.size(); i++) { + cachedAnimatedFileDrawables.get(i).repeatCount = 0; + } + } + public DispatchQueue getCacheOutQueue() { return cacheOutQueue; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java index ac7559b45..c9b8a5e61 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLocation.java @@ -30,7 +30,7 @@ public class ImageLocation { public int thumbVersion; - public int currentSize; + public long currentSize; public long photoId; public long documentId; @@ -107,6 +107,7 @@ public class ImageLocation { public static final int TYPE_BIG = 0; public static final int TYPE_SMALL = 1; public static final int TYPE_STRIPPED = 2; + public static final int TYPE_VIDEO_THUMB = 3; public static ImageLocation getForUserOrChat(TLObject object, int type) { if (object instanceof TLRPC.User) { @@ -129,6 +130,23 @@ public class ImageLocation { if (user == null || user.access_hash == 0 || user.photo == null) { return null; } + if (type == TYPE_VIDEO_THUMB) { + int currentAccount = UserConfig.selectedAccount; + if (MessagesController.getInstance(currentAccount).isPremiumUser(user) && user.photo.has_video) { + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id); + if (userFull != null && userFull.profile_photo !=null && userFull.profile_photo.video_sizes != null && !userFull.profile_photo.video_sizes.isEmpty()) { + TLRPC.VideoSize videoSize = userFull.profile_photo.video_sizes.get(0); + for (int i = 0; i < userFull.profile_photo.video_sizes.size(); i++) { + if ("p".equals(userFull.profile_photo.video_sizes.get(i).type)) { + videoSize = userFull.profile_photo.video_sizes.get(i); + break; + } + } + return ImageLocation.getForPhoto(videoSize, userFull.profile_photo); + } + } + return null; + } if (type == TYPE_STRIPPED) { if (user.photo.stripped_thumb == null) { return null; @@ -223,7 +241,11 @@ public class ImageLocation { return null; } ImageLocation location = getForPhoto(videoSize.location, videoSize.size, null, document, null, TYPE_SMALL, document.dc_id, null, videoSize.type); - location.imageType = FileLoader.IMAGE_TYPE_ANIMATION; + if ("f".equals(videoSize.type)) { + location.imageType = FileLoader.IMAGE_TYPE_LOTTIE; + } else { + location.imageType = FileLoader.IMAGE_TYPE_ANIMATION; + } return location; } @@ -301,7 +323,7 @@ public class ImageLocation { return imageLocation; } - public static String getStippedKey(Object parentObject, Object fullObject, Object strippedObject) { + public static String getStrippedKey(Object parentObject, Object fullObject, Object strippedObject) { if (parentObject instanceof TLRPC.WebPage) { if (fullObject instanceof ImageLocation) { ImageLocation imageLocation = (ImageLocation) fullObject; @@ -341,7 +363,7 @@ public class ImageLocation { return secureDocument.secureFile.dc_id + "_" + secureDocument.secureFile.id; } else if (photoSize instanceof TLRPC.TL_photoStrippedSize || photoSize instanceof TLRPC.TL_photoPathSize) { if (photoSize.bytes.length > 0) { - return getStippedKey(parentObject, fullObject, photoSize); + return getStrippedKey(parentObject, fullObject, photoSize); } } else if (location != null) { return location.volume_id + "_" + location.local_id; @@ -365,7 +387,7 @@ public class ImageLocation { return key != null; } - public int getSize() { + public long getSize() { if (photoSize != null) { return photoSize.size; } else if (secureDocument != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index d913399af..9853a0ed0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -20,6 +20,7 @@ import android.graphics.Path; 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.BitmapDrawable; @@ -132,7 +133,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg public ImageLocation mediaLocation; public String mediaFilter; public Drawable thumb; - public int size; + public long size; public int cacheType; public Object parentObject; public String ext; @@ -221,7 +222,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private int currentGuid; - private int currentSize; + private long currentSize; private int currentCacheType; private boolean allowStartAnimation = true; private boolean allowStartLottieAnimation = true; @@ -278,6 +279,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private String uniqKeyPrefix; private ArrayList loadingOperations = new ArrayList<>(); private boolean attachedToWindow; + private boolean videoThumbIsSame; + + public int animatedFileDrawableRepeatMaxCount; public ImageReceiver() { this(null); @@ -319,11 +323,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg setImage(imageLocation, imageFilter, null, null, thumb, 0, ext, parentObject, cacheType); } - public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { + public void setImage(ImageLocation imageLocation, String imageFilter, Drawable thumb, long size, String ext, Object parentObject, int cacheType) { setImage(imageLocation, imageFilter, null, null, thumb, size, ext, parentObject, cacheType); } - public void setImage(String imagePath, String imageFilter, Drawable thumb, String ext, int size) { + public void setImage(String imagePath, String imageFilter, Drawable thumb, String ext, long size) { setImage(ImageLocation.getForPath(imagePath), imageFilter, null, null, thumb, size, ext, null, 1); } @@ -331,26 +335,46 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, 0, ext, parentObject, cacheType); } - public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, int size, String ext, Object parentObject, int cacheType) { + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, long size, String ext, Object parentObject, int cacheType) { setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, size, ext, parentObject, cacheType); } public void setForUserOrChat(TLObject object, Drawable avatarDrawable) { setForUserOrChat(object, avatarDrawable, null); } - public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object parentObject) { + setForUserOrChat(object, avatarDrawable, null, false); + } + + public void setForUserOrChat(TLObject object, Drawable avatarDrawable, Object parentObject, boolean animationEnabled) { if (parentObject == null) { parentObject = object; } setUseRoundForThumbDrawable(true); BitmapDrawable strippedBitmap = null; boolean hasStripped = false; + ImageLocation videoLocation = null; if (object instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) object; if (user.photo != null) { strippedBitmap = user.photo.strippedBitmap; hasStripped = user.photo.stripped_thumb != null; + if (MessagesController.getInstance(currentAccount).isPremiumUser(user) && user.photo.has_video && animationEnabled) { + final TLRPC.UserFull userFull = MessagesController.getInstance(currentAccount).getUserFull(user.id); + if (userFull == null) { + MessagesController.getInstance(currentAccount).loadFullUser(user, currentGuid, false); + } + if (userFull != null && userFull.profile_photo != null && userFull.profile_photo.video_sizes != null && !userFull.profile_photo.video_sizes.isEmpty()) { + TLRPC.VideoSize videoSize = userFull.profile_photo.video_sizes.get(0); + for (int i = 0; i < userFull.profile_photo.video_sizes.size(); i++) { + if ("p".equals(userFull.profile_photo.video_sizes.get(i).type)) { + videoSize = userFull.profile_photo.video_sizes.get(i); + break; + } + } + videoLocation = ImageLocation.getForPhoto(videoSize, userFull.profile_photo); + } + } } } else if (object instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) object; @@ -359,24 +383,32 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg hasStripped = chat.photo.stripped_thumb != null; } } - if (strippedBitmap != null) { - setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", strippedBitmap, null, parentObject, 0); - } else if (hasStripped) { - setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50_b", avatarDrawable, parentObject, 0); + ImageLocation location = ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL); + String filter = "50_50"; + if (videoLocation != null) { + setImage(videoLocation, "avatar", location, filter, null, null,strippedBitmap, 0, null, parentObject, 0); + animatedFileDrawableRepeatMaxCount = 3; } else { - setImage(ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, null, parentObject, 0); + if (strippedBitmap != null) { + setImage(location, filter, strippedBitmap, null, parentObject, 0); + } else if (hasStripped) { + setImage(location, filter, ImageLocation.getForUserOrChat(object, ImageLocation.TYPE_STRIPPED), "50_50_b", avatarDrawable, parentObject, 0); + } else { + setImage(location, filter, avatarDrawable, null, parentObject, 0); + } } + } public void setImage(ImageLocation fileLocation, String fileFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, Object parentObject, int cacheType) { setImage(null, null, fileLocation, fileFilter, thumbLocation, thumbFilter, thumb, 0, null, parentObject, cacheType); } - public void setImage(ImageLocation fileLocation, String fileFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { + public void setImage(ImageLocation fileLocation, String fileFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, long size, String ext, Object parentObject, int cacheType) { setImage(null, null, fileLocation, fileFilter, thumbLocation, thumbFilter, thumb, size, ext, parentObject, cacheType); } - public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, int size, String ext, Object parentObject, int cacheType) { + public void setImage(ImageLocation mediaLocation, String mediaFilter, ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, Drawable thumb, long size, String ext, Object parentObject, int cacheType) { if (ignoreImageSet) { return; } @@ -445,6 +477,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (imageKey == null && imageLocation != null) { imageLocation = null; } + animatedFileDrawableRepeatMaxCount = 0; currentKeyQuality = false; if (imageKey == null && needsQualityThumb && (parentObject instanceof MessageObject || qulityThumbDocument != null)) { TLRPC.Document document = qulityThumbDocument != null ? qulityThumbDocument : ((MessageObject) parentObject).getDocument(); @@ -497,6 +530,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (currentMediaDrawable != null) { if (currentMediaDrawable instanceof AnimatedFileDrawable) { ((AnimatedFileDrawable) currentMediaDrawable).stop(); + ((AnimatedFileDrawable) currentMediaDrawable).removeParent(this); } recycleBitmap(thumbKey, TYPE_THUMB); recycleBitmap(null, TYPE_CROSSFDADE); @@ -712,11 +746,11 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) bitmap; fileDrawable.setParentView(parentView); if (attachedToWindow) { - fileDrawable.addParent(parentView); + fileDrawable.addParent(this); } fileDrawable.setUseSharedQueue(useSharedAnimationQueue || fileDrawable.isWebmSticker); if (allowStartAnimation && currentOpenedLayerFlags == 0) { - fileDrawable.start(); + fileDrawable.checkRepeat(); } fileDrawable.setAllowDecodeSingleFrame(allowDecodeSingleFrame); } else if (bitmap instanceof RLottieDrawable) { @@ -733,6 +767,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg updateDrawableRadius(bitmap); currentMediaLocation = null; currentMediaFilter = null; + if (currentMediaDrawable instanceof AnimatedFileDrawable) { + ((AnimatedFileDrawable) currentMediaDrawable).removeParent(this); + } currentMediaDrawable = null; currentMediaKey = null; mediaShader = null; @@ -834,7 +871,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; animatedFileDrawable.setRoundRadius(roundRadius); } else if (bitmapDrawable.getBitmap() != null) { - setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + setDrawableShader(drawable, new BitmapShader(bitmapDrawable.getBitmap(), Shader.TileMode.REPEAT, Shader.TileMode.REPEAT)); } } else { setDrawableShader(drawable, null); @@ -882,7 +919,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg AnimatedFileDrawable animatedFileDrawable = getAnimation(); if (animatedFileDrawable != null) { - animatedFileDrawable.removeParent(parentView); + animatedFileDrawable.removeParent(this); } } @@ -918,10 +955,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } AnimatedFileDrawable animatedFileDrawable = getAnimation(); if (animatedFileDrawable != null && parentView != null) { - animatedFileDrawable.addParent(parentView); + animatedFileDrawable.addParent(this); } if (animatedFileDrawable != null && allowStartAnimation && currentOpenedLayerFlags == 0) { - animatedFileDrawable.start(); + animatedFileDrawable.checkRepeat(); if (parentView != null) { parentView.invalidate(); } @@ -1040,12 +1077,13 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg drawRegion.set(imageX + (imageW - bitmapW) / 2, imageY + (imageH - bitmapH) / 2, imageX + (imageW + bitmapW) / 2, imageY + (imageH + bitmapH) / 2); if (isVisible) { - roundPaint.setShader(shader); shaderMatrix.reset(); - shaderMatrix.setTranslate(drawRegion.left, drawRegion.top); + shaderMatrix.setTranslate((int) drawRegion.left, (int) drawRegion.top); + float toScale = 1.0f / scale; shaderMatrix.preScale(1.0f / scale, 1.0f / scale); shader.setLocalMatrix(shaderMatrix); + roundPaint.setShader(shader); roundPaint.setAlpha(alpha); roundRect.set(drawRegion); @@ -1101,7 +1139,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } if (isVisible) { shaderMatrix.reset(); - shaderMatrix.setTranslate(drawRegion.left + sideClip, drawRegion.top + sideClip); + shaderMatrix.setTranslate((int) (drawRegion.left + sideClip), (int) (drawRegion.top + sideClip)); if (orientation == 90) { shaderMatrix.preRotate(90); shaderMatrix.preTranslate(0, -drawRegion.width()); @@ -1789,6 +1827,15 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg imageH = height; } + public void setImageCoords(Rect bounds) { + if (bounds != null) { + imageX = bounds.left; + imageY = bounds.top; + imageW = bounds.width(); + imageH = bounds.height(); + } + } + public void setSideClip(float value) { sideClip = value; } @@ -1857,7 +1904,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg return currentThumbKey; } - public int getSize() { + public long getSize() { return currentSize; } @@ -1957,7 +2004,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg qulityThumbDocument = document; } - public TLRPC.Document getQulityThumbDocument() { + public TLRPC.Document getQualityThumbDocument() { return qulityThumbDocument; } @@ -2109,6 +2156,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (!key.equals(currentImageKey)) { return false; } + boolean allowCrossFade = true; if (!(drawable instanceof AnimatedFileDrawable)) { ImageLoader.getInstance().incrementUseCount(currentImageKey); } else { @@ -2117,6 +2165,9 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg if (animatedFileDrawable.isWebmSticker) { ImageLoader.getInstance().incrementUseCount(currentImageKey); } + if (videoThumbIsSame) { + allowCrossFade = !animatedFileDrawable.hasBitmap(); + } } currentImageDrawable = drawable; if (drawable instanceof ExtendedBitmapDrawable) { @@ -2124,14 +2175,14 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } updateDrawableRadius(drawable); - if (isVisible && (!memCache && !forcePreview || forceCrossfade) && crossfadeDuration != 0) { - boolean allowCorssfade = true; + if (allowCrossFade && isVisible && (!memCache && !forcePreview || forceCrossfade) && crossfadeDuration != 0) { + boolean allowCrossfade = true; if (currentMediaDrawable instanceof AnimatedFileDrawable && ((AnimatedFileDrawable) currentMediaDrawable).hasBitmap()) { - allowCorssfade = false; + allowCrossfade = false; } else if (currentImageDrawable instanceof RLottieDrawable) { - allowCorssfade = staticThumbDrawable instanceof LoadingStickerDrawable || staticThumbDrawable instanceof SvgHelper.SvgDrawable || staticThumbDrawable instanceof Emoji.EmojiDrawable; + allowCrossfade = staticThumbDrawable instanceof LoadingStickerDrawable || staticThumbDrawable instanceof SvgHelper.SvgDrawable || staticThumbDrawable instanceof Emoji.EmojiDrawable; } - if (allowCorssfade && (currentThumbDrawable != null || staticThumbDrawable != null || forceCrossfade)) { + if (allowCrossfade && (currentThumbDrawable != null || staticThumbDrawable != null || forceCrossfade)) { if (currentThumbDrawable != null && staticThumbDrawable != null) { previousAlpha = currentAlpha; } else { @@ -2155,7 +2206,16 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) drawable; animatedFileDrawable.setStartEndTime(startTime, endTime); if (animatedFileDrawable.isWebmSticker) { - ImageLoader.getInstance().incrementUseCount(currentImageKey); + ImageLoader.getInstance().incrementUseCount(currentMediaKey); + } + if (videoThumbIsSame && (currentThumbDrawable instanceof AnimatedFileDrawable || currentImageDrawable instanceof AnimatedFileDrawable)) { + long currentTimestamp = 0; + if (currentThumbDrawable instanceof AnimatedFileDrawable) { + currentTimestamp = ((AnimatedFileDrawable) currentThumbDrawable).getLastFrameTimestamp(); + } else if (currentImageDrawable instanceof AnimatedFileDrawable) { + currentTimestamp = ((AnimatedFileDrawable) currentImageDrawable).getLastFrameTimestamp(); + } + animatedFileDrawable.seekTo(currentTimestamp, true, true); } } currentMediaDrawable = drawable; @@ -2225,10 +2285,10 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg AnimatedFileDrawable fileDrawable = (AnimatedFileDrawable) drawable; fileDrawable.setUseSharedQueue(useSharedAnimationQueue); if (attachedToWindow) { - fileDrawable.addParent(parentView); + fileDrawable.addParent(this); } if (allowStartAnimation && currentOpenedLayerFlags == 0) { - fileDrawable.start(); + fileDrawable.checkRepeat(); } fileDrawable.setAllowDecodeSingleFrame(allowDecodeSingleFrame); animationReadySent = false; @@ -2291,8 +2351,8 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg lottieDrawable.removeParentView(parentView); } if (image instanceof AnimatedFileDrawable) { - AnimatedFileDrawable lottieDrawable = (AnimatedFileDrawable) image; - lottieDrawable.removeParent(parentView); + AnimatedFileDrawable animatedFileDrawable = (AnimatedFileDrawable) image; + animatedFileDrawable.removeParent(this); } if (key != null && (newKey == null || !newKey.equals(key)) && image != null) { if (image instanceof RLottieDrawable) { @@ -2315,14 +2375,18 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg fileDrawable.stop(); } } else { - fileDrawable.recycle(); + if (fileDrawable.getParents().isEmpty()) { + fileDrawable.recycle(); + } } } else if (image instanceof BitmapDrawable) { Bitmap bitmap = ((BitmapDrawable) image).getBitmap(); boolean canDelete = ImageLoader.getInstance().decrementUseCount(key); if (!ImageLoader.getInstance().isInMemCache(key, false)) { if (canDelete) { - bitmap.recycle(); + ArrayList bitmapToRecycle = new ArrayList<>(); + bitmapToRecycle.add(bitmap); + AndroidUtilities.recycleBitmaps(bitmapToRecycle); } } } @@ -2400,7 +2464,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg } AnimatedFileDrawable animatedFileDrawable = getAnimation(); if (allowStartAnimation && animatedFileDrawable != null) { - animatedFileDrawable.start(); + animatedFileDrawable.checkRepeat(); if (parentView != null) { parentView.invalidate(); } @@ -2440,4 +2504,17 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg ImageLoader.getInstance().moveToFront(currentImageKey); ImageLoader.getInstance().moveToFront(currentThumbKey); } + + public View getParentView() { + return parentView; + } + + public boolean isAttachedToWindow() { + return attachedToWindow; + } + + public void setVideoThumbIsSame(boolean b) { + videoThumbIsSame = b; + } + } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 655d33074..d06b25d8f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -1161,14 +1161,17 @@ public class LocaleController { return getString(param, key + "_other", resourceId); } - public static String formatPluralString(String key, int plural) { + public static String formatPluralString(String key, int plural, Object... args) { if (key == null || key.length() == 0 || getInstance().currentPluralRules == null) { return "LOC_ERR:" + key; } String param = getInstance().stringForQuantity(getInstance().currentPluralRules.quantityForNumber(plural)); param = key + "_" + param; int resourceId = ApplicationLoader.applicationContext.getResources().getIdentifier(param, "string", ApplicationLoader.applicationContext.getPackageName()); - return formatString(param, key + "_other", resourceId, plural); + Object[] argsWithPlural = new Object[args.length + 1]; + argsWithPlural[0] = plural; + System.arraycopy(args, 0, argsWithPlural, 1, args.length); + return formatString(param, key + "_other", resourceId, argsWithPlural); } public static String formatPluralStringComma(String key, int plural) { @@ -1798,15 +1801,17 @@ public class LocaleController { return text; } - public static String formatDateOnline(long date) { + public static String formatDateOnline(long date, boolean[] madeShorter) { try { date *= 1000; Calendar rightNow = Calendar.getInstance(); int day = rightNow.get(Calendar.DAY_OF_YEAR); int year = rightNow.get(Calendar.YEAR); + int hour = rightNow.get(Calendar.HOUR_OF_DAY); rightNow.setTimeInMillis(date); int dateDay = rightNow.get(Calendar.DAY_OF_YEAR); int dateYear = rightNow.get(Calendar.YEAR); + int dateHour = rightNow.get(Calendar.HOUR_OF_DAY); PersianDate persianDate = null; if (usePersianCalendar) { persianDate = new PersianDate(date); @@ -1823,7 +1828,15 @@ public class LocaleController { return LocaleController.formatPluralString("LastSeenHours", (int) Math.ceil(diff / 60.0f)); }*/ } else if (dateDay + 1 == day && year == dateYear) { - return LocaleController.formatString("LastSeenFormatted", R.string.LastSeenFormatted, LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date)))); + if (madeShorter != null) { + madeShorter[0] = true; + if (hour <= 6 && dateHour > 18 && is24HourFormat) { + return LocaleController.formatString("LastSeenFormatted", R.string.LastSeenFormatted, getInstance().formatterDay.format(new Date(date))); + } + return LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date))); + } else { + return LocaleController.formatString("LastSeenFormatted", R.string.LastSeenFormatted, LocaleController.formatString("YesterdayAtFormatted", R.string.YesterdayAtFormatted, getInstance().formatterDay.format(new Date(date)))); + } } else if (Math.abs(System.currentTimeMillis() - date) < 31536000000L) { if (usePersianCalendar) { String format = LocaleController.formatString("formatDateAtTime", R.string.formatDateAtTime, persianDate.getPersianMonthDay(), getInstance().formatterDay.format(new Date(date))); @@ -2100,6 +2113,10 @@ public class LocaleController { } public static String formatUserStatus(int currentAccount, TLRPC.User user, boolean[] isOnline) { + return formatUserStatus(currentAccount, user, isOnline, null); + } + + public static String formatUserStatus(int currentAccount, TLRPC.User user, boolean[] isOnline, boolean[] madeShorter) { if (user != null && user.status != null && user.status.expires == 0) { if (user.status instanceof TLRPC.TL_userStatusRecently) { user.status.expires = -100; @@ -2136,7 +2153,7 @@ public class LocaleController { } else if (user.status.expires == -102) { return getString("WithinAMonth", R.string.WithinAMonth); } else { - return formatDateOnline(user.status.expires); + return formatDateOnline(user.status.expires, madeShorter); } } } @@ -2282,6 +2299,10 @@ public class LocaleController { } public void loadRemoteLanguages(final int currentAccount) { + loadRemoteLanguages(currentAccount, true); + } + + public void loadRemoteLanguages(final int currentAccount, boolean applyCurrent) { if (loadingRemoteLanguages) { return; } @@ -2349,7 +2370,9 @@ public class LocaleController { } saveOtherLanguages(); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.suggestedLangpack); - applyLanguage(currentLocaleInfo, true, false, currentAccount); + if (applyCurrent) { + applyLanguage(currentLocaleInfo, true, false, currentAccount); + } }); } }, ConnectionsManager.RequestFlagWithoutLogin); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 3e60bcc8f..fa1314697 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -406,9 +406,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, @Override public String getPath() { if (photoSize != null) { - return FileLoader.getPathToAttach(photoSize, true).getAbsolutePath(); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoSize, true).getAbsolutePath(); } else if (document != null) { - return FileLoader.getPathToAttach(document, true).getAbsolutePath(); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true).getAbsolutePath(); } else { return ImageLoader.getHttpFilePath(imageUrl, "jpg").getAbsolutePath(); } @@ -430,9 +430,9 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, public String getPathToAttach() { if (photoSize != null) { - return FileLoader.getPathToAttach(photoSize, true).getAbsolutePath(); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(photoSize, true).getAbsolutePath(); } else if (document != null) { - return FileLoader.getPathToAttach(document, true).getAbsolutePath(); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true).getAbsolutePath(); } else { return imageUrl; } @@ -600,7 +600,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private ArrayList recordBuffers = new ArrayList<>(); private ByteBuffer fileBuffer; public int recordBufferSize = 1280; - public int sampleRate = NekoConfig.increaseVoiceMessageQuality.Bool() ? 48000 : 16000; + public int sampleRate = 48000; private int sendAfterDone; private boolean sendAfterDoneNotify; private int sendAfterDoneScheduleDate; @@ -905,7 +905,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, recordQueue.postRunnable(() -> { try { - sampleRate = NekoConfig.increaseVoiceMessageQuality.Bool() ? 48000 : 16000; + sampleRate = 48000; int minBuferSize = AudioRecord.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); if (minBuferSize <= 0) { minBuferSize = 1280; @@ -1329,7 +1329,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, playMessage(playingMessageObject); } else if (audioInfo == null) { try { - File cacheFile = FileLoader.getPathToMessage(playingMessageObject.messageOwner); + File cacheFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToMessage(playingMessageObject.messageOwner); audioInfo = AudioInfo.getAudioInfo(cacheFile); } catch (Exception e) { FileLog.e(e); @@ -2382,7 +2382,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, file = null; } } - final File cacheFile = file != null ? file : FileLoader.getPathToMessage(nextAudio.messageOwner); + final File cacheFile = file != null ? file : FileLoader.getInstance(currentAccount).getPathToMessage(nextAudio.messageOwner); boolean exist = cacheFile.exists(); if (cacheFile != file && !cacheFile.exists()) { FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0); @@ -2421,7 +2421,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, file = null; } } - final File cacheFile = file != null ? file : FileLoader.getPathToMessage(nextAudio.messageOwner); + final File cacheFile = file != null ? file : FileLoader.getInstance(currentAccount).getPathToMessage(nextAudio.messageOwner); boolean exist = cacheFile.exists(); if (cacheFile != file && !cacheFile.exists() && nextAudio.isMusic()) { FileLoader.getInstance(currentAccount).loadFile(nextAudio.getDocument(), nextAudio, 0, 0); @@ -2785,7 +2785,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, document.mime_type = "sound/ogg"; document.file_reference = sound.fileReference; document.dc_id = accountInstance.getConnectionsManager().getCurrentDatacenterId(); - File file = FileLoader.getPathToAttach(document, true); + File file = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document, true); if (file.exists()) { if (loadOnly) { return; @@ -2859,10 +2859,28 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, }); } + private static long volumeBarLastTimeShown; + public void checkVolumeBarUI() { + try { + final long now = System.currentTimeMillis(); + if (Math.abs(now - volumeBarLastTimeShown) < 5000) { + return; + } + AudioManager audioManager = (AudioManager) ApplicationLoader.applicationContext.getSystemService(Context.AUDIO_SERVICE); + int stream = useFrontSpeaker ? AudioManager.STREAM_VOICE_CALL : AudioManager.STREAM_MUSIC; + int volume = audioManager.getStreamVolume(stream); + if (volume == 0) { + audioManager.adjustStreamVolume(stream, volume, AudioManager.FLAG_SHOW_UI); + volumeBarLastTimeShown = now; + } + } catch (Exception ignore) {} + } + public boolean playMessage(final MessageObject messageObject) { if (messageObject == null) { return false; } + checkVolumeBarUI(); if ((audioPlayer != null || videoPlayer != null) && isSamePlayingMessage(messageObject)) { if (isPaused) { resumeAudio(messageObject); @@ -2897,7 +2915,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, file = null; } } - final File cacheFile = file != null ? file : FileLoader.getPathToMessage(messageObject.messageOwner); + final File cacheFile = file != null ? file : FileLoader.getInstance(messageObject.currentAccount).getPathToMessage(messageObject.messageOwner); boolean canStream = SharedConfig.streamMedia && (messageObject.isMusic() || messageObject.isRoundVideo() || messageObject.isVideo() && messageObject.canStreamVideo()) && !DialogObject.isEncryptedDialog(messageObject.getDialogId()); if (cacheFile != file && !(exists = cacheFile.exists()) && !canStream) { FileLoader.getInstance(messageObject.currentAccount).loadFile(messageObject.getDocument(), messageObject, 0, 0); @@ -3515,7 +3533,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, recordingAudioFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), FileLoader.getAttachFileName(recordingAudio)); try { - if (startRecord(recordingAudioFile.getAbsolutePath(), NekoConfig.increaseVoiceMessageQuality.Bool() ? 48000 : 16000) == 0) { + if (startRecord(recordingAudioFile.getAbsolutePath(), sampleRate) == 0) { AndroidUtilities.runOnUIThread(() -> { recordStartRunnable = null; NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recordStartError, guid); @@ -3564,7 +3582,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, public void generateWaveform(MessageObject messageObject) { final String id = messageObject.getId() + "_" + messageObject.getDialogId(); - final String path = FileLoader.getPathToMessage(messageObject.messageOwner).getAbsolutePath(); + final String path = FileLoader.getInstance(messageObject.currentAccount).getPathToMessage(messageObject.messageOwner).getAbsolutePath(); if (generatingWaveform.containsKey(id)) { return; } @@ -3732,7 +3750,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(message.messageOwner).toString(); + path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); } File sourceFile = new File(path); if (!sourceFile.exists()) { @@ -3786,7 +3804,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(message.messageOwner).toString(); + path = FileLoader.getInstance(currentAccount.getCurrentAccount()).getPathToMessage(message.messageOwner).toString(); } File sourceFile = new File(path); if (!sourceFile.exists()) { @@ -4292,10 +4310,24 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } f = AndroidUtilities.getSharingDirectory(); f.mkdirs(); - f = new File(f, name); if (AndroidUtilities.isInternalUri(Uri.fromFile(f))) { return null; } + int count = 0; + do { + f = AndroidUtilities.getSharingDirectory(); + if (count == 0) { + f = new File(f, name); + } else { + int lastDotIndex = name.lastIndexOf("."); + if (lastDotIndex > 0) { + f = new File(f, name.substring(0, lastDotIndex) + " (" + count + ")" + name.substring(lastDotIndex)); + } else { + f = new File(f, name + " (" + count + ")"); + } + } + count++; + } while (f.exists()); inputStream = ApplicationLoader.applicationContext.getContentResolver().openInputStream(uri); if (inputStream instanceof FileInputStream) { FileInputStream fileInputStream = (FileInputStream) inputStream; @@ -4833,7 +4865,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, resultWidth = temp; } -// if (framerate > 40 && (Math.min(resultHeight, resultWidth) <= 480)) { +// if (!info.shouldLimitFps && framerate > 40 && (Math.min(resultHeight, resultWidth) <= 480)) { // framerate = 30; // } // diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index c01a14a33..cfe28fabe 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -32,6 +32,8 @@ import android.text.Spanned; import android.text.SpannedString; import android.text.TextUtils; import android.text.style.CharacterStyle; +import android.text.style.URLSpan; +import android.text.util.Linkify; import android.util.SparseArray; import android.widget.Toast; @@ -57,8 +59,11 @@ import org.telegram.tgnet.SerializedData; 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.Components.AvatarDrawable; import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.ChatThemeBottomSheet; +import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; import org.telegram.ui.Components.StickerSetBulletinLayout; import org.telegram.ui.Components.StickersArchiveAlert; import org.telegram.ui.Components.TextStyleSpan; @@ -164,6 +169,7 @@ public class MediaDataController extends BaseController { } loadStickersByEmojiOrName(AndroidUtilities.STICKERS_PLACEHOLDER_PACK_NAME, false, true); + loadEmojiThemes(); ringtoneDataStore = new RingtoneDataStore(currentAccount); } @@ -188,6 +194,10 @@ public class MediaDataController extends BaseController { private boolean isLoadingReactions; private int reactionsUpdateDate; + private TLRPC.TL_help_premiumPromo premiumPromo; + private boolean isLoadingPremiumPromo; + private int premiumPromoUpdateDate; + private ArrayList[] stickerSets = new ArrayList[]{new ArrayList<>(), new ArrayList<>(), new ArrayList<>(0), new ArrayList<>(), new ArrayList<>()}; private LongSparseArray[] stickersByIds = new LongSparseArray[]{new LongSparseArray<>(), new LongSparseArray<>(), new LongSparseArray<>(), new LongSparseArray<>(), new LongSparseArray<>()}; private LongSparseArray stickerSetsById = new LongSparseArray<>(); @@ -223,6 +233,7 @@ public class MediaDataController extends BaseController { private long loadFeaturedHash; private int loadFeaturedDate; + public boolean loadFeaturedPremium; private ArrayList featuredStickerSets = new ArrayList<>(); private LongSparseArray featuredStickerSetsById = new LongSparseArray<>(); private ArrayList unreadStickerSets = new ArrayList<>(); @@ -232,6 +243,10 @@ public class MediaDataController extends BaseController { private TLRPC.Document greetingsSticker; public final RingtoneDataStore ringtoneDataStore; + public final ArrayList defaultEmojiThemes = new ArrayList<>(); + + public final ArrayList premiumPreviewStickers = new ArrayList<>(); + boolean previewStickersLoading; public void cleanup() { for (int a = 0; a < recentStickers.length; a++) { @@ -315,6 +330,16 @@ public class MediaDataController extends BaseController { } } + public void checkPremiumPromo() { + if (!isLoadingPremiumPromo && Math.abs(System.currentTimeMillis() / 1000 - premiumPromoUpdateDate) >= 60 * 60) { + loadPremiumPromo(true); + } + } + + public TLRPC.TL_help_premiumPromo getPremiumPromo() { + return premiumPromo; + } + public TLRPC.TL_attachMenuBots getAttachMenuBots() { return attachMenuBots; } @@ -365,7 +390,7 @@ public class MediaDataController extends BaseController { } } - private void processLoadedMenuBots(TLRPC.TL_attachMenuBots bots, long hash, int date, boolean cache) { + public void processLoadedMenuBots(TLRPC.TL_attachMenuBots bots, long hash, int date, boolean cache) { if (bots != null && date != 0) { attachMenuBots = bots; menuBotsUpdateHash = hash; @@ -411,6 +436,86 @@ public class MediaDataController extends BaseController { }); } + public void loadPremiumPromo(boolean cache) { + isLoadingPremiumPromo = true; + if (cache) { + getMessagesStorage().getStorageQueue().postRunnable(() -> { + SQLiteCursor c = null; + int date = 0; + TLRPC.TL_help_premiumPromo premiumPromo = null; + try { + c = getMessagesStorage().getDatabase().queryFinalized("SELECT data, date FROM premium_promo"); + if (c.next()) { + NativeByteBuffer data = c.byteBufferValue(0); + if (data != null) { + premiumPromo = TLRPC.TL_help_premiumPromo.TLdeserialize(data, data.readInt32(false), true); + data.reuse(); + } + date = c.intValue(1); + } + } catch (Exception e) { + FileLog.e(e, false); + } finally { + if (c != null) { + c.dispose(); + } + } + if (premiumPromo != null) { + processLoadedPremiumPromo(premiumPromo, date, true); + } + }); + } else { + TLRPC.TL_help_getPremiumPromo req = new TLRPC.TL_help_getPremiumPromo(); + getConnectionsManager().sendRequest(req, (response, error) -> { + int date = (int) (System.currentTimeMillis() / 1000); + if (response instanceof TLRPC.TL_help_premiumPromo) { + TLRPC.TL_help_premiumPromo r = (TLRPC.TL_help_premiumPromo) response; + processLoadedPremiumPromo(r, date, false); + } + }); + } + } + + private void processLoadedPremiumPromo(TLRPC.TL_help_premiumPromo premiumPromo, int date, boolean cache) { + this.premiumPromo = premiumPromo; + premiumPromoUpdateDate = date; + getMessagesController().putUsers(premiumPromo.users, cache); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.premiumPromoUpdated)); + + if (!cache) { + putPremiumPromoToCache(premiumPromo, date); + } else if (Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60 * 24 || BuildVars.DEBUG_PRIVATE_VERSION) { + loadPremiumPromo(false); + } + } + + private void putPremiumPromoToCache(TLRPC.TL_help_premiumPromo premiumPromo, int date) { + getMessagesStorage().getStorageQueue().postRunnable(() -> { + try { + if (premiumPromo != null) { + getMessagesStorage().getDatabase().executeFast("DELETE FROM premium_promo").stepThis().dispose(); + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO premium_promo VALUES(?, ?)"); + state.requery(); + NativeByteBuffer data = new NativeByteBuffer(premiumPromo.getObjectSize()); + premiumPromo.serializeToStream(data); + state.bindByteBuffer(1, data); + state.bindInteger(2, date); + state.step(); + data.reuse(); + state.dispose(); + } else { + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("UPDATE premium_promo SET date = ?"); + state.requery(); + state.bindInteger(1, date); + state.step(); + state.dispose(); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + public List getReactionsList() { return reactionsList; } @@ -463,7 +568,7 @@ public class MediaDataController extends BaseController { } } - private void processLoadedReactions(List reactions, int hash, int date, boolean cache) { + public void processLoadedReactions(List reactions, int hash, int date, boolean cache) { if (reactions != null && date != 0) { reactionsList.clear(); reactionsMap.clear(); @@ -484,29 +589,27 @@ public class MediaDataController extends BaseController { for (int i = 0; i < reactions.size(); i++) { ImageReceiver imageReceiver = new ImageReceiver(); TLRPC.TL_availableReaction reaction = reactions.get(i); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.activate_animation), null, null, null, 0, 1); + imageReceiver.setImage(ImageLocation.getForDocument(reaction.activate_animation), null, null, null, 0, FileLoader.PRELOAD_CACHE_TYPE); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); imageReceiver = new ImageReceiver(); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.appear_animation), "60_60_nolimit", null, null, 0, 1); + imageReceiver.setImage(ImageLocation.getForDocument(reaction.appear_animation), "60_60_nolimit", null, null, 0, FileLoader.PRELOAD_CACHE_TYPE); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + + int size = ReactionsEffectOverlay.sizeForBigReaction(); + imageReceiver = new ImageReceiver(); + imageReceiver.setImage(ImageLocation.getForDocument(reaction.around_animation), size + "_" + size, null, null, 0, FileLoader.PRELOAD_CACHE_TYPE); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); imageReceiver = new ImageReceiver(); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.around_animation), null, null, null, 0, 1); - ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); - - imageReceiver = new ImageReceiver(); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.center_icon), null, null, null, 0, 1); - ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); - - imageReceiver = new ImageReceiver(); - imageReceiver.setImage(ImageLocation.getForDocument(reaction.static_icon), null, null, null, 0, 1); + imageReceiver.setImage(ImageLocation.getForDocument(reaction.center_icon), null, null, null, 0, FileLoader.PRELOAD_CACHE_TYPE); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.reactionsDidLoad); }); } + isLoadingReactions = false; if (!cache) { putReactionsToCache(reactions, hash, date); } else if (Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60) { @@ -582,6 +685,24 @@ public class MediaDataController extends BaseController { return false; } + public void clearRecentStickers() { + TLRPC.TL_messages_clearRecentStickers req = new TLRPC.TL_messages_clearRecentStickers(); + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()-> { + if (response instanceof TLRPC.TL_boolTrue) { + getMessagesStorage().getStorageQueue().postRunnable(() -> { + try { + getMessagesStorage().getDatabase().executeFast("DELETE FROM web_recent_v3 WHERE type = " + 3).stepThis().dispose(); + } catch (Exception e) { + FileLog.e(e); + } + }); + + recentStickers[TYPE_IMAGE].clear(); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.recentDocumentsDidLoad, false, TYPE_IMAGE); + } + })); + } + public void addRecentSticker(int type, Object parentObject, TLRPC.Document document, int date, boolean remove) { if (type == TYPE_GREETINGS || !MessageObject.isStickerDocument(document) && !MessageObject.isAnimatedStickerDocument(document, true)) { return; @@ -606,7 +727,8 @@ public class MediaDataController extends BaseController { if (remove) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_STICKER, document, StickerSetBulletinLayout.TYPE_REMOVED_FROM_FAVORITES); } else { - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_STICKER, document, StickerSetBulletinLayout.TYPE_ADDED_TO_FAVORITES); + boolean replace = recentStickers[type].size() > getMessagesController().maxFaveStickersCount; + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_STICKER, document, replace ? StickerSetBulletinLayout.TYPE_REPLACED_TO_FAVORITES : StickerSetBulletinLayout.TYPE_ADDED_TO_FAVORITES); } TLRPC.TL_messages_faveSticker req = new TLRPC.TL_messages_faveSticker(); req.id = new TLRPC.TL_inputDocument(); @@ -719,7 +841,7 @@ public class MediaDataController extends BaseController { return false; } - public void addRecentGif(TLRPC.Document document, int date) { + public void addRecentGif(TLRPC.Document document, int date, boolean showReplaceBulletin) { if (document == null) { return; } @@ -736,7 +858,7 @@ public class MediaDataController extends BaseController { if (!found) { recentGifs.add(0, document); } - if (recentGifs.size() > getMessagesController().maxRecentGifsCount) { + if ((recentGifs.size() > getMessagesController().savedGifsLimitDefault && !UserConfig.getInstance(currentAccount).isPremium()) || recentGifs.size() > getMessagesController().savedGifsLimitPremium) { TLRPC.Document old = recentGifs.remove(recentGifs.size() - 1); getMessagesStorage().getStorageQueue().postRunnable(() -> { try { @@ -745,6 +867,11 @@ public class MediaDataController extends BaseController { FileLog.e(e); } }); + if (showReplaceBulletin) { + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_STICKER, document, StickerSetBulletinLayout.TYPE_REPLACED_TO_FAVORITES_GIFS); + }); + } } ArrayList arrayList = new ArrayList<>(); arrayList.add(document); @@ -930,6 +1057,9 @@ public class MediaDataController extends BaseController { } public TLRPC.Document getEmojiAnimatedSticker(CharSequence message) { + if (message == null) { + return null; + } String emoji = message.toString().replace("\uFE0F", ""); ArrayList arrayList = getStickerSets(MediaDataController.TYPE_EMOJI); for (int a = 0, N = arrayList.size(); a < N; a++) { @@ -999,6 +1129,34 @@ public class MediaDataController extends BaseController { return value != null ? value : ""; } + public static boolean canShowAttachMenuBotForTarget(TLRPC.TL_attachMenuBot bot, String target) { + for (TLRPC.AttachMenuPeerType peerType : bot.peer_types) { + if ((peerType instanceof TLRPC.TL_attachMenuPeerTypeSameBotPM || peerType instanceof TLRPC.TL_attachMenuPeerTypeBotPM) && target.equals("bots") || + peerType instanceof TLRPC.TL_attachMenuPeerTypeBroadcast && target.equals("channels") || + peerType instanceof TLRPC.TL_attachMenuPeerTypeChat && target.equals("groups") || + peerType instanceof TLRPC.TL_attachMenuPeerTypePM && target.equals("users")) { + return true; + } + } + return false; + } + + public static boolean canShowAttachMenuBot(TLRPC.TL_attachMenuBot bot, TLObject peer) { + TLRPC.User user = peer instanceof TLRPC.User ? (TLRPC.User) peer : null; + TLRPC.Chat chat = peer instanceof TLRPC.Chat ? (TLRPC.Chat) peer : null; + + for (TLRPC.AttachMenuPeerType peerType : bot.peer_types) { + if (peerType instanceof TLRPC.TL_attachMenuPeerTypeSameBotPM && user != null && user.bot && user.id == bot.bot_id || + peerType instanceof TLRPC.TL_attachMenuPeerTypeBotPM && user != null && user.bot && user.id != bot.bot_id || + peerType instanceof TLRPC.TL_attachMenuPeerTypePM && user != null && !user.bot || + peerType instanceof TLRPC.TL_attachMenuPeerTypeChat && chat != null && !ChatObject.isChannelAndNotMegaGroup(chat) || + peerType instanceof TLRPC.TL_attachMenuPeerTypeBroadcast && chat != null && ChatObject.isChannelAndNotMegaGroup(chat)) { + return true; + } + } + return false; + } + @Nullable public static TLRPC.TL_attachMenuBotIcon getAnimatedAttachMenuBotIcon(@NonNull TLRPC.TL_attachMenuBot bot) { for (TLRPC.TL_attachMenuBotIcon icon : bot.icons) { @@ -1391,9 +1549,10 @@ public class MediaDataController extends BaseController { ArrayList unread = new ArrayList<>(); int date = 0; long hash = 0; + boolean premium = false; SQLiteCursor cursor = null; try { - cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT data, unread, date, hash FROM stickers_featured WHERE 1"); + cursor = getMessagesStorage().getDatabase().queryFinalized("SELECT data, unread, date, hash, premium FROM stickers_featured WHERE 1"); if (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -1415,6 +1574,7 @@ public class MediaDataController extends BaseController { } date = cursor.intValue(2); hash = calcFeaturedStickersHash(newStickerArray); + premium = cursor.intValue(4) == 1; } } catch (Throwable e) { FileLog.e(e); @@ -1423,7 +1583,7 @@ public class MediaDataController extends BaseController { cursor.dispose(); } } - processLoadedFeaturedStickers(newStickerArray, unread, true, date, hash); + processLoadedFeaturedStickers(newStickerArray, unread, premium, true, date, hash); }); } else { TLRPC.TL_messages_getFeaturedStickers req = new TLRPC.TL_messages_getFeaturedStickers(); @@ -1431,15 +1591,15 @@ public class MediaDataController extends BaseController { getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (response instanceof TLRPC.TL_messages_featuredStickers) { TLRPC.TL_messages_featuredStickers res = (TLRPC.TL_messages_featuredStickers) response; - processLoadedFeaturedStickers(res.sets, res.unread, false, (int) (System.currentTimeMillis() / 1000), res.hash); + processLoadedFeaturedStickers(res.sets, res.unread, res.premium,false, (int) (System.currentTimeMillis() / 1000), res.hash); } else { - processLoadedFeaturedStickers(null, null, false, (int) (System.currentTimeMillis() / 1000), req.hash); + processLoadedFeaturedStickers(null, null, false, false, (int) (System.currentTimeMillis() / 1000), req.hash); } })); } } - private void processLoadedFeaturedStickers(ArrayList res, ArrayList unreadStickers, boolean cache, int date, long hash) { + private void processLoadedFeaturedStickers(ArrayList res, ArrayList unreadStickers, boolean premium, boolean cache, int date, long hash) { AndroidUtilities.runOnUIThread(() -> { loadingFeaturedStickers = false; featuredStickersLoaded = true; @@ -1468,7 +1628,7 @@ public class MediaDataController extends BaseController { } if (!cache) { - putFeaturedStickersToCache(stickerSetsNew, unreadStickers, date, hash); + putFeaturedStickersToCache(stickerSetsNew, unreadStickers, date, hash, premium); } AndroidUtilities.runOnUIThread(() -> { unreadStickerSets = unreadStickers; @@ -1476,6 +1636,7 @@ public class MediaDataController extends BaseController { featuredStickerSets = stickerSetsNew; loadFeaturedHash = hash; loadFeaturedDate = date; + loadFeaturedPremium = premium; loadStickers(TYPE_FEATURED, true, false); getNotificationCenter().postNotificationName(NotificationCenter.featuredStickersDidLoad); }); @@ -1484,17 +1645,17 @@ public class MediaDataController extends BaseController { } } else { AndroidUtilities.runOnUIThread(() -> loadFeaturedDate = date); - putFeaturedStickersToCache(null, null, date, 0); + putFeaturedStickersToCache(null, null, date, 0, premium); } }); } - private void putFeaturedStickersToCache(ArrayList stickers, ArrayList unreadStickers, int date, long hash) { + private void putFeaturedStickersToCache(ArrayList stickers, ArrayList unreadStickers, int date, long hash, boolean premium) { ArrayList stickersFinal = stickers != null ? new ArrayList<>(stickers) : null; getMessagesStorage().getStorageQueue().postRunnable(() -> { try { if (stickersFinal != null) { - SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO stickers_featured VALUES(?, ?, ?, ?, ?)"); + SQLitePreparedStatement state = getMessagesStorage().getDatabase().executeFast("REPLACE INTO stickers_featured VALUES(?, ?, ?, ?, ?, ?)"); state.requery(); int size = 4; for (int a = 0; a < stickersFinal.size(); a++) { @@ -1515,6 +1676,7 @@ public class MediaDataController extends BaseController { state.bindByteBuffer(3, data2); state.bindInteger(4, date); state.bindLong(5, hash); + state.bindInteger(6, premium ? 1 : 0); state.step(); data.reuse(); data2.reuse(); @@ -1564,7 +1726,7 @@ public class MediaDataController extends BaseController { unreadStickerSets.clear(); loadFeaturedHash = calcFeaturedStickersHash(featuredStickerSets); getNotificationCenter().postNotificationName(NotificationCenter.featuredStickersDidLoad); - putFeaturedStickersToCache(featuredStickerSets, unreadStickerSets, loadFeaturedDate, loadFeaturedHash); + putFeaturedStickersToCache(featuredStickerSets, unreadStickerSets, loadFeaturedDate, loadFeaturedHash, loadFeaturedPremium); if (query) { TLRPC.TL_messages_readFeaturedStickers req = new TLRPC.TL_messages_readFeaturedStickers(); getConnectionsManager().sendRequest(req, (response, error) -> { @@ -1600,7 +1762,7 @@ public class MediaDataController extends BaseController { readingStickerSets.remove(id); loadFeaturedHash = calcFeaturedStickersHash(featuredStickerSets); getNotificationCenter().postNotificationName(NotificationCenter.featuredStickersDidLoad); - putFeaturedStickersToCache(featuredStickerSets, unreadStickerSets, loadFeaturedDate, loadFeaturedHash); + putFeaturedStickersToCache(featuredStickerSets, unreadStickerSets, loadFeaturedDate, loadFeaturedHash, loadFeaturedPremium); }, 1000); } @@ -2058,7 +2220,7 @@ public class MediaDataController extends BaseController { } }); Utilities.stageQueue.postRunnable(() -> { - if (cache && (res == null || Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60) || !cache && res == null && hash == 0) { + if (cache && (res == null || BuildVars.DEBUG_PRIVATE_VERSION || Math.abs(System.currentTimeMillis() / 1000 - date) >= 60 * 60) || !cache && res == null && hash == 0) { AndroidUtilities.runOnUIThread(() -> { if (res != null && hash != 0) { loadHash[type] = hash; @@ -2989,10 +3151,11 @@ public class MediaDataController extends BaseController { continue; } - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, true, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, true, false); messageObject.createStrippedThumb(); objects.add(messageObject); } + getFileLoader().checkMediaExistance(objects); AndroidUtilities.runOnUIThread(() -> { int totalCount = res.count; @@ -3428,7 +3591,7 @@ public class MediaDataController extends BaseController { Bitmap bitmap = null; if (photo != null) { try { - File path = FileLoader.getPathToAttach(photo, true); + File path = getFileLoader().getPathToAttach(photo, true); bitmap = BitmapFactory.decodeFile(path.toString()); if (bitmap != null) { int size = AndroidUtilities.dp(48); @@ -3902,7 +4065,7 @@ public class MediaDataController extends BaseController { if (overrideAvatar || photo != null) { try { if (!overrideAvatar) { - File path = FileLoader.getPathToAttach(photo, true); + File path = getFileLoader().getPathToAttach(photo, true); bitmap = BitmapFactory.decodeFile(path.toString()); } if (overrideAvatar || bitmap != null) { @@ -5133,6 +5296,26 @@ public class MediaDataController extends BaseController { } } } + + if (spannable instanceof Spannable) { + AndroidUtilities.addLinks((Spannable) spannable, Linkify.WEB_URLS); + URLSpan[] spansUrl = spannable.getSpans(0, message[0].length(), URLSpan.class); + if (spansUrl != null && spansUrl.length > 0) { + if (entities == null) { + entities = new ArrayList<>(); + } + for (int b = 0; b < spansUrl.length; b++) { + if (spansUrl[b] instanceof URLSpanReplacement || spansUrl[b] instanceof URLSpanUserMention) { + continue; + } + TLRPC.TL_messageEntityUrl entity = new TLRPC.TL_messageEntityUrl(); + entity.offset = spannable.getSpanStart(spansUrl[b]); + entity.length = Math.min(spannable.getSpanEnd(spansUrl[b]), message[0].length()) - entity.offset; + entity.url = spansUrl[b].getURL(); + entities.add(entity); + } + } + } } CharSequence cs = message[0]; @@ -5153,12 +5336,23 @@ public class MediaDataController extends BaseController { int offset = 0; while (m.find()) { String gr = m.group(1); - cs = cs.subSequence(0, m.start() - offset) + gr + cs.subSequence(m.end() - offset, cs.length()); + boolean allowEntity = true; + if (cs instanceof Spannable) { + // check if it is inside a link: do not convert __ ** to styles inside links + URLSpan[] spansUrl = ((Spannable) cs).getSpans(m.start() - offset, m.end() - offset, URLSpan.class); + if (spansUrl != null && spansUrl.length > 0) { + allowEntity = false; + } + } - TLRPC.MessageEntity entity = entityProvider.provide(null); - entity.offset = m.start() - offset; - entity.length = gr.length(); - entities.add(entity); + if (allowEntity) { + cs = cs.subSequence(0, m.start() - offset) + gr + cs.subSequence(m.end() - offset, cs.length()); + + TLRPC.MessageEntity entity = entityProvider.provide(null); + entity.offset = m.start() - offset; + entity.length = gr.length(); + entities.add(entity); + } offset += m.end() - m.start() - gr.length(); } @@ -5769,6 +5963,51 @@ public class MediaDataController extends BaseController { return true; } + public void preloadPremiumPreviewStickers() { + if (previewStickersLoading || !premiumPreviewStickers.isEmpty()) { + for (int i = 0; i < Math.min(premiumPreviewStickers.size(), 3); i++) { + TLRPC.Document document = premiumPreviewStickers.get(i == 2 ? premiumPreviewStickers.size() - 1 : i); + if (MessageObject.isPremiumSticker(document)) { + ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setImage(ImageLocation.getForDocument(document), null, null, "webp", null, 1); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + + imageReceiver = new ImageReceiver(); + imageReceiver.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", null, 1); + ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); + } + } + return; + } + final TLRPC.TL_messages_getStickers req2 = new TLRPC.TL_messages_getStickers(); + req2.emoticon = Emoji.fixEmoji("⭐") + Emoji.fixEmoji("⭐"); + req2.hash = 0; + previewStickersLoading = true; + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + return; + } + previewStickersLoading = false; + TLRPC.TL_messages_stickers res = (TLRPC.TL_messages_stickers) response; + premiumPreviewStickers.clear(); + premiumPreviewStickers.addAll(res.stickers); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.premiumStickersPreviewLoaded); + })); + } + + public void chekAllMedia(boolean force) { + if (force) { + reactionsUpdateDate = 0; + loadFeaturedDate = 0; + } + loadRecents(MediaDataController.TYPE_FAVE, false, true, false); + loadRecents(MediaDataController.TYPE_GREETINGS, false, true, false); + checkFeaturedStickers(); + checkReactions(); + checkMenuBots(); + checkPremiumPromo(); + } + //---------------- BOT END ---------------- //---------------- EMOJI START ---------------- @@ -6048,5 +6287,81 @@ public class MediaDataController extends BaseController { } } + + public void loadEmojiThemes() { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config_" + currentAccount, Context.MODE_PRIVATE); + int count = preferences.getInt("count", 0); + ArrayList previewItems = new ArrayList<>(); + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); + for (int i = 0; i < count; ++i) { + String value = preferences.getString("theme_" + i, ""); + SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); + try { + TLRPC.TL_theme theme = TLRPC.Theme.TLdeserialize(serializedData, serializedData.readInt32(true), true); + EmojiThemes fullTheme = EmojiThemes.createPreviewFullTheme(theme); + if (fullTheme.items.size() >= 4) { + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(fullTheme)); + } + + ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { + @Override + public void run() { + for (int i = 0; i < previewItems.size(); i++) { + previewItems.get(i).chatTheme.loadPreviewColors(0); + } + AndroidUtilities.runOnUIThread(() -> { + defaultEmojiThemes.clear(); + defaultEmojiThemes.addAll(previewItems); + }); + } + }); + } catch (Throwable e) { + FileLog.e(e); + } + } + } + + public void generateEmojiPreviewThemes(final ArrayList emojiPreviewThemes, int currentAccount) { + SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config_" + currentAccount, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("count", emojiPreviewThemes.size()); + for (int i = 0; i < emojiPreviewThemes.size(); ++i) { + TLRPC.TL_theme tlChatTheme = emojiPreviewThemes.get(i); + SerializedData data = new SerializedData(tlChatTheme.getObjectSize()); + tlChatTheme.serializeToStream(data); + editor.putString("theme_" + i, Utilities.bytesToHex(data.toByteArray())); + } + editor.apply(); + + if (!emojiPreviewThemes.isEmpty()) { + final ArrayList previewItems = new ArrayList<>(); + previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); + for (int i = 0; i < emojiPreviewThemes.size(); i++) { + TLRPC.TL_theme theme = emojiPreviewThemes.get(i); + EmojiThemes chatTheme = EmojiThemes.createPreviewFullTheme(theme); + ChatThemeBottomSheet.ChatThemeItem item = new ChatThemeBottomSheet.ChatThemeItem(chatTheme); + if (chatTheme.items.size() >= 4) { + previewItems.add(item); + } + } + ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { + @Override + public void run() { + for (int i = 0; i < previewItems.size(); i++) { + previewItems.get(i).chatTheme.loadPreviewColors(currentAccount); + } + AndroidUtilities.runOnUIThread(() -> { + defaultEmojiThemes.clear(); + defaultEmojiThemes.addAll(previewItems); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiPreviewThemesChanged); + }); + } + }); + } else { + defaultEmojiThemes.clear(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiPreviewThemesChanged); + } + } + //---------------- EMOJI END ---------------- } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java new file mode 100644 index 000000000..33129ea8f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageCustomParamsHelper.java @@ -0,0 +1,101 @@ +package org.telegram.messenger; + +import org.telegram.tgnet.AbstractSerializedData; +import org.telegram.tgnet.NativeByteBuffer; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; + +public class MessageCustomParamsHelper { + + public static boolean isEmpty(TLRPC.Message message) { + return message.voiceTranscription == null && + !message.voiceTranscriptionOpen && + !message.voiceTranscriptionFinal && + !message.voiceTranscriptionRated && + message.voiceTranscriptionId == 0 && + !message.premiumEffectWasPlayed; + } + + public static void copyParams(TLRPC.Message fromMessage, TLRPC.Message toMessage) { + toMessage.voiceTranscription = fromMessage.voiceTranscription; + toMessage.voiceTranscriptionOpen = fromMessage.voiceTranscriptionOpen; + toMessage.voiceTranscriptionFinal = fromMessage.voiceTranscriptionFinal; + toMessage.voiceTranscriptionRated = fromMessage.voiceTranscriptionRated; + toMessage.voiceTranscriptionId = fromMessage.voiceTranscriptionId; + toMessage.premiumEffectWasPlayed = fromMessage.premiumEffectWasPlayed; + } + + + public static void readLocalParams(TLRPC.Message message, NativeByteBuffer byteBuffer) { + if (byteBuffer == null) { + return; + } + int version = byteBuffer.readInt32(true); + TLObject params; + switch (version) { + case 1: + params = new Params_v1(message); + break; + default: + throw new RuntimeException("can't read params version = " + version); + } + params.readParams(byteBuffer, true); + } + + public static NativeByteBuffer writeLocalParams(TLRPC.Message message) { + if (isEmpty(message)) { + return null; + } + TLObject params = new Params_v1(message); + try { + NativeByteBuffer nativeByteBuffer = new NativeByteBuffer(params.getObjectSize()); + params.serializeToStream(nativeByteBuffer); + return nativeByteBuffer; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + private static class Params_v1 extends TLObject { + + private final static int VERSION = 1; + final TLRPC.Message message; + int flags = 0; + + private Params_v1(TLRPC.Message message) { + this.message = message; + flags += message.voiceTranscription != null ? 1 : 0; + } + + @Override + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(VERSION); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeString(message.voiceTranscription); + } + stream.writeBool(message.voiceTranscriptionOpen); + stream.writeBool(message.voiceTranscriptionFinal); + stream.writeBool(message.voiceTranscriptionRated); + stream.writeInt64(message.voiceTranscriptionId); + + stream.writeBool(message.premiumEffectWasPlayed); + } + + @Override + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(true); + if ((flags & 1) != 0) { + message.voiceTranscription = stream.readString(exception); + } + message.voiceTranscriptionOpen = stream.readBool(exception); + message.voiceTranscriptionFinal = stream.readBool(exception); + message.voiceTranscriptionRated = stream.readBool(exception); + message.voiceTranscriptionId = stream.readInt64(exception); + + message.premiumEffectWasPlayed = stream.readBool(exception); + } + + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index 039a26b50..f9ae16b25 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -8,11 +8,17 @@ package org.telegram.messenger; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.PixelFormat; +import android.graphics.Rect; import android.graphics.Typeface; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; +import android.os.SystemClock; import android.text.Layout; import android.text.Spannable; import android.text.SpannableString; @@ -21,11 +27,16 @@ import android.text.Spanned; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; +import android.text.style.ImageSpan; import android.text.style.URLSpan; import android.text.util.Linkify; import android.util.Base64; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.collection.LongSparseArray; import org.telegram.PhoneFormat.PhoneFormat; @@ -37,7 +48,9 @@ import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanBrowser; @@ -51,6 +64,7 @@ import org.telegram.ui.Components.spoilers.SpoilerEffect; import java.io.BufferedReader; import java.io.File; import java.io.StringReader; +import java.lang.ref.WeakReference; import java.net.URLEncoder; import java.util.AbstractMap; import java.util.ArrayList; @@ -106,6 +120,7 @@ public class MessageObject { public boolean isReactionPush; public boolean putInDownloadsStore; public boolean isDownloadingFile; + public boolean forcePlayEffect; private int isRoundVideoCached; public long eventId; public int contentType; @@ -139,6 +154,8 @@ public class MessageObject { public boolean isRestrictedMessage; public long loadedFileSize; + public AtomicReference> viewRef = new AtomicReference<>(null); + public boolean isSpoilersRevealed = NekoConfig.showSpoilersDirectly.Bool(); public byte[] sponsoredId; public int sponsoredChannelPost; @@ -251,6 +268,18 @@ public class MessageObject { return false; } + public static boolean isPremiumSticker(TLRPC.Document document) { + if (document == null || document.thumbs == null) { + return false; + } + for (int i = 0; i < document.video_thumbs.size(); i++) { + if ("f".equals(document.video_thumbs.get(i).type)) { + return true; + } + } + return false; + } + public int getEmojiOnlyCount() { return emojiOnlyCount; } @@ -286,6 +315,29 @@ public class MessageObject { } } + public boolean isPremiumSticker() { + if (messageOwner.media != null && messageOwner.media.nopremium) { + return false; + } + return isPremiumSticker(getDocument()); + } + + public TLRPC.VideoSize getPremiumStickerAnimation() { + return getPremiumStickerAnimation(getDocument()); + } + + public static TLRPC.VideoSize getPremiumStickerAnimation(TLRPC.Document document) { + if (document == null || document.thumbs == null) { + return null; + } + for (int i = 0; i < document.video_thumbs.size(); i++) { + if ("f".equals(document.video_thumbs.get(i).type)) { + return document.video_thumbs.get(i); + } + } + return null; + } + public static class SendAnimationData { public float x; public float y; @@ -1034,7 +1086,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(), AndroidUtilities.dp(20), false, emojiOnly, contentType == 0, viewRef); checkEmojiOnly(emojiOnly); emojiAnimatedSticker = null; if (emojiOnlyCount == 1 && !(message.media instanceof TLRPC.TL_messageMediaWebPage) && !(message.media instanceof TLRPC.TL_messageMediaInvoice) && message.entities.isEmpty() && (message.media instanceof TLRPC.TL_messageMediaEmpty || message.media == null) && messageOwner.grouped_id == 0) { @@ -1944,9 +1996,15 @@ public class MessageObject { } } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest) { TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest action = (TLRPC.TL_channelAdminLogEventActionParticipantJoinByRequest) event.action; - messageText = replaceWithLink(LocaleController.getString("JoinedViaInviteLinkApproved", R.string.JoinedViaInviteLinkApproved), "un1", fromUser); - messageText = replaceWithLink(messageText, "un2", action.invite); - messageText = replaceWithLink(messageText, "un3", MessagesController.getInstance(currentAccount).getUser(action.approved_by)); + if (action.invite instanceof TLRPC.TL_chatInviteExported && "https://t.me/+PublicChat".equals(((TLRPC.TL_chatInviteExported) action.invite).link) || + action.invite instanceof TLRPC.TL_chatInvitePublicJoinRequests) { + messageText = replaceWithLink(LocaleController.getString("JoinedViaRequestApproved", R.string.JoinedViaRequestApproved), "un1", fromUser); + messageText = replaceWithLink(messageText, "un2", MessagesController.getInstance(currentAccount).getUser(action.approved_by)); + } else { + messageText = replaceWithLink(LocaleController.getString("JoinedViaInviteLinkApproved", R.string.JoinedViaInviteLinkApproved), "un1", fromUser); + messageText = replaceWithLink(messageText, "un2", action.invite); + messageText = replaceWithLink(messageText, "un3", MessagesController.getInstance(currentAccount).getUser(action.approved_by)); + } } else if (event.action instanceof TLRPC.TL_channelAdminLogEventActionSendMessage) { message = ((TLRPC.TL_channelAdminLogEventActionSendMessage) event.action).message; messageText = replaceWithLink(LocaleController.getString("EventLogSendMessages", R.string.EventLogSendMessages), "un1", fromUser); @@ -2026,7 +2084,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(), AndroidUtilities.dp(20), false, emojiOnly, contentType == 0, viewRef); checkEmojiOnly(emojiOnly); if (mediaController.isPlayingMessage(this)) { MessageObject player = mediaController.getPlayingMessageObject(); @@ -2083,7 +2141,11 @@ public class MessageObject { } public void applyNewText() { - if (TextUtils.isEmpty(messageOwner.message)) { + applyNewText(messageOwner.message); + } + + public void applyNewText(CharSequence text) { + if (TextUtils.isEmpty(text)) { return; } @@ -2092,8 +2154,7 @@ public class MessageObject { fromUser = MessagesController.getInstance(currentAccount).getUser(messageOwner.from_id.user_id); } - messageText = messageOwner.message; - + messageText = text; TextPaint paint; if (messageOwner.media instanceof TLRPC.TL_messageMediaGame) { paint = Theme.chat_msgGameTextPaint; @@ -2101,7 +2162,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(), AndroidUtilities.dp(20), false, emojiOnly, contentType == 0, viewRef); checkEmojiOnly(emojiOnly); generateLayout(fromUser); } @@ -2155,10 +2216,25 @@ public class MessageObject { } else { name = ""; } + String currency; + try { + currency = LocaleController.getInstance().formatCurrencyString(messageOwner.action.total_amount, messageOwner.action.currency); + } catch (Exception e) { + currency = ""; + FileLog.e(e); + } if (replyMessageObject != null && replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) { - messageText = LocaleController.formatString("PaymentSuccessfullyPaid", R.string.PaymentSuccessfullyPaid, LocaleController.getInstance().formatCurrencyString(messageOwner.action.total_amount, messageOwner.action.currency), name, replyMessageObject.messageOwner.media.title); + if (messageOwner.action.recurring_init) { + messageText = LocaleController.formatString(R.string.PaymentSuccessfullyPaidRecurrent, currency, name, replyMessageObject.messageOwner.media.title); + } else { + messageText = LocaleController.formatString("PaymentSuccessfullyPaid", R.string.PaymentSuccessfullyPaid, currency, name, replyMessageObject.messageOwner.media.title); + } } else { - messageText = LocaleController.formatString("PaymentSuccessfullyPaidNoItem", R.string.PaymentSuccessfullyPaidNoItem, LocaleController.getInstance().formatCurrencyString(messageOwner.action.total_amount, messageOwner.action.currency), name); + if (messageOwner.action.recurring_init) { + messageText = LocaleController.formatString(R.string.PaymentSuccessfullyPaidNoItemRecurrent, currency, name); + } else { + messageText = LocaleController.formatString("PaymentSuccessfullyPaidNoItem", R.string.PaymentSuccessfullyPaidNoItem, currency, name); + } } } @@ -2208,13 +2284,13 @@ public class MessageObject { messageText = replaceWithLink(LocaleController.getString("ActionPinnedPhoto", R.string.ActionPinnedPhoto), "un1", fromUser != null ? fromUser : chat); } else if (replyMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaGame) { messageText = replaceWithLink(LocaleController.formatString("ActionPinnedGame", R.string.ActionPinnedGame, "\uD83C\uDFAE " + replyMessageObject.messageOwner.media.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(), AndroidUtilities.dp(20), false, contentType == 0, viewRef); } else if (replyMessageObject.messageText != null && replyMessageObject.messageText.length() > 0) { CharSequence mess = replyMessageObject.messageText; if (mess.length() > 20) { mess = mess.subSequence(0, 20) + "..."; } - mess = Emoji.replaceEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + mess = Emoji.replaceEmoji(mess, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false, contentType == 0, viewRef); MediaDataController.addTextStyleRuns(replyMessageObject, (Spannable) mess); messageText = replaceWithLink(AndroidUtilities.formatSpannable(LocaleController.getString("ActionPinnedText", R.string.ActionPinnedText), mess), "un1", fromUser != null ? fromUser : chat); } else { @@ -2552,7 +2628,7 @@ 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(), AndroidUtilities.dp(15), false, contentType == 0, viewRef); } StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, AndroidUtilities.dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (staticLayout.getLineCount() > 0) { @@ -2572,7 +2648,7 @@ public class MessageObject { TLRPC.TL_reactionCount reactionCount = messageOwner.reactions.results.get(a); int maxButtonSize = 0; botButtonsLayout.append(0).append(a); - CharSequence text = Emoji.replaceEmoji(String.format("%d %s", reactionCount.count, reactionCount.reaction), Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false); + CharSequence text = Emoji.replaceEmoji(String.format("%d %s", reactionCount.count, reactionCount.reaction), Theme.chat_msgBotButtonPaint.getFontMetricsInt(), AndroidUtilities.dp(15), false, contentType == 0, viewRef); StaticLayout staticLayout = new StaticLayout(text, Theme.chat_msgBotButtonPaint, AndroidUtilities.dp(2000), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (staticLayout.getLineCount() > 0) { float width = staticLayout.getLineWidth(0); @@ -3322,7 +3398,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(), AndroidUtilities.dp(20), false, emojiOnly, contentType == 0, viewRef); checkEmojiOnly(emojiOnly); generateLayout(fromUser); return true; @@ -3831,7 +3907,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(), AndroidUtilities.dp(20), false, contentType == 0, viewRef); if (hashtagsType != 0) { if (!(linkDescription instanceof Spannable)) { linkDescription = new SpannableStringBuilder(linkDescription); @@ -3841,6 +3917,51 @@ public class MessageObject { } } + public CharSequence getVoiceTranscription() { + if (messageOwner == null || messageOwner.voiceTranscription == null) { + return null; + } + if (TextUtils.isEmpty(messageOwner.voiceTranscription)) { + SpannableString ssb = new SpannableString(LocaleController.getString("NoWordsRecognized", R.string.NoWordsRecognized)); + ssb.setSpan(new CharacterStyle() { + @Override + public void updateDrawState(TextPaint textPaint) { + textPaint.setTextSize(textPaint.getTextSize() * .8f); + textPaint.setColor(Theme.chat_timePaint.getColor()); + } + }, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + return ssb; + } + CharSequence text = messageOwner.voiceTranscription; + if (!TextUtils.isEmpty(text)) { + text = Emoji.replaceEmoji(text, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false, contentType == 0, viewRef); + } + return text; + } + + public float measureVoiceTranscriptionHeight() { + CharSequence voiceTranscription = getVoiceTranscription(); + if (voiceTranscription == null) { + return 0; + } + int width = AndroidUtilities.displaySize.x - AndroidUtilities.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) + .setBreakStrategy(StaticLayout.BREAK_STRATEGY_HIGH_QUALITY) + .setHyphenationFrequency(StaticLayout.HYPHENATION_FREQUENCY_NONE) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .build(); + } else { + captionLayout = new StaticLayout(voiceTranscription, Theme.chat_msgTextPaint, width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + } + return captionLayout.getHeight(); + } + + public boolean isVoiceTranscriptionOpen() { + return isVoice() && messageOwner != null && messageOwner.voiceTranscriptionOpen && messageOwner.voiceTranscription != null && (messageOwner.voiceTranscriptionFinal || TranscribeButton.isTranscribing(this)) && UserConfig.getInstance(currentAccount).isPremium(); + } + public void generateCaption() { if (caption != null || isRoundVideo()) { return; @@ -3854,7 +3975,7 @@ public class MessageObject { msg = messageOwner.message; } - caption = Emoji.replaceEmoji(msg, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + caption = Emoji.replaceEmoji(msg, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false, contentType == 0, viewRef); boolean hasEntities; if (messageOwner.send_state != MESSAGE_SEND_STATE_SENT) { @@ -3864,15 +3985,16 @@ public class MessageObject { } boolean useManualParse = !hasEntities && ( - eventId != 0 || - messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_old || - messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_layer68 || - messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_layer74 || - messageOwner.media instanceof TLRPC.TL_messageMediaDocument_old || - messageOwner.media instanceof TLRPC.TL_messageMediaDocument_layer68 || - messageOwner.media instanceof TLRPC.TL_messageMediaDocument_layer74 || - isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || - messageOwner.id < 0); + eventId != 0 || + messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_old || + messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_layer68 || + messageOwner.media instanceof TLRPC.TL_messageMediaPhoto_layer74 || + messageOwner.media instanceof TLRPC.TL_messageMediaDocument_old || + messageOwner.media instanceof TLRPC.TL_messageMediaDocument_layer68 || + messageOwner.media instanceof TLRPC.TL_messageMediaDocument_layer74 || + isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT || + messageOwner.id < 0 + ); if (useManualParse) { if (containsUrls(caption)) { @@ -3901,11 +4023,14 @@ public class MessageObject { } public static void addUrlsByPattern(boolean isOut, CharSequence charSequence, boolean botCommands, int patternType, int duration, boolean check) { + if (charSequence == null) { + return; + } try { Matcher matcher; if (patternType == 3 || patternType == 4) { if (videoTimeUrlPattern == null) { - videoTimeUrlPattern = Pattern.compile("\\b(?:(\\d{1,2}):)?(\\d{1,3}):([0-5][0-9])\\b"); + videoTimeUrlPattern = Pattern.compile("\\b(?:(\\d{1,2}):)?(\\d{1,3}):([0-5][0-9])\\b([^\\n]*)"); } matcher = videoTimeUrlPattern.matcher(charSequence); } else if (patternType == 1) { @@ -3925,10 +4050,6 @@ public class MessageObject { int end = matcher.end(); URLSpanNoUnderline url = null; if (patternType == 3 || patternType == 4) { - URLSpan[] spans = spannable.getSpans(start, end, URLSpan.class); - if (spans != null && spans.length > 0) { - continue; - } int count = matcher.groupCount(); int s1 = matcher.start(1); int e1 = matcher.end(1); @@ -3936,9 +4057,19 @@ public class MessageObject { int e2 = matcher.end(2); int s3 = matcher.start(3); int e3 = matcher.end(3); + int s4 = matcher.start(4); + int e4 = matcher.end(4); int minutes = Utilities.parseInt(charSequence.subSequence(s2, e2)); int seconds = Utilities.parseInt(charSequence.subSequence(s3, e3)); int hours = s1 >= 0 && e1 >= 0 ? Utilities.parseInt(charSequence.subSequence(s1, e1)) : -1; + String label = s4 < 0 || e4 < 0 ? null : charSequence.subSequence(s4, e4).toString(); + if (s4 >= 0 || e4 >= 0) { + end = e3; + } + URLSpan[] spans = spannable.getSpans(start, end, URLSpan.class); + if (spans != null && spans.length > 0) { + continue; + } seconds += minutes * 60; if (hours > 0) { seconds += hours * 60 * 60; @@ -3951,6 +4082,7 @@ public class MessageObject { } else { url = new URLSpanNoUnderline("audio?" + seconds); } + url.label = label; } else { char ch = charSequence.charAt(start); if (patternType != 0) { @@ -4102,6 +4234,9 @@ public class MessageObject { } public boolean addEntitiesToText(CharSequence text, boolean photoViewer, boolean useManualParse) { + if (text == null) { + return false; + } if (isRestrictedMessage) { ArrayList entities = new ArrayList<>(); TLRPC.TL_messageEntityItalic entityItalic = new TLRPC.TL_messageEntityItalic(); @@ -4225,6 +4360,9 @@ public class MessageObject { for (int b = 0, N2 = runs.size(); b < N2; b++) { TextStyleSpan.TextStyleRun run = runs.get(b); + if ((run.flags & TextStyleSpan.FLAG_STYLE_SPOILER) != 0 && newRun.start >= run.start && newRun.end <= run.end) { + continue; + } if (newRun.start > run.start) { if (newRun.start >= run.end) { @@ -4836,7 +4974,7 @@ public class MessageObject { return messageOwner.realId != 0 ? messageOwner.realId : messageOwner.id; } - public static int getMessageSize(TLRPC.Message message) { + public static long getMessageSize(TLRPC.Message message) { TLRPC.Document document; if (message.media instanceof TLRPC.TL_messageMediaWebPage) { document = message.media.webpage.document; @@ -4851,7 +4989,7 @@ public class MessageObject { return 0; } - public int getSize() { + public long getSize() { return getMessageSize(messageOwner); } @@ -5841,7 +5979,7 @@ public class MessageObject { && !messageOwner.fwd_from.imported && ( messageOwner.fwd_from.saved_from_peer == null - || messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel && messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id + || !(messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerChannel) || messageOwner.fwd_from.saved_from_peer.channel_id != messageOwner.fwd_from.from_id.channel_id || (((messageOwner.flags & TLRPC.MESSAGE_FLAG_REPLY) == 0) && (messageOwner.fwd_from.from_id instanceof TLRPC.TL_peerUser || messageOwner.fwd_from.from_id == null && messageOwner.fwd_from.from_name != null)) @@ -6172,13 +6310,17 @@ public class MessageObject { } public void checkMediaExistance() { + checkMediaExistance(true); + } + + public void checkMediaExistance(boolean useFileDatabaseQueue) { File cacheFile = null; attachPathExists = false; mediaExists = false; if (type == TYPE_PHOTO) { TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, AndroidUtilities.getPhotoSize()); if (currentPhotoObject != null) { - File file = FileLoader.getPathToMessage(messageOwner); + File file = FileLoader.getInstance(currentAccount).getPathToMessage(messageOwner, useFileDatabaseQueue); if (needDrawBluredPreview()) { mediaExists = new File(file.getAbsolutePath() + ".enc").exists(); } @@ -6193,7 +6335,7 @@ public class MessageObject { attachPathExists = f.exists(); } if (!attachPathExists) { - File file = FileLoader.getPathToMessage(messageOwner); + File file = FileLoader.getInstance(currentAccount).getPathToMessage(messageOwner, useFileDatabaseQueue); if (type == 3 && needDrawBluredPreview()) { mediaExists = new File(file.getAbsolutePath() + ".enc").exists(); } @@ -6206,22 +6348,22 @@ public class MessageObject { TLRPC.Document document = getDocument(); if (document != null) { if (isWallpaper()) { - mediaExists = FileLoader.getPathToAttach(document, true).exists(); + mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, true, useFileDatabaseQueue).exists(); } else { - mediaExists = FileLoader.getPathToAttach(document).exists(); + mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(document, null, false, useFileDatabaseQueue).exists(); } } else if (type == 0) { TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoThumbs, AndroidUtilities.getPhotoSize()); if (currentPhotoObject == null) { return; } - mediaExists = FileLoader.getPathToAttach(currentPhotoObject, true).exists(); + mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(currentPhotoObject, null, true, useFileDatabaseQueue).exists(); } else if (type == 11) { TLRPC.Photo photo = messageOwner.action.photo; if (photo == null || photo.video_sizes.isEmpty()) { return; } - mediaExists = FileLoader.getPathToAttach(photo.video_sizes.get(0), true).exists(); + mediaExists = FileLoader.getInstance(currentAccount).getPathToAttach(photo.video_sizes.get(0), null, true, useFileDatabaseQueue).exists(); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 15915670d..c60e86d4a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -54,9 +54,11 @@ import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.JoinCallAlert; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.SwipeGestureSettingsView; +import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.DialogsActivity; import org.telegram.ui.EditWidgetActivity; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import org.telegram.ui.ProfileActivity; import java.io.File; @@ -153,7 +155,8 @@ public class MessagesController extends BaseController implements NotificationCe private LongSparseArray> pollsToCheck = new LongSparseArray<>(); private int pollsToCheckSize; private long lastViewsCheckTime; - + public SparseIntArray premiumFeaturesTypesToPosition = new SparseIntArray(); + public ArrayList dialogFilters = new ArrayList<>(); public SparseArray dialogFiltersById = new SparseArray<>(); private boolean loadingSuggestedFilters; @@ -324,6 +327,7 @@ public class MessagesController extends BaseController implements NotificationCe public boolean backgroundConnection; public float animatedEmojisZoom; public boolean filtersEnabled; + public boolean getfileExperimentalParams; public boolean showFiltersTooltip; public String venueSearchBot; public String gifSearchBot; @@ -353,11 +357,37 @@ public class MessagesController extends BaseController implements NotificationCe public int ringtoneDurationMax; public int ringtoneSizeMax; + public int channelsLimitDefault; + public int channelsLimitPremium; + public int savedGifsLimitDefault; + public int savedGifsLimitPremium; + public int stickersFavedLimitDefault; + public int stickersFavedLimitPremium; + public int dialogFiltersLimitDefault; + public int dialogFiltersLimitPremium; + public int dialogFiltersChatsLimitDefault; + public int dialogFiltersChatsLimitPremium; + public int dialogFiltersPinnedLimitDefault; + public int dialogFiltersPinnedLimitPremium; + public int publicLinksLimitDefault; + public int publicLinksLimitPremium; + public int captionLengthLimitDefault; + public int captionLengthLimitPremium; + public int aboutLengthLimitDefault; + public int aboutLengthLimitPremium; + + public int uploadMaxFileParts; + public int uploadMaxFilePartsPremium; + + public String premiumBotUsername; + public String premiumInvoiceSlug; + private SharedPreferences notificationsPreferences; private SharedPreferences mainPreferences; private SharedPreferences emojiPreferences; public volatile boolean ignoreSetOnline; + public boolean premiumLocked; public void getNextReactionMention(long dialogId, int count, Consumer callback) { final MessagesStorage messagesStorage = getMessagesStorage(); @@ -399,6 +429,125 @@ public class MessagesController extends BaseController implements NotificationCe }); } + public void updatePremium(boolean premium) { + if (dialogFilters.isEmpty()) { + return; + } + if (!premium) { + if (!dialogFilters.get(0).isDefault()) { + for (int i = 1; i < dialogFilters.size(); i++) { + if (dialogFilters.get(i).isDefault()) { + DialogFilter defaultFilter = dialogFilters.remove(i); + dialogFilters.add(0, defaultFilter); + break; + } + } + } + lockFiltersInternal(); + } else { + for (int i = 0; i < dialogFilters.size(); i++) { + dialogFilters.get(i).locked = false; + } + } + + getMessagesStorage().saveDialogFiltersOrder(); + getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); + } + + public void lockFiltersInternal() { + boolean changed = false; + if (!getUserConfig().isPremium() && dialogFilters.size() - 1 > dialogFiltersLimitDefault) { + int n = dialogFilters.size() - 1 - dialogFiltersLimitDefault; + ArrayList filtersSortedById = new ArrayList<>(dialogFilters); + Collections.reverse(filtersSortedById); + for (int i = 0; i < filtersSortedById.size(); i++) { + if (i < n) { + if (!filtersSortedById.get(i).locked) { + changed = true; + } + filtersSortedById.get(i).locked = true; + } else { + if (filtersSortedById.get(i).locked) { + changed = true; + } + filtersSortedById.get(i).locked = false; + } + } + } + if (changed) { + getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); + } + } + + public int getCaptionMaxLengthLimit() { + return getUserConfig().isPremium() ? captionLengthLimitPremium : captionLengthLimitDefault; + } + + public int getAboutLimit() { + return getUserConfig().isPremium() ? aboutLengthLimitPremium : aboutLengthLimitDefault; + } + + public boolean isPremiumUser(TLRPC.User currentUser) { + return !premiumLocked && currentUser.premium; + } + + + public ArrayList filterPremiumStickers(ArrayList stickerSets) { + if (!premiumLocked) { + return stickerSets; + } + for (int i = 0; i < stickerSets.size(); i++) { + TLRPC.TL_messages_stickerSet newSet = MessagesController.getInstance(currentAccount).filterPremiumStickers(stickerSets.get(i)); + if (newSet == null) { + stickerSets.remove(i); + i--; + } else { + stickerSets.set(i, newSet); + } + } + return stickerSets; + } + + public TLRPC.TL_messages_stickerSet filterPremiumStickers(TLRPC.TL_messages_stickerSet stickerSet) { + if (!premiumLocked || stickerSet == null) { + return stickerSet; + } + try { + + boolean hasPremiumSticker = false; + for (int i = 0; i < stickerSet.documents.size(); i++) { + if (MessageObject.isPremiumSticker(stickerSet.documents.get(i))) { + hasPremiumSticker = true; + break; + } + } + if (hasPremiumSticker) { + NativeByteBuffer nativeByteBuffer = new NativeByteBuffer(stickerSet.getObjectSize()); + stickerSet.serializeToStream(nativeByteBuffer); + nativeByteBuffer.position(0); + TLRPC.TL_messages_stickerSet newStickersSet = new TLRPC.TL_messages_stickerSet(); + nativeByteBuffer.readInt32(true); + newStickersSet.readParams(nativeByteBuffer, true); + nativeByteBuffer.reuse(); + stickerSet = newStickersSet; + + for (int i = 0; i < stickerSet.documents.size(); i++) { + if (MessageObject.isPremiumSticker(stickerSet.documents.get(i))) { + stickerSet.documents.remove(i); + stickerSet.packs.remove(i); + i--; + if (stickerSet.documents.isEmpty()) { + return null; + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return stickerSet; + } + private class SponsoredMessagesInfo { private ArrayList messages; private long loadTime; @@ -574,6 +723,7 @@ public class MessagesController extends BaseController implements NotificationCe private static int dialogFilterPointer = 10; public int localId = dialogFilterPointer++; + public boolean locked; public boolean includesDialog(AccountInstance accountInstance, long dialogId) { MessagesController messagesController = accountInstance.getMessagesController(); @@ -653,6 +803,10 @@ public class MessagesController extends BaseController implements NotificationCe return alwaysShow.contains(dialogId); } + + public boolean isDefault() { + return id == 0; + } } private DialogFilter sortingDialogFilter; @@ -819,7 +973,7 @@ public class MessagesController extends BaseController implements NotificationCe public static MessagesController getInstance(int num) { MessagesController localInstance = Instance.get(num); if (localInstance == null) { - synchronized (MessagesController.class) { + synchronized (lockObjects[num]) { localInstance = Instance.get(num); if (localInstance == null) { Instance.put(num, localInstance = new MessagesController(num)); @@ -855,7 +1009,6 @@ public class MessagesController extends BaseController implements NotificationCe public MessagesController(int num) { super(num); - currentAccount = num; ImageLoader.getInstance(); getMessagesStorage(); getLocationController(); @@ -928,6 +1081,7 @@ public class MessagesController extends BaseController implements NotificationCe qrLoginCamera = mainPreferences.getBoolean("qrLoginCamera", false); saveGifsWithStickers = mainPreferences.getBoolean("saveGifsWithStickers", false); filtersEnabled = mainPreferences.getBoolean("filtersEnabled", false); + getfileExperimentalParams = mainPreferences.getBoolean("getfileExperimentalParams", false); showFiltersTooltip = mainPreferences.getBoolean("showFiltersTooltip", false); autoarchiveAvailable = mainPreferences.getBoolean("autoarchiveAvailable", false); groupCallVideoMaxParticipants = mainPreferences.getInt("groipCallVideoMaxParticipants", 30); @@ -941,6 +1095,31 @@ public class MessagesController extends BaseController implements NotificationCe roundVideoBitrate = mainPreferences.getInt("roundVideoBitrate", 1000); roundAudioBitrate = mainPreferences.getInt("roundAudioBitrate", 64); pendingSuggestions = mainPreferences.getStringSet("pendingSuggestions", null); + channelsLimitDefault = mainPreferences.getInt("channelsLimitDefault", 500); + channelsLimitPremium = mainPreferences.getInt("channelsLimitPremium", 2 * channelsLimitDefault); + savedGifsLimitDefault = mainPreferences.getInt("savedGifsLimitDefault", 200); + savedGifsLimitPremium = mainPreferences.getInt("savedGifsLimitPremium", 400); + stickersFavedLimitDefault = mainPreferences.getInt("stickersFavedLimitDefault", 5); + stickersFavedLimitPremium = mainPreferences.getInt("stickersFavedLimitPremium", 200); + dialogFiltersLimitDefault = mainPreferences.getInt("dialogFiltersLimitDefault", 10); + dialogFiltersLimitPremium = mainPreferences.getInt("dialogFiltersLimitPremium", 20); + dialogFiltersChatsLimitDefault = mainPreferences.getInt("dialogFiltersChatsLimitDefault", 100); + dialogFiltersChatsLimitPremium = mainPreferences.getInt("dialogFiltersChatsLimitPremium", 200); + dialogFiltersPinnedLimitDefault = mainPreferences.getInt("dialogFiltersPinnedLimitDefault", 5); + dialogFiltersPinnedLimitPremium = mainPreferences.getInt("dialogFiltersPinnedLimitPremium", 10); + publicLinksLimitDefault = mainPreferences.getInt("publicLinksLimitDefault", 10); + publicLinksLimitPremium = mainPreferences.getInt("publicLinksLimitPremium", 20); + captionLengthLimitDefault = mainPreferences.getInt("captionLengthLimitDefault", 1024); + captionLengthLimitPremium = mainPreferences.getInt("captionLengthLimitPremium", 4096); + aboutLengthLimitDefault = mainPreferences.getInt("aboutLengthLimitDefault", 70); + aboutLengthLimitPremium = mainPreferences.getInt("aboutLengthLimitPremium", 140); + uploadMaxFileParts = mainPreferences.getInt("uploadMaxFileParts", (int) (FileLoader.DEFAULT_MAX_FILE_SIZE / 1024L / 512L)); + uploadMaxFilePartsPremium = mainPreferences.getInt("uploadMaxFilePartsPremium", uploadMaxFileParts * 2); + premiumInvoiceSlug = mainPreferences.getString("premiumInvoiceSlug", null); + premiumBotUsername = mainPreferences.getString("premiumBotUsername", null); + premiumLocked = mainPreferences.getBoolean("premiumLocked", false); + + loadPremiumFeaturesPreviewOrder(mainPreferences.getString("premiumFeaturesTypesToPosition", null)); if (pendingSuggestions != null) { pendingSuggestions = new HashSet<>(pendingSuggestions); } else { @@ -1061,8 +1240,15 @@ public class MessagesController extends BaseController implements NotificationCe FileLog.e(e); } } + + if (BuildVars.DEBUG_VERSION) { + AndroidUtilities.runOnUIThread(() -> { + loadAppConfig(); + }, 2000); + } } + private void sendLoadPeersRequest(TLObject req, ArrayList requests, TLRPC.messages_Dialogs pinnedDialogs, TLRPC.messages_Dialogs pinnedRemoteDialogs, ArrayList users, ArrayList chats, ArrayList filtersToSave, SparseArray filtersToDelete, ArrayList filtersOrder, HashMap> filterDialogRemovals, HashMap> filterUserRemovals, HashSet filtersUnreadCounterReset) { getConnectionsManager().sendRequest(req, (response, error) -> { if (response instanceof TLRPC.TL_messages_chats) { @@ -1188,6 +1374,7 @@ public class MessagesController extends BaseController implements NotificationCe enc_chats_dict = null; } + ArrayList newMessages = new ArrayList<>(); for (int a = 0; a < pinnedDialogs.messages.size(); a++) { TLRPC.Message message = pinnedDialogs.messages.get(a); if (message.peer_id.channel_id != 0) { @@ -1201,9 +1388,11 @@ public class MessagesController extends BaseController implements NotificationCe continue; } } - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, false); + newMessages.add(messageObject); new_dialogMessage.put(messageObject.getDialogId(), messageObject); } + getFileLoader().checkMediaExistance(newMessages); for (int a = 0; a < pinnedDialogs.dialogs.size(); a++) { TLRPC.Dialog d = pinnedDialogs.dialogs.get(a); @@ -1413,6 +1602,8 @@ public class MessagesController extends BaseController implements NotificationCe loadingRemoteFilters = false; getNotificationCenter().postNotificationName(NotificationCenter.filterSettingsUpdated); } + + lockFiltersInternal(); }); }); } @@ -1527,6 +1718,7 @@ public class MessagesController extends BaseController implements NotificationCe if (dialogFilters.size() == 1 && SharedConfig.getChatSwipeAction(currentAccount) != SwipeGestureSettingsView.SWIPE_GESTURE_FOLDERS) { SharedConfig.updateChatListSwipeSetting(SwipeGestureSettingsView.SWIPE_GESTURE_FOLDERS); } + lockFiltersInternal(); } public void removeFilter(DialogFilter filter) { @@ -1550,6 +1742,45 @@ public class MessagesController extends BaseController implements NotificationCe for (int a = 0, N = object.value.size(); a < N; a++) { TLRPC.TL_jsonObjectValue value = object.value.get(a); switch (value.key) { + case "premium_purchase_blocked": { + if (value.value instanceof TLRPC.TL_jsonBool) { + if (premiumLocked != ((TLRPC.TL_jsonBool) value.value).value) { + premiumLocked = ((TLRPC.TL_jsonBool) value.value).value; + editor.putBoolean("premiumLocked", premiumLocked); + changed = true; + } + } + break; + } + case "premium_bot_username": { + if (value.value instanceof TLRPC.TL_jsonString) { + String string = ((TLRPC.TL_jsonString) value.value).value; + if (!string.equals(premiumBotUsername)) { + premiumBotUsername = string; + editor.putString("premiumBotUsername", premiumBotUsername); + changed = true; + } + } + break; + } + case "premium_invoice_slug": { + if (value.value instanceof TLRPC.TL_jsonString) { + String string = ((TLRPC.TL_jsonString) value.value).value; + if (!string.equals(premiumInvoiceSlug)) { + premiumInvoiceSlug = string; + editor.putString("premiumInvoiceSlug", premiumInvoiceSlug); + changed = true; + } + } + break; + } + case "premium_promo_order": { + if (value.value instanceof TLRPC.TL_jsonArray) { + TLRPC.TL_jsonArray order = (TLRPC.TL_jsonArray) value.value; + changed = savePremiumFeaturesPreviewOrder(editor, order.value); + } + break; + } case "emojies_animated_zoom": { if (value.value instanceof TLRPC.TL_jsonNumber) { TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; @@ -1561,6 +1792,17 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "getfile_experimental_params": { + if (value.value instanceof TLRPC.TL_jsonBool) { + TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; + if (bool.value != getfileExperimentalParams) { + getfileExperimentalParams = bool.value; + editor.putBoolean("getfileExperimentalParams", getfileExperimentalParams); + changed = true; + } + } + break; + } case "dialog_filters_enabled": { if (value.value instanceof TLRPC.TL_jsonBool) { TLRPC.TL_jsonBool bool = (TLRPC.TL_jsonBool) value.value; @@ -2047,10 +2289,230 @@ public class MessagesController extends BaseController implements NotificationCe } break; } + case "channels_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != channelsLimitDefault) { + channelsLimitDefault = (int) number.value; + editor.putInt("channelsLimitDefault", channelsLimitDefault); + changed = true; + } + } + break; + } + case "channels_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != channelsLimitPremium) { + channelsLimitPremium = (int) number.value; + editor.putInt("channelsLimitPremium", channelsLimitPremium); + changed = true; + } + } + break; + } + case "saved_gifs_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != savedGifsLimitDefault) { + savedGifsLimitDefault = (int) number.value; + editor.putInt("savedGifsLimitDefault", savedGifsLimitDefault); + changed = true; + } + } + break; + } + case "saved_gifs_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != savedGifsLimitPremium) { + savedGifsLimitPremium = (int) number.value; + editor.putInt("savedGifsLimitPremium", savedGifsLimitPremium); + changed = true; + } + } + break; + } + case "stickers_faved_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != stickersFavedLimitDefault) { + stickersFavedLimitDefault = (int) number.value; + editor.putInt("stickersFavedLimitDefault", stickersFavedLimitDefault); + changed = true; + } + } + break; + } + case "stickers_faved_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != stickersFavedLimitPremium) { + stickersFavedLimitPremium = (int) number.value; + editor.putInt("stickersFavedLimitPremium", stickersFavedLimitPremium); + changed = true; + } + } + break; + } + case "dialog_filters_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersLimitDefault) { + dialogFiltersLimitDefault = (int) number.value; + editor.putInt("dialogFiltersLimitDefault", dialogFiltersLimitDefault); + changed = true; + } + } + break; + } + case "dialog_filters_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersLimitPremium) { + dialogFiltersLimitPremium = (int) number.value; + editor.putInt("dialogFiltersLimitPremium", dialogFiltersLimitPremium); + changed = true; + } + } + break; + } + case "dialog_filters_chats_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersChatsLimitDefault) { + dialogFiltersChatsLimitDefault = (int) number.value; + editor.putInt("dialogFiltersChatsLimitDefault", dialogFiltersChatsLimitDefault); + changed = true; + } + } + break; + } + case "dialog_filters_chats_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersChatsLimitPremium) { + dialogFiltersChatsLimitPremium = (int) number.value; + editor.putInt("dialogFiltersChatsLimitPremium", dialogFiltersChatsLimitPremium); + changed = true; + } + } + break; + } + case "dialog_filters_pinned_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersPinnedLimitDefault) { + dialogFiltersPinnedLimitDefault = (int) number.value; + editor.putInt("dialogFiltersPinnedLimitDefault", dialogFiltersPinnedLimitDefault); + changed = true; + } + } + break; + } + case "dialog_filters_pinned_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != dialogFiltersPinnedLimitPremium) { + dialogFiltersPinnedLimitPremium = (int) number.value; + editor.putInt("dialogFiltersPinnedLimitPremium", dialogFiltersPinnedLimitPremium); + changed = true; + } + } + break; + } + case "upload_max_fileparts_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != uploadMaxFileParts) { + uploadMaxFileParts = (int) number.value; + editor.putInt("uploadMaxFileParts", uploadMaxFileParts); + changed = true; + } + } + break; + } + case "upload_max_fileparts_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != uploadMaxFilePartsPremium) { + uploadMaxFilePartsPremium = (int) number.value; + editor.putInt("uploadMaxFilePartsPremium", uploadMaxFilePartsPremium); + changed = true; + } + } + break; + } + case "channels_public_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != publicLinksLimitDefault) { + publicLinksLimitDefault = (int) number.value; + editor.putInt("publicLinksLimit", publicLinksLimitDefault); + changed = true; + } + } + break; + } + case "channels_public_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != publicLinksLimitPremium) { + publicLinksLimitPremium = (int) number.value; + editor.putInt("publicLinksLimitPremium", publicLinksLimitPremium); + changed = true; + } + } + break; + } + case "caption_length_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != captionLengthLimitDefault) { + captionLengthLimitDefault = (int) number.value; + editor.putInt("captionLengthLimitDefault", captionLengthLimitDefault); + changed = true; + } + } + break; + } + case "caption_length_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != captionLengthLimitPremium) { + captionLengthLimitPremium = (int) number.value; + editor.putInt("captionLengthLimitPremium", captionLengthLimitPremium); + changed = true; + } + } + break; + } + case "about_length_limit_default": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != aboutLengthLimitDefault) { + aboutLengthLimitDefault = (int) number.value; + editor.putInt("aboutLengthLimitDefault", aboutLengthLimitDefault); + changed = true; + } + } + break; + } + case "about_length_limit_premium": { + if (value.value instanceof TLRPC.TL_jsonNumber) { + TLRPC.TL_jsonNumber number = (TLRPC.TL_jsonNumber) value.value; + if (number.value != aboutLengthLimitPremium) { + aboutLengthLimitPremium = (int) number.value; + editor.putInt("aboutLengthLimitPremium", aboutLengthLimitPremium); + changed = true; + } + } + break; + } } } if (changed) { - editor.commit(); + editor.apply(); } if (keelAliveChanged) { ApplicationLoader.startPushService(); @@ -2062,6 +2524,49 @@ public class MessagesController extends BaseController implements NotificationCe })); } + private boolean savePremiumFeaturesPreviewOrder(SharedPreferences.Editor editor, ArrayList value) { + StringBuilder stringBuilder = new StringBuilder(); + premiumFeaturesTypesToPosition.clear(); + for (int i = 0; i < value.size(); i++) { + String s = null; + if (value.get(i) instanceof TLRPC.TL_jsonString) { + s = ((TLRPC.TL_jsonString) value.get(i)).value; + } + if (s != null) { + int type = PremiumPreviewFragment.severStringToFeatureType(s); + if (type >= 0) { + premiumFeaturesTypesToPosition.put(type, i); + if (stringBuilder.length() > 0) { + stringBuilder.append('_'); + } + stringBuilder.append(type); + } + } + } + + boolean changed; + if (stringBuilder.length() > 0) { + String string = stringBuilder.toString(); + changed = !string.equals(mainPreferences.getString("premiumFeaturesTypesToPosition", null)); + editor.putString("premiumFeaturesTypesToPosition", string); + } else { + editor.remove("premiumFeaturesTypesToPosition"); + changed = mainPreferences.getString("premiumFeaturesTypesToPosition", null) != null; + } + return changed; + } + + private void loadPremiumFeaturesPreviewOrder(String string) { + premiumFeaturesTypesToPosition.clear(); + if (string != null) { + String[] types = string.split("_"); + for (int i = 0; i < types.length; i++) { + int type = Integer.parseInt(types[i]); + premiumFeaturesTypesToPosition.put(type, i); + } + } + + } public void removeSuggestion(long did, String suggestion) { if (TextUtils.isEmpty(suggestion)) { return; @@ -2104,6 +2609,7 @@ public class MessagesController extends BaseController implements NotificationCe revokeTimePmLimit = config.revoke_pm_time_limit; canRevokePmInbox = config.revoke_pm_inbox; linkPrefix = config.me_url_prefix; + boolean forceTryIpV6 = config.force_try_ipv6; if (linkPrefix.endsWith("/")) { linkPrefix = linkPrefix.substring(0, linkPrefix.length() - 1); } @@ -2221,8 +2727,10 @@ public class MessagesController extends BaseController implements NotificationCe editor.putString("dcDomainName2", dcDomainName); editor.putInt("webFileDatacenterId", webFileDatacenterId); editor.putString("suggestedLangCode", suggestedLangCode); + editor.putBoolean("forceTryIpV6", forceTryIpV6); editor.commit(); + getConnectionsManager().setForceTryIpV6(forceTryIpV6); LocaleController.getInstance().checkUpdateForCurrentRemoteLocale(currentAccount, config.lang_pack_version, config.base_lang_pack_version); getNotificationCenter().postNotificationName(NotificationCenter.configLoaded); }); @@ -2447,7 +2955,7 @@ public class MessagesController extends BaseController implements NotificationCe File path = new File(ApplicationLoader.getFilesDirFixed(), overrideWallpaperInfo.originalFileName); if (wallPaper != null) { try { - AndroidUtilities.copyFile(path, FileLoader.getPathToAttach(wallPaper.document, true)); + AndroidUtilities.copyFile(path, getFileLoader().getPathToAttach(wallPaper.document, true)); } catch (Exception ignore) { } @@ -2936,7 +3444,7 @@ public class MessagesController extends BaseController implements NotificationCe } addSupportUser(); - AndroidUtilities.runOnUIThread(()->{ + AndroidUtilities.runOnUIThread(() -> { getNotificationCenter().postNotificationName(NotificationCenter.suggestedFiltersLoaded); getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); getNotificationCenter().postNotificationName(NotificationCenter.dialogsNeedReload); @@ -3723,6 +4231,7 @@ public class MessagesController extends BaseController implements NotificationCe applyDialogNotificationsSettings(user.id, userFull.notify_settings); if (userFull.bot_info instanceof TLRPC.TL_botInfo) { + userFull.bot_info.user_id = user.id; getMediaDataController().putBotInfo(user.id, userFull.bot_info); } int index = blockePeers.indexOfKey(user.id); @@ -3748,7 +4257,11 @@ public class MessagesController extends BaseController implements NotificationCe if (!names.equals(userFull.user.first_name + userFull.user.last_name + userFull.user.username)) { getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_NAME); } + if (userFull.user.photo != null && userFull.user.photo.has_video) { + getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_AVATAR); + } if (userFull.bot_info instanceof TLRPC.TL_botInfo) { + userFull.bot_info.user_id = userFull.id; getNotificationCenter().postNotificationName(NotificationCenter.botInfoDidLoad, userFull.bot_info, classGuid); } getNotificationCenter().postNotificationName(NotificationCenter.userInfoDidLoad, user.id, userFull); @@ -4344,7 +4857,7 @@ public class MessagesController extends BaseController implements NotificationCe setUserAdminRole(chatId, user, rights, rank, isChannel, parentFragment, addingNew, forceAdmin, botHash, onSuccess, null); } - public void setUserAdminRole(long chatId, TLRPC.User user, TLRPC.TL_chatAdminRights rights, String rank, boolean isChannel, BaseFragment parentFragment, boolean addingNew, boolean forceAdmin, String botHash, Runnable onSuccess, Runnable onError) { + public void setUserAdminRole(long chatId, TLRPC.User user, TLRPC.TL_chatAdminRights rights, String rank, boolean isChannel, BaseFragment parentFragment, boolean addingNew, boolean forceAdmin, String botHash, Runnable onSuccess, ErrorDelegate onError) { if (user == null || rights == null) { return; } @@ -4367,11 +4880,11 @@ public class MessagesController extends BaseController implements NotificationCe } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, parentFragment, req, isChannel)); if (onError != null) { - AndroidUtilities.runOnUIThread(onError); + AndroidUtilities.runOnUIThread(() -> onError.run(error)); } } }; - if (chat.megagroup && addingNew) { + if (chat.megagroup && addingNew || !TextUtils.isEmpty(botHash)) { addUserToChat(chatId, user, 0, botHash, parentFragment, true, () -> getConnectionsManager().sendRequest(req, requestDelegate), onError); } else { getConnectionsManager().sendRequest(req, requestDelegate); @@ -4392,11 +4905,11 @@ public class MessagesController extends BaseController implements NotificationCe } else { AndroidUtilities.runOnUIThread(() -> AlertsCreator.processError(currentAccount, error, parentFragment, req, false)); if (onError != null) { - AndroidUtilities.runOnUIThread(onError); + AndroidUtilities.runOnUIThread(() -> onError.run(error)); } } }; - if (req.is_admin || addingNew) { + if (req.is_admin || addingNew || !TextUtils.isEmpty(botHash)) { addUserToChat(chatId, user, 0, botHash, parentFragment, true, () -> getConnectionsManager().sendRequest(req, requestDelegate), onError); } else { getConnectionsManager().sendRequest(req, requestDelegate); @@ -5026,7 +5539,7 @@ public class MessagesController extends BaseController implements NotificationCe long fromId = 0; if (fromUser != null) { fromId = fromUser.id; - } else if (fromChat != null){ + } else if (fromChat != null) { fromId = fromChat.id; } if (offset == 0) { @@ -6945,7 +7458,9 @@ public class MessagesController extends BaseController implements NotificationCe } if (!needProcess && DialogObject.isEncryptedDialog(dialogId)) { - AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoadWithoutProcess, classGuid, messagesRes.messages.size(), isCache, isEnd, last_message_id)); + AndroidUtilities.runOnUIThread(() -> { + getNotificationCenter().postNotificationName(NotificationCenter.messagesDidLoadWithoutProcess, classGuid, messagesRes.messages.size(), isCache, isEnd, last_message_id); + }); return; } ArrayList objects = new ArrayList<>(); @@ -6957,7 +7472,7 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.Message message = messagesRes.messages.get(a); message.dialog_id = dialogId; long checkFileTime = SystemClock.elapsedRealtime(); - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, true, false); messageObject.createStrippedThumb(); fileProcessTime += (SystemClock.elapsedRealtime() - checkFileTime); messageObject.scheduled = mode == 1; @@ -6984,6 +7499,8 @@ public class MessagesController extends BaseController implements NotificationCe } } } + + getFileLoader().checkMediaExistance(objects); if (BuildVars.LOGS_ENABLED) { FileLog.d("process time = " + (SystemClock.elapsedRealtime() - startProcessTime) + " file time = " + fileProcessTime + " for dialog = " + dialogId); } @@ -8032,6 +8549,7 @@ public class MessagesController extends BaseController implements NotificationCe } TLRPC.Message lastMessage = null; + ArrayList newMessages = new ArrayList<>(); for (int a = 0; a < dialogsRes.messages.size(); a++) { TLRPC.Message message = dialogsRes.messages.get(a); if (NekoConfig.ignoreBlocked.Bool() && getMessagesController().blockePeers.indexOfKey(message.peer_id.user_id) >= 0) { @@ -8051,9 +8569,11 @@ public class MessagesController extends BaseController implements NotificationCe continue; } } - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, false); + newMessages.add(messageObject); new_dialogMessage.put(messageObject.getDialogId(), messageObject); } + getFileLoader().checkMediaExistance(newMessages); if (!fromCache && !migrate && dialogsLoadOffset[UserConfig.i_dialogsLoadOffsetId] != -1 && loadType == 0) { int totalDialogsLoadCount = getUserConfig().getTotalDialogsCount(folderId); @@ -8713,6 +9233,7 @@ public class MessagesController extends BaseController implements NotificationCe chatsDict.put(c.id, c); } + ArrayList newMessages = new ArrayList<>(); for (int a = 0; a < dialogsRes.messages.size(); a++) { TLRPC.Message message = dialogsRes.messages.get(a); if (promoDialogId == 0 || promoDialogId != message.dialog_id) { @@ -8728,9 +9249,12 @@ public class MessagesController extends BaseController implements NotificationCe } } } - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, false); + newMessages.add(messageObject); new_dialogMessage.put(messageObject.getDialogId(), messageObject); } + getFileLoader().checkMediaExistance(newMessages); + for (int a = 0; a < dialogsRes.dialogs.size(); a++) { TLRPC.Dialog d = dialogsRes.dialogs.get(a); DialogObject.initDialog(d); @@ -9473,6 +9997,10 @@ public class MessagesController extends BaseController implements NotificationCe } public void convertToMegaGroup(Context context, long chatId, BaseFragment fragment, MessagesStorage.LongCallback convertRunnable) { + convertToMegaGroup(context, chatId, fragment, convertRunnable, null); + } + + public void convertToMegaGroup(Context context, long chatId, BaseFragment fragment, MessagesStorage.LongCallback convertRunnable, Runnable errorRunnable) { TLRPC.TL_messages_migrateChat req = new TLRPC.TL_messages_migrateChat(); req.chat_id = chatId; AlertDialog progressDialog = context != null ? new AlertDialog(context, 3) : null; @@ -9503,6 +10031,9 @@ public class MessagesController extends BaseController implements NotificationCe } }); } else { + if (errorRunnable != null) { + errorRunnable.run(); + } AndroidUtilities.runOnUIThread(() -> { if (convertRunnable != null) { convertRunnable.run(0); @@ -9631,7 +10162,59 @@ public class MessagesController extends BaseController implements NotificationCe }, ConnectionsManager.RequestFlagInvokeAfter); } - public void toogleChannelSignatures(long chatId, boolean enabled) { + public void toggleChatJoinToSend(long chatId, boolean enabled, Runnable onSuccess, Runnable onError) { + TLRPC.TL_channels_toggleJoinToSend req = new TLRPC.TL_channels_toggleJoinToSend(); + req.channel = getInputChannel(chatId); + req.enabled = enabled; + getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + processUpdates((TLRPC.Updates) response, false); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT)); + if (onSuccess != null) { + onSuccess.run(); + } + } + if (error != null) { + if (!"CHAT_NOT_MODIFIED".equals(error.text)) { + if (onError != null) { + onError.run(); + } + } else if (response == null) { + if (onSuccess != null) { + onSuccess.run(); + } + } + } + }, ConnectionsManager.RequestFlagInvokeAfter); + } + + public void toggleChatJoinRequest(long chatId, boolean enabled, Runnable onSuccess, Runnable onError) { + TLRPC.TL_channels_toggleJoinRequest req = new TLRPC.TL_channels_toggleJoinRequest(); + req.channel = getInputChannel(chatId); + req.enabled = enabled; + getConnectionsManager().sendRequest(req, (response, error) -> { + if (response != null) { + processUpdates((TLRPC.Updates) response, false); + AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT)); + if (onSuccess != null) { + onSuccess.run(); + } + } + if (error != null) { + if (!"CHAT_NOT_MODIFIED".equals(error.text)) { + if (onError != null) { + onError.run(); + } + } else if (response == null) { + if (onSuccess != null) { + onSuccess.run(); + } + } + } + }, ConnectionsManager.RequestFlagInvokeAfter); + } + + public void toggleChannelSignatures(long chatId, boolean enabled) { TLRPC.TL_channels_toggleSignatures req = new TLRPC.TL_channels_toggleSignatures(); req.channel = getInputChannel(chatId); req.enabled = enabled; @@ -9643,7 +10226,7 @@ public class MessagesController extends BaseController implements NotificationCe }, ConnectionsManager.RequestFlagInvokeAfter); } - public void toogleChannelInvitesHistory(long chatId, boolean enabled) { + public void toggleChannelInvitesHistory(long chatId, boolean enabled) { TLRPC.TL_channels_togglePreHistoryHidden req = new TLRPC.TL_channels_togglePreHistoryHidden(); req.channel = getInputChannel(chatId); req.enabled = enabled; @@ -9718,8 +10301,16 @@ public class MessagesController extends BaseController implements NotificationCe addUserToChat(chatId, user, forwardCount, botHash, fragment, false, onFinishRunnable, null); } - public void addUserToChat(long chatId, TLRPC.User user, int forwardCount, String botHash, BaseFragment fragment, boolean ignoreIfAlreadyExists, Runnable onFinishRunnable, Runnable onError) { + public interface ErrorDelegate { + // if returns true, a delegate allows to show default alert + public boolean run(TLRPC.TL_error error); + } + + public void addUserToChat(long chatId, TLRPC.User user, int forwardCount, String botHash, BaseFragment fragment, boolean ignoreIfAlreadyExists, Runnable onFinishRunnable, ErrorDelegate onError) { if (user == null) { + if (onError != null) { + onError.run(null); + } return; } @@ -9732,6 +10323,9 @@ public class MessagesController extends BaseController implements NotificationCe if (isChannel) { if (inputUser instanceof TLRPC.TL_inputUserSelf) { if (joiningToChannels.contains(chatId)) { + if (onError != null) { + onError.run(null); + } return; } TLRPC.TL_channels_joinChannel req = new TLRPC.TL_channels_joinChannel(); @@ -9777,10 +10371,17 @@ public class MessagesController extends BaseController implements NotificationCe return; } if (onError != null) { - AndroidUtilities.runOnUIThread(onError); + AndroidUtilities.runOnUIThread(() -> { + boolean handleErrors = onError.run(error); + if (handleErrors) { + AlertsCreator.processError(currentAccount, error, fragment, request, isChannel && !isMegagroup); + } + }); } AndroidUtilities.runOnUIThread(() -> { - AlertsCreator.processError(currentAccount, error, fragment, request, isChannel && !isMegagroup); + if (onError == null) { + AlertsCreator.processError(currentAccount, error, fragment, request, isChannel && !isMegagroup); + } if (isChannel && inputUser instanceof TLRPC.TL_inputUserSelf) { getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, UPDATE_MASK_CHAT); } @@ -9971,8 +10572,8 @@ public class MessagesController extends BaseController implements NotificationCe TLRPC.PhotoSize small = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 150); TLRPC.VideoSize videoSize = photo.video_sizes.isEmpty() ? null : photo.video_sizes.get(0); if (small != null && smallSize != null) { - File destFile = FileLoader.getPathToAttach(small, true); - File src = FileLoader.getPathToAttach(smallSize, true); + File destFile = getFileLoader().getPathToAttach(small, true); + File src = getFileLoader().getPathToAttach(smallSize, true); src.renameTo(destFile); String oldKey = smallSize.volume_id + "_" + smallSize.local_id + "@50_50"; String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; @@ -9980,12 +10581,12 @@ public class MessagesController extends BaseController implements NotificationCe } TLRPC.PhotoSize big = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 800); if (big != null && bigSize != null) { - File destFile = FileLoader.getPathToAttach(big, true); - File src = FileLoader.getPathToAttach(bigSize, true); + File destFile = getFileLoader().getPathToAttach(big, true); + File src = getFileLoader().getPathToAttach(bigSize, true); src.renameTo(destFile); } if (videoSize != null && videoPath != null) { - File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); + File destFile = getFileLoader().getPathToAttach(videoSize, "mp4", true); File src = new File(videoPath); src.renameTo(destFile); } @@ -10092,14 +10693,10 @@ public class MessagesController extends BaseController implements NotificationCe for (int i = 0; i < count; i++) { String value = preferences.getString("log_out_token_" + i, ""); SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); - // try { - TLRPC.TL_auth_loggedOut token = TLRPC.TL_auth_loggedOut.TLdeserialize(serializedData, serializedData.readInt32(true), true); - if (token != null) { - tokens.add(token); - } -// } catch (Throwable e) { -// FileLog.e(e); -// } + TLRPC.TL_auth_loggedOut token = TLRPC.TL_auth_loggedOut.TLdeserialize(serializedData, serializedData.readInt32(true), true); + if (token != null) { + tokens.add(token); + } } return tokens; } @@ -10110,17 +10707,17 @@ public class MessagesController extends BaseController implements NotificationCe preferences.edit().clear().apply(); int date = (int) (System.currentTimeMillis() / 1000L); for (int i = 0; i < Math.min(20, tokens.size()); i++) { - activeTokens.add(tokens.get(i)); + activeTokens.add(tokens.get(i)); } if (activeTokens.size() > 0) { - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("count", activeTokens.size()); - for (int i = 0; i < activeTokens.size(); i++) { - SerializedData data = new SerializedData(activeTokens.get(i).getObjectSize()); - activeTokens.get(i).serializeToStream(data); - editor.putString("log_out_token_" + i, Utilities.bytesToHex(data.toByteArray())); - } - editor.apply(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putInt("count", activeTokens.size()); + for (int i = 0; i < activeTokens.size(); i++) { + SerializedData data = new SerializedData(activeTokens.get(i).getObjectSize()); + activeTokens.get(i).serializeToStream(data); + editor.putString("log_out_token_" + i, Utilities.bytesToHex(data.toByteArray())); + } + editor.apply(); } } @@ -11279,6 +11876,7 @@ public class MessagesController extends BaseController implements NotificationCe chatsDict.put(c.id, c); } + ArrayList newMessages = new ArrayList<>(); for (int a = 0; a < res.messages.size(); a++) { TLRPC.Message message = res.messages.get(a); if (message.peer_id.channel_id != 0) { @@ -11292,9 +11890,11 @@ public class MessagesController extends BaseController implements NotificationCe continue; } } - MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, true); + MessageObject messageObject = new MessageObject(currentAccount, message, usersDict, chatsDict, false, false); + newMessages.add(messageObject); new_dialogMessage.put(messageObject.getDialogId(), messageObject); } + getFileLoader().checkMediaExistance(newMessages); boolean firstIsFolder = !newPinnedDialogs.isEmpty() && newPinnedDialogs.get(0) instanceof TLRPC.TL_dialogFolder; for (int a = 0, N = newPinnedDialogs.size(); a < N; a++) { TLRPC.Dialog d = newPinnedDialogs.get(a); @@ -13384,6 +13984,16 @@ public class MessagesController extends BaseController implements NotificationCe updatesOnMainThread = new ArrayList<>(); } updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateTranscribeAudio) { + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); + } else if (baseUpdate instanceof TLRPC.TL_updateTranscribedAudio) { + if (updatesOnMainThread == null) { + updatesOnMainThread = new ArrayList<>(); + } + updatesOnMainThread.add(baseUpdate); } } if (messages != null) { @@ -14062,6 +14672,20 @@ public class MessagesController extends BaseController implements NotificationCe getMemberRequestsController().onPendingRequestsUpdated(update); } else if (baseUpdate instanceof TLRPC.TL_updateSavedRingtones) { getMediaDataController().ringtoneDataStore.loadUserRingtones(); + } else if (baseUpdate instanceof TLRPC.TL_updateTranscribeAudio) { + FileLog.e("Received legacy TL_updateTranscribeAudio update"); + } else if (baseUpdate instanceof TLRPC.TL_updateTranscribedAudio) { + TLRPC.TL_updateTranscribedAudio update = (TLRPC.TL_updateTranscribedAudio) baseUpdate; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("Transcription update received, pending=" + update.pending + " id=" + update.transcription_id + " text=" + update.text); + } + + if (!(update.pending && TextUtils.isEmpty(update.text))) { + if (update.pending || !TranscribeButton.finishTranscription(null, update.transcription_id, update.text)) { + getMessagesStorage().updateMessageVoiceTranscription(DialogObject.getPeerDialogId(update.peer), update.msg_id, update.text, update.transcription_id, !update.pending); + getNotificationCenter().postNotificationName(NotificationCenter.voiceTranscriptionUpdate, null, (Long) update.transcription_id, (String) update.text, null, (Boolean) !update.pending); + } + } } } if (editor != null) { @@ -14805,7 +15429,7 @@ public class MessagesController extends BaseController implements NotificationCe save = true; } if (save) { - getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date); + getMediaDataController().addRecentGif(message.messageOwner.media.document, message.messageOwner.date, true); } } else if (!message.isAnimatedEmoji() && (message.isSticker() || message.isAnimatedSticker())) { getMediaDataController().addRecentSticker(MediaDataController.TYPE_IMAGE, message, message.messageOwner.media.document, message.messageOwner.date, false); @@ -15511,7 +16135,7 @@ public class MessagesController extends BaseController implements NotificationCe } public void markSponsoredAsRead(long dialog_id, MessageObject object) { - // sponsoredMessages.remove(dialog_id); + // sponsoredMessages.remove(dialog_id); } public void deleteMessagesRange(long dialogId, long channelId, int minDate, int maxDate, boolean forAll, Runnable callback) { @@ -15581,9 +16205,9 @@ public class MessagesController extends BaseController implements NotificationCe if (callback != null) { TLRPC.ChannelParticipant participant = res instanceof TLRPC.TL_channels_channelParticipant ? ((TLRPC.TL_channels_channelParticipant) res).participant : null; callback.run( - err == null && participant != null && !participant.left, - participant != null ? participant.admin_rights : null, - participant != null ? participant.rank : null + err == null && participant != null && !participant.left, + participant != null ? participant.admin_rights : null, + participant != null ? participant.rank : null ); } }); @@ -15603,9 +16227,9 @@ public class MessagesController extends BaseController implements NotificationCe } if (callback != null) { callback.run( - userParticipant != null, - chatFull.participants != null && chatFull.participants.admin_id == user.id ? ChatRightsEditActivity.emptyAdminRights(true) : null, - null + userParticipant != null, + chatFull.participants != null && chatFull.participants.admin_id == user.id ? ChatRightsEditActivity.emptyAdminRights(true) : null, + null ); } } else { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index 3627ac6d7..80f7dddef 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -28,6 +28,7 @@ import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLiteDatabase; import org.telegram.SQLite.SQLiteException; import org.telegram.SQLite.SQLitePreparedStatement; +import org.telegram.messenger.ringtone.RingtoneDataStore; import org.telegram.messenger.support.LongSparseIntArray; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.RequestDelegate; @@ -56,7 +57,7 @@ import tw.nekomimi.nekogram.transtale.TranslateDb; public class MessagesStorage extends BaseController { - private DispatchQueue storageQueue = new DispatchQueue("storageQueue"); + private DispatchQueue storageQueue; private SQLiteDatabase database; private File cacheFile; private File walCacheFile; @@ -88,7 +89,7 @@ public class MessagesStorage extends BaseController { private CountDownLatch openSync = new CountDownLatch(1); private static SparseArray Instance = new SparseArray(); - private final static int LAST_DB_VERSION = 93; + private final static int LAST_DB_VERSION = 98; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; @@ -194,6 +195,7 @@ public class MessagesStorage extends BaseController { public MessagesStorage(int instance) { super(instance); + storageQueue = new DispatchQueue("storageQueue_" + instance); //storageQueue.setPriority(Thread.MAX_PRIORITY); storageQueue.postRunnable(() -> openDatabase(1)); } @@ -291,7 +293,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_idx_scheduled_messages_v2 ON scheduled_messages_v2(uid, date);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, reply_to_message_id);").stepThis().dispose(); - database.executeFast("CREATE TABLE messages_v2(mid INTEGER, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER, forwards INTEGER, replies_data BLOB, thread_reply_id INTEGER, is_channel INTEGER, reply_to_message_id INTEGER, PRIMARY KEY(mid, uid))").stepThis().dispose(); + database.executeFast("CREATE TABLE messages_v2(mid INTEGER, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER, forwards INTEGER, replies_data BLOB, thread_reply_id INTEGER, is_channel INTEGER, reply_to_message_id INTEGER, custom_params BLOB, PRIMARY KEY(mid, uid))").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_read_out_idx_messages_v2 ON messages_v2(uid, mid, read_state, out);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages_v2 ON messages_v2(uid, date, mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages_v2 ON messages_v2(mid, out);").stepThis().dispose(); @@ -365,7 +367,7 @@ public class MessagesStorage extends BaseController { 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(); - database.executeFast("CREATE TABLE stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash INTEGER);").stepThis().dispose(); + database.executeFast("CREATE TABLE stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash INTEGER, premium INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE stickers_dice(emoji TEXT PRIMARY KEY, data BLOB, date INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE hashtag_recent_v2(id TEXT PRIMARY KEY, date INTEGER);").stepThis().dispose(); database.executeFast("CREATE TABLE webpage_pending_v2(id INTEGER, mid INTEGER, uid INTEGER, PRIMARY KEY (id, mid, uid));").stepThis().dispose(); @@ -402,6 +404,8 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE TABLE downloading_documents(data BLOB, hash INTEGER, id INTEGER, state INTEGER, date INTEGER, PRIMARY KEY(hash, id));").stepThis().dispose(); database.executeFast("CREATE TABLE attach_menu_bots(data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose(); + + database.executeFast("CREATE TABLE premium_promo(data BLOB, date INTEGER);").stepThis().dispose(); //version database.executeFast("PRAGMA user_version = " + LAST_DB_VERSION).stepThis().dispose(); } else { @@ -1576,6 +1580,28 @@ public class MessagesStorage extends BaseController { if (version == 92) { database.executeFast("CREATE TABLE IF NOT EXISTS attach_menu_bots(data BLOB, hash INTEGER, date INTEGER);").stepThis().dispose(); database.executeFast("PRAGMA user_version = 93").stepThis().dispose(); + version = 95; + } + + if (version == 95 || version == 93) { + executeNoException("ALTER TABLE messages_v2 ADD COLUMN custom_params BLOB default NULL"); + database.executeFast("PRAGMA user_version = 96").stepThis().dispose(); + version = 96; + } + + // skip 94, 95. private beta db rollback + if (version == 96) { + database.executeFast("CREATE TABLE IF NOT EXISTS premium_promo(data BLOB, date INTEGER);").stepThis().dispose(); + database.executeFast("UPDATE stickers_v2 SET date = 0"); + database.executeFast("PRAGMA user_version = 97").stepThis().dispose(); + version = 97; + } + + if (version == 97) { + database.executeFast("DROP TABLE IF EXISTS stickers_featured;").stepThis().dispose(); + database.executeFast("CREATE TABLE stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash INTEGER, premium INTEGER);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 98").stepThis().dispose(); + version = 98; } FileLog.d("MessagesStorage db migration finished"); @@ -2187,7 +2213,6 @@ public class MessagesStorage extends BaseController { } - private static class ReadDialog { public int lastMid; public int date; @@ -2403,6 +2428,7 @@ public class MessagesStorage extends BaseController { SQLiteCursor filtersCursor = database.queryFinalized("SELECT id, ord, unread_count, flags, title, emoticon FROM dialog_filter_neko WHERE 1"); boolean updateCounters = false; + boolean hasDefaultFilter = false; while (filtersCursor.next()) { MessagesController.DialogFilter filter = new MessagesController.DialogFilter(); filter.id = filtersCursor.intValue(0); @@ -2460,9 +2486,33 @@ public class MessagesStorage extends BaseController { } cursor2.dispose(); } + if (filter.id == 0) { + hasDefaultFilter = true; + } } filtersCursor.dispose(); + if (!hasDefaultFilter) { + MessagesController.DialogFilter filter = new MessagesController.DialogFilter(); + filter.id = 0; + filter.order = 0; + filter.name = "ALL_CHATS"; + for (int i = 0; i < dialogFilters.size(); i++) { + dialogFilters.get(i).order++; + } + dialogFilters.add(filter); + dialogFiltersMap.put(filter.id, filter); + filtersById.put(filter.id, filter); + + SQLitePreparedStatement state = database.executeFast("REPLACE INTO dialog_filter VALUES(?, ?, ?, ?, ?)"); + state.bindInteger(1, filter.id); + state.bindInteger(2, filter.order); + state.bindInteger(3, filter.unreadCount); + state.bindInteger(4, filter.flags); + state.bindString(5, filter.name); + state.stepThis().dispose(); + } + Collections.sort(dialogFilters, (o1, o2) -> { if (o1.order > o2.order) { return 1; @@ -2902,7 +2952,7 @@ public class MessagesStorage extends BaseController { state.bindInteger(2, filter.order); state.bindInteger(3, filter.unreadCount); state.bindInteger(4, filter.flags); - state.bindString(5, filter.name); + state.bindString(5, filter.id == 0 ? "ALL_CHATS" : filter.name); if (filter.emoticon != null) { state.bindString(6, filter.emoticon); } else { @@ -2971,7 +3021,7 @@ public class MessagesStorage extends BaseController { HashMap> filterDialogRemovals = new HashMap<>(); HashSet filtersUnreadCounterReset = new HashSet<>(); for (int a = 0, N = vector.objects.size(); a < N; a++) { - TLRPC.TL_dialogFilter newFilter = (TLRPC.TL_dialogFilter) vector.objects.get(a); + TLRPC.DialogFilter newFilter = (TLRPC.DialogFilter) vector.objects.get(a); filtersOrder.add(newFilter.id); int newFlags = 0; if (newFilter.contacts) { @@ -3366,7 +3416,17 @@ public class MessagesStorage extends BaseController { } public void saveDialogFiltersOrder() { - storageQueue.postRunnable(this::saveDialogFiltersOrderInternal); + ArrayList filtersFinal = new ArrayList<>(getMessagesController().dialogFilters); + storageQueue.postRunnable(() -> { + dialogFilters.clear(); + dialogFiltersMap.clear(); + dialogFilters.addAll(filtersFinal); + for (int i = 0; i < filtersFinal.size(); i++) { + filtersFinal.get(i).order = i; + dialogFiltersMap.put(filtersFinal.get(i).id, filtersFinal.get(i)); + } + saveDialogFiltersOrderInternal(); + }); } protected static void addReplyMessages(TLRPC.Message message, LongSparseArray>> replyMessageOwners, LongSparseArray> dialogReplyMessagesIds) { @@ -3781,6 +3841,9 @@ public class MessagesStorage extends BaseController { if (document == null) { return false; } + if (getMediaDataController().ringtoneDataStore.contains(document.id)) { + return false; + } id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_AUDIO; } else if (MessageObject.isStickerMessage(message) || MessageObject.isAnimatedStickerMessage(message)) { @@ -3796,6 +3859,9 @@ public class MessagesStorage extends BaseController { id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_VIDEO; } else if (document != null) { + if (getMediaDataController().ringtoneDataStore.contains(document.id)) { + return false; + } id = document.id; type = DownloadController.AUTODOWNLOAD_TYPE_DOCUMENT; } else if (photo != null) { @@ -3815,7 +3881,7 @@ public class MessagesStorage extends BaseController { if (!TextUtils.isEmpty(name)) { namesToDelete.add(name); } - File file = FileLoader.getPathToAttach(photoSize, forceCache); + File file = getFileLoader().getPathToAttach(photoSize, forceCache); if (file.toString().length() > 0) { filesToDelete.add(file); } @@ -3826,13 +3892,13 @@ public class MessagesStorage extends BaseController { if (!TextUtils.isEmpty(name)) { namesToDelete.add(name); } - File file = FileLoader.getPathToAttach(document, forceCache); + File file = getFileLoader().getPathToAttach(document, forceCache); if (file.toString().length() > 0) { filesToDelete.add(file); } for (int a = 0, N = document.thumbs.size(); a < N; a++) { TLRPC.PhotoSize photoSize = document.thumbs.get(a); - file = FileLoader.getPathToAttach(photoSize); + file = getFileLoader().getPathToAttach(photoSize); if (file.toString().length() > 0) { filesToDelete.add(file); } @@ -4217,7 +4283,7 @@ public class MessagesStorage extends BaseController { ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); ArrayList messages = new ArrayList<>(); - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date, uid FROM messages_v2 WHERE mid IN (%s) AND uid = %d", TextUtils.join(",", mids), dialogId)); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, mid, date, uid, custom_params FROM messages_v2 WHERE mid IN (%s) AND uid = %d", TextUtils.join(",", mids), dialogId)); while (cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(0); if (data != null) { @@ -4238,6 +4304,11 @@ public class MessagesStorage extends BaseController { message.id = cursor.intValue(1); message.date = cursor.intValue(2); message.dialog_id = cursor.longValue(3); + NativeByteBuffer customParams = cursor.byteBufferValue(4); + if (customParams != null) { + MessageCustomParamsHelper.readLocalParams(message, customParams); + customParams.reuse(); + } messages.add(message); } } @@ -4245,7 +4316,8 @@ public class MessagesStorage extends BaseController { cursor.dispose(); deleteFromDownloadQueue(idsToDelete, true); if (!messages.isEmpty()) { - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0, ?)"); + for (int a = 0; a < messages.size(); a++) { TLRPC.Message message = messages.get(a); @@ -4289,12 +4361,20 @@ public class MessagesStorage extends BaseController { state.bindInteger(14, 0); } state.bindLong(15, MessageObject.getChannelId(message)); + NativeByteBuffer customParams = MessageCustomParamsHelper.writeLocalParams(message); + if (customParams != null) { + state.bindByteBuffer(16, customParams); + } else { + state.bindNull(16); + } state.step(); - data.reuse(); if (repliesData != null) { repliesData.reuse(); } + if (customParams != null) { + customParams.reuse(); + } } state.dispose(); AndroidUtilities.runOnUIThread(() -> { @@ -4414,6 +4494,145 @@ public class MessagesStorage extends BaseController { }); } + public void updateMessageVoiceTranscriptionOpen(long dialogId, int msgId, TLRPC.Message saveFromMessage) { + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + TLRPC.Message message = getMessageWithCustomParamsOnly(msgId, dialogId); + message.voiceTranscriptionOpen = saveFromMessage.voiceTranscriptionOpen; + message.voiceTranscriptionRated = saveFromMessage.voiceTranscriptionRated; + message.voiceTranscriptionFinal = saveFromMessage.voiceTranscriptionFinal; + message.voiceTranscriptionId = saveFromMessage.voiceTranscriptionId; + + SQLitePreparedStatement state = database.executeFast("UPDATE messages_v2 SET custom_params = ? WHERE mid = ? AND uid = ?"); + state.requery(); + NativeByteBuffer nativeByteBuffer = MessageCustomParamsHelper.writeLocalParams(message); + if (nativeByteBuffer != null) { + state.bindByteBuffer(1, nativeByteBuffer); + } else { + state.bindNull(1); + } + state.bindInteger(2, msgId); + state.bindLong(3, dialogId); + state.step(); + state.dispose(); + if (nativeByteBuffer != null) { + nativeByteBuffer.reuse(); + } + database.commitTransaction(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void updateMessageVoiceTranscription(long dialogId, int messageId, String text, long transcriptionId, boolean isFinal) { + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + TLRPC.Message message = getMessageWithCustomParamsOnly(messageId, dialogId); + message.voiceTranscriptionFinal = isFinal; + message.voiceTranscriptionId = transcriptionId; + message.voiceTranscription = text; + + SQLitePreparedStatement state = database.executeFast("UPDATE messages_v2 SET custom_params = ? WHERE mid = ? AND uid = ?"); + state.requery(); + NativeByteBuffer nativeByteBuffer = MessageCustomParamsHelper.writeLocalParams(message); + if (nativeByteBuffer != null) { + state.bindByteBuffer(1, nativeByteBuffer); + } else { + state.bindNull(1); + } + state.bindInteger(2, messageId); + state.bindLong(3, dialogId); + state.step(); + state.dispose(); + database.commitTransaction(); + if (nativeByteBuffer != null) { + nativeByteBuffer.reuse(); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void updateMessageVoiceTranscription(long dialogId, int messageId, String text, TLRPC.Message saveFromMessage) { + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + TLRPC.Message message = getMessageWithCustomParamsOnly(messageId, dialogId); + message.voiceTranscriptionOpen = saveFromMessage.voiceTranscriptionOpen; + message.voiceTranscriptionRated = saveFromMessage.voiceTranscriptionRated; + message.voiceTranscriptionFinal = saveFromMessage.voiceTranscriptionFinal; + message.voiceTranscriptionId = saveFromMessage.voiceTranscriptionId; + message.voiceTranscription = text; + + SQLitePreparedStatement state = database.executeFast("UPDATE messages_v2 SET custom_params = ? WHERE mid = ? AND uid = ?"); + state.requery(); + NativeByteBuffer nativeByteBuffer = MessageCustomParamsHelper.writeLocalParams(message); + if (nativeByteBuffer != null) { + state.bindByteBuffer(1, nativeByteBuffer); + } else { + state.bindNull(1); + } + state.bindInteger(2, messageId); + state.bindLong(3, dialogId); + state.step(); + state.dispose(); + database.commitTransaction(); + if (nativeByteBuffer != null) { + nativeByteBuffer.reuse(); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + public void updateMessageCustomParams(long dialogId, TLRPC.Message saveFromMessage) { + storageQueue.postRunnable(() -> { + try { + database.beginTransaction(); + TLRPC.Message message = getMessageWithCustomParamsOnly(saveFromMessage.id, dialogId); + MessageCustomParamsHelper.copyParams(saveFromMessage, message); + + SQLitePreparedStatement state = database.executeFast("UPDATE messages_v2 SET custom_params = ? WHERE mid = ? AND uid = ?"); + state.requery(); + NativeByteBuffer nativeByteBuffer = MessageCustomParamsHelper.writeLocalParams(message); + if (nativeByteBuffer != null) { + state.bindByteBuffer(1, nativeByteBuffer); + } else { + state.bindNull(1); + } + state.bindInteger(2, saveFromMessage.id); + state.bindLong(3, dialogId); + state.step(); + state.dispose(); + database.commitTransaction(); + if (nativeByteBuffer != null) { + nativeByteBuffer.reuse(); + } + } catch (Exception e) { + FileLog.e(e); + } + }); + } + + private TLRPC.Message getMessageWithCustomParamsOnly(int messageId, long dialogId) { + TLRPC.Message message = new TLRPC.TL_message(); + try { + SQLiteCursor cursor = database.queryFinalized("SELECT custom_params FROM messages_v2 WHERE mid = " + messageId + " AND uid = " + dialogId); + if (cursor.next()) { + MessageCustomParamsHelper.readLocalParams(message, cursor.byteBufferValue(0)); + } + cursor.dispose(); + } catch (SQLiteException e) { + FileLog.e(e); + } + return message; + } + public void getNewTask(LongSparseArray> oldTask, LongSparseArray> oldTaskMedia) { storageQueue.postRunnable(() -> { try { @@ -6901,7 +7120,7 @@ public class MessagesStorage extends BaseController { LongSparseArray> replyMessageRandomOwners = new LongSparseArray<>(); ArrayList replyMessageRandomIds = new ArrayList<>(); SQLiteCursor cursor; - String messageSelect = "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention, m.imp, m.forwards, m.replies_data FROM messages_v2 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid AND r.uid = m.uid"; + String messageSelect = "SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl, m.mention, m.imp, m.forwards, m.replies_data, m.custom_params FROM messages_v2 as m LEFT JOIN randoms_v2 as r ON r.mid = m.mid AND r.uid = m.uid"; if (scheduled) { isEnd = true; @@ -7355,6 +7574,11 @@ public class MessagesStorage extends BaseController { } else if ((flags & 2) != 0) { message.stickerVerified = 2; } + NativeByteBuffer customParams = cursor.byteBufferValue(13); + if (customParams != null) { + MessageCustomParamsHelper.readLocalParams(message, customParams); + customParams.reuse(); + } res.messages.add(message); addUsersAndChatsFromMessage(message, usersToLoad, chatsToLoad); @@ -9068,7 +9292,7 @@ public class MessagesStorage extends BaseController { LongSparseArray> dialogMessagesIdsMap = new LongSparseArray<>(); LongSparseArray> dialogMentionsIdsMap = new LongSparseArray<>(); - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0, ?)"); SQLitePreparedStatement state_media = null; SQLitePreparedStatement state_randoms = database.executeFast("REPLACE INTO randoms_v2 VALUES(?, ?, ?)"); SQLitePreparedStatement state_download = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?, ?)"); @@ -9341,6 +9565,12 @@ public class MessagesStorage extends BaseController { state_messages.bindInteger(14, 0); } state_messages.bindLong(15, MessageObject.getChannelId(message)); + NativeByteBuffer customParams = MessageCustomParamsHelper.writeLocalParams(message); + if (customParams != null) { + state_messages.bindByteBuffer(16, customParams); + } else { + state_messages.bindNull(16); + } state_messages.step(); if (message.random_id != 0) { @@ -9398,6 +9628,9 @@ public class MessagesStorage extends BaseController { if (repliesData != null) { repliesData.reuse(); } + if (customParams != null) { + customParams.reuse(); + } data.reuse(); if (downloadMask != 0 && (message.peer_id.channel_id == 0 || message.post) && message.date >= getConnectionsManager().getCurrentTime() - 60 * 60 && getDownloadController().canDownloadMedia(message) == 1) { @@ -10852,12 +11085,14 @@ public class MessagesStorage extends BaseController { try { SQLiteCursor cursor = null; int readState = 0; + NativeByteBuffer customParams = null; try { - cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state FROM messages_v2 WHERE mid = %d AND uid = %d LIMIT 1", message.id, MessageObject.getDialogId(message))); + cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state, custom_params FROM messages_v2 WHERE mid = %d AND uid = %d LIMIT 1", message.id, MessageObject.getDialogId(message))); if (!cursor.next()) { return; } readState = cursor.intValue(1); + customParams = cursor.byteBufferValue(2); } catch (Exception e) { FileLog.e(e); } finally { @@ -10868,7 +11103,7 @@ public class MessagesStorage extends BaseController { database.beginTransaction(); - SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0, ?)"); SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); if (message.dialog_id == 0) { MessageObject.getDialogId(message); @@ -10914,6 +11149,11 @@ public class MessagesStorage extends BaseController { state.bindInteger(14, 0); } state.bindLong(15, MessageObject.getChannelId(message)); + if (customParams != null) { + state.bindByteBuffer(16, customParams); + } else { + state.bindNull(16); + } state.step(); if (MediaDataController.canAddMessageToMedia(message)) { @@ -10928,6 +11168,9 @@ public class MessagesStorage extends BaseController { if (repliesData != null) { repliesData.reuse(); } + if (customParams != null) { + customParams.reuse(); + } data.reuse(); state.dispose(); @@ -11026,7 +11269,7 @@ public class MessagesStorage extends BaseController { ArrayList namesToDelete = new ArrayList<>(); ArrayList> idsToDelete = new ArrayList<>(); - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0, ?)"); SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state_polls = null; SQLitePreparedStatement state_webpage = null; @@ -11042,7 +11285,7 @@ public class MessagesStorage extends BaseController { } if (load_type == -2) { - SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, data, ttl, mention, read_state, send_state FROM messages_v2 WHERE mid = %d AND uid = %d", message.id, MessageObject.getDialogId(message))); + SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, data, ttl, mention, read_state, send_state, custom_params FROM messages_v2 WHERE mid = %d AND uid = %d", message.id, MessageObject.getDialogId(message))); boolean exist; if (exist = cursor.next()) { NativeByteBuffer data = cursor.byteBufferValue(1); @@ -11066,6 +11309,11 @@ public class MessagesStorage extends BaseController { if (!sameMedia) { addFilesToDelete(oldMessage, filesToDelete, idsToDelete, namesToDelete, false); } + NativeByteBuffer customParams = cursor.byteBufferValue(6); + MessageCustomParamsHelper.readLocalParams(message, customParams); + if (customParams != null) { + customParams.reuse(); + } } boolean oldMention = cursor.intValue(3) != 0; int readState = cursor.intValue(4); @@ -11180,6 +11428,12 @@ public class MessagesStorage extends BaseController { state_messages.bindInteger(14, 0); } state_messages.bindLong(15, MessageObject.getChannelId(message)); + NativeByteBuffer customParams = MessageCustomParamsHelper.writeLocalParams(message); + if (customParams == null) { + state_messages.bindNull(16); + } else { + state_messages.bindByteBuffer(16, customParams); + } state_messages.step(); if (MediaDataController.canAddMessageToMedia(message)) { @@ -11201,6 +11455,9 @@ public class MessagesStorage extends BaseController { if (repliesData != null) { repliesData.reuse(); } + if (customParams != null) { + customParams.reuse(); + } data.reuse(); if (message.ttl_period != 0 && message.id > 0) { @@ -11683,7 +11940,7 @@ public class MessagesStorage extends BaseController { } if (!dialogs.dialogs.isEmpty()) { - SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0)"); + SQLitePreparedStatement state_messages = database.executeFast("REPLACE INTO messages_v2 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, 0, NULL)"); SQLitePreparedStatement state_dialogs = database.executeFast("REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); SQLitePreparedStatement state_media = database.executeFast("REPLACE INTO media_v4 VALUES(?, ?, ?, ?, ?)"); SQLitePreparedStatement state_settings = database.executeFast("REPLACE INTO dialog_settings VALUES(?, ?)"); @@ -12297,6 +12554,8 @@ public class MessagesStorage extends BaseController { } String savedMessages = LocaleController.getString("SavedMessages", R.string.SavedMessages).toLowerCase(); String savedMessages2 = "saved messages"; + String replies = LocaleController.getString("RepliesTitle", R.string.RepliesTitle).toLowerCase(); + String replies2 = "replies"; String search2 = LocaleController.getInstance().getTranslitString(search1); if (search1.equals(search2) || search2.length() == 0) { search2 = null; @@ -12360,6 +12619,21 @@ public class MessagesStorage extends BaseController { resultCount++; } + if (dialogsType != 4 && (replies).startsWith(search1) || replies2.startsWith(search1)) { + TLRPC.User user = getMessagesController().getUser(708513L); + if (user == null) { + user = getMessagesController().getUser(1271266957L); + } + if (user != null) { + DialogsSearchAdapter.DialogSearchResult dialogSearchResult = new DialogsSearchAdapter.DialogSearchResult(); + dialogSearchResult.date = Integer.MAX_VALUE; + dialogSearchResult.name = LocaleController.getString("RepliesTitle", R.string.RepliesTitle); + dialogSearchResult.object = user; + dialogsResult.put(user.id, dialogSearchResult); + resultCount++; + } + } + if (!usersToLoad.isEmpty()) { cursor = getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, status, name, uid FROM users WHERE uid IN(%s)", TextUtils.join(",", usersToLoad))); while (cursor.next()) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java index f1c54e889..abfd1deaf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicBrowserService.java @@ -35,6 +35,8 @@ import android.os.SystemClock; import android.service.media.MediaBrowserService; import android.text.TextUtils; +import androidx.collection.LongSparseArray; + import org.telegram.SQLite.SQLiteCursor; import org.telegram.messenger.audioinfo.AudioInfo; import org.telegram.tgnet.NativeByteBuffer; @@ -47,8 +49,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import androidx.collection.LongSparseArray; - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public class MusicBrowserService extends MediaBrowserService implements NotificationCenter.NotificationCenterDelegate { @@ -297,7 +297,7 @@ public class MusicBrowserService extends MediaBrowserService implements Notifica } Bitmap bitmap = null; if (avatar != null) { - bitmap = createRoundBitmap(FileLoader.getPathToAttach(avatar, true)); + bitmap = createRoundBitmap(FileLoader.getInstance(currentAccount).getPathToAttach(avatar, true)); if (bitmap != null) { builder.setIconBitmap(bitmap); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java index a4d83778e..0cc8a5bb7 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MusicPlayerService.java @@ -241,7 +241,7 @@ public class MusicPlayerService extends Service implements NotificationCenter.No albumArt = loadArtworkFromUrl(artworkUrlBig, false, !forBitmap); } } else { - loadingFilePath = FileLoader.getPathToAttach(messageObject.getDocument()).getAbsolutePath(); + loadingFilePath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(messageObject.getDocument()).getAbsolutePath(); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java index 90ffb9982..732fbacbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationCenter.java @@ -124,6 +124,7 @@ public class NotificationCenter { public static final int stickersImportComplete = totalEvents++; public static final int dialogDeleted = totalEvents++; public static final int webViewResultSent = totalEvents++; + public static final int voiceTranscriptionUpdate = totalEvents++; public static final int didGenerateFingerprintKeyPair = totalEvents++; @@ -246,6 +247,12 @@ public class NotificationCenter { public static final int onActivityResultReceived = totalEvents++; public static final int onRequestPermissionResultReceived = totalEvents++; public static final int onUserRingtonesUpdated = totalEvents++; + public static final int currentUserPremiumStatusChanged = totalEvents++; + public static final int premiumPromoUpdated = totalEvents++; + public static final int premiumStatusChangedGlobal = totalEvents++; + public static final int currentUserShowLimitReachedDialog = totalEvents++; + public static final int billingProductDetailsUpdated = totalEvents++; + public static final int premiumStickersPreviewLoaded = totalEvents++; // custom diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java index ed738844a..530178cd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/NotificationsController.java @@ -34,8 +34,6 @@ import android.graphics.PorterDuffXfermode; import android.graphics.drawable.BitmapDrawable; import android.media.AudioAttributes; import android.media.AudioManager; -import android.media.Ringtone; -import android.media.RingtoneManager; import android.media.SoundPool; import android.net.Uri; import android.os.Build; @@ -43,7 +41,6 @@ import android.os.PowerManager; import android.os.SystemClock; import android.provider.Settings; import android.text.TextUtils; -import android.util.Log; import android.util.SparseArray; import android.util.SparseBooleanArray; import android.text.TextUtils; @@ -3788,7 +3785,7 @@ public class NotificationsController extends BaseController { mBuilder.setLargeIcon(img.getBitmap()); } else { try { - File file = FileLoader.getPathToAttach(photoPath, true); + File file = getFileLoader().getPathToAttach(photoPath, true); if (file.exists()) { float scaleFactor = 160.0f / AndroidUtilities.dp(50); BitmapFactory.Options options = new BitmapFactory.Options(); @@ -4173,7 +4170,7 @@ public class NotificationsController extends BaseController { } if (photoPath != null) { - avatalFile = FileLoader.getPathToAttach(photoPath, true); + avatalFile = getFileLoader().getPathToAttach(photoPath, true); if (Build.VERSION.SDK_INT < 28) { BitmapDrawable img = ImageLoader.getInstance().getImageFromMemory(photoPath, null, "50_50"); if (img != null) { @@ -4245,7 +4242,7 @@ public class NotificationsController extends BaseController { try { if (sender != null && sender.photo != null && sender.photo.photo_small != null && sender.photo.photo_small.volume_id != 0 && sender.photo.photo_small.local_id != 0) { Person.Builder personBuilder = new Person.Builder().setName(LocaleController.getString("FromYou", R.string.FromYou)); - File avatar = FileLoader.getPathToAttach(sender.photo.photo_small, true); + File avatar = getFileLoader().getPathToAttach(sender.photo.photo_small, true); loadRoundAvatar(avatar, personBuilder); selfPerson = personBuilder.build(); personCache.put(selfUserId, selfPerson); @@ -4348,7 +4345,7 @@ public class NotificationsController extends BaseController { } } if (sender != null && sender.photo != null && sender.photo.photo_small != null && sender.photo.photo_small.volume_id != 0 && sender.photo.photo_small.local_id != 0) { - avatar = FileLoader.getPathToAttach(sender.photo.photo_small, true); + avatar = getFileLoader().getPathToAttach(sender.photo.photo_small, true); } } loadRoundAvatar(avatar, personBuilder); @@ -4361,7 +4358,7 @@ public class NotificationsController extends BaseController { boolean setPhoto = false; if (preview[0] && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !((ActivityManager) ApplicationLoader.applicationContext.getSystemService(Context.ACTIVITY_SERVICE)).isLowRamDevice()) { if (!waitingForPasscode && !messageObject.isSecretMedia() && (messageObject.type == 1 || messageObject.isSticker())) { - File attach = FileLoader.getPathToMessage(messageObject.messageOwner); + File attach = getFileLoader().getPathToMessage(messageObject.messageOwner); NotificationCompat.MessagingStyle.Message msg = new NotificationCompat.MessagingStyle.Message(message, ((long) messageObject.messageOwner.date) * 1000L, person); String mimeType = messageObject.isSticker() ? "image/webp" : "image/jpeg"; Uri uri; @@ -4404,7 +4401,7 @@ public class NotificationsController extends BaseController { if (preview[0] && !waitingForPasscode && messageObject.isVoice()) { List messages = messagingStyle.getMessages(); if (!messages.isEmpty()) { - File f = FileLoader.getPathToMessage(messageObject.messageOwner); + File f = getFileLoader().getPathToMessage(messageObject.messageOwner); Uri uri; if (Build.VERSION.SDK_INT >= 24) { try { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java index e934c9d6f..559847f86 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SecretChatHelper.java @@ -532,7 +532,7 @@ public class SecretChatHelper extends BaseController { size.location.local_id = file.key_fingerprint; String fileName2 = size.location.volume_id + "_" + size.location.local_id; File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); - File cacheFile2 = FileLoader.getPathToAttach(size); + File cacheFile2 = getFileLoader().getPathToAttach(size); cacheFile.renameTo(cacheFile2); ImageLoader.getInstance().replaceImageInCache(fileName, fileName2, ImageLocation.getForPhoto(size, newMsg.media.photo), true); ArrayList arr = new ArrayList<>(); @@ -561,7 +561,7 @@ public class SecretChatHelper extends BaseController { if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(newMsg.media.document); + File cacheFile2 = getFileLoader().getPathToAttach(newMsg.media.document); if (cacheFile.renameTo(cacheFile2)) { newMsgObj.mediaExists = newMsgObj.attachPathExists; newMsgObj.attachPathExists = false; @@ -923,7 +923,7 @@ public class SecretChatHelper extends BaseController { big.w = decryptedMessage.media.w; big.h = decryptedMessage.media.h; big.type = "x"; - big.size = file.size; + big.size = (int) file.size; big.location = new TLRPC.TL_fileEncryptedLocation(); big.location.key = decryptedMessage.media.key; big.location.iv = decryptedMessage.media.iv; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 8869f54b8..535b339b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -11,6 +11,8 @@ package org.telegram.messenger; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; +import android.content.res.AssetFileDescriptor; +import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.PorterDuff; @@ -27,6 +29,7 @@ import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.provider.MediaStore; +import android.provider.OpenableColumns; import android.text.TextUtils; import android.util.Base64; import android.util.SparseArray; @@ -61,11 +64,13 @@ import org.telegram.ui.Components.AnimatedFileDrawable; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Point; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.TwoStepVerificationActivity; import org.telegram.ui.TwoStepVerificationSetupActivity; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStream; import java.io.RandomAccessFile; @@ -1552,7 +1557,7 @@ public boolean retriedToSend; } TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (thumb instanceof TLRPC.TL_photoSize || thumb instanceof TLRPC.TL_photoSizeProgressive) { - File file = FileLoader.getPathToAttach(thumb, true); + File file = FileLoader.getInstance(currentAccount).getPathToAttach(thumb, true); if (file.exists()) { try { int len = (int) file.length(); @@ -1608,8 +1613,8 @@ public boolean retriedToSend; docFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_VIDEO), mediaLocationKey + docExt); } - ensureMediaThumbExists(false, finalDocument, docFile.getAbsolutePath(), null, 0); - keyFinal[0] = getKeyForPhotoSize(FileLoader.getClosestPhotoSizeWithSize(finalDocument.thumbs, 320), bitmapFinal, true, true); + ensureMediaThumbExists(getAccountInstance(), false, finalDocument, docFile.getAbsolutePath(), null, 0); + keyFinal[0] = getKeyForPhotoSize(getAccountInstance(), FileLoader.getClosestPhotoSizeWithSize(finalDocument.thumbs, 320), bitmapFinal, true, true); AndroidUtilities.runOnUIThread(() -> { if (bitmapFinal[0] != null && keyFinal[0] != null) { @@ -1694,12 +1699,13 @@ public boolean retriedToSend; } continue; } - if (!canSendStickers && (msgObj.isSticker() || msgObj.isAnimatedSticker() || msgObj.isGif() || msgObj.isGame())) { + boolean mediaIsSticker = (msgObj.isSticker() || msgObj.isAnimatedSticker() || msgObj.isGif() || msgObj.isGame()); + if (!canSendStickers && mediaIsSticker) { if (sendResult == 0) { sendResult = ChatObject.isActionBannedByDefault(chat, ChatObject.ACTION_SEND_STICKERS) ? 4 : 1; } continue; - } else if (!canSendMedia && (msgObj.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || msgObj.messageOwner.media instanceof TLRPC.TL_messageMediaDocument)) { + } else if (!canSendMedia && (msgObj.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto || msgObj.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) && !mediaIsSticker) { if (sendResult == 0) { sendResult = ChatObject.isActionBannedByDefault(chat, ChatObject.ACTION_SEND_MEDIA) ? 5 : 2; } @@ -2221,7 +2227,7 @@ public boolean retriedToSend; newMsg.attachPath = path; } else { TLRPC.FileLocation location1 = photo.sizes.get(photo.sizes.size() - 1).location; - newMsg.attachPath = FileLoader.getPathToAttach(location1, true).toString(); + newMsg.attachPath = FileLoader.getInstance(currentAccount).getPathToAttach(location1, true).toString(); } } else if (document != null) { newMsg.media = new TLRPC.TL_messageMediaDocument(); @@ -2951,8 +2957,10 @@ public boolean retriedToSend; } else if (button instanceof TLRPC.TL_keyboardButtonBuy) { if ((messageObject.messageOwner.media.flags & 4) == 0) { TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); - req.msg_id = messageObject.getId(); - req.peer = getMessagesController().getInputPeer(messageObject.messageOwner.peer_id); + TLRPC.TL_inputInvoiceMessage inputInvoice = new TLRPC.TL_inputInvoiceMessage(); + 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)); @@ -3298,7 +3306,7 @@ public boolean retriedToSend; newMsg.attachPath = path; } else { TLRPC.FileLocation location1 = photo.sizes.get(photo.sizes.size() - 1).location; - newMsg.attachPath = FileLoader.getPathToAttach(location1, true).toString(); + newMsg.attachPath = FileLoader.getInstance(currentAccount).getPathToAttach(location1, true).toString(); } } else if (game != null) { newMsg = new TLRPC.TL_message(); @@ -3381,7 +3389,7 @@ public boolean retriedToSend; params.put("ve", ve); } if (encryptedChat != null && document.dc_id > 0 && !MessageObject.isStickerDocument(document) && !MessageObject.isAnimatedStickerDocument(document, true)) { - newMsg.attachPath = FileLoader.getPathToAttach(document).toString(); + newMsg.attachPath = FileLoader.getInstance(currentAccount).getPathToAttach(document).toString(); } else { newMsg.attachPath = path; } @@ -4460,16 +4468,16 @@ public boolean retriedToSend; ImageLoader.getInstance().loadHttpFile(message.httpLocation, "file", currentAccount); } else { if (message.sendRequest != null) { - String location = FileLoader.getPathToAttach(message.photoSize).toString(); + String location = FileLoader.getInstance(currentAccount).getPathToAttach(message.photoSize).toString(); putToDelayedMessages(location, message); getFileLoader().uploadFile(location, false, true, ConnectionsManager.FileTypePhoto); putToUploadingMessages(message.obj); } else { - String location = FileLoader.getPathToAttach(message.photoSize).toString(); + String location = FileLoader.getInstance(currentAccount).getPathToAttach(message.photoSize).toString(); if (message.sendEncryptedRequest != null && message.photoSize.location.dc_id != 0) { File file = new File(location); if (!file.exists()) { - location = FileLoader.getPathToAttach(message.photoSize, true).toString(); + location = FileLoader.getInstance(currentAccount).getPathToAttach(message.photoSize, true).toString(); file = new File(location); } if (!file.exists()) { @@ -4697,7 +4705,7 @@ public boolean retriedToSend; TLRPC.TL_messages_sendEncryptedMultiMedia request = (TLRPC.TL_messages_sendEncryptedMultiMedia) message.sendEncryptedRequest; inputMedia = request.files.get(index); } - String location = FileLoader.getPathToAttach(message.photoSize).toString(); + String location = FileLoader.getInstance(currentAccount).getPathToAttach(message.photoSize).toString(); putToDelayedMessages(location, message); message.extraHashMap.put(location, inputMedia); message.extraHashMap.put(messageObject, location); @@ -5608,7 +5616,7 @@ public boolean retriedToSend; File cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName + ".jpg"); File cacheFile2; if (sentMessage.media.ttl_seconds == 0 && (sentMessage.media.photo.sizes.size() == 1 || size.w > 90 || size.h > 90)) { - cacheFile2 = FileLoader.getPathToAttach(size); + cacheFile2 = FileLoader.getInstance(currentAccount).getPathToAttach(size); } else { cacheFile2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName2 + ".jpg"); } @@ -5703,7 +5711,7 @@ public boolean retriedToSend; save = true; } if (save) { - getMediaDataController().addRecentGif(sentMessage.media.document, sentMessage.date); + getMediaDataController().addRecentGif(sentMessage.media.document, sentMessage.date, true); } } else if (MessageObject.isStickerDocument(sentMessage.media.document) || MessageObject.isAnimatedStickerDocument(sentMessage.media.document, true)) { getMediaDataController().addRecentSticker(MediaDataController.TYPE_IMAGE, sentMessage, sentMessage.media.document, sentMessage.date, false); @@ -5712,7 +5720,7 @@ public boolean retriedToSend; if (newMsg.attachPath != null && newMsg.attachPath.startsWith(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE).getAbsolutePath())) { File cacheFile = new File(newMsg.attachPath); - File cacheFile2 = FileLoader.getPathToAttach(sentMessage.media.document, sentMessage.media.ttl_seconds != 0); + File cacheFile2 = FileLoader.getInstance(currentAccount).getPathToAttach(sentMessage.media.document, sentMessage.media.ttl_seconds != 0); if (!cacheFile.renameTo(cacheFile2)) { if (cacheFile.exists()) { sentMessage.attachPath = newMsg.attachPath; @@ -6001,14 +6009,26 @@ public boolean retriedToSend; } } - private static boolean prepareSendingDocumentInternal(AccountInstance accountInstance, String path, String originalPath, Uri uri, String mime, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, boolean forceDocument, boolean notify, int scheduleDate, Integer[] docType) { + 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, CharSequence caption, final ArrayList entities, final MessageObject editingMessageObject, long[] groupId, boolean isGroupFinal, boolean forceDocument, boolean notify, int scheduleDate, Integer[] docType) { if ((path == null || path.length() == 0) && uri == null) { - return false; + return ERROR_TYPE_UNSUPPORTED; + } + if (uri != null && AndroidUtilities.isInternalUri(uri)) { + return ERROR_TYPE_UNSUPPORTED; + } + if (path != null && AndroidUtilities.isInternalUri(Uri.fromFile(new File(path)))) { + return ERROR_TYPE_UNSUPPORTED; } MimeTypeMap myMime = MimeTypeMap.getSingleton(); TLRPC.TL_documentAttributeAudio attributeAudio = null; String extension = null; if (uri != null && path == null) { + if (checkFileSize(accountInstance, uri)) { + return ERROR_TYPE_FILE_TOO_LARGE; + } boolean hasExt = false; if (mime != null) { extension = myMime.getExtensionFromMimeType(mime); @@ -6020,7 +6040,7 @@ public boolean retriedToSend; } path = MediaController.copyFileToCache(uri, extension); if (path == null) { - return false; + return ERROR_TYPE_UNSUPPORTED; } if (!hasExt) { extension = null; @@ -6028,7 +6048,11 @@ public boolean retriedToSend; } final File f = new File(path); if (!f.exists() || f.length() == 0) { - return false; + return ERROR_TYPE_UNSUPPORTED; + } + + if (!FileLoader.checkUploadFileSize(accountInstance.getCurrentAccount(), f.length())) { + return ERROR_TYPE_FILE_TOO_LARGE; } boolean isEncrypted = DialogObject.isEncryptedDialog(dialogId); @@ -6127,7 +6151,7 @@ public boolean retriedToSend; parentObject = (String) sentData[1]; } } - ensureMediaThumbExists(isEncrypted, document, path, null, 0); + ensureMediaThumbExists(accountInstance, isEncrypted, document, path, null, 0); } if (document == null) { document = new TLRPC.TL_document(); @@ -6137,7 +6161,7 @@ public boolean retriedToSend; fileName.file_name = name; document.file_reference = new byte[0]; document.attributes.add(fileName); - document.size = (int) f.length(); + document.size = f.length(); document.dc_id = 0; if (attributeAudio != null) { document.attributes.add(attributeAudio); @@ -6264,7 +6288,31 @@ public boolean retriedToSend; accountInstance.getSendMessagesHelper().sendMessage(documentFinal, null, pathFinal, dialogId, replyToMsg, replyToTopMsg, captionFinal, entities, null, params, notify, scheduleDate, 0, parentFinal, null); } }); - return true; + return 0; + } + + private static boolean checkFileSize(AccountInstance accountInstance, Uri uri) { + long len = 0; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + try { + + AssetFileDescriptor assetFileDescriptor = ApplicationLoader.applicationContext.getContentResolver().openAssetFileDescriptor(uri, "r", null); + if (assetFileDescriptor != null ) { + len = assetFileDescriptor.getLength(); + } + Cursor cursor = ApplicationLoader.applicationContext.getContentResolver().query(uri, new String[]{OpenableColumns.SIZE}, null, null, null); + int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE); + cursor.moveToFirst(); + len = cursor.getLong(sizeIndex); + + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + } + if (!FileLoader.checkUploadFileSize(accountInstance.getCurrentAccount(), len)) { + return true; + } + return false; } @UiThread @@ -6314,7 +6362,7 @@ public boolean retriedToSend; if (sentData != null && sentData[0] instanceof TLRPC.TL_document) { document = (TLRPC.TL_document) sentData[0]; parentObject = (String) sentData[1]; - ensureMediaThumbExists(isEncrypted, document, originalPath, null, 0); + ensureMediaThumbExists(accountInstance, isEncrypted, document, originalPath, null, 0); } } if (document == null) { @@ -6380,8 +6428,8 @@ public boolean retriedToSend; if (paths == null && originalPaths == null && uris == null || paths != null && originalPaths != null && paths.size() != originalPaths.size()) { return; } - new Thread(() -> { - boolean error = false; + Utilities.globalQueue.postRunnable(() -> { + int error = 0; long[] groupId = new long[1]; int mediaCount = 0; Integer[] docType = new Integer[1]; @@ -6401,9 +6449,7 @@ public boolean retriedToSend; } mediaCount++; long prevGroupId = groupId[0]; - if (!prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType)) { - error = true; - } + error = prepareSendingDocumentInternal(accountInstance, paths.get(a), originalPaths.get(a), null, mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType); if (prevGroupId != groupId[0] || groupId[0] == -1) { mediaCount = 1; } @@ -6424,9 +6470,7 @@ public boolean retriedToSend; } mediaCount++; long prevGroupId = groupId[0]; - if (!prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType)) { - error = true; - } + error = prepareSendingDocumentInternal(accountInstance, null, null, uris.get(a), mime, dialogId, replyToMsg, replyToTopMsg, captionFinal, null, editingMessageObject, groupId, mediaCount == 10 || a == count - 1, inputContent == null, notify, scheduleDate, docType); if (prevGroupId != groupId[0] || groupId[0] == -1) { mediaCount = 1; } @@ -6435,16 +6479,25 @@ public boolean retriedToSend; if (inputContent != null) { inputContent.releasePermission(); } - if (error) { - AndroidUtilities.runOnUIThread(() -> { - try { + handleError(error, accountInstance); + }); + } + + private static void handleError(int error, AccountInstance accountInstance) { + if (error != 0) { + int finalError = error; + AndroidUtilities.runOnUIThread(() -> { + try { + if (finalError == ERROR_TYPE_UNSUPPORTED) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.getString("UnsupportedAttachment", R.string.UnsupportedAttachment)); - } catch (Exception e) { - FileLog.e(e); + } else if (finalError == ERROR_TYPE_FILE_TOO_LARGE) { + NotificationCenter.getInstance(accountInstance.getCurrentAccount()).postNotificationName(NotificationCenter.currentUserShowLimitReachedDialog, LimitReachedBottomSheet.TYPE_LARGE_FILE); } - }); - } - }).start(); + } catch (Exception e) { + FileLog.e(e); + } + }); + } } @UiThread @@ -6745,12 +6798,12 @@ public boolean retriedToSend; if (MessageObject.isGifDocument(document)) { TLRPC.PhotoSize photoSizeThumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 320); - File gifFile = FileLoader.getPathToAttach(document); + File gifFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document); if (!gifFile.exists()) { - gifFile = FileLoader.getPathToAttach(document, true); + gifFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document, true); } - ensureMediaThumbExists(isEncrypted, document, gifFile.getAbsolutePath(), null, 0); - precachedKey[0] = getKeyForPhotoSize(photoSizeThumb, precahcedThumb, true, true); + ensureMediaThumbExists(accountInstance, isEncrypted, document, gifFile.getAbsolutePath(), null, 0); + precachedKey[0] = getKeyForPhotoSize(accountInstance, photoSizeThumb, precahcedThumb, true, true); } AndroidUtilities.runOnUIThread(() -> { if (finalDocument != null) { @@ -6864,7 +6917,7 @@ public boolean retriedToSend; }))); } - public static void ensureMediaThumbExists(boolean isEncrypted, TLObject object, String path, Uri uri, long startTime) { + public static void ensureMediaThumbExists(AccountInstance accountInstance, boolean isEncrypted, TLObject object, String path, Uri uri, long startTime) { if (object instanceof TLRPC.TL_photo) { TLRPC.TL_photo photo = (TLRPC.TL_photo) object; boolean smallExists; @@ -6872,11 +6925,11 @@ public boolean retriedToSend; if (smallSize instanceof TLRPC.TL_photoStrippedSize || smallSize instanceof TLRPC.TL_photoPathSize) { smallExists = true; } else { - File smallFile = FileLoader.getPathToAttach(smallSize, true); + File smallFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(smallSize, true); smallExists = smallFile.exists(); } TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); - File bigFile = FileLoader.getPathToAttach(bigSize, false); + File bigFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(bigSize, false); boolean bigExists = bigFile.exists(); if (!smallExists || !bigExists) { Bitmap bitmap = ImageLoader.loadBitmap(path, uri, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), true); @@ -6906,7 +6959,7 @@ public boolean retriedToSend; if (photoSize instanceof TLRPC.TL_photoStrippedSize || photoSize instanceof TLRPC.TL_photoPathSize) { return; } - File smallFile = FileLoader.getPathToAttach(photoSize, true); + File smallFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(photoSize, true); if (!smallFile.exists()) { Bitmap thumb = createVideoThumbnailAtTime(path, startTime); if (thumb == null) { @@ -6919,7 +6972,7 @@ public boolean retriedToSend; } } - public static String getKeyForPhotoSize(TLRPC.PhotoSize photoSize, Bitmap[] bitmap, boolean blur, boolean forceCache) { + public static String getKeyForPhotoSize(AccountInstance accountInstance, TLRPC.PhotoSize photoSize, Bitmap[] bitmap, boolean blur, boolean forceCache) { if (photoSize == null || photoSize.location == null) { return null; } @@ -6929,7 +6982,7 @@ public boolean retriedToSend; try { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; - File file = FileLoader.getPathToAttach(photoSize, forceCache); + File file = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(photoSize, forceCache); FileInputStream is = new FileInputStream(file); BitmapFactory.decodeStream(is, null, opts); @@ -7060,7 +7113,7 @@ public boolean retriedToSend; parentObject = (String) sentData[1]; } } - ensureMediaThumbExists(isEncrypted, photo, info.path, info.uri, 0); + ensureMediaThumbExists(accountInstance, isEncrypted, photo, info.path, info.uri, 0); } final MediaSendPrepareWorker worker = new MediaSendPrepareWorker(); workers.put(info, worker); @@ -7108,7 +7161,7 @@ public boolean retriedToSend; File cacheFile; if (info.searchImage.document instanceof TLRPC.TL_document) { document = (TLRPC.TL_document) info.searchImage.document; - cacheFile = FileLoader.getPathToAttach(document, true); + cacheFile = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(document, true); } else { /*if (!isEncrypted) { Object[] sentData = getMessagesStorage().getSentFile(info.searchImage.imageUrl, !isEncrypted ? 1 : 4); @@ -7286,7 +7339,7 @@ public boolean retriedToSend; if (!forceDocument && (videoEditedInfo != null || info.path.endsWith("mp4"))) { if (info.path == null && info.searchImage != null) { if (info.searchImage.photo instanceof TLRPC.TL_photo) { - info.path = FileLoader.getPathToAttach(info.searchImage.photo, true).getAbsolutePath(); + info.path = FileLoader.getInstance(accountInstance.getCurrentAccount()).getPathToAttach(info.searchImage.photo, true).getAbsolutePath(); } else { String md5 = Utilities.MD5(info.searchImage.imageUrl) + "." + ImageLoader.getHttpUrlExtension(info.searchImage.imageUrl, "jpg"); info.path = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), md5).getAbsolutePath(); @@ -7314,7 +7367,7 @@ public boolean retriedToSend; if (sentData != null && sentData[0] instanceof TLRPC.TL_document) { document = (TLRPC.TL_document) sentData[0]; parentObject = (String) sentData[1]; - ensureMediaThumbExists(isEncrypted, document, info.path, null, startTime); + ensureMediaThumbExists(accountInstance, isEncrypted, document, info.path, null, startTime); } } if (document == null) { @@ -7332,7 +7385,7 @@ public boolean retriedToSend; if (thumb != null) { int side = isEncrypted || info.ttl != 0 ? 90 : Math.max(thumb.getWidth(), thumb.getHeight()); size = ImageLoader.scaleAndSaveImage(thumb, side, side, side > 90 ? 80 : 55, isEncrypted); - thumbKey = getKeyForPhotoSize(size, null, true, false); + thumbKey = getKeyForPhotoSize(accountInstance, size, null, true, false); } document = new TLRPC.TL_document(); document.file_reference = new byte[0]; @@ -7578,7 +7631,7 @@ public boolean retriedToSend; parentObject = (String) sentData[1]; } } - ensureMediaThumbExists(isEncrypted, photo, info.path, info.uri, 0); + ensureMediaThumbExists(accountInstance, isEncrypted, photo, info.path, info.uri, 0); } if (photo == null) { photo = accountInstance.getSendMessagesHelper().generatePhotoSizes(info.path, info.uri); @@ -7613,7 +7666,7 @@ public boolean retriedToSend; if (!groupMediaFinal || media.size() == 1) { TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(photoFinal.sizes, AndroidUtilities.getPhotoSize()); if (currentPhotoObject != null) { - keyFinal[0] = getKeyForPhotoSize(currentPhotoObject, bitmapFinal, false, false); + keyFinal[0] = getKeyForPhotoSize(accountInstance, currentPhotoObject, bitmapFinal, false, false); } } } catch (Exception e) { @@ -7671,7 +7724,8 @@ public boolean retriedToSend; mediaCount = 0; } mediaCount++; - prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, forceDocument, notify, scheduleDate, null); + int error = prepareSendingDocumentInternal(accountInstance, sendAsDocuments.get(a), sendAsDocumentsOriginal.get(a), sendAsDocumentsUri.get(a), extension, dialogId, replyToMsg, replyToTopMsg, sendAsDocumentsCaptions.get(a), sendAsDocumentsEntities.get(a), editingMessageObject, groupId2, mediaCount == 10 || a == documentsCount - 1, forceDocument, notify, scheduleDate, null); + handleError(error, accountInstance); } } if (BuildVars.LOGS_ENABLED) { @@ -7967,7 +8021,7 @@ public boolean retriedToSend; if (sentData != null && sentData[0] instanceof TLRPC.TL_document) { document = (TLRPC.TL_document) sentData[0]; parentObject = (String) sentData[1]; - ensureMediaThumbExists(isEncrypted, document, videoPath, null, startTime); + ensureMediaThumbExists(accountInstance, isEncrypted, document, videoPath, null, startTime); } } if (document == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index dd5bf88e7..5cc75b46c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -19,6 +19,7 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Base64; import android.util.SparseArray; +import android.webkit.WebView; import androidx.annotation.Nullable; import androidx.core.content.pm.ShortcutManagerCompat; @@ -84,6 +85,10 @@ public class SharedConfig { }) public @interface PasscodeType {} + public final static int SAVE_TO_GALLERY_FLAG_PEER = 1; + public final static int SAVE_TO_GALLERY_FLAG_GROUP = 2; + public final static int SAVE_TO_GALLERY_FLAG_CHANNELS = 4; + public static String pushString = ""; public static String pushStringStatus = ""; public static long pushStringGetTimeStart; @@ -135,7 +140,7 @@ public class SharedConfig { private static final Object sync = new Object(); private static final Object localIdSync = new Object(); - public static boolean saveToGallery; + public static int saveToGalleryFlags; public static int mapPreviewType = 2; public static boolean chatBubbles = Build.VERSION.SDK_INT >= 30; public static boolean autoplayGifs = true; @@ -156,6 +161,7 @@ public class SharedConfig { public static boolean noiseSupression; public static boolean noStatusBar = true; public static boolean forceRtmpStream; + public static boolean debugWebView; public static boolean sortContactsByName; public static boolean sortFilesByName; public static boolean shuffleMusic; @@ -1206,7 +1212,13 @@ public class SharedConfig { } preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - saveToGallery = preferences.getBoolean("save_gallery", false); + boolean saveToGalleryLegacy = preferences.getBoolean("save_gallery", false); + if (saveToGalleryLegacy) { + saveToGalleryFlags = SAVE_TO_GALLERY_FLAG_PEER + SAVE_TO_GALLERY_FLAG_CHANNELS + SAVE_TO_GALLERY_FLAG_GROUP; + preferences.edit().remove("save_gallery").putInt("save_gallery_flags", saveToGalleryFlags).apply(); + } else { + saveToGalleryFlags = preferences.getInt("save_gallery_flags", 0); + } autoplayGifs = preferences.getBoolean("autoplay_gif", true); autoplayVideo = preferences.getBoolean("autoplay_video", true); mapPreviewType = preferences.getInt("mapPreviewType", 2); @@ -1244,6 +1256,7 @@ public class SharedConfig { keepMedia = preferences.getInt("keep_media", 2); noStatusBar = NekoConfig.transparentStatusBar.Bool(); forceRtmpStream = preferences.getBoolean("forceRtmpStream", false); + debugWebView = preferences.getBoolean("debugWebView", false); lastKeepMediaCheckTime = preferences.getInt("lastKeepMediaCheckTime", 0); lastLogsCheckTime = preferences.getInt("lastLogsCheckTime", 0); searchMessagesAsListHintShows = preferences.getInt("searchMessagesAsListHintShows", 0); @@ -1300,6 +1313,13 @@ public class SharedConfig { configLoaded = true; + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && debugWebView) { + WebView.setWebContentsDebuggingEnabled(true); + } + } catch (Exception e) { + FileLog.e(e); + } } } @@ -1494,7 +1514,7 @@ public class SharedConfig { editor.commit(); } - public static void removeScheduledOrNoSuoundHint() { + public static void removeScheduledOrNoSoundHint() { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putInt("scheduledOrNoSoundHintShows", 3); @@ -1627,6 +1647,17 @@ public class SharedConfig { editor.apply(); } + public static void toggleDebugWebView() { + debugWebView = !debugWebView; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + WebView.setWebContentsDebuggingEnabled(debugWebView); + } + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + SharedPreferences.Editor editor = preferences.edit(); + editor.putBoolean("debugWebView", debugWebView); + editor.apply(); + } + // public static void toggleNoStatusBar() { // noStatusBar = !noStatusBar; // noStatusBar |= NekoConfig.transparentStatusBar.Bool(); @@ -1682,12 +1713,14 @@ public class SharedConfig { editor.commit(); } - public static void toggleSaveToGallery() { - saveToGallery = !saveToGallery; + public static void toggleSaveToGalleryFlag(int flag) { + if ((saveToGalleryFlags & flag) != 0) { + saveToGalleryFlags &= ~flag; + } else { + saveToGalleryFlags |= flag; + } SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - SharedPreferences.Editor editor = preferences.edit(); - editor.putBoolean("save_gallery", saveToGallery); - editor.commit(); + preferences.edit().putInt("save_gallery_flags", saveToGalleryFlags).apply(); ImageLoader.getInstance().checkMediaPaths(); ImageLoader.getInstance().getCacheOutQueue().postRunnable(() -> { checkSaveToGalleryFiles(); @@ -2209,7 +2242,7 @@ public class SharedConfig { File videoPath = new File(telegramPath, "videos"); videoPath.mkdirs(); - if (saveToGallery) { + if (saveToGalleryFlags != 0 || !BuildVars.NO_SCOPED_STORAGE) { if (imagePath.isDirectory()) { new File(imagePath, ".nomedia").delete(); } @@ -2338,6 +2371,7 @@ public class SharedConfig { public static boolean canBlurChat() { return getDevicePerformanceClass() == PERFORMANCE_CLASS_HIGH || NekoConfig.forceBlurInChat.Bool(); } + public static boolean chatBlurEnabled() { return (canBlurChat() && chatBlur) || NekoConfig.forceBlurInChat.Bool(); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java index 65f2aa53d..c4cec3a41 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java @@ -102,6 +102,7 @@ public class SvgHelper { protected ArrayList commands = new ArrayList<>(); protected HashMap paints = new HashMap<>(); + private Paint overridePaint; protected int width; protected int height; private static int[] parentPosition = new int[2]; @@ -148,9 +149,7 @@ public class SvgHelper { setupGradient(currentColorKey, colorAlpha); } Rect bounds = getBounds(); - float scaleX = bounds.width() / (float) width; - float scaleY = bounds.height() / (float) height; - float scale = aspectFill ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY); + float scale = getScale(); canvas.save(); canvas.translate(bounds.left, bounds.top); if (!aspectFill) { @@ -165,7 +164,12 @@ public class SvgHelper { } else if (object == null) { canvas.restore(); } else { - Paint paint = paints.get(object); + Paint paint; + if (overridePaint != null) { + paint = overridePaint; + } else { + paint = paints.get(object); + } int originalAlpha = paint.getAlpha(); paint.setAlpha((int) (crossfadeAlpha * originalAlpha)); if (object instanceof Path) { @@ -222,6 +226,13 @@ public class SvgHelper { } } + public float getScale() { + Rect bounds = getBounds(); + float scaleX = bounds.width() / (float) width; + float scaleY = bounds.height() / (float) height; + return aspectFill ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY); + } + @Override public void setAlpha(int alpha) { crossfadeAlpha = alpha / 255.0f; @@ -283,6 +294,10 @@ public class SvgHelper { } } } + + public void setPaint(Paint paint) { + overridePaint = paint; + } } public static Bitmap getBitmap(int res, int width, int height, int color) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java index f7abe3e64..90ee83d69 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserConfig.java @@ -22,7 +22,8 @@ import java.util.Arrays; public class UserConfig extends BaseController { public static int selectedAccount; - //public final static int MAX_ACCOUNT_COUNT = 16; + //public final static int MAX_ACCOUNT_DEFAULT_COUNT = 16; + public final static int MAX_ACCOUNT_COUNT = 4; private final Object sync = new Object(); private boolean configLoaded; @@ -96,6 +97,19 @@ public class UserConfig extends BaseController { super(instance); } + public static boolean hasPremiumOnAccounts() { + for (int a = 0; a < MAX_ACCOUNT_COUNT; a++) { + if (AccountInstance.getInstance(a).getUserConfig().isClientActivated() && AccountInstance.getInstance(a).getUserConfig().getUserConfig().isPremium()) { + return true; + } + } + return false; + } + + public static int getMaxAccountCount() { + return hasPremiumOnAccounts() ? 5 : 3; + } + public int getNewMessageId() { int id; synchronized (sync) { @@ -223,8 +237,22 @@ public class UserConfig extends BaseController { public void setCurrentUser(TLRPC.User user) { synchronized (sync) { + TLRPC.User oldUser = currentUser; currentUser = user; clientUserId = user.id; + checkPremium(oldUser, user); + } + } + + private void checkPremium(TLRPC.User oldUser, TLRPC.User newUser) { + if (oldUser == null || (newUser != null && oldUser.premium != newUser.premium)) { + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().updatePremium(newUser.premium); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.currentUserPremiumStatusChanged); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.premiumStatusChangedGlobal); + + getMediaDataController().loadPremiumPromo(false); + }); } } @@ -306,6 +334,7 @@ public class UserConfig extends BaseController { } } if (currentUser != null) { + checkPremium(null, currentUser); clientUserId = currentUser.id; } configLoaded = true; @@ -441,4 +470,11 @@ public class UserConfig extends BaseController { editor.putBoolean("hasValidDialogLoadIds", true); editor.commit(); } + + public boolean isPremium() { + if (currentUser == null) { + return false; + } + return currentUser.premium; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java index ea3f1862a..58a7df743 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/Utilities.java @@ -65,7 +65,7 @@ public class Utilities { private native static void aesIgeEncryption(ByteBuffer buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length); private native static void aesIgeEncryptionByteArray(byte[] buffer, byte[] key, byte[] iv, boolean encrypt, int offset, int length); public native static void aesCtrDecryption(ByteBuffer buffer, byte[] key, byte[] iv, int offset, int length); - public native static void aesCtrDecryptionByteArray(byte[] buffer, byte[] key, byte[] iv, int offset, int length, int n); + public native static void aesCtrDecryptionByteArray(byte[] buffer, byte[] key, byte[] iv, int offset, long length, int n); private native static void aesCbcEncryptionByteArray(byte[] buffer, byte[] key, byte[] iv, int offset, int length, int n, int encrypt); public native static void aesCbcEncryption(ByteBuffer buffer, byte[] key, byte[] iv, int offset, int length, int encrypt); public native static String readlink(String path); @@ -113,16 +113,47 @@ public class Utilities { } int val = 0; try { - Matcher matcher = pattern.matcher(value); - if (matcher.find()) { - String num = matcher.group(0); - val = Integer.parseInt(num); + int start = -1, end; + for (end = 0; end < value.length(); ++end) { + char character = value.charAt(end); + boolean allowedChar = character == '-' || character >= '0' && character <= '9'; + if (allowedChar && start < 0) { + start = end; + } else if (!allowedChar && start >= 0) { + end++; + break; + } } - } catch (Exception ignore) { - - } + if (start >= 0) { + String str = value.subSequence(start, end).toString(); +// val = parseInt(str); + val = Integer.parseInt(str); + } +// Matcher matcher = pattern.matcher(value); +// if (matcher.find()) { +// String num = matcher.group(0); +// val = Integer.parseInt(num); +// } + } catch (Exception ignore) {} return val; } + private static int parseInt(final String s) { + int num = 0; + boolean negative = true; + final int len = s.length(); + final char ch = s.charAt(0); + if (ch == '-') { + negative = false; + } else { + num = '0' - ch; + } + int i = 1; + while (i < len) { + num = num * 10 + '0' - s.charAt(i++); + } + + return negative ? -num : num; + } public static Long parseLong(String value) { if (value == null) { @@ -283,10 +314,10 @@ public class Utilities { return computeSHA256(convertme, 0, convertme.length); } - public static byte[] computeSHA256(byte[] convertme, int offset, int len) { + public static byte[] computeSHA256(byte[] convertme, int offset, long len) { try { MessageDigest md = MessageDigest.getInstance("SHA-256"); - md.update(convertme, offset, len); + md.update(convertme, offset, (int) len); return md.digest(); } catch (Exception e) { FileLog.e(e); @@ -403,8 +434,14 @@ public class Utilities { return null; } - public static float clamp(float value, float top, float bottom) { - return Math.max(Math.min(value, top), bottom); + public static float clamp(float value, float maxValue, float minValue) { + if (Float.isNaN(value)) { + return minValue; + } + if (Float.isInfinite(value)) { + return maxValue; + } + return Math.max(Math.min(value, maxValue), minValue); } public static String generateRandomString() { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java index ae3bbf151..a023c6b5d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/VideoEditedInfo.java @@ -54,6 +54,7 @@ public class VideoEditedInfo { public boolean canceled; public boolean videoConvertFirstWrite; public boolean needUpdateProgress = false; + public boolean shouldLimitFps = true; public static class MediaEntity { public byte type; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java index b6bde5a59..382263382 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/browser/Browser.java @@ -340,7 +340,7 @@ public class Browser { .build(); builder.setDefaultColorSchemeParams(params); builder.setShowTitle(true); - builder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.abc_ic_menu_share_mtrl_alpha), LocaleController.getString("ShareFile", R.string.ShareFile), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, share, 0), true); + builder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.msg_filled_shareout), LocaleController.getString("ShareFile", R.string.ShareFile), PendingIntent.getBroadcast(ApplicationLoader.applicationContext, 0, share, 0), true); CustomTabsIntent intent = builder.build(); intent.intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.launchUrl(context, uri); 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 7603578f7..1e399dd7d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraController.java @@ -239,7 +239,7 @@ public class CameraController implements MediaRecorder.OnInfoListener { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.cameraInitied); }); } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, !"APP_PAUSED".equals(e.getMessage())); AndroidUtilities.runOnUIThread(() -> { onFinishCameraInitRunnables.clear(); loadingCameras = false; 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 bed3eb41a..a80b830c0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/camera/CameraView.java @@ -24,7 +24,6 @@ import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; -import android.hardware.Camera; import android.media.AudioFormat; import android.media.AudioRecord; import android.media.MediaCodec; @@ -42,7 +41,6 @@ import android.os.Looper; import android.os.Message; import android.os.VibrationEffect; import android.os.Vibrator; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.Surface; @@ -151,6 +149,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private FloatBuffer vertexBuffer; private FloatBuffer textureBuffer; + private final static int audioSampleRate = 44100; + public void setRecordFile(File generateVideoPath) { recordFile = generateVideoPath; } @@ -415,8 +415,8 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur int photoMaxHeight; if (initialFrontface) { aspectRatio = new Size(16, 9); - photoMaxWidth = wantedWidth = 480; - photoMaxHeight = wantedHeight = 270; + photoMaxWidth = wantedWidth = 1280; + photoMaxHeight = wantedHeight = 720; } else { if (Math.abs(screenSize - size4to3) < 0.1f) { aspectRatio = new Size(4, 3); @@ -1298,7 +1298,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur } buffer.offset[a] = audioPresentationTimeUs; buffer.read[a] = readResult; - int bufferDurationUs = 1000000 * readResult / 44100 / 2; + int bufferDurationUs = 1000000 * readResult / audioSampleRate / 2; audioPresentationTimeUs += bufferDurationUs; } if (buffer.results >= 0 || buffer.last) { @@ -1676,7 +1676,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur private void prepareEncoder() { try { - int recordBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); + int recordBufferSize = AudioRecord.getMinBufferSize(audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); if (recordBufferSize <= 0) { recordBufferSize = 3584; } @@ -1687,7 +1687,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur for (int a = 0; a < 3; a++) { buffers.add(new InstantCameraView.AudioBufferInfo()); } - audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); + audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); audioRecorder.startRecording(); if (BuildVars.LOGS_ENABLED) { FileLog.d("CameraView " + "initied audio record with channels " + audioRecorder.getChannelCount() + " sample rate = " + audioRecorder.getSampleRate() + " bufferSize = " + bufferSize); @@ -1701,7 +1701,7 @@ public class CameraView extends FrameLayout implements TextureView.SurfaceTextur MediaFormat audioFormat = new MediaFormat(); audioFormat.setString(MediaFormat.KEY_MIME, AUDIO_MIME_TYPE); - audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); + audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, audioSampleRate); audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, 32000); audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 2048 * InstantCameraView.AudioBufferInfo.MAX_SAMPLES); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ringtone/RingtoneDataStore.java b/TMessagesProj/src/main/java/org/telegram/messenger/ringtone/RingtoneDataStore.java index d486846d4..56e25b652 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ringtone/RingtoneDataStore.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ringtone/RingtoneDataStore.java @@ -106,7 +106,9 @@ public class RingtoneDataStore { } } if (notify) { - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onUserRingtonesUpdated); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.onUserRingtonesUpdated); + }); } } @@ -226,7 +228,7 @@ public class RingtoneDataStore { if (!TextUtils.isEmpty(userRingtones.get(i).localUri)) { return userRingtones.get(i).localUri; } - return FileLoader.getPathToAttach(userRingtones.get(i).document).toString(); + return FileLoader.getInstance(currentAccount).getPathToAttach(userRingtones.get(i).document).toString(); } } return "NoSound"; @@ -241,6 +243,9 @@ public class RingtoneDataStore { Utilities.globalQueue.postRunnable(() -> { for (int i = 0; i < cachedTones.size(); i++) { CachedTone tone = cachedTones.get(i); + if (tone == null) { + continue; + } if (!TextUtils.isEmpty(tone.localUri)) { File file = new File(tone.localUri); if (file.exists()) { @@ -250,7 +255,7 @@ public class RingtoneDataStore { if (tone.document != null) { TLRPC.Document document = tone.document; - File file = FileLoader.getPathToAttach(document); + File file = FileLoader.getInstance(currentAccount).getPathToAttach(document); if (file == null || !file.exists()) { AndroidUtilities.runOnUIThread(() -> { FileLoader.getInstance(currentAccount).loadFile(document, document, 0, 0); @@ -303,10 +308,14 @@ public class RingtoneDataStore { loadFromPrefs(true); loaded = true; } - for (int i = 0; i < userRingtones.size(); i++) { - if (userRingtones.get(i).document != null && userRingtones.get(i).document.id == id) { - return userRingtones.get(i).document; + try { + for (int i = 0; i < userRingtones.size(); i++) { + if (userRingtones.get(i) != null && userRingtones.get(i).document != null && userRingtones.get(i).document.id == id) { + return userRingtones.get(i).document; + } } + } catch (Exception e) { + FileLog.e(e); } return null; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/voip/Instance.java b/TMessagesProj/src/main/java/org/telegram/messenger/voip/Instance.java index cc9b6e11a..6d3451ebc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/Instance.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/Instance.java @@ -204,8 +204,9 @@ public final class Instance { public final boolean stun; public final String username; public final String password; + public final boolean tcp; - public Endpoint(boolean isRtc, long id, String ipv4, String ipv6, int port, int type, byte[] peerTag, boolean turn, boolean stun, String username, String password) { + public Endpoint(boolean isRtc, long id, String ipv4, String ipv6, int port, int type, byte[] peerTag, boolean turn, boolean stun, String username, String password, boolean tcp) { this.isRtc = isRtc; this.id = id; this.ipv4 = ipv4; @@ -217,6 +218,7 @@ public final class Instance { this.stun = stun; this.username = username; this.password = password; + this.tcp = tcp; } @Override @@ -232,6 +234,7 @@ public final class Instance { ", stun=" + stun + ", username=" + username + ", password=" + password + + ", tcp=" + tcp + '}'; } } 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 2f296d610..e2bb25deb 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -89,7 +89,6 @@ import org.telegram.messenger.BuildConfig; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; -import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -2351,7 +2350,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa final Instance.Endpoint[] endpoints = new Instance.Endpoint[privateCall.connections.size()]; for (int i = 0; i < endpoints.length; i++) { final TLRPC.PhoneConnection connection = privateCall.connections.get(i); - endpoints[i] = new Instance.Endpoint(connection instanceof TLRPC.TL_phoneConnectionWebrtc, connection.id, connection.ip, connection.ipv6, connection.port, endpointType, connection.peer_tag, connection.turn, connection.stun, connection.username, connection.password); + endpoints[i] = new Instance.Endpoint(connection instanceof TLRPC.TL_phoneConnectionWebrtc, connection.id, connection.ip, connection.ipv6, connection.port, endpointType, connection.peer_tag, connection.turn, connection.stun, connection.username, connection.password, connection.tcp); } if (forceTcp) { AndroidUtilities.runOnUIThread(() -> Toast.makeText(VoIPService.this, "This call uses TCP which will degrade its quality.", Toast.LENGTH_SHORT).show()); @@ -3411,62 +3410,15 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa req.peer = new TLRPC.TL_inputPhoneCall(); req.peer.access_hash = privateCall.access_hash; req.peer.id = privateCall.id; - - File file = new File(VoIPHelper.getLogFilePath(privateCall.id, true)); - String cachedFile = MediaController.copyFileToCache(Uri.fromFile(file), "log"); - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { if (BuildVars.LOGS_ENABLED) { FileLog.d("Sent debug logs, response = " + response); } - try { - if (response instanceof TLRPC.TL_boolFalse) { - AndroidUtilities.runOnUIThread(() -> { - uploadLogFile(cachedFile); - }); - } else { - File cacheFile = new File(cachedFile); - cacheFile.delete(); - } - } catch (Exception e) { - FileLog.e(e); - } }); needSendDebugLog = false; } } - private void uploadLogFile(String filePath) { - NotificationCenter.NotificationCenterDelegate uploadDelegate = new NotificationCenter.NotificationCenterDelegate() { - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.fileUploaded || id == NotificationCenter.fileUploadFailed) { - final String location = (String) args[0]; - if (location.equals(filePath)) { - if (id == NotificationCenter.fileUploaded) { - TLRPC.TL_phone_saveCallLog req = new TLRPC.TL_phone_saveCallLog(); - final TLRPC.InputFile file = (TLRPC.InputFile) args[1]; - req.file = file; - req.peer = new TLRPC.TL_inputPhoneCall(); - req.peer.access_hash = privateCall.access_hash; - req.peer.id = privateCall.id; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (BuildVars.LOGS_ENABLED) { - FileLog.d("Sent debug file log, response = " + response); - } - }); - } - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploaded); - NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileUploadFailed); - } - } - } - }; - NotificationCenter.getInstance(currentAccount).addObserver(uploadDelegate, NotificationCenter.fileUploaded); - NotificationCenter.getInstance(currentAccount).addObserver(uploadDelegate, NotificationCenter.fileUploadFailed); - FileLoader.getInstance(currentAccount).uploadFile(filePath, false, true, ConnectionsManager.FileTypeFile); - } - private void initializeAccountRelatedThings() { updateServerConfig(); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.appDidLogout); @@ -3911,7 +3863,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa try { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inMutable = true; - bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(user.photo.photo_small, true).toString(), opts); + bitmap = BitmapFactory.decodeFile(FileLoader.getInstance(currentAccount).getPathToAttach(user.photo.photo_small, true).toString(), opts); } catch (Throwable e) { FileLog.e(e); } @@ -3927,7 +3879,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa try { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inMutable = true; - bitmap = BitmapFactory.decodeFile(FileLoader.getPathToAttach(chat.photo.photo_small, true).toString(), opts); + bitmap = BitmapFactory.decodeFile(FileLoader.getInstance(currentAccount).getPathToAttach(chat.photo.photo_small, true).toString(), opts); } catch (Throwable e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index e2cdbb85c..9f930131b 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -10,7 +10,6 @@ import android.util.Base64; import android.util.SparseArray; import com.v2ray.ang.util.Utils; - import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -114,12 +113,21 @@ public class ConnectionsManager extends BaseController { } }; + private boolean forceTryIpV6; + static { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); threadPoolExecutor.allowCoreThreadTimeOut(true); DNS_THREAD_POOL_EXECUTOR = threadPoolExecutor; } + public void setForceTryIpV6(boolean forceTryIpV6) { + if (this.forceTryIpV6 != forceTryIpV6) { + this.forceTryIpV6 = forceTryIpV6; + checkConnection(); + } + } + private static class ResolvedDomain { public InetAddress[] addresses; @@ -216,6 +224,13 @@ public class ConnectionsManager extends BaseController { String pushString = getRegId(); int timezoneOffset = (TimeZone.getDefault().getRawOffset() + TimeZone.getDefault().getDSTSavings()) / 1000; +SharedPreferences mainPreferences; + if (currentAccount == 0) { + mainPreferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); + } else { + mainPreferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig" + currentAccount, Activity.MODE_PRIVATE); + } + forceTryIpV6 = mainPreferences.getBoolean("forceTryIpV6", false); init(version, TLRPC.LAYER, appId, deviceModel, systemVersion, appVersion, langCode, systemLangCode, configPath, FileLog.getNetworkLogPath(), pushString, fingerprint, timezoneOffset, getUserConfig().getClientUserId(), enablePushConnection); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index 089205eff..583380e18 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -71,7 +71,7 @@ public class TLRPC { public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800; public static final int MESSAGE_FLAG_EDITED = 0x00008000; - public static final int LAYER = 140; + public static final int LAYER = 143; public static class TL_stats_megagroupStats extends TLObject { public static int constructor = 0xef7ff916; @@ -3099,13 +3099,17 @@ public class TLRPC { } public static class TL_payments_paymentForm extends TLObject { - public static int constructor = 0x1694761b; + public static int constructor = 0xb0133b37; public int flags; public boolean can_save_credentials; public boolean password_missing; + public boolean test; public long form_id; public long bot_id; + public String title; + public String description; + public WebDocument photo; public TL_invoice invoice; public long provider_id; public String url; @@ -3132,8 +3136,14 @@ public class TLRPC { flags = stream.readInt32(exception); can_save_credentials = (flags & 4) != 0; password_missing = (flags & 8) != 0; + test = (flags & 64) != 0; form_id = stream.readInt64(exception); bot_id = stream.readInt64(exception); + title = stream.readString(exception); + description = stream.readString(exception); + if ((flags & 32) != 0) { + photo = WebDocument.TLdeserialize(stream, stream.readInt32(exception), exception); + } invoice = TL_invoice.TLdeserialize(stream, stream.readInt32(exception), exception); provider_id = stream.readInt64(exception); url = stream.readString(exception); @@ -3170,9 +3180,15 @@ public class TLRPC { stream.writeInt32(constructor); flags = can_save_credentials ? (flags | 4) : (flags &~ 4); flags = password_missing ? (flags | 8) : (flags &~ 8); + flags = test ? (flags | 64) : (flags &~ 64); stream.writeInt32(flags); stream.writeInt64(form_id); stream.writeInt64(bot_id); + stream.writeString(title); + stream.writeString(description); + if ((flags & 32) != 0) { + photo.serializeToStream(stream); + } invoice.serializeToStream(stream); stream.writeInt64(provider_id); stream.writeString(url); @@ -3287,16 +3303,19 @@ public class TLRPC { public static abstract class EncryptedFile extends TLObject { public long id; public long access_hash; - public int size; + public long size; public int dc_id; public int key_fingerprint; public static EncryptedFile TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { EncryptedFile result = null; switch (constructor) { - case 0x4a70994c: + case 0xa8008cd8: result = new TL_encryptedFile(); break; + case 0x4a70994c: + result = new TL_encryptedFile_layer142(); + break; case 0xc21f497e: result = new TL_encryptedFileEmpty(); break; @@ -3312,6 +3331,27 @@ public class TLRPC { } public static class TL_encryptedFile extends EncryptedFile { + public static int constructor = 0xa8008cd8; + + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + size = stream.readInt64(exception); + dc_id = stream.readInt32(exception); + key_fingerprint = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt64(size); + stream.writeInt32(dc_id); + stream.writeInt32(key_fingerprint); + } + } + + public static class TL_encryptedFile_layer142 extends EncryptedFile { public static int constructor = 0x4a70994c; @@ -3327,7 +3367,7 @@ public class TLRPC { stream.writeInt32(constructor); stream.writeInt64(id); stream.writeInt64(access_hash); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeInt32(dc_id); stream.writeInt32(key_fingerprint); } @@ -4215,16 +4255,41 @@ public class TLRPC { } public static class TL_secureFile extends SecureFile { - public static int constructor = 0xe0277a62; + public static int constructor = 0x7d09c27e; public long id; public long access_hash; - public int size; + public long size; public int dc_id; public int date; public byte[] file_hash; public byte[] secret; + public void readParams(AbstractSerializedData stream, boolean exception) { + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + size = stream.readInt64(exception); + dc_id = stream.readInt32(exception); + date = stream.readInt32(exception); + file_hash = stream.readByteArray(exception); + secret = stream.readByteArray(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeInt64(size); + stream.writeInt32(dc_id); + stream.writeInt32(date); + stream.writeByteArray(file_hash); + stream.writeByteArray(secret); + } + } + + public static class TL_secureFile_layer142 extends TL_secureFile { + public static int constructor = 0xe0277a62; + public void readParams(AbstractSerializedData stream, boolean exception) { id = stream.readInt64(exception); access_hash = stream.readInt64(exception); @@ -4239,7 +4304,7 @@ public class TLRPC { stream.writeInt32(constructor); stream.writeInt64(id); stream.writeInt64(access_hash); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeInt32(dc_id); stream.writeInt32(date); stream.writeByteArray(file_hash); @@ -7328,6 +7393,7 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); + nopremium = (flags & 8) != 0; if ((flags & 1) != 0) { document = Document.TLdeserialize(stream, stream.readInt32(exception), exception); } else { @@ -7340,6 +7406,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = nopremium ? (flags | 8) : (flags &~ 8); + flags = document != null ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); if ((flags & 1) != 0) { document.serializeToStream(stream); @@ -8639,6 +8707,206 @@ public class TLRPC { } } + public static class TL_help_premiumPromo_layer140 extends TL_help_premiumPromo { + public static int constructor = 0xe0360f1b; + + public void readParams(AbstractSerializedData stream, boolean exception) { + status_text = stream.readString(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + status_entities.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++) { + video_sections.add(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++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + videos.add(object); + } + currency = stream.readString(exception); + monthly_amount = stream.readInt64(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(status_text); + stream.writeInt32(0x1cb5c415); + int count = status_entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + status_entities.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = video_sections.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(video_sections.get(a)); + } + stream.writeInt32(0x1cb5c415); + count = videos.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + videos.get(a).serializeToStream(stream); + } + stream.writeString(currency); + stream.writeInt64(monthly_amount); + } + } + + public static class TL_help_premiumPromo extends TLObject { + public static int constructor = 0x8a4f3c29; + + public String status_text; + public ArrayList status_entities = new ArrayList<>(); + public ArrayList video_sections = new ArrayList<>(); + public ArrayList videos = new ArrayList<>(); + public String currency; + public long monthly_amount; + public ArrayList users = new ArrayList<>(); + + public static TL_help_premiumPromo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + TL_help_premiumPromo result = null; + switch (constructor) { + case 0x8a4f3c29: + result = new TL_help_premiumPromo(); + break; + case 0xe0360f1b: + result = new TL_help_premiumPromo_layer140(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_help_premiumPromo", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + status_text = stream.readString(exception); + int magic = stream.readInt32(exception); + if (magic != 0x1cb5c415) { + if (exception) { + throw new RuntimeException(String.format("wrong Vector magic, got %x", magic)); + } + return; + } + int count = stream.readInt32(exception); + for (int a = 0; a < count; a++) { + MessageEntity object = MessageEntity.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + status_entities.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++) { + video_sections.add(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++) { + Document object = Document.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + videos.add(object); + } + currency = stream.readString(exception); + monthly_amount = stream.readInt64(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++) { + 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.writeString(status_text); + stream.writeInt32(0x1cb5c415); + int count = status_entities.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + status_entities.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = video_sections.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + stream.writeString(video_sections.get(a)); + } + stream.writeInt32(0x1cb5c415); + count = videos.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + videos.get(a).serializeToStream(stream); + } + stream.writeString(currency); + stream.writeInt64(monthly_amount); + 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 help_UserInfo extends TLObject { public static help_UserInfo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -9250,10 +9518,16 @@ public class TLRPC { public ArrayList commands = new ArrayList<>(); public int version; public BotMenuButton menu_button; + public int flags; + public Photo description_photo; + public Document description_document; public static BotInfo TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { BotInfo result = null; switch (constructor) { + case 0xe4169b5d: + result = new TL_botInfo_layer140(); + break; case 0xbb2e37ce: result = new TL_botInfoEmpty_layer48(); break; @@ -9266,7 +9540,7 @@ public class TLRPC { case 0x1b74b335: result = new TL_botInfo_layer139(); break; - case 0xe4169b5d: + case 0x8f300b57: result = new TL_botInfo(); break; } @@ -9405,6 +9679,75 @@ public class TLRPC { } public static class TL_botInfo extends BotInfo { + public static int constructor = 0x8f300b57; + + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + if ((flags & 1) != 0) { + user_id = stream.readInt64(exception); + } + if ((flags & 2) != 0) { + description = stream.readString(exception); + } + if ((flags & 16) != 0) { + description_photo = Photo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 32) != 0) { + description_document = Document.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++) { + TL_botCommand object = TL_botCommand.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + commands.add(object); + } + } + if ((flags & 8) != 0) { + menu_button = BotMenuButton.TLdeserialize(stream, stream.readInt32(exception), exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + if ((flags & 1) != 0) { + stream.writeInt64(user_id); + } + if ((flags & 2) != 0) { + stream.writeString(description); + } + if ((flags & 16) != 0) { + description_photo.serializeToStream(stream); + } + if ((flags & 32) != 0) { + description_document.serializeToStream(stream); + } + if ((flags & 4) != 0) { + stream.writeInt32(0x1cb5c415); + int count = commands.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + commands.get(a).serializeToStream(stream); + } + } + if ((flags & 8) != 0) { + menu_button.serializeToStream(stream); + } + } + } + + public static class TL_botInfo_layer140 extends TL_botInfo { public static int constructor = 0xe4169b5d; @@ -18581,7 +18924,7 @@ public class TLRPC { public static messages_FeaturedStickers TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { messages_FeaturedStickers result = null; switch (constructor) { - case 0x84c02310: + case 0xbe382906: result = new TL_messages_featuredStickers(); break; case 0xc6dc0c66: @@ -18599,14 +18942,18 @@ public class TLRPC { } public static class TL_messages_featuredStickers extends messages_FeaturedStickers { - public static int constructor = 0x84c02310; + public static int constructor = 0xbe382906; + public int flags; + public boolean premium; public long hash; public int count; public ArrayList sets = new ArrayList<>(); public ArrayList unread = new ArrayList<>(); public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + premium = (flags & 1) != 0; hash = stream.readInt64(exception); count = stream.readInt32(exception); int magic = stream.readInt32(exception); @@ -18639,6 +18986,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = premium ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); stream.writeInt64(hash); stream.writeInt32(count); stream.writeInt32(0x1cb5c415); @@ -19122,8 +19471,7 @@ public class TLRPC { } } - public static class TL_dialogFilter extends TLObject { - public static int constructor = 0x7438f7e8; + public static abstract class DialogFilter extends TLObject { public int flags; public boolean contacts; @@ -19141,18 +19489,37 @@ public class TLRPC { public ArrayList include_peers = new ArrayList<>(); public ArrayList exclude_peers = new ArrayList<>(); - public static TL_dialogFilter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { - if (TL_dialogFilter.constructor != constructor) { - if (exception) { - throw new RuntimeException(String.format("can't parse magic %x in TL_dialogFilter", constructor)); - } else { - return null; - } + public static DialogFilter TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + DialogFilter result = null; + switch (constructor) { + case 0x363293ae: + result = new TL_dialogFilterDefault(); + break; + case 0x7438f7e8: + result = new TL_dialogFilter(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in DialogFilter", constructor)); + } + if (result != null) { + result.readParams(stream, exception); } - TL_dialogFilter result = new TL_dialogFilter(); - result.readParams(stream, exception); return result; } + } + + public static class TL_dialogFilterDefault extends DialogFilter { + public static int constructor = 0x363293ae; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_dialogFilter extends DialogFilter { + public static int constructor = 0x7438f7e8; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); @@ -19227,7 +19594,7 @@ public class TLRPC { flags = exclude_read ? (flags | 4096) : (flags &~ 4096); flags = exclude_archived ? (flags | 8192) : (flags &~ 8192); stream.writeInt32(flags); - stream.writeInt32((int) id); + stream.writeInt32(id); stream.writeString(title); if ((flags & 33554432) != 0) { stream.writeString(emoticon); @@ -20220,6 +20587,7 @@ public class TLRPC { public boolean scam; public boolean apply_min_photo; public boolean fake; + public boolean premium; public int bot_info_version; public String bot_inline_placeholder; public String lang_code; @@ -20391,7 +20759,7 @@ public class TLRPC { apply_min_photo = (flags & 33554432) != 0; fake = (flags & 67108864) != 0; bot_attach_menu = (flags & 134217728) != 0; - bot_menu_webview = (flags & 268435456) != 0; + premium = (flags & 268435456) != 0; id = stream.readInt64(exception); if ((flags & 1) != 0) { access_hash = stream.readInt64(exception); @@ -20460,7 +20828,7 @@ public class TLRPC { flags = apply_min_photo ? (flags | 33554432) : (flags &~ 33554432); flags = fake ? (flags | 67108864) : (flags &~ 67108864); flags = bot_attach_menu ? (flags | 134217728) : (flags &~ 134217728); - flags = bot_menu_webview ? (flags | 268435456) : (flags &~ 268435456); + flags = premium ? (flags | 268435456) : (flags &~ 268435456); stream.writeInt32(flags); stream.writeInt64(id); if ((flags & 1) != 0) { @@ -21710,8 +22078,11 @@ public class TLRPC { public long call_id; public PhoneCallDiscardReason reason; public int duration; + public boolean recurring_init; + public boolean recurring_used; public String currency; public long total_amount; + public String invoice_slug; public long game_id; public int score; public boolean video; @@ -21842,9 +22213,12 @@ public class TLRPC { case 0xabe9affe: result = new TL_messageActionBotAllowed(); break; - case 0x40699cd0: + case 0x96163f56: result = new TL_messageActionPaymentSent(); break; + case 0x40699cd0: + result = new TL_messageActionPaymentSent_layer140(); + break; case 0xb6aef7b0: result = new TL_messageActionEmpty(); break; @@ -21854,6 +22228,9 @@ public class TLRPC { case 0xb3a07661: result = new TL_messageActionGroupCallScheduled(); break; + case 0x8f31b327: + result = new TL_messageActionPaymentSentMe(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in MessageAction", constructor)); @@ -22565,8 +22942,34 @@ public class TLRPC { } public static class TL_messageActionPaymentSent extends MessageAction { - public static int constructor = 0x40699cd0; + public static int constructor = 0x96163f56; + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + recurring_init = (flags & 4) != 0; + recurring_used = (flags & 8) != 0; + currency = stream.readString(exception); + total_amount = stream.readInt64(exception); + if ((flags & 1) != 0) { + invoice_slug = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = recurring_init ? (flags | 4) : (flags &~ 4); + flags = recurring_used ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeString(currency); + stream.writeInt64(total_amount); + if ((flags & 1) != 0) { + stream.writeString(invoice_slug); + } + } + } + + public static class TL_messageActionPaymentSent_layer140 extends TL_messageActionPaymentSent { + public static int constructor = 0x40699cd0; public void readParams(AbstractSerializedData stream, boolean exception) { currency = stream.readString(exception); @@ -22620,6 +23023,46 @@ public class TLRPC { } } + public static class TL_messageActionPaymentSentMe extends MessageAction { + public static int constructor = 0x8f31b327; + + public int flags; + public byte[] payload; + public TL_paymentRequestedInfo info; + public String shipping_option_id; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + recurring_init = (flags & 4) != 0; + recurring_used = (flags & 8) != 0; + currency = stream.readString(exception); + total_amount = stream.readInt64(exception); + payload = stream.readByteArray(exception); + if ((flags & 1) != 0) { + info = TL_paymentRequestedInfo.TLdeserialize(stream, stream.readInt32(exception), exception); + } + if ((flags & 2) != 0) { + shipping_option_id = stream.readString(exception); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = recurring_init ? (flags | 4) : (flags &~ 4); + flags = recurring_used ? (flags | 8) : (flags &~ 8); + stream.writeInt32(flags); + stream.writeString(currency); + stream.writeInt64(total_amount); + stream.writeByteArray(payload); + if ((flags & 1) != 0) { + info.serializeToStream(stream); + } + if ((flags & 2) != 0) { + stream.writeString(shipping_option_id); + } + } + } + public static class TL_messageActionGroupCallScheduled extends MessageAction { public static int constructor = 0xb3a07661; @@ -23140,7 +23583,7 @@ public class TLRPC { } public static class TL_invoice extends TLObject { - public static int constructor = 0xcd886e0; + public static int constructor = 0x3e85a91b; public int flags; public boolean test; @@ -23151,10 +23594,12 @@ public class TLRPC { public boolean flexible; public boolean phone_to_provider; public boolean email_to_provider; + public boolean recurring; public String currency; public ArrayList prices = new ArrayList<>(); public long max_tip_amount; public ArrayList suggested_tip_amounts = new ArrayList<>(); + public String recurring_terms_url; public static TL_invoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_invoice.constructor != constructor) { @@ -23179,6 +23624,7 @@ public class TLRPC { flexible = (flags & 32) != 0; phone_to_provider = (flags & 64) != 0; email_to_provider = (flags & 128) != 0; + recurring = (flags & 512) != 0; currency = stream.readString(exception); int magic = stream.readInt32(exception); if (magic != 0x1cb5c415) { @@ -23211,6 +23657,9 @@ public class TLRPC { suggested_tip_amounts.add(stream.readInt64(exception)); } } + if ((flags & 512) != 0) { + recurring_terms_url = stream.readString(exception); + } } public void serializeToStream(AbstractSerializedData stream) { @@ -23223,6 +23672,7 @@ public class TLRPC { flags = flexible ? (flags | 32) : (flags &~ 32); flags = phone_to_provider ? (flags | 64) : (flags &~ 64); flags = email_to_provider ? (flags | 128) : (flags &~ 128); + flags = recurring ? (flags | 512) : (flags &~ 512); stream.writeInt32(flags); stream.writeString(currency); stream.writeInt32(0x1cb5c415); @@ -23242,6 +23692,9 @@ public class TLRPC { stream.writeInt64(suggested_tip_amounts.get(a)); } } + if ((flags & 512) != 0) { + stream.writeString(recurring_terms_url); + } } } @@ -24778,7 +25231,7 @@ public class TLRPC { public int date; public String file_name; public String mime_type; - public int size; + public long size; public ArrayList thumbs = new ArrayList<>(); public ArrayList video_thumbs = new ArrayList<>(); public int version; @@ -24787,6 +25240,7 @@ public class TLRPC { public byte[] iv; public ArrayList attributes = new ArrayList<>(); public String file_name_fixed; //custom + public String localPath; //custom public static Document TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { Document result = null; @@ -24803,9 +25257,12 @@ public class TLRPC { case 0x55555556: result = new TL_documentEncrypted_old(); break; - case 0x1e87342b: + case 0x8fd4c4d8: result = new TL_document(); break; + case 0x1e87342b: + result = new TL_document_layer142(); + break; case 0x9efc6326: result = new TL_document_old(); break; @@ -24867,7 +25324,7 @@ public class TLRPC { stream.writeByteArray(file_reference); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); stream.writeInt32(0x1cb5c415); @@ -24915,7 +25372,7 @@ public class TLRPC { stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); stream.writeInt32(0); @@ -24954,7 +25411,7 @@ public class TLRPC { stream.writeInt32(date); stream.writeString(file_name); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); stream.writeByteArray(key); @@ -24963,6 +25420,104 @@ public class TLRPC { } public static class TL_document extends Document { + public static int constructor = 0x8fd4c4d8; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + id = stream.readInt64(exception); + access_hash = stream.readInt64(exception); + file_reference = stream.readByteArray(exception); + date = stream.readInt32(exception); + mime_type = stream.readString(exception); + size = stream.readInt64(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++) { + PhotoSize object = PhotoSize.TLdeserialize(0, id, 0, stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + thumbs.add(object); + } + } + 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++) { + VideoSize object = VideoSize.TLdeserialize(0, id, stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + video_thumbs.add(object); + } + } + dc_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++) { + DocumentAttribute object = DocumentAttribute.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + attributes.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeInt32(flags); + stream.writeInt64(id); + stream.writeInt64(access_hash); + stream.writeByteArray(file_reference); + stream.writeInt32(date); + stream.writeString(mime_type); + stream.writeInt64(size); + if ((flags & 1) != 0) { + stream.writeInt32(0x1cb5c415); + int count = thumbs.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + thumbs.get(a).serializeToStream(stream); + } + } + if ((flags & 2) != 0) { + stream.writeInt32(0x1cb5c415); + int count = video_thumbs.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + video_thumbs.get(a).serializeToStream(stream); + } + } + stream.writeInt32(dc_id); + stream.writeInt32(0x1cb5c415); + int count = attributes.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + attributes.get(a).serializeToStream(stream); + } + } + } + + public static class TL_document_layer142 extends TL_document { public static int constructor = 0x1e87342b; @@ -25034,7 +25589,7 @@ public class TLRPC { stream.writeByteArray(file_reference); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); if ((flags & 1) != 0) { stream.writeInt32(0x1cb5c415); int count = thumbs.size(); @@ -25116,7 +25671,7 @@ public class TLRPC { stream.writeByteArray(file_reference); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); if ((flags & 1) != 0) { stream.writeInt32(0x1cb5c415); int count = thumbs.size(); @@ -25159,7 +25714,7 @@ public class TLRPC { stream.writeInt32(date); stream.writeString(file_name); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); } @@ -25216,7 +25771,7 @@ public class TLRPC { stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); stream.writeInt32(0x1cb5c415); @@ -25265,7 +25820,7 @@ public class TLRPC { stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumbs.get(0).serializeToStream(stream); stream.writeInt32(dc_id); stream.writeInt32(0x1cb5c415); @@ -27869,7 +28424,7 @@ public class TLRPC { public static class TL_dialogFilterSuggested extends TLObject { public static int constructor = 0x77744d4a; - public TL_dialogFilter filter; + public DialogFilter filter; public String description; public static TL_dialogFilterSuggested TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -27886,7 +28441,7 @@ public class TLRPC { } public void readParams(AbstractSerializedData stream, boolean exception) { - filter = TL_dialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); + filter = DialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); description = stream.readString(exception); } @@ -28107,12 +28662,18 @@ public class TLRPC { case 0x2661bf09: result = new TL_updatePhoneCallSignalingData(); break; + case 0x88617090: + result = new TL_updateTranscribeAudio(); + break; case 0xfa0f3ca2: result = new TL_updatePinnedDialogs(); break; case 0x74d8be99: result = new TL_updateSavedRingtones(); break; + case 0x84cd5a: + result = new TL_updateTranscribedAudio(); + break; case 0xb4afcfb0: result = new TL_updatePeerLocated(); break; @@ -29215,6 +29776,36 @@ public class TLRPC { } } + public static class TL_updateTranscribedAudio extends Update { + public static int constructor = 0x84cd5a; + + public int flags; + public boolean pending; + public Peer peer; + public int msg_id; + public long transcription_id; + public String text; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pending = (flags & 1) != 0; + peer = Peer.TLdeserialize(stream, stream.readInt32(exception), exception); + msg_id = stream.readInt32(exception); + transcription_id = stream.readInt64(exception); + text = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pending ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + stream.writeInt64(transcription_id); + stream.writeString(text); + } + } + public static class TL_updateLangPack extends Update { public static int constructor = 0x56022f4d; @@ -29456,13 +30047,13 @@ public class TLRPC { public int flags; public int id; - public TL_dialogFilter filter; + public DialogFilter filter; public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); id = stream.readInt32(exception); if ((flags & 1) != 0) { - filter = TL_dialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); + filter = DialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); } } @@ -29557,6 +30148,30 @@ public class TLRPC { } } + public static class TL_updateTranscribeAudio extends Update { + public static int constructor = 0x88617090; + + public int flags; + public boolean isFinal; + public long transcription_id; + public String text; + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + isFinal = (flags & 1) != 0; + transcription_id = stream.readInt64(exception); + text = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = isFinal ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(transcription_id); + stream.writeString(text); + } + } + public static class TL_updatePinnedDialogs extends Update { public static int constructor = 0xfa0f3ca2; @@ -31239,6 +31854,9 @@ public class TLRPC { case 0x208e68c9: result = new TL_inputMessageEntityMentionName(); break; + case 0x5eef0214: + result = new TL_messageEntityAnimatedEmoji(); + break; case 0x4c4e743f: result = new TL_messageEntityCashtag(); break; @@ -31479,6 +32097,24 @@ public class TLRPC { } } + public static class TL_messageEntityAnimatedEmoji extends MessageEntity { + public static int constructor = 0x5eef0214; + + public int offset; + public int length; + + 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_messageEntityBold extends MessageEntity { public static int constructor = 0xbd610bc9; @@ -32624,6 +33260,7 @@ public class TLRPC { public boolean revoke_pm_inbox; public boolean blocked_mode; public boolean pfs_enabled; + public boolean force_try_ipv6; public int date; public int expires; public boolean test_mode; @@ -32691,6 +33328,7 @@ public class TLRPC { revoke_pm_inbox = (flags & 64) != 0; blocked_mode = (flags & 256) != 0; pfs_enabled = (flags & 8192) != 0; + force_try_ipv6 = (flags & 16384) != 0; date = stream.readInt32(exception); expires = stream.readInt32(exception); test_mode = stream.readBool(exception); @@ -32778,6 +33416,7 @@ public class TLRPC { flags = revoke_pm_inbox ? (flags | 64) : (flags &~ 64); flags = blocked_mode ? (flags | 256) : (flags &~ 256); flags = pfs_enabled ? (flags | 8192) : (flags &~ 8192); + flags = force_try_ipv6 ? (flags | 16384) : (flags &~ 16384); stream.writeInt32(flags); stream.writeInt32(date); stream.writeInt32(expires); @@ -33666,11 +34305,12 @@ public class TLRPC { public String username; public String password; public byte[] peer_tag; + public boolean tcp; public static PhoneConnection TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { PhoneConnection result = null; switch (constructor) { - case 0x9d4c17c0: + case 0x9cc123c7: result = new TL_phoneConnection(); break; case 0x635fe375: @@ -33688,10 +34328,11 @@ public class TLRPC { } public static class TL_phoneConnection extends PhoneConnection { - public static int constructor = 0x9d4c17c0; - + public static int constructor = 0x9cc123c7; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + tcp = (flags & 1) != 0; id = stream.readInt64(exception); ip = stream.readString(exception); ipv6 = stream.readString(exception); @@ -33701,6 +34342,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + flags = tcp ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); stream.writeInt64(id); stream.writeString(ip); stream.writeString(ipv6); @@ -36640,7 +37283,7 @@ public class TLRPC { public static abstract class DecryptedMessageMedia extends TLObject { public int duration; public String mime_type; - public int size; + public long size; public byte[] key; public byte[] iv; public double lat; @@ -36741,7 +37384,7 @@ public class TLRPC { stream.writeInt32(constructor); stream.writeInt32(duration); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -36829,7 +37472,7 @@ public class TLRPC { stream.writeInt32(thumb_w); stream.writeInt32(thumb_h); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); stream.writeInt32(0x1cb5c415); @@ -36880,7 +37523,7 @@ public class TLRPC { stream.writeInt32(thumb_h); stream.writeInt32(w); stream.writeInt32(h); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); stream.writeString(caption); @@ -36915,7 +37558,7 @@ public class TLRPC { stream.writeString(mime_type); stream.writeInt32(w); stream.writeInt32(h); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); stream.writeString(caption); @@ -36945,7 +37588,7 @@ public class TLRPC { stream.writeInt32(thumb_h); stream.writeString(file_name); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -36976,7 +37619,7 @@ public class TLRPC { stream.writeInt32(duration); stream.writeInt32(w); stream.writeInt32(h); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -37042,7 +37685,7 @@ public class TLRPC { stream.writeInt64(access_hash); stream.writeInt32(date); stream.writeString(mime_type); - stream.writeInt32(size); + stream.writeInt32((int) size); thumb.serializeToStream(stream); stream.writeInt32(dc_id); stream.writeInt32(0x1cb5c415); @@ -37081,7 +37724,7 @@ public class TLRPC { stream.writeString(mime_type); stream.writeInt32(w); stream.writeInt32(h); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -37101,7 +37744,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(duration); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -37130,7 +37773,7 @@ public class TLRPC { stream.writeInt32(thumb_h); stream.writeInt32(w); stream.writeInt32(h); - stream.writeInt32(size); + stream.writeInt32((int) size); stream.writeByteArray(key); stream.writeByteArray(iv); } @@ -37401,6 +38044,7 @@ public class TLRPC { public int flags; public boolean inactive; + public boolean premium; public String reaction; public String title; public Document static_icon; @@ -37428,6 +38072,7 @@ public class TLRPC { public void readParams(AbstractSerializedData stream, boolean exception) { flags = stream.readInt32(exception); inactive = (flags & 1) != 0; + premium = (flags & 4) != 0; reaction = stream.readString(exception); title = stream.readString(exception); static_icon = Document.TLdeserialize(stream, stream.readInt32(exception), exception); @@ -37446,6 +38091,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); flags = inactive ? (flags | 1) : (flags &~ 1); + flags = premium ? (flags | 4) : (flags &~ 4); stream.writeInt32(flags); stream.writeString(reaction); stream.writeString(title); @@ -37974,7 +38620,7 @@ public class TLRPC { public TL_chatInviteExported invite; public void readParams(AbstractSerializedData stream, boolean exception) { - invite = (TL_chatInviteExported) ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); + invite = ExportedChatInvite.TLdeserialize(stream, stream.readInt32(exception), exception); } public void serializeToStream(AbstractSerializedData stream) { @@ -38533,7 +39179,7 @@ public class TLRPC { } public static class TL_autoDownloadSettings extends TLObject { - public static int constructor = 0xe04232f3; + public static int constructor = 0x8efab953; public int flags; public boolean disabled; @@ -38541,8 +39187,8 @@ public class TLRPC { public boolean audio_preload_next; public boolean phonecalls_less_data; public int photo_size_max; - public int video_size_max; - public int file_size_max; + public long video_size_max; + public long file_size_max; public int video_upload_maxbitrate; public static TL_autoDownloadSettings TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -38565,8 +39211,8 @@ public class TLRPC { audio_preload_next = (flags & 4) != 0; phonecalls_less_data = (flags & 8) != 0; photo_size_max = stream.readInt32(exception); - video_size_max = stream.readInt32(exception); - file_size_max = stream.readInt32(exception); + video_size_max = stream.readInt64(exception); + file_size_max = stream.readInt64(exception); video_upload_maxbitrate = stream.readInt32(exception); } @@ -38578,8 +39224,8 @@ public class TLRPC { flags = phonecalls_less_data ? (flags | 8) : (flags &~ 8); stream.writeInt32(flags); stream.writeInt32(photo_size_max); - stream.writeInt32(video_size_max); - stream.writeInt32(file_size_max); + stream.writeInt64(video_size_max); + stream.writeInt64(file_size_max); stream.writeInt32(video_upload_maxbitrate); } } @@ -38796,6 +39442,8 @@ public class TLRPC { public TL_chatBannedRights banned_rights; public TL_chatBannedRights default_banned_rights; public InputChannel migrated_to; + public boolean join_to_send; + public boolean join_request; public boolean verifiedExtended() { return verified ||( ArrayUtil.contains(NekoXConfig.officialChats, id) && NekoXConfig.isDeveloper()); @@ -39266,6 +39914,8 @@ public class TLRPC { fake = (flags & 33554432) != 0; gigagroup = (flags & 67108864) != 0; noforwards = (flags & 134217728) != 0; + join_to_send = (flags & 268435456) != 0; + join_request = (flags & 536870912) != 0; id = stream.readInt64(exception); if ((flags & 8192) != 0) { access_hash = stream.readInt64(exception); @@ -39326,6 +39976,8 @@ public class TLRPC { 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); stream.writeInt32(flags); stream.writeInt64(id); if ((flags & 8192) != 0) { @@ -42026,6 +42678,9 @@ public class TLRPC { case 0xfc2e05bc: result = new TL_chatInviteExported_layer122(); break; + case 0xed107ab7: + result = new TL_chatInvitePublicJoinRequests(); + break; } if (result == null && exception) { throw new RuntimeException(String.format("can't parse magic %x in ExportedChatInvite", constructor)); @@ -45043,9 +45698,9 @@ public class TLRPC { } public static class TL_fileHash extends TLObject { - public static int constructor = 0x6242c773; + public static int constructor = 0xf39b035c; - public int offset; + public long offset; public int limit; public byte[] hash; @@ -45063,14 +45718,14 @@ public class TLRPC { } public void readParams(AbstractSerializedData stream, boolean exception) { - offset = stream.readInt32(exception); + offset = stream.readInt64(exception); limit = stream.readInt32(exception); hash = stream.readByteArray(exception); } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - stream.writeInt32(offset); + stream.writeInt64(offset); stream.writeInt32(limit); stream.writeByteArray(hash); } @@ -46632,6 +47287,19 @@ public class TLRPC { } } + public static class TL_help_getPremiumPromo extends TLObject { + public static int constructor = 0xb81b93d4; + + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_help_premiumPromo.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + public static class TL_help_getUserInfo extends TLObject { public static int constructor = 0x38a08d3; @@ -47535,13 +48203,13 @@ public class TLRPC { } public static class TL_upload_getFile extends TLObject { - public static int constructor = 0xb15a9afc; + public static int constructor = 0xbe5335be; public int flags; public boolean precise; public boolean cdn_supported; public InputFileLocation location; - public int offset; + public long offset; public int limit; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -47554,7 +48222,7 @@ public class TLRPC { flags = cdn_supported ? (flags | 2) : (flags &~ 2); stream.writeInt32(flags); location.serializeToStream(stream); - stream.writeInt32(offset); + stream.writeInt64(offset); stream.writeInt32(limit); } } @@ -50832,7 +51500,7 @@ public class TLRPC { Vector vector = new Vector(); int size = stream.readInt32(exception); for (int a = 0; a < size; a++) { - TL_dialogFilter object = TL_dialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); + DialogFilter object = DialogFilter.TLdeserialize(stream, stream.readInt32(exception), exception); if (object == null) { return vector; } @@ -52533,23 +53201,6 @@ public class TLRPC { } } - public static class TL_phone_saveCallLog extends TLObject { - public static int constructor = 0x41248786; - - public TL_inputPhoneCall peer; - public InputFile file; - - 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); - file.serializeToStream(stream); - } - } - public static class TL_phone_sendSignalingData extends TLObject { public static int constructor = 0xff7a9383; @@ -53095,11 +53746,10 @@ public class TLRPC { } public static class TL_payments_getPaymentForm extends TLObject { - public static int constructor = 0x8a333c8d; + public static int constructor = 0x37148dbb; public int flags; - public InputPeer peer; - public int msg_id; + public InputInvoice invoice; public TL_dataJSON theme_params; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -53109,8 +53759,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(msg_id); + invoice.serializeToStream(stream); if ((flags & 1) != 0) { theme_params.serializeToStream(stream); } @@ -53135,12 +53784,11 @@ public class TLRPC { } public static class TL_payments_validateRequestedInfo extends TLObject { - public static int constructor = 0xdb103170; + public static int constructor = 0xb6c8f12b; public int flags; public boolean save; - public InputPeer peer; - public int msg_id; + public InputInvoice invoice; public TL_paymentRequestedInfo info; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -53151,19 +53799,17 @@ public class TLRPC { stream.writeInt32(constructor); flags = save ? (flags | 1) : (flags &~ 1); stream.writeInt32(flags); - peer.serializeToStream(stream); - stream.writeInt32(msg_id); + invoice.serializeToStream(stream); info.serializeToStream(stream); } } public static class TL_payments_sendPaymentForm extends TLObject { - public static int constructor = 0x30c3bc9d; + public static int constructor = 0x2d03522f; public int flags; public long form_id; - public InputPeer peer; - public int msg_id; + public InputInvoice invoice; public String requested_info_id; public String shipping_option_id; public InputPaymentCredentials credentials; @@ -53177,8 +53823,7 @@ public class TLRPC { stream.writeInt32(constructor); stream.writeInt32(flags); stream.writeInt64(form_id); - peer.serializeToStream(stream); - stream.writeInt32(msg_id); + invoice.serializeToStream(stream); if ((flags & 1) != 0) { stream.writeString(requested_info_id); } @@ -53300,6 +53945,21 @@ public class TLRPC { } } + public static class TL_payments_assignPlayMarketTransaction extends TLObject { + public static int constructor = 0x4faa4aed; + + public String purchase_token; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(purchase_token); + } + } + public static class TL_payments_getSavedInfo extends TLObject { public static int constructor = 0x227d824b; @@ -53843,6 +54503,7 @@ public class TLRPC { public int period; public int ttl_seconds; public int proximity_notification_radius; + public boolean nopremium; public static MessageMedia TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageMedia result = null; @@ -54391,6 +55052,14 @@ public class TLRPC { public int realId; //custom public int stickerVerified = 1; //custom public boolean isThreadMessage; //custom + public String voiceTranscription; //custom + public boolean voiceTranscriptionOpen; //custom + public boolean voiceTranscriptionRated; //custom + public boolean voiceTranscriptionFinal; //custom + public long voiceTranscriptionId; //custom + public boolean premiumEffectWasPlayed; //custom + + // NekoX Customs public String translatedMessage; //custom public boolean translated; // custom public boolean hide; // custom @@ -57747,10 +58416,10 @@ public class TLRPC { } public static class TL_upload_getCdnFile extends TLObject { - public static int constructor = 0x2000bcc3; + public static int constructor = 0x395f69da; public byte[] file_token; - public int offset; + public long offset; public int limit; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { @@ -57760,7 +58429,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeByteArray(file_token); - stream.writeInt32(offset); + stream.writeInt64(offset); stream.writeInt32(limit); } } @@ -57792,10 +58461,10 @@ public class TLRPC { } public static class TL_upload_getCdnFileHashes extends TLObject { - public static int constructor = 0x4da54231; + public static int constructor = 0x91dc3f31; public byte[] file_token; - public int offset; + public long offset; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { Vector vector = new Vector(); @@ -57813,7 +58482,7 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); stream.writeByteArray(file_token); - stream.writeInt32(offset); + stream.writeInt64(offset); } } @@ -58278,15 +58947,9 @@ public class TLRPC { } } - public static class TL_attachMenuBot extends TLObject { + public static class TL_attachMenuBot_layer140 extends TL_attachMenuBot { public static int constructor = 0xe93cb772; - public int flags; - public boolean inactive; - public long bot_id; - public String short_name; - public ArrayList icons = new ArrayList<>(); - public static TL_attachMenuBot TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { if (TL_attachMenuBot.constructor != constructor) { if (exception) { @@ -58337,6 +59000,99 @@ public class TLRPC { } } + public static class TL_attachMenuBot extends AttachMenuBot { + public static int constructor = 0xc8aa2cd2; + + public int flags; + public boolean inactive; + public boolean has_settings; + public long bot_id; + public String short_name; + public ArrayList peer_types = new ArrayList<>(); + public ArrayList icons = new ArrayList<>(); + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + inactive = (flags & 1) != 0; + has_settings = (flags & 2) != 0; + bot_id = stream.readInt64(exception); + short_name = 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++) { + AttachMenuPeerType object = AttachMenuPeerType.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + peer_types.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++) { + TL_attachMenuBotIcon object = TL_attachMenuBotIcon.TLdeserialize(stream, stream.readInt32(exception), exception); + if (object == null) { + return; + } + icons.add(object); + } + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = inactive ? (flags | 1) : (flags &~ 1); + flags = has_settings ? (flags | 2) : (flags &~ 2); + stream.writeInt32(flags); + stream.writeInt64(bot_id); + stream.writeString(short_name); + stream.writeInt32(0x1cb5c415); + int count = peer_types.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + peer_types.get(a).serializeToStream(stream); + } + stream.writeInt32(0x1cb5c415); + count = icons.size(); + stream.writeInt32(count); + for (int a = 0; a < count; a++) { + icons.get(a).serializeToStream(stream); + } + } + } + + public static abstract class AttachMenuBot extends TLObject { + + public static TL_attachMenuBot TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + TL_attachMenuBot result = null; + switch (constructor) { + case 0xe93cb772: + result = new TL_attachMenuBot_layer140(); + break; + case 0xc8aa2cd2: + result = new TL_attachMenuBot(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in AttachMenuBot", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + public static abstract class AttachMenuBots extends TLObject { public static AttachMenuBots TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { @@ -58565,18 +59321,18 @@ public class TLRPC { } public static class TL_messages_requestWebView extends TLObject { - public static int constructor = 0xfa04dff; + public static int constructor = 0x91b15831; public int flags; + public boolean from_bot_menu; public boolean silent; - public boolean background; public InputPeer peer; public InputUser bot; public String url; public String start_param; public TL_dataJSON theme_params; public int reply_to_msg_id; - public boolean from_bot_menu; + public InputPeer send_as; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return TL_webViewResultUrl.TLdeserialize(stream, constructor, exception); @@ -58584,9 +59340,8 @@ public class TLRPC { public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); - flags = silent ? (flags | 32) : (flags &~ 32); - flags = background ? (flags | 64) : (flags &~ 64); flags = from_bot_menu ? (flags | 16) : (flags &~ 16); + flags = silent ? (flags | 32) : (flags &~ 32); stream.writeInt32(flags); peer.serializeToStream(stream); bot.serializeToStream(stream); @@ -58602,11 +59357,14 @@ public class TLRPC { if ((flags & 1) != 0) { stream.writeInt32(reply_to_msg_id); } + if ((flags & 8192) != 0) { + send_as.serializeToStream(stream); + } } } public static class TL_messages_prolongWebView extends TLObject { - public static int constructor = 0xd22ad148; + public static int constructor = 0xea5fbcce; public int flags; public boolean silent; @@ -58614,6 +59372,7 @@ public class TLRPC { public InputUser bot; public long query_id; public int reply_to_msg_id; + public InputPeer send_as; public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { return Bool.TLdeserialize(stream, constructor, exception); @@ -58629,6 +59388,9 @@ public class TLRPC { if ((flags & 1) != 0) { stream.writeInt32(reply_to_msg_id); } + if ((flags & 8192) != 0) { + send_as.serializeToStream(stream); + } } } @@ -59228,6 +59990,366 @@ public class TLRPC { stream.writeInt32(constructor); } } + + public static class TL_channels_toggleJoinToSend extends TLObject { + public static int constructor = 0xe4cb9580; + + public InputChannel channel; + public boolean enabled; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + channel.serializeToStream(stream); + stream.writeBool(enabled); + } + } + + public static class TL_channels_toggleJoinRequest extends TLObject { + public static int constructor = 0x4c2985b6; + + public InputChannel channel; + public boolean enabled; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + channel.serializeToStream(stream); + stream.writeBool(enabled); + } + } + + public static class TL_chatInvitePublicJoinRequests extends TL_chatInviteExported { + public static int constructor = 0xed107ab7; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + + } + } + + public static class TL_phone_saveCallLog extends TLObject { + public static int constructor = 0x41248786; + + public TL_inputPhoneCall peer; + public InputFile file; + + 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); + file.serializeToStream(stream); + } + } + + public static abstract class AttachMenuPeerType extends TLObject { + + public static AttachMenuPeerType TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + AttachMenuPeerType result = null; + switch (constructor) { + case 0xc32bfa1a: + result = new TL_attachMenuPeerTypeBotPM(); + break; + case 0xf146d31f: + result = new TL_attachMenuPeerTypePM(); + break; + case 0x7bfbdefc: + result = new TL_attachMenuPeerTypeBroadcast(); + break; + case 0x509113f: + result = new TL_attachMenuPeerTypeChat(); + break; + case 0x7d6be90e: + result = new TL_attachMenuPeerTypeSameBotPM(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in AttachMenuPeerType", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_attachMenuPeerTypeBotPM extends AttachMenuPeerType { + public static int constructor = 0xc32bfa1a; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_attachMenuPeerTypePM extends AttachMenuPeerType { + public static int constructor = 0xf146d31f; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_attachMenuPeerTypeBroadcast extends AttachMenuPeerType { + public static int constructor = 0x7bfbdefc; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_attachMenuPeerTypeChat extends AttachMenuPeerType { + public static int constructor = 0x509113f; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_attachMenuPeerTypeSameBotPM extends AttachMenuPeerType { + public static int constructor = 0x7d6be90e; + + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static abstract class InputInvoice extends TLObject { + + public static InputInvoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + InputInvoice result = null; + switch (constructor) { + case 0xc5b56859: + result = new TL_inputInvoiceMessage(); + break; + case 0xc326caef: + result = new TL_inputInvoiceSlug(); + break; + } + if (result == null && exception) { + throw new RuntimeException(String.format("can't parse magic %x in InputInvoice", constructor)); + } + if (result != null) { + result.readParams(stream, exception); + } + return result; + } + } + + public static class TL_inputInvoiceMessage extends InputInvoice { + public static int constructor = 0xc5b56859; + + public InputPeer peer; + public int msg_id; + + public void readParams(AbstractSerializedData stream, boolean exception) { + peer = InputPeer.TLdeserialize(stream, stream.readInt32(exception), exception); + msg_id = stream.readInt32(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + } + } + + public static class TL_inputInvoiceSlug extends InputInvoice { + public static int constructor = 0xc326caef; + + public String slug; + + public void readParams(AbstractSerializedData stream, boolean exception) { + slug = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(slug); + } + } + + public static class TL_payments_exportedInvoice extends TLObject { + public static int constructor = 0xaed0cbd9; + + public String url; + + public static TL_payments_exportedInvoice TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_payments_exportedInvoice.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_payments_exportedInvoice", constructor)); + } else { + return null; + } + } + TL_payments_exportedInvoice result = new TL_payments_exportedInvoice(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + url = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeString(url); + } + } + + public static class TL_payments_exportInvoice extends TLObject { + public static int constructor = 0xf91b065; + + public InputMedia invoice_media; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_payments_exportedInvoice.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + invoice_media.serializeToStream(stream); + } + } + + public static class TL_messages_transcribeAudio extends TLObject { + public static int constructor = 0x269e9a49; + + public InputPeer peer; + public int msg_id; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return TL_messages_transcribedAudio.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + peer.serializeToStream(stream); + stream.writeInt32(msg_id); + } + } + + public static class TL_messages_rateTranscribedAudio extends TLObject { + public static int constructor = 0x7f1d072f; + + public InputPeer peer; + public int msg_id; + public long transcription_id; + public boolean good; + + 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(msg_id); + stream.writeInt64(transcription_id); + stream.writeBool(good); + } + } + + public static class TL_messages_transcribedAudio extends TLObject { + public static int constructor = 0x93752c52; + + public int flags; + public boolean pending; + public long transcription_id; + public String text; + + public static TL_messages_transcribedAudio TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { + if (TL_messages_transcribedAudio.constructor != constructor) { + if (exception) { + throw new RuntimeException(String.format("can't parse magic %x in TL_messages_transcribedAudio", constructor)); + } else { + return null; + } + } + TL_messages_transcribedAudio result = new TL_messages_transcribedAudio(); + result.readParams(stream, exception); + return result; + } + + public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); + pending = (flags & 1) != 0; + transcription_id = stream.readInt64(exception); + text = stream.readString(exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + flags = pending ? (flags | 1) : (flags &~ 1); + stream.writeInt32(flags); + stream.writeInt64(transcription_id); + stream.writeString(text); + } + } + + public static class TL_payments_restorePlayMarketReceipt extends TLObject { + public static int constructor = 0xd164e36a; + + public byte[] receipt; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + stream.writeByteArray(receipt); + } + } + + public static class TL_payments_canPurchasePremium extends TLObject { + public static int constructor = 0xaa6a90c8; + + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Bool.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + } + } + + public static class TL_payments_requestRecurringPayment extends TLObject { + public static int constructor = 0x146e958d; + + public InputUser user_id; + public String recurring_init_charge; + public InputMedia invoice_media; + + public TLObject deserializeResponse(AbstractSerializedData stream, int constructor, boolean exception) { + return Updates.TLdeserialize(stream, constructor, exception); + } + + public void serializeToStream(AbstractSerializedData stream) { + stream.writeInt32(constructor); + user_id.serializeToStream(stream); + stream.writeString(recurring_init_charge); + invoice_media.serializeToStream(stream); + } + } //functions public static class Vector extends TLObject { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java index 7f5114e02..494d8f5a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java @@ -74,12 +74,14 @@ public class ActionBar extends FrameLayout { } private UnreadImageView backButtonImageView; + private Drawable backButtonDrawable; private SimpleTextView[] titleTextView = new SimpleTextView[2]; private SimpleTextView subtitleTextView; private SimpleTextView additionalSubtitleTextView; private View actionModeTop; private int actionModeColor; private int actionBarColor; + private boolean isMenuOffsetSuppressed; private ActionBarMenu menu; private ActionBarMenu actionMode; private String actionModeTag; @@ -89,6 +91,7 @@ public class ActionBar extends FrameLayout { private boolean addToContainer = true; private boolean clipContent; private boolean interceptTouches = true; + private boolean forceSkipTouches; private int extraHeight; private AnimatorSet actionModeAnimation; private View actionModeExtraView; @@ -132,6 +135,11 @@ public class ActionBar extends FrameLayout { private View.OnTouchListener interceptTouchEventListener; private final Theme.ResourcesProvider resourcesProvider; + SizeNotifierFrameLayout contentView; + boolean blurredBackground; + public Paint blurScrimPaint = new Paint(); + Rect rectTmp = new Rect(); + EllipsizeSpanAnimator ellipsizeSpanAnimator = new EllipsizeSpanAnimator(this); public ActionBar(Context context) { @@ -176,12 +184,16 @@ public class ActionBar extends FrameLayout { backButtonImageView.setContentDescription(LocaleController.getString("AccDescrGoBack", R.string.AccDescrGoBack)); } + public Drawable getBackButtonDrawable() { + return backButtonDrawable; + } + public void setBackButtonDrawable(Drawable drawable) { if (backButtonImageView == null) { createBackButtonImage(); } backButtonImageView.setVisibility(drawable == null ? GONE : VISIBLE); - backButtonImageView.setImageDrawable(drawable); + backButtonImageView.setImageDrawable(backButtonDrawable = drawable); if (drawable instanceof BackDrawable) { BackDrawable backDrawable = (BackDrawable) drawable; backDrawable.setRotation(isActionModeShowed() ? 1 : 0, false); @@ -1054,13 +1066,19 @@ public class ActionBar extends FrameLayout { menu.measure(menuWidth, actionBarHeightSpec); int itemsWidth = menu.getItemsMeasuredWidth(); menuWidth = MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66) + menu.getItemsMeasuredWidth(), MeasureSpec.EXACTLY); - menu.translateXItems(-itemsWidth); + if (!isMenuOffsetSuppressed) { + menu.translateXItems(-itemsWidth); + } } else if (isSearchFieldVisible) { menuWidth = MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66), MeasureSpec.EXACTLY); - menu.translateXItems(0); + if (!isMenuOffsetSuppressed) { + menu.translateXItems(0); + } } else { menuWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST); - menu.translateXItems(0); + if (!isMenuOffsetSuppressed) { + menu.translateXItems(0); + } } menu.measure(menuWidth, actionBarHeightSpec); @@ -1124,6 +1142,10 @@ public class ActionBar extends FrameLayout { } } + public void setMenuOffsetSuppressed(boolean menuOffsetSuppressed) { + isMenuOffsetSuppressed = menuOffsetSuppressed; + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int additionalTop = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0; @@ -1404,6 +1426,9 @@ public class ActionBar extends FrameLayout { @Override public boolean onTouchEvent(MotionEvent event) { + if (forceSkipTouches) { + return false; + } return super.onTouchEvent(event) || interceptTouches; } @@ -1589,9 +1614,6 @@ public class ActionBar extends FrameLayout { return color != null ? color : Theme.getColor(key); } - SizeNotifierFrameLayout contentView; - boolean blurredBackground; - public void setDrawBlurBackground(SizeNotifierFrameLayout contentView) { blurredBackground = true; this.contentView = contentView; @@ -1599,8 +1621,6 @@ public class ActionBar extends FrameLayout { setBackground(null); } - public Paint blurScrimPaint = new Paint(); - Rect rectTmp = new Rect(); @Override protected void dispatchDraw(Canvas canvas) { if (blurredBackground && actionBarColor != Color.TRANSPARENT) { @@ -1611,6 +1631,10 @@ public class ActionBar extends FrameLayout { super.dispatchDraw(canvas); } + public void setForceSkipTouches(boolean forceSkipTouches) { + this.forceSkipTouches = forceSkipTouches; + } + // NekoX Changes private StaticLayout countLayout; 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 1fc5b4424..3d7fcf1d3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java @@ -12,6 +12,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; @@ -36,6 +37,7 @@ import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import androidx.annotation.Keep; @@ -45,6 +47,7 @@ import androidx.core.math.MathUtils; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; @@ -74,6 +77,8 @@ public class ActionBarLayout extends FrameLayout { void onRebuildAllFragments(ActionBarLayout layout, boolean last); } + public boolean highlightActionButtons = false; + public class LayoutContainer extends FrameLayout { private Rect rect = new Rect(); @@ -83,6 +88,8 @@ public class ActionBarLayout extends FrameLayout { private Paint backgroundPaint = new Paint(); private int backgroundColor; + private boolean wasPortrait; + public LayoutContainer(Context context) { super(context); setWillNotDraw(false); @@ -130,6 +137,12 @@ public class ActionBarLayout extends FrameLayout { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); + boolean isPortrait = height > width; + if (wasPortrait != isPortrait && isInPreviewMode()) { + finishPreviewFragment(); + } + wasPortrait = isPortrait; + int count = getChildCount(); int actionBarHeight = 0; for (int a = 0; a < count; a++) { @@ -190,11 +203,11 @@ public class ActionBarLayout extends FrameLayout { @Override public boolean dispatchTouchEvent(MotionEvent ev) { + processMenuButtonsTouch(ev); boolean passivePreview = inPreviewMode && previewMenu == null; if ((passivePreview || transitionAnimationPreviewMode) && (ev.getActionMasked() == MotionEvent.ACTION_DOWN || ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN)) { return false; } - // try { return (!passivePreview || this != containerView) && super.dispatchTouchEvent(ev); } catch (Throwable e) { @@ -219,6 +232,76 @@ public class ActionBarLayout extends FrameLayout { this.fragmentPanTranslationOffset = fragmentPanTranslationOffset; invalidate(); } + + // for menu buttons to be clicked by hover: + private float pressX, pressY; + private boolean allowToPressByHover; + public void processMenuButtonsTouch(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + pressX = event.getX(); + pressY = event.getY(); + allowToPressByHover = false; + } else if (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_UP) { + if (previewMenu != null && highlightActionButtons) { +// movePreviewFragment(Math.min(pressY, AndroidUtilities.displaySize.y * .4f) - event.getY()); + if (!allowToPressByHover && Math.sqrt(Math.pow(pressX - event.getX(), 2) + Math.pow(pressY - event.getY(), 2)) > AndroidUtilities.dp(30)) { + allowToPressByHover = true; + } + if (allowToPressByHover && (previewMenu.getSwipeBack() == null || !previewMenu.getSwipeBack().isForegroundOpen())) { + for (int i = 0; i < previewMenu.getItemsCount(); ++i) { + ActionBarMenuSubItem button = (ActionBarMenuSubItem) previewMenu.getItemAt(i); + if (button != null) { + Drawable ripple = button.getBackground(); + button.getGlobalVisibleRect(AndroidUtilities.rectTmp2); + boolean shouldBeEnabled = AndroidUtilities.rectTmp2.contains((int) event.getX(), (int) event.getY()), + enabled = ripple.getState().length == 2; + if (event.getAction() == MotionEvent.ACTION_MOVE) { + if (shouldBeEnabled != enabled) { + ripple.setState(shouldBeEnabled ? new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled} : new int[]{}); + if (shouldBeEnabled) { + try { + button.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } + } + } else if (event.getAction() == MotionEvent.ACTION_UP) { + if (shouldBeEnabled) { + button.performClick(); + } + } + } + } + } + } + } + if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + if (previewMenu != null && highlightActionButtons) { + int alpha = 255; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + alpha = Theme.moveUpDrawable.getAlpha(); + } + ValueAnimator arrowAlphaUpdate = ValueAnimator.ofFloat(alpha, 0); + arrowAlphaUpdate.addUpdateListener(a -> { + Theme.moveUpDrawable.setAlpha(((Float) a.getAnimatedValue()).intValue()); + if (drawerLayoutContainer != null) { + drawerLayoutContainer.invalidate(); + } + if (containerView != null) { + containerView.invalidate(); + } + ActionBarLayout.this.invalidate(); + }); + arrowAlphaUpdate.setDuration(150); + arrowAlphaUpdate.setInterpolator(CubicBezierInterpolator.DEFAULT); + arrowAlphaUpdate.start(); + ObjectAnimator containerTranslationUpdate = ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0); + containerTranslationUpdate.setDuration(150); + containerTranslationUpdate.setInterpolator(CubicBezierInterpolator.DEFAULT); + containerTranslationUpdate.start(); + } + highlightActionButtons = false; + } + } } public static class ThemeAnimationSettings { @@ -270,10 +353,11 @@ public class ActionBarLayout extends FrameLayout { private BaseFragment oldFragment; /* Contest */ - private View previewMenu; + private ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu; private AnimatorSet currentAnimation; private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(1.5f); + private OvershootInterpolator overshootInterpolator = new OvershootInterpolator(1.02f); private AccelerateDecelerateInterpolator accelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator(); public float innerTranslationX; @@ -369,6 +453,7 @@ public class ActionBarLayout extends FrameLayout { fragment.setParentLayout(this); } } + @Override public void onConfigurationChanged(android.content.res.Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -474,6 +559,13 @@ public class ActionBarLayout extends FrameLayout { } } + public void onUserLeaveHint() { + if (!fragmentsStack.isEmpty()) { + BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1); + lastFragment.onUserLeaveHint(); + } + } + public void onPause() { if (!fragmentsStack.isEmpty()) { BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 1); @@ -600,9 +692,10 @@ public class ActionBarLayout extends FrameLayout { previewBackgroundDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); previewBackgroundDrawable.draw(canvas); if (previewMenu == null) { - int x = (getMeasuredWidth() - AndroidUtilities.dp(24)) / 2; + int width = AndroidUtilities.dp(32), height = width / 2; + int x = (getMeasuredWidth() - width) / 2; int y = (int) (view.getTop() + containerView.getTranslationY() - AndroidUtilities.dp(12 + (Build.VERSION.SDK_INT < 21 ? 20 : 0))); - Theme.moveUpDrawable.setBounds(x, y, x + AndroidUtilities.dp(24), y + AndroidUtilities.dp(24)); + Theme.moveUpDrawable.setBounds(x, y, x + width, y + height); Theme.moveUpDrawable.draw(canvas); } } @@ -976,7 +1069,7 @@ public class ActionBarLayout extends FrameLayout { return presentFragment(fragment, false, false, true, true, null); } - public boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, View menu) { + public boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, ActionBarPopupWindow.ActionBarPopupWindowLayout menu) { return presentFragment(fragment, false, false, true, true, menu); } @@ -1009,7 +1102,8 @@ public class ActionBarLayout extends FrameLayout { dt = 18; } lastFrameTime = newTime; - animationProgress += dt / 150.0f; + float duration = preview && open ? 190.0f : 150.0f; + animationProgress += dt / duration; if (animationProgress > 1.0f) { animationProgress = 1.0f; } @@ -1021,30 +1115,49 @@ public class ActionBarLayout extends FrameLayout { } Integer oldNavigationBarColor = oldFragment != null ? oldFragment.getNavigationBarColor() : null; Integer newNavigationBarColor = newFragment != null ? newFragment.getNavigationBarColor() : null; - if (newFragment != null && !newFragment.inPreviewMode && oldNavigationBarColor != null) { + if (newFragment != null && oldNavigationBarColor != null) { float ratio = MathUtils.clamp(2f * animationProgress - (open ? 1f : 0f), 0f, 1f); newFragment.setNavigationBarColor(ColorUtils.blendARGB(oldNavigationBarColor, newNavigationBarColor, ratio)); } - float interpolated = decelerateInterpolator.getInterpolation(animationProgress); + float interpolated; + if (preview) { + if (open) { + interpolated = overshootInterpolator.getInterpolation(animationProgress); + } else { + interpolated = CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(animationProgress); + } + } else { + interpolated = decelerateInterpolator.getInterpolation(animationProgress); + } if (open) { - containerView.setAlpha(interpolated); + float clampedInterpolated = MathUtils.clamp(interpolated, 0, 1); + containerView.setAlpha(clampedInterpolated); if (preview) { - containerView.setScaleX(0.9f + 0.1f * interpolated); - containerView.setScaleY(0.9f + 0.1f * interpolated); - previewBackgroundDrawable.setAlpha((int) (0x2e * interpolated)); - Theme.moveUpDrawable.setAlpha((int) (255 * interpolated)); + containerView.setScaleX(0.7f + 0.3f * interpolated); + containerView.setScaleY(0.7f + 0.3f * interpolated); + if (previewMenu != null) { + containerView.setTranslationY(AndroidUtilities.dp(40) * (1f - interpolated)); + previewMenu.setTranslationY(-AndroidUtilities.dp(40 + 30) * (1f - interpolated)); + previewMenu.setScaleX(0.95f + 0.05f * interpolated); + previewMenu.setScaleY(0.95f + 0.05f * interpolated); + } + previewBackgroundDrawable.setAlpha((int) (0x2e * clampedInterpolated)); + Theme.moveUpDrawable.setAlpha((int) (255 * clampedInterpolated)); containerView.invalidate(); invalidate(); } else { containerView.setTranslationX(AndroidUtilities.dp(48) * (1.0f - interpolated)); } } else { - containerViewBack.setAlpha(1.0f - interpolated); + float clampedReverseInterpolated = MathUtils.clamp(1f - interpolated, 0, 1); + containerViewBack.setAlpha(clampedReverseInterpolated); if (preview) { containerViewBack.setScaleX(0.9f + 0.1f * (1.0f - interpolated)); containerViewBack.setScaleY(0.9f + 0.1f * (1.0f - interpolated)); - previewBackgroundDrawable.setAlpha((int) (0x2e * (1.0f - interpolated))); - Theme.moveUpDrawable.setAlpha((int) (255 * (1.0f - interpolated))); + previewBackgroundDrawable.setAlpha((int) (0x2e * clampedReverseInterpolated)); + if (previewMenu == null) { + Theme.moveUpDrawable.setAlpha((int) (255 * clampedReverseInterpolated)); + } containerView.invalidate(); invalidate(); } else { @@ -1087,13 +1200,27 @@ public class ActionBarLayout extends FrameLayout { return presentFragment(fragment, removeLast, forceWithoutAnimation, check, preview, null); } - public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check, final boolean preview, View menu) { + public boolean presentFragment(final BaseFragment fragment, final boolean removeLast, boolean forceWithoutAnimation, boolean check, final boolean preview, ActionBarPopupWindow.ActionBarPopupWindowLayout menu) { Log.i("UI", "presenting Fragment " + fragment); if (fragment == null || checkTransitionAnimation() || delegate != null && check && !delegate.needPresentFragment(fragment, removeLast, forceWithoutAnimation, this) || !fragment.onFragmentCreate()) { return false; } + if (inPreviewMode && transitionAnimationPreviewMode) { + if (delayedOpenAnimationRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(delayedOpenAnimationRunnable); + delayedOpenAnimationRunnable = null; + } + closeLastFragment(false, true); + } fragment.setInPreviewMode(preview); - fragment.setInMenuMode(menu != null); + if (previewMenu != null) { + if (previewMenu.getParent() != null) { + ((ViewGroup) previewMenu.getParent()).removeView(previewMenu); + } + previewMenu = null; + } + previewMenu = menu; + fragment.setInMenuMode(previewMenu != null); if (parentActivity.getCurrentFocus() != null && fragment.hideKeyboardOnShow() && !preview) { AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus()); } @@ -1138,11 +1265,12 @@ public class ActionBarLayout extends FrameLayout { layoutParams.height = height; layoutParams.topMargin = statusBarHeight + (getMeasuredHeight() - statusBarHeight - height) / 2; } else { - layoutParams.topMargin = layoutParams.bottomMargin = AndroidUtilities.dp(menu != null ? 0 : 46); + layoutParams.topMargin = layoutParams.bottomMargin = AndroidUtilities.dp(menu != null ? 0 : 24); layoutParams.topMargin += AndroidUtilities.statusBarHeight; } if (menu != null) { layoutParams.bottomMargin += menuHeight + AndroidUtilities.dp(8); +// layoutParams.topMargin += AndroidUtilities.dp(32); } layoutParams.rightMargin = layoutParams.leftMargin = AndroidUtilities.dp(8); } else { @@ -1380,6 +1508,7 @@ public class ActionBarLayout extends FrameLayout { if (onFragmentStackChangedListener != null) { onFragmentStackChangedListener.run(); } + ImageLoader.getInstance().onFragmentStackChanged(); } public boolean addFragmentToStack(BaseFragment fragment) { @@ -1431,7 +1560,7 @@ public class ActionBarLayout extends FrameLayout { } public void movePreviewFragment(float dy) { - if (!inPreviewMode || transitionAnimationPreviewMode || previewMenu != null) { + if (!inPreviewMode || previewMenu != null || transitionAnimationPreviewMode) { return; } float currentTranslation = containerView.getTranslationY(); @@ -1439,43 +1568,8 @@ public class ActionBarLayout extends FrameLayout { if (nextTranslation > 0) { nextTranslation = 0; } else if (nextTranslation < -AndroidUtilities.dp(60)) { - previewOpenAnimationInProgress = true; - inPreviewMode = false; nextTranslation = 0; - - BaseFragment prevFragment = fragmentsStack.get(fragmentsStack.size() - 2); - BaseFragment fragment = fragmentsStack.get(fragmentsStack.size() - 1); - - if (Build.VERSION.SDK_INT >= 21) { - fragment.fragmentView.setOutlineProvider(null); - fragment.fragmentView.setClipToOutline(false); - } - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.fragmentView.getLayoutParams(); - layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; - layoutParams.height = LayoutHelper.MATCH_PARENT; - fragment.fragmentView.setLayoutParams(layoutParams); - - presentFragmentInternalRemoveOld(false, prevFragment); - - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether( - ObjectAnimator.ofFloat(fragment.fragmentView, View.SCALE_X, 1.0f, 1.05f, 1.0f), - ObjectAnimator.ofFloat(fragment.fragmentView, View.SCALE_Y, 1.0f, 1.05f, 1.0f)); - animatorSet.setDuration(200); - animatorSet.setInterpolator(new CubicBezierInterpolator(0.42, 0.0, 0.58, 1.0)); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - previewOpenAnimationInProgress = false; - fragment.onPreviewOpenAnimationEnd(); - } - }); - animatorSet.start(); - if (!NekoConfig.disableVibration.Bool()) { - performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); - } - - fragment.setInPreviewMode(false); + expandPreviewFragment(); } if (currentTranslation != nextTranslation) { containerView.setTranslationY(nextTranslation); @@ -1483,6 +1577,46 @@ public class ActionBarLayout extends FrameLayout { } } + public void expandPreviewFragment() { + previewOpenAnimationInProgress = true; + inPreviewMode = false; + + BaseFragment prevFragment = fragmentsStack.get(fragmentsStack.size() - 2); + BaseFragment fragment = fragmentsStack.get(fragmentsStack.size() - 1); + + if (Build.VERSION.SDK_INT >= 21) { + fragment.fragmentView.setOutlineProvider(null); + fragment.fragmentView.setClipToOutline(false); + } + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fragment.fragmentView.getLayoutParams(); + layoutParams.topMargin = layoutParams.bottomMargin = layoutParams.rightMargin = layoutParams.leftMargin = 0; + layoutParams.height = LayoutHelper.MATCH_PARENT; + fragment.fragmentView.setLayoutParams(layoutParams); + + presentFragmentInternalRemoveOld(false, prevFragment); + + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether( + ObjectAnimator.ofFloat(fragment.fragmentView, View.SCALE_X, 1.0f, 1.05f, 1.0f), + ObjectAnimator.ofFloat(fragment.fragmentView, View.SCALE_Y, 1.0f, 1.05f, 1.0f)); + animatorSet.setDuration(200); + animatorSet.setInterpolator(new CubicBezierInterpolator(0.42, 0.0, 0.58, 1.0)); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + previewOpenAnimationInProgress = false; + fragment.onPreviewOpenAnimationEnd(); + } + }); + animatorSet.start(); + if (!NekoConfig.disableVibration.Bool()) { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } + + fragment.setInPreviewMode(false); + fragment.setInMenuMode(false); + } + public void finishPreviewFragment() { if (!inPreviewMode && !transitionAnimationPreviewMode) { return; @@ -1495,6 +1629,10 @@ public class ActionBarLayout extends FrameLayout { } public void closeLastFragment(boolean animated) { + closeLastFragment(animated, false); + } + + public void closeLastFragment(boolean animated, boolean forceNoAnimation) { if (delegate != null && !delegate.needCloseLastFragment(this) || checkTransitionAnimation() || fragmentsStack.isEmpty()) { return; } @@ -1502,7 +1640,7 @@ public class ActionBarLayout extends FrameLayout { AndroidUtilities.hideKeyboard(parentActivity.getCurrentFocus()); } setInnerTranslationX(0); - boolean needAnimation = inPreviewMode || transitionAnimationPreviewMode || animated && MessagesController.getGlobalMainSettings().getBoolean("view_animations", true); + boolean needAnimation = !forceNoAnimation && (inPreviewMode || transitionAnimationPreviewMode || animated && MessagesController.getGlobalMainSettings().getBoolean("view_animations", true)); final BaseFragment currentFragment = fragmentsStack.get(fragmentsStack.size() - 1); BaseFragment previousFragment = null; if (fragmentsStack.size() > 1) { @@ -1567,10 +1705,6 @@ public class ActionBarLayout extends FrameLayout { fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } - if (!needAnimation) { - closeLastFragmentInternalRemoveOld(currentFragment); - } - if (needAnimation) { transitionAnimationStartTime = System.currentTimeMillis(); transitionAnimationInProgress = true; @@ -1631,12 +1765,13 @@ public class ActionBarLayout extends FrameLayout { } onFragmentStackChanged(); } else { + closeLastFragmentInternalRemoveOld(currentFragment); currentFragment.onTransitionAnimationEnd(false, true); previousFragment.onTransitionAnimationEnd(true, true); previousFragment.onBecomeFullyVisible(); } } else { - if (useAlphaAnimations) { + if (useAlphaAnimations && !forceNoAnimation) { transitionAnimationStartTime = System.currentTimeMillis(); transitionAnimationInProgress = true; layoutToIgnore = containerView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java index 7290a988a..e132fee1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java @@ -82,6 +82,10 @@ public class ActionBarMenu extends LinearLayout { return addItem(id, icon, null, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, null, width, null); } + public ActionBarMenuItem addItemWithWidth(int id, Drawable drawable, int width, CharSequence title) { + return addItem(id, 0, null, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, drawable, width, title); + } + public ActionBarMenuItem addItemWithWidth(int id, int icon, int width, CharSequence title) { return addItem(id, icon, null, isActionMode ? parentActionBar.itemsActionModeBackgroundColor : parentActionBar.itemsBackgroundColor, null, width, title); } @@ -355,7 +359,7 @@ public class ActionBarMenu extends LinearLayout { return false; } - public void translateXItems(int offset) { + public void translateXItems(float offset) { int count = getChildCount(); for (int a = 0; a < count; a++) { View view = getChildAt(a); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java index 73ff195c0..6b42a6836 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.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.ActionMode; import android.view.Gravity; @@ -59,6 +60,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.XiaomiUtilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Components.BackupImageView; @@ -379,7 +381,7 @@ public class ActionBarMenuItem extends FrameLayout { if (popupLayout == null) { return; } - popupLayout.setShownFromBotton(value); + popupLayout.setShownFromBottom(value); } public void addSubItem(View view, int width, int height) { @@ -791,7 +793,7 @@ public class ActionBarMenuItem extends FrameLayout { } } } - clearSearchFilters(); +// clearSearchFilters(); } if (listener != null) { listener.onSearchCollapse(); @@ -1333,6 +1335,8 @@ public class ActionBarMenuItem extends FrameLayout { searchField.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_ACTION_SEARCH); searchField.setTextIsSelectable(false); + searchField.setHighlightColor(getThemedColor(Theme.key_chat_inTextSelectionHighlight)); + searchField.setHandlesColor(getThemedColor(Theme.key_chat_TextSelectionCursor)); searchFilterLayout = new LinearLayout(getContext()); searchFilterLayout.setOrientation(LinearLayout.HORIZONTAL); @@ -1720,11 +1724,17 @@ public class ActionBarMenuItem extends FrameLayout { } public void showSubItem(int id) { + showSubItem(id, false); + } + + public void showSubItem(int id, boolean animated) { if (popupLayout == null) { return; } View view = popupLayout.findViewWithTag(id); if (view != null && view.getVisibility() != VISIBLE) { + view.setAlpha(0); + view.animate().alpha(1f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start(); view.setVisibility(VISIBLE); measurePopup = true; } @@ -1774,6 +1784,13 @@ public class ActionBarMenuItem extends FrameLayout { } } } + if (searchField != null) { + searchField.setCursorColor(getThemedColor(Theme.key_actionBarDefaultSearch)); + searchField.setHintTextColor(getThemedColor(Theme.key_actionBarDefaultSearchPlaceholder)); + searchField.setTextColor(getThemedColor(Theme.key_actionBarDefaultSearch)); + searchField.setHighlightColor(getThemedColor(Theme.key_chat_inTextSelectionHighlight)); + searchField.setHandlesColor(getThemedColor(Theme.key_chat_TextSelectionCursor)); + } } public void collapseSearchFilters() { @@ -1781,7 +1798,7 @@ public class ActionBarMenuItem extends FrameLayout { onFiltersChanged(); } - public void setTransitionOffset(int offset) { + public void setTransitionOffset(float offset) { this.transitionOffset = offset; setTranslationX(0); } @@ -1942,13 +1959,13 @@ public class ActionBarMenuItem extends FrameLayout { public ActionBarPopupWindow.GapView addColoredGap() { createPopupLayout(); - ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), Theme.key_graySection); + ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getContext(), resourcesProvider, Theme.key_actionBarDefaultSubmenuSeparator); gap.setTag(R.id.fit_width_tag, 1); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); return gap; } - public static ActionBarMenuSubItem addItem(ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, String text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { + public static ActionBarMenuSubItem addItem(ActionBarPopupWindow.ActionBarPopupWindowLayout windowLayout, int icon, CharSequence text, boolean needCheck, Theme.ResourcesProvider resourcesProvider) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(windowLayout.getContext(), needCheck, false, false, resourcesProvider); cell.setTextAndIcon(text, icon); cell.setMinimumWidth(AndroidUtilities.dp(196)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java index 0e3046c38..d9461ff01 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuSubItem.java @@ -4,16 +4,21 @@ import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; 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.messenger.R; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.LayoutHelper; @@ -101,6 +106,17 @@ public class ActionBarMenuSubItem extends FrameLayout { checkView.setChecked(checked, true); } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(isEnabled()); + if (checkView != null && checkView.isChecked()) { + info.setCheckable(true); + info.setChecked(checkView.isChecked()); + info.setClassName("android.widget.CheckBox"); + } + } + public void setCheckColor(String colorKey) { checkView.setColor(null, null, colorKey); } 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 6582b707d..c5fade8e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java @@ -17,16 +17,17 @@ 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.Rect; import android.graphics.drawable.Drawable; import android.os.Build; - +import android.util.Log; +import android.view.Gravity; import androidx.annotation.Keep; import androidx.core.view.ViewCompat; import androidx.core.widget.ScrollerCompat; - import android.view.KeyEvent; import android.view.View; import android.view.ViewGroup; @@ -67,6 +68,7 @@ public class ActionBarPopupWindow extends PopupWindow { private int currentAccount = UserConfig.selectedAccount; private boolean pauseNotifications; private long outEmptyTime = -1; + private boolean scaleOut; static { Field f = null; @@ -87,21 +89,27 @@ public class ActionBarPopupWindow extends PopupWindow { private ViewTreeObserver mViewTreeObserver; private int popupAnimationIndex = -1; + public void setScaleOut(boolean b) { + scaleOut = b; + } + public interface OnDispatchKeyEventListener { void onDispatchKeyEvent(KeyEvent keyEvent); } public static class ActionBarPopupWindowLayout extends FrameLayout { public final static int FLAG_USE_SWIPEBACK = 1; + public final static int FLAG_SHOWN_FROM_BOTTOM = 2; public boolean updateAnimation; public boolean swipeBackGravityRight; private OnDispatchKeyEventListener mOnDispatchKeyEventListener; private float backScaleX = 1; private float backScaleY = 1; + private boolean startAnimationPending = false; private int backAlpha = 255; private int lastStartedChild = 0; - private boolean shownFromBotton; + private boolean shownFromBottom; private boolean animationEnabled = allowAnimation; private ArrayList itemAnimators; private HashMap positions = new HashMap<>(); @@ -121,6 +129,8 @@ public class ActionBarPopupWindow extends PopupWindow { private final Theme.ResourcesProvider resourcesProvider; private View topView; + public int subtractBackgroundHeight; + public ActionBarPopupWindowLayout(Context context) { this(context, null); } @@ -148,6 +158,10 @@ public class ActionBarPopupWindow extends PopupWindow { setWillNotDraw(false); + if ((flags & FLAG_SHOWN_FROM_BOTTOM) > 0) { + shownFromBottom = true; + } + if ((flags & FLAG_USE_SWIPEBACK) > 0) { swipeBackLayout = new PopupSwipeBackLayout(context, resourcesProvider); addView(swipeBackLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); @@ -157,8 +171,10 @@ public class ActionBarPopupWindow extends PopupWindow { scrollView = new ScrollView(context); // scrollView.setVerticalScrollBarEnabled(verticalScrollBarEnabled); if (swipeBackLayout != null) { - swipeBackLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - } else addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + swipeBackLayout.addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, shownFromBottom ? Gravity.BOTTOM : Gravity.TOP)); + } else { + addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + } } catch (Throwable e) { FileLog.e(e); } @@ -207,12 +223,20 @@ public class ActionBarPopupWindow extends PopupWindow { } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child instanceof GapView) { + return false; + } + return super.drawChild(canvas, child, drawingTime); + } }; linearLayout.setOrientation(LinearLayout.VERTICAL); if (scrollView != null) { scrollView.addView(linearLayout, new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } else if (swipeBackLayout != null) { - swipeBackLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + swipeBackLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, shownFromBottom ? Gravity.BOTTOM : Gravity.TOP)); } else { addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); } @@ -224,7 +248,7 @@ public class ActionBarPopupWindow extends PopupWindow { } public int addViewToSwipeBack(View v) { - swipeBackLayout.addView(v, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + swipeBackLayout.addView(v, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, shownFromBottom ? Gravity.BOTTOM : Gravity.TOP)); return swipeBackLayout.getChildCount() - 1; } @@ -232,8 +256,8 @@ public class ActionBarPopupWindow extends PopupWindow { fitItems = value; } - public void setShownFromBotton(boolean value) { - shownFromBotton = value; + public void setShownFromBottom(boolean value) { + shownFromBottom = value; } public void setDispatchKeyEventListener(OnDispatchKeyEventListener listener) { @@ -262,8 +286,7 @@ public class ActionBarPopupWindow extends PopupWindow { @Keep public void setBackScaleX(float value) { - if (backScaleY != value) { - backScaleY = value; + if (backScaleX != value) { backScaleX = value; invalidate(); if (onSizeChangedListener != null) { @@ -272,13 +295,23 @@ public class ActionBarPopupWindow extends PopupWindow { } } + public void translateChildrenAfter(int index, float ty) { + subtractBackgroundHeight = (int) -ty; + for (int i = index + 1; i < linearLayout.getChildCount(); ++i) { + View child = linearLayout.getChildAt(i); + if (child != null) { + child.setTranslationY(ty); + } + } + } + @Keep public void setBackScaleY(float value) { if (backScaleY != value) { backScaleY = value; if (animationEnabled && updateAnimation) { int height = getMeasuredHeight() - AndroidUtilities.dp(16); - if (shownFromBotton) { + if (shownFromBottom) { for (int a = lastStartedChild; a >= 0; a--) { View child = getItemAt(a); if (child.getVisibility() != VISIBLE || child instanceof GapView) { @@ -332,7 +365,7 @@ public class ActionBarPopupWindow extends PopupWindow { AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether( ObjectAnimator.ofFloat(child, View.ALPHA, 0f, child.isEnabled() ? 1f : 0.5f), - ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, AndroidUtilities.dp(shownFromBotton ? 6 : -6), 0)); + ObjectAnimator.ofFloat(child, View.TRANSLATION_Y, AndroidUtilities.dp(shownFromBottom ? 6 : -6), 0)); animatorSet.setDuration(180); animatorSet.addListener(new AnimatorListenerAdapter() { @Override @@ -362,6 +395,16 @@ public class ActionBarPopupWindow extends PopupWindow { linearLayout.addView(child, layoutParams); } + public int getViewsCount() { + return linearLayout.getChildCount(); + } + + public int precalculateHeight() { + int MOST_SPEC = View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST); + linearLayout.measure(MOST_SPEC, MOST_SPEC); + return linearLayout.getMeasuredHeight(); + } + public void removeInnerViews() { linearLayout.removeAllViews(); } @@ -405,7 +448,7 @@ public class ActionBarPopupWindow extends PopupWindow { int end = gapEndY - scrollView.getScrollY(); boolean hasGap = false; for (int i = 0; i < linearLayout.getChildCount(); i++) { - if (linearLayout.getChildAt(i) instanceof GapView) { + if (linearLayout.getChildAt(i) instanceof GapView && linearLayout.getChildAt(i).getVisibility() == View.VISIBLE) { hasGap = true; break; } @@ -426,14 +469,14 @@ public class ActionBarPopupWindow extends PopupWindow { canvas.clipRect(0, bgPaddings.top, getMeasuredWidth(), getMeasuredHeight()); } backgroundDrawable.setAlpha(applyAlpha ? backAlpha : 255); - if (shownFromBotton) { + if (shownFromBottom) { final int height = getMeasuredHeight(); backgroundDrawable.setBounds(0, (int) (height * (1.0f - backScaleY)), (int) (getMeasuredWidth() * backScaleX), height); } else { if (start > -AndroidUtilities.dp(16)) { int h = (int) (getMeasuredHeight() * backScaleY); if (a == 0) { - backgroundDrawable.setBounds(0, -scrollView.getScrollY() + (gapStartY != -1000000 ? AndroidUtilities.dp(1) : 0), (int) (getMeasuredWidth() * backScaleX), (gapStartY != -1000000 ? Math.min(h, start + AndroidUtilities.dp(16)) : h)); + backgroundDrawable.setBounds(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) { @@ -441,34 +484,35 @@ public class ActionBarPopupWindow extends PopupWindow { } continue; } - backgroundDrawable.setBounds(0, end, (int) (getMeasuredWidth() * backScaleX), h); + backgroundDrawable.setBounds(0, end, (int) (getMeasuredWidth() * backScaleX), h - subtractBackgroundHeight); } } else { - backgroundDrawable.setBounds(0, gapStartY < 0 ? 0 : -AndroidUtilities.dp(16), (int) (getMeasuredWidth() * backScaleX), (int) (getMeasuredHeight() * backScaleY)); + backgroundDrawable.setBounds(0, (gapStartY < 0 ? 0 : -AndroidUtilities.dp(16)), (int) (getMeasuredWidth() * backScaleX), (int) (getMeasuredHeight() * backScaleY) - subtractBackgroundHeight); } } - backgroundDrawable.draw(canvas); + backgroundDrawable.draw(canvas); if (hasGap) { canvas.save(); AndroidUtilities.rectTmp2.set(backgroundDrawable.getBounds()); AndroidUtilities.rectTmp2.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8)); canvas.clipRect(AndroidUtilities.rectTmp2); for (int i = 0; i < linearLayout.getChildCount(); i++) { - if (linearLayout.getChildAt(i) instanceof GapView) { + if (linearLayout.getChildAt(i) instanceof GapView && linearLayout.getChildAt(i).getVisibility() == View.VISIBLE) { canvas.save(); float x = 0, y = 0; - View view = linearLayout.getChildAt(i) ; + GapView child = (GapView) linearLayout.getChildAt(i); + View view = child; while (view != this) { x += view.getX(); y += view.getY(); view = (View) view.getParent(); if (view == null) { - return; + break; } } - canvas.translate(x, y); - linearLayout.getChildAt(i).draw(canvas); + canvas.translate(x, y * scrollView.getScaleY()); + child.draw(canvas); canvas.restore(); } } @@ -560,6 +604,14 @@ public class ActionBarPopupWindow extends PopupWindow { public void setSwipeBackForegroundColor(int color) { getSwipeBack().setForegroundColor(color); } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (swipeBackLayout != null) { + swipeBackLayout.invalidateTransforms(!startAnimationPending); + } + } } public ActionBarPopupWindow() { @@ -697,10 +749,12 @@ public class ActionBarPopupWindow extends PopupWindow { ActionBarPopupWindowLayout content = null; if (viewGroup instanceof ActionBarPopupWindowLayout) { content = (ActionBarPopupWindowLayout) viewGroup; + content.startAnimationPending = true; } else { for (int i = 0; i < viewGroup.getChildCount(); i++) { if (viewGroup.getChildAt(i) instanceof ActionBarPopupWindowLayout) { content = (ActionBarPopupWindowLayout) viewGroup.getChildAt(i); + content.startAnimationPending = true; } } } @@ -726,19 +780,19 @@ public class ActionBarPopupWindow extends PopupWindow { content.positions.put(child, visibleCount); visibleCount++; } - if (content.shownFromBotton) { + if (content.shownFromBottom) { content.lastStartedChild = count - 1; } else { content.lastStartedChild = 0; } - float finalsScaleY = 1f; + float finalScaleY = 1f; if (content.getSwipeBack() != null) { content.getSwipeBack().invalidateTransforms(); - finalsScaleY = content.backScaleY; + finalScaleY = content.backScaleY; } windowAnimatorSet = new AnimatorSet(); windowAnimatorSet.playTogether( - ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, finalsScaleY), + ObjectAnimator.ofFloat(content, "backScaleY", 0.0f, finalScaleY), ObjectAnimator.ofInt(content, "backAlpha", 0, 255)); windowAnimatorSet.setDuration(150 + 16 * visibleCount); int finalCount = count; @@ -750,10 +804,12 @@ public class ActionBarPopupWindow extends PopupWindow { ActionBarPopupWindowLayout content = null; if (viewGroup instanceof ActionBarPopupWindowLayout) { content = (ActionBarPopupWindowLayout) viewGroup; + content.startAnimationPending = false; } else { for (int i = 0; i < viewGroup.getChildCount(); i++) { if (viewGroup.getChildAt(i) instanceof ActionBarPopupWindowLayout) { content = (ActionBarPopupWindowLayout) viewGroup.getChildAt(i); + content.startAnimationPending = false; } } } @@ -832,9 +888,15 @@ public class ActionBarPopupWindow extends PopupWindow { if (outEmptyTime > 0) { windowAnimatorSet.playTogether(ValueAnimator.ofFloat(0, 1f)); windowAnimatorSet.setDuration(outEmptyTime); + } else if (scaleOut) { + windowAnimatorSet.playTogether( + ObjectAnimator.ofFloat(viewGroup, View.SCALE_Y, 0.8f), + ObjectAnimator.ofFloat(viewGroup, View.SCALE_X, 0.8f), + ObjectAnimator.ofFloat(viewGroup, View.ALPHA, 0.0f)); + windowAnimatorSet.setDuration(dismissAnimationDuration); } else { windowAnimatorSet.playTogether( - ObjectAnimator.ofFloat(viewGroup, View.TRANSLATION_Y, AndroidUtilities.dp((content != null && content.shownFromBotton) ? 5 : -5)), + ObjectAnimator.ofFloat(viewGroup, View.TRANSLATION_Y, AndroidUtilities.dp((content != null && content.shownFromBottom) ? 5 : -5)), ObjectAnimator.ofFloat(viewGroup, View.ALPHA, 0.0f)); windowAnimatorSet.setDuration(dismissAnimationDuration); } @@ -880,26 +942,24 @@ public class ActionBarPopupWindow extends PopupWindow { public static class GapView extends FrameLayout { - Paint paint = new Paint(); + Theme.ResourcesProvider resourcesProvider; String colorKey; - int color = 0; - public GapView(Context context, String colorKey) { + + public GapView(Context context, Theme.ResourcesProvider resourcesProvider, String colorKey) { super(context); + this.resourcesProvider = resourcesProvider; this.colorKey = colorKey; + + setBackgroundColor(getThemedColor(colorKey)); } - @Override - protected void onDraw(Canvas canvas) { - if (color == 0) { - paint.setColor(Theme.getColor(colorKey)); - } else { - paint.setColor(color); - } - canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint); + private int getThemedColor(String key) { + Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; + return color != null ? color : Theme.getColor(key); } public void setColor(int color) { - this.color = color; + setBackgroundColor(color); } } } \ No newline at end of file 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 4f08716c6..50c01e342 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AdjustPanLayoutHelper.java @@ -5,15 +5,22 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; +import android.os.Build; +import android.os.SystemClock; import android.view.ContextThemeWrapper; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsAnimation; import android.view.animation.Interpolator; import android.widget.FrameLayout; +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.ChatListItemAnimator; import org.telegram.messenger.AndroidUtilities; @@ -22,9 +29,12 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import java.util.ArrayList; +import java.util.List; public class AdjustPanLayoutHelper { + public static boolean USE_ANDROID11_INSET_ANIMATOR = false; + public final static Interpolator keyboardInterpolator = ChatListItemAnimator.DEFAULT_INTERPOLATOR; public final static long keyboardDuration = 250; @@ -33,6 +43,7 @@ public class AdjustPanLayoutHelper { private ViewGroup contentView; private View resizableView; + private boolean usingInsetAnimator = false; private boolean animationInProgress; private boolean needDelay; private Runnable delayedAnimationRunnable = new Runnable() { @@ -44,6 +55,14 @@ public class AdjustPanLayoutHelper { } }; + public View getAdjustingParent() { + return parent; + } + + public View getAdjustingContentView() { + return contentView; + } + int previousHeight = -1; int previousContentHeight = -1; int previousStartOffset = -1; @@ -58,6 +77,11 @@ public class AdjustPanLayoutHelper { boolean checkHierarchyHeight; + float from, to; + boolean inverse; + boolean isKeyboardVisible; + long startAfter; + ViewTreeObserver.OnPreDrawListener onPreDrawListener = new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { @@ -71,6 +95,7 @@ public class AdjustPanLayoutHelper { previousHeight = contentHeight; previousContentHeight = contentView.getHeight(); previousStartOffset = startOffset(); + usingInsetAnimator = false; } return true; } @@ -79,11 +104,12 @@ public class AdjustPanLayoutHelper { previousHeight = contentHeight; previousContentHeight = contentView.getHeight(); previousStartOffset = startOffset(); + usingInsetAnimator = false; return true; } if (previousHeight != -1 && previousContentHeight == contentView.getHeight()) { - boolean isKeyboardVisible = contentHeight < contentView.getBottom(); + isKeyboardVisible = contentHeight < contentView.getBottom(); animateHeight(previousHeight, contentHeight, isKeyboardVisible); previousHeight = contentHeight; previousContentHeight = contentView.getHeight(); @@ -99,6 +125,43 @@ public class AdjustPanLayoutHelper { }; private void animateHeight(int previousHeight, int contentHeight, boolean isKeyboardVisible) { + if (ignoreOnce) { + ignoreOnce = false; + return; + } + if (!enabled) { + return; + } + startTransition(previousHeight, contentHeight, isKeyboardVisible); + animator.addUpdateListener(animation -> { + if (!usingInsetAnimator) { + updateTransition((float) animation.getAnimatedValue()); + } + }); + int selectedAccount = UserConfig.selectedAccount; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (!usingInsetAnimator) { + stopTransition(); + } + } + }); + animator.setDuration(keyboardDuration); + animator.setInterpolator(keyboardInterpolator); + + notificationsIndex = NotificationCenter.getInstance(selectedAccount).setAnimationInProgress(notificationsIndex, null); + if (needDelay) { + needDelay = false; + startAfter = SystemClock.elapsedRealtime() + 100; + AndroidUtilities.runOnUIThread(delayedAnimationRunnable, 100); + } else { + animator.start(); + startAfter = -1; + } + } + + public void startTransition(int previousHeight, int contentHeight, boolean isKeyboardVisible) { if (animator != null) { animator.cancel(); } @@ -118,59 +181,67 @@ public class AdjustPanLayoutHelper { onTransitionStart(isKeyboardVisible, contentHeight); float dy = contentHeight - previousHeight; - float from; - float to; keyboardSize = Math.abs(dy); + animationInProgress = true; if (contentHeight > previousHeight) { dy -= startOffset; parent.setTranslationY(-dy); onPanTranslationUpdate(dy, 1f, isKeyboardVisible); from = -dy; to = 0; - animator = ValueAnimator.ofFloat(1f, 0); + inverse = true; } else { parent.setTranslationY(previousStartOffset); onPanTranslationUpdate(-previousStartOffset, 0f, isKeyboardVisible); to = -previousStartOffset; from = dy; - animator = ValueAnimator.ofFloat(0, 1f); - } - animator.addUpdateListener(animation -> { - float v = (float) animation.getAnimatedValue(); - float y = (int) (from * v + to * (1f - v)); - parent.setTranslationY(y); - onPanTranslationUpdate(-y, v, isKeyboardVisible); - }); - animationInProgress = true; - int selectedAccount = UserConfig.selectedAccount; - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - animationInProgress = false; - NotificationCenter.getInstance(selectedAccount).onAnimationFinish(notificationsIndex); - animator = null; - setViewHeight(ViewGroup.LayoutParams.MATCH_PARENT); - viewsToHeightSet.clear(); - resizableView.requestLayout(); - onPanTranslationUpdate(0, isKeyboardVisible ? 1f : 0f, isKeyboardVisible); - parent.setTranslationY(0); - onTransitionEnd(); - } - }); - animator.setDuration(keyboardDuration); - animator.setInterpolator(keyboardInterpolator); - - notificationsIndex = NotificationCenter.getInstance(selectedAccount).setAnimationInProgress(notificationsIndex, null); - if (needDelay) { - needDelay = false; - AndroidUtilities.runOnUIThread(delayedAnimationRunnable, 100); - } else { - animator.start(); + inverse = false; } + animator = ValueAnimator.ofFloat(0, 1); + usingInsetAnimator = false; } - private void setViewHeight(int height) { + public void updateTransition(float t) { + if (inverse) { + t = 1f - t; + } + float y = (int) (from * t + to * (1f - t)); + parent.setTranslationY(y); + onPanTranslationUpdate(-y, t, isKeyboardVisible); + } + + public void stopTransition() { + if (animator != null) { + animator.cancel(); + } + animationInProgress = false; + usingInsetAnimator = false; + NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(notificationsIndex); + animator = null; + setViewHeight(ViewGroup.LayoutParams.MATCH_PARENT); + viewsToHeightSet.clear(); + resizableView.requestLayout(); + onPanTranslationUpdate(0, isKeyboardVisible ? 1f : 0f, isKeyboardVisible); + parent.setTranslationY(0); + onTransitionEnd(); + } + public void stopTransition(float t, boolean isKeyboardVisible) { + if (animator != null) { + animator.cancel(); + } + animationInProgress = false; + NotificationCenter.getInstance(UserConfig.selectedAccount).onAnimationFinish(notificationsIndex); + animator = null; + setViewHeight(ViewGroup.LayoutParams.MATCH_PARENT); + viewsToHeightSet.clear(); + resizableView.requestLayout(); + onPanTranslationUpdate(0, t, this.isKeyboardVisible = isKeyboardVisible); + parent.setTranslationY(0); + onTransitionEnd(); + } + + public void setViewHeight(int height) { for (int i = 0; i < viewsToHeightSet.size(); i++) { viewsToHeightSet.get(i).getLayoutParams().height = height; viewsToHeightSet.get(i).requestLayout(); @@ -181,7 +252,7 @@ public class AdjustPanLayoutHelper { return 0; } - private void getViewsToSetHeight(View parent) { + public void getViewsToSetHeight(View parent) { viewsToHeightSet.clear(); View v = parent; while (v != null) { @@ -202,6 +273,12 @@ public class AdjustPanLayoutHelper { onAttach(); } + public AdjustPanLayoutHelper(View parent, boolean useInsetsAnimator) { + USE_ANDROID11_INSET_ANIMATOR = USE_ANDROID11_INSET_ANIMATOR && useInsetsAnimator; + this.parent = parent; + onAttach(); + } + public void onAttach() { if (!SharedConfig.smoothKeyboard) { return; @@ -218,6 +295,9 @@ public class AdjustPanLayoutHelper { parentForListener = resizableView; resizableView.getViewTreeObserver().addOnPreDrawListener(onPreDrawListener); } + if (USE_ANDROID11_INSET_ANIMATOR && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + setupNewCallback(); + } } private Activity getActivity(Context context) { @@ -255,12 +335,35 @@ public class AdjustPanLayoutHelper { parentForListener.getViewTreeObserver().removeOnPreDrawListener(onPreDrawListener); parentForListener = null; } + if (parent != null && USE_ANDROID11_INSET_ANIMATOR && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + parent.setWindowInsetsAnimationCallback(null); + } + } + + private boolean enabled = true; + public void setEnabled(boolean value) { + this.enabled = value; + } + + private boolean ignoreOnce; + public void ignoreOnce() { + ignoreOnce = true; } protected boolean heightAnimationEnabled() { return true; } + public void OnPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { + onPanTranslationUpdate(y, progress, keyboardVisible); + } + public void OnTransitionStart(boolean keyboardVisible, int contentHeight) { + onTransitionStart(keyboardVisible, contentHeight); + } + public void OnTransitionEnd() { + onTransitionEnd(); + } + protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { } @@ -293,4 +396,44 @@ public class AdjustPanLayoutHelper { AndroidUtilities.cancelRunOnUIThread(delayedAnimationRunnable); delayedAnimationRunnable.run(); } + + @RequiresApi(api = Build.VERSION_CODES.R) + private void setupNewCallback() { + if (resizableView == null) { + return; + } + resizableView.setWindowInsetsAnimationCallback( + new WindowInsetsAnimation.Callback(WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) { + @NonNull + @Override + public WindowInsets onProgress(@NonNull WindowInsets insets, @NonNull List runningAnimations) { + if (!animationInProgress || AndroidUtilities.screenRefreshRate < 90) { + return insets; + } + + WindowInsetsAnimation imeAnimation = null; + for (WindowInsetsAnimation animation : runningAnimations) { + if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) { + imeAnimation = animation; + break; + } + } + + if (imeAnimation != null && SystemClock.elapsedRealtime() >= startAfter) { + usingInsetAnimator = true; + updateTransition((float) imeAnimation.getInterpolatedFraction()); + } + return insets; + } + + @Override + public void onEnd(@NonNull WindowInsetsAnimation animation) { + if (!animationInProgress || AndroidUtilities.screenRefreshRate < 90) { + return; + } + stopTransition(); + } + } + ); + } } 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 ac9b8b5fa..845ff549b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -723,10 +723,10 @@ public class AlertDialog extends Dialog implements Drawable.Callback { } if (totalWidth > availableWidth) { View negative = findViewWithTag(BUTTON_NEGATIVE); - View neuntral = findViewWithTag(BUTTON_NEUTRAL); - if (negative != null && neuntral != null) { - if (negative.getMeasuredWidth() < neuntral.getMeasuredWidth()) { - neuntral.measure(MeasureSpec.makeMeasureSpec(neuntral.getMeasuredWidth() - (totalWidth - availableWidth), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(neuntral.getMeasuredHeight(), MeasureSpec.EXACTLY)); + View neutral = findViewWithTag(BUTTON_NEUTRAL); + if (negative != null && neutral != null) { + if (negative.getMeasuredWidth() < neutral.getMeasuredWidth()) { + neutral.measure(MeasureSpec.makeMeasureSpec(neutral.getMeasuredWidth() - (totalWidth - availableWidth), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(neutral.getMeasuredHeight(), MeasureSpec.EXACTLY)); } else { negative.measure(MeasureSpec.makeMeasureSpec(negative.getMeasuredWidth() - (totalWidth - availableWidth), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(negative.getMeasuredHeight(), MeasureSpec.EXACTLY)); } @@ -841,7 +841,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback { textView.setEllipsize(TextUtils.TruncateAt.END); textView.setSingleLine(true); textView.setText(neutralButtonText.toString().toUpperCase()); - textView.setBackgroundDrawable(Theme.getRoundRectSelectorDrawable(getThemedColor(dialogButtonColorKey))); + textView.setBackground(Theme.getRoundRectSelectorDrawable(getThemedColor(dialogButtonColorKey))); textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); if (verticalButtons) { buttonsLayout.addView(textView, 1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT)); @@ -1210,6 +1210,10 @@ public class AlertDialog extends Dialog implements Drawable.Callback { return null; } + public ViewGroup getButtonsLayout() { + return buttonsLayout; + } + public static class Builder { private AlertDialog alertDialog; 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 68d0b4e91..b1dc93ceb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java @@ -237,13 +237,15 @@ public abstract class BaseFragment { } if (parentLayout != null && actionBar == null) { actionBar = createActionBar(parentLayout.getContext()); - actionBar.parentFragment = this; + if (actionBar != null) { + actionBar.parentFragment = this; + } } } } protected ActionBar createActionBar(Context context) { - ActionBar actionBar = new ActionBar(context); + ActionBar actionBar = new ActionBar(context, getResourceProvider()); actionBar.setBackgroundColor(getThemedColor(Theme.key_actionBarDefault)); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSelector), false); actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), true); @@ -322,6 +324,8 @@ public abstract class BaseFragment { } } + public void onUserLeaveHint() {} + @CallSuper public void onResume() { isPaused = false; @@ -396,7 +400,7 @@ public abstract class BaseFragment { return allowPresentFragment() && parentLayout != null && parentLayout.presentFragmentAsPreview(fragment); } - public boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, View menu) { + public boolean presentFragmentAsPreviewWithMenu(BaseFragment fragment, ActionBarPopupWindow.ActionBarPopupWindowLayout menu) { return allowPresentFragment() && parentLayout != null && parentLayout.presentFragmentAsPreviewWithMenu(fragment, menu); } 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 f02f41829..aa8afa63c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -38,6 +38,7 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.ImageView; @@ -74,6 +75,7 @@ public class BottomSheet extends Dialog { protected boolean keyboardVisible; private WindowInsets lastInsets; public boolean drawNavigationBar; + public boolean drawDoubleNavigationBar; public boolean scrollNavBar; protected boolean useSmoothKeyboard; @@ -95,6 +97,7 @@ public class BottomSheet extends Dialog { private View customView; private CharSequence title; private boolean bigTitle; + private boolean multipleLinesTitle; private int bottomInset; private int leftInset; private int rightInset; @@ -152,6 +155,8 @@ public class BottomSheet extends Dialog { protected AnimatorSet currentSheetAnimation; protected int currentSheetAnimationType; + protected ValueAnimator navigationBarAnimation; + protected float navigationBarAlpha = 0; protected View nestedScrollChild; private boolean disableScroll; @@ -162,6 +167,7 @@ public class BottomSheet extends Dialog { private OnDismissListener onHideListener; protected Theme.ResourcesProvider resourcesProvider; + protected boolean isPortrait; public void setDisableScroll(boolean b) { disableScroll = b; @@ -172,6 +178,7 @@ public class BottomSheet extends Dialog { private boolean openNoDelay; private float hideSystemVerticalInsetsProgress; + public boolean useBackgroundTopPadding = true; protected class ContainerView extends LinearLayout implements NestedScrollingParent { @@ -280,9 +287,18 @@ public class BottomSheet extends Dialog { allowCustomAnimation = allowOld; } else { currentAnimation = new AnimatorSet(); - currentAnimation.playTogether(ObjectAnimator.ofFloat(containerView, "translationY", 0)); - currentAnimation.setDuration((int) (150 * (Math.max(0, translationY) / AndroidUtilities.getPixelsInCM(0.8f, false)))); - currentAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); + ValueAnimator invalidateContainer = ValueAnimator.ofFloat(0, 1); + invalidateContainer.addUpdateListener(a -> { + if (container != null) { + container.invalidate(); + } + }); + currentAnimation.playTogether( + ObjectAnimator.ofFloat(containerView, "translationY", 0), + invalidateContainer + ); + currentAnimation.setDuration((int) (250 * (Math.max(0, translationY) / AndroidUtilities.getPixelsInCM(0.8f, false)))); + currentAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); currentAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -421,7 +437,7 @@ public class BottomSheet extends Dialog { if (lastInsets != null && Build.VERSION.SDK_INT >= 21) { width -= getRightInset() + getLeftInset(); } - boolean isPortrait = width < height; + isPortrait = width < height; if (containerView != null) { if (!fullWidth) { @@ -429,7 +445,7 @@ public class BottomSheet extends Dialog { if (AndroidUtilities.isTablet()) { widthSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f) + backgroundPaddingLeft * 2, MeasureSpec.EXACTLY); } else { - widthSpec = MeasureSpec.makeMeasureSpec(isPortrait ? width + backgroundPaddingLeft * 2 : (int) Math.max(width * 0.8f, Math.min(AndroidUtilities.dp(480), width)) + backgroundPaddingLeft * 2, MeasureSpec.EXACTLY); + widthSpec = MeasureSpec.makeMeasureSpec((getBottomSheetWidth(isPortrait, width, height)) + backgroundPaddingLeft * 2, MeasureSpec.EXACTLY); } containerView.measure(widthSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); } else { @@ -588,6 +604,9 @@ public class BottomSheet extends Dialog { } else { backgroundPaint.setColor(0xff000000); } + if (drawDoubleNavigationBar && !shouldOverlayCameraViewOverNavBar()) { + drawNavigationBar(canvas, 1f); + } if (backgroundPaint.getAlpha() < 255 && drawNavigationBar) { float translation = 0; if (scrollNavBar || Build.VERSION.SDK_INT >= 29 && getAdditionalMandatoryOffsets() > 0) { @@ -603,7 +622,7 @@ public class BottomSheet extends Dialog { super.dispatchDraw(canvas); } if (!shouldOverlayCameraViewOverNavBar()) { - drawNavigationBar(canvas); + drawNavigationBar(canvas, (drawDoubleNavigationBar ? 0.7f * navigationBarAlpha : 1f)); } if (drawNavigationBar && rightInset != 0 && rightInset > leftInset && fullWidth && AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { canvas.drawRect(containerView.getRight() - backgroundPaddingLeft, containerView.getTranslationY(), containerView.getRight() + rightInset, getMeasuredHeight(), backgroundPaint); @@ -623,7 +642,7 @@ public class BottomSheet extends Dialog { protected boolean drawChild(Canvas canvas, View child, long drawingTime) { if (child instanceof CameraView) { if (shouldOverlayCameraViewOverNavBar()) { - drawNavigationBar(canvas); + drawNavigationBar(canvas, 1f); } return super.drawChild(canvas, child, drawingTime); } @@ -655,7 +674,7 @@ public class BottomSheet extends Dialog { } } - public void drawNavigationBar(Canvas canvas) { + public void drawNavigationBar(Canvas canvas, float alpha) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (navBarColorKey != null) { backgroundPaint.setColor(getThemedColor(navBarColorKey)); @@ -667,21 +686,40 @@ public class BottomSheet extends Dialog { } if ((drawNavigationBar && bottomInset != 0) || currentPanTranslationY != 0) { float translation = 0; - if (scrollNavBar || Build.VERSION.SDK_INT >= 29 && getAdditionalMandatoryOffsets() > 0) { - float dist = containerView.getMeasuredHeight() - containerView.getTranslationY(); - translation = Math.max(0, getBottomInset() - dist); - } int navBarHeight = drawNavigationBar ? getBottomInset() : 0; + if (scrollNavBar || Build.VERSION.SDK_INT >= 29 && getAdditionalMandatoryOffsets() > 0) { + if (drawDoubleNavigationBar) { + translation = Math.max(0, Math.min(navBarHeight - currentPanTranslationY, containerView.getTranslationY())); + } else { + float dist = containerView.getMeasuredHeight() - containerView.getTranslationY(); + translation = Math.max(0, getBottomInset() - dist); + } + } + int wasAlpha = backgroundPaint.getAlpha(); + if (alpha < 1f) { + backgroundPaint.setAlpha((int) (wasAlpha * alpha)); + } canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - navBarHeight + translation - currentPanTranslationY, containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight() + translation, backgroundPaint); + backgroundPaint.setAlpha(wasAlpha); if (overlayDrawNavBarColor != 0) { backgroundPaint.setColor(overlayDrawNavBarColor); + wasAlpha = backgroundPaint.getAlpha(); + if (alpha < 1f) { + backgroundPaint.setAlpha((int) (wasAlpha * alpha)); + translation = 0; + } canvas.drawRect(containerView.getLeft() + backgroundPaddingLeft, getMeasuredHeight() - navBarHeight + translation - currentPanTranslationY, containerView.getRight() - backgroundPaddingLeft, getMeasuredHeight() + translation, backgroundPaint); + backgroundPaint.setAlpha(wasAlpha); } } } } + protected int getBottomSheetWidth(boolean isPortrait, int width,int height) { + return isPortrait ? width : (int) Math.max(width * 0.8f, Math.min(AndroidUtilities.dp(480), width)); + } + protected boolean shouldOverlayCameraViewOverNavBar() { return false; } @@ -785,7 +823,7 @@ public class BottomSheet extends Dialog { textView.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - textView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), getThemedColor(Theme.key_featuredStickers_addButton), getThemedColor(Theme.key_featuredStickers_addButtonPressed))); + textView.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 4)); addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16)); } } @@ -847,6 +885,16 @@ public class BottomSheet extends Dialog { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + public boolean isSelected = false; + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (isSelected) { + info.setSelected(true); + } + } } public void setAllowNestedScroll(boolean value) { @@ -892,6 +940,12 @@ public class BottomSheet extends Dialog { } return true; } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + mainContainerDispatchDraw(canvas); + } }; container.setBackgroundDrawable(backDrawable); focusable = needFocus; @@ -920,6 +974,22 @@ public class BottomSheet extends Dialog { backDrawable.setAlpha(0); } + protected void mainContainerDispatchDraw(Canvas canvas) { + + } + + public void fixNavigationBar() { + fixNavigationBar(getThemedColor(Theme.key_dialogBackground)); + } + + public void fixNavigationBar(int bgColor) { + drawNavigationBar = true; + drawDoubleNavigationBar = true; + scrollNavBar = true; + navBarColorKey = null; + setOverlayNavBarColor(navBarColor = bgColor); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -963,8 +1033,29 @@ public class BottomSheet extends Dialog { containerView.setVisibility(View.INVISIBLE); container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + int topOffset = 0; if (title != null) { - titleView = new TextView(getContext()); + titleView = new TextView(getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (multipleLinesTitle) { + int topOffset = getMeasuredHeight(); + if (customView != null) { + ((ViewGroup.MarginLayoutParams) customView.getLayoutParams()).topMargin = topOffset; + } else if (containerView != null) { + for (int i = 1; i < containerView.getChildCount(); ++i) { + View child = containerView.getChildAt(i); + if (child instanceof BottomSheetCell) { + ((ViewGroup.MarginLayoutParams) child.getLayoutParams()).topMargin = topOffset; + topOffset += AndroidUtilities.dp(48); + } + } + } + } + } + }; + int height = 48; titleView.setText(title); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); titleView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); @@ -975,34 +1066,52 @@ public class BottomSheet extends Dialog { titleView.setEllipsize(TextUtils.TruncateAt.MIDDLE); titleView.setTextColor(getThemedColor(Theme.key_dialogTextBlue2)); titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setPadding(AndroidUtilities.dp(21), AndroidUtilities.dp(multipleLinesTitle ? 14 : 6), AndroidUtilities.dp(21), AndroidUtilities.dp(8)); } else { titleView.setTextColor(getThemedColor(Theme.key_dialogTextGray2)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + titleView.setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(multipleLinesTitle ? 8 : 0), AndroidUtilities.dp(16), AndroidUtilities.dp(8)); + } + if (multipleLinesTitle) { + titleView.setSingleLine(false); + titleView.setMaxLines(5); + titleView.setEllipsize(TextUtils.TruncateAt.END); + } else { + titleView.setLines(1); + titleView.setSingleLine(true); + titleView.setEllipsize(TextUtils.TruncateAt.MIDDLE); } titleView.setGravity(Gravity.CENTER_VERTICAL); - containerView.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0)); + containerView.addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, multipleLinesTitle ? ViewGroup.LayoutParams.WRAP_CONTENT : height)); titleView.setOnTouchListener((v, event) -> true); + topOffset += height; } if (customView != null) { if (customView.getParent() != null) { ViewGroup viewGroup = (ViewGroup) customView.getParent(); viewGroup.removeView(customView); } - containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); + if (!useBackgroundTopPadding) { + containerView.setClipToPadding(false); + containerView.setClipChildren(false); + container.setClipToPadding(false); + container.setClipChildren(false); + containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, -backgroundPaddingTop + topOffset, 0, 0)); + } else { + containerView.addView(customView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, topOffset, 0, 0)); + } } else { if (items != null) { - FrameLayout rootView = new ScrollView(getContext()); - LinearLayout rowView = new LinearLayout(getContext()); - rowView.setOrientation(LinearLayout.VERTICAL); - rootView.addView(rowView, new ScrollView.LayoutParams(-1, -1)); - containerView.addView(rootView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); - + FrameLayout rowLayout = null; + int lastRowLayoutNum = 0; for (int a = 0; a < items.length; a++) { if (items[a] == null) { continue; } BottomSheetCell cell = new BottomSheetCell(getContext(), 0, resourcesProvider); cell.setTextAndIcon(items[a], itemIcons != null ? itemIcons[a] : 0, null, bigTitle); - rowView.addView(cell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 56, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); + containerView.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 0, topOffset, 0, 0)); + topOffset += 48; cell.setTag(a); cell.setOnClickListener(v -> dismissWithButtonClick((Integer) v.getTag())); itemViews.add(cell); @@ -1197,8 +1306,8 @@ public class BottomSheet extends Dialog { if (currentSheetAnimation != null) { currentSheetAnimation.cancel(); currentSheetAnimation = null; - currentSheetAnimationType = 0; } + currentSheetAnimationType = 0; } public void setOnHideListener(OnDismissListener listener) { @@ -1219,12 +1328,24 @@ public class BottomSheet extends Dialog { if (Build.VERSION.SDK_INT >= 20 && useHardwareLayer) { container.setLayerType(View.LAYER_TYPE_HARDWARE, null); } - containerView.setTranslationY(containerView.getMeasuredHeight() + (scrollNavBar ? getBottomInset() : 0)); + containerView.setTranslationY(getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)); currentSheetAnimationType = 1; + if (navigationBarAnimation != null) { + navigationBarAnimation.cancel(); + } + navigationBarAnimation = ValueAnimator.ofFloat(navigationBarAlpha, 1f); + navigationBarAnimation.addUpdateListener(a -> { + navigationBarAlpha = (float) a.getAnimatedValue(); + if (container != null) { + container.invalidate(); + } + }); currentSheetAnimation = new AnimatorSet(); currentSheetAnimation.playTogether( ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, 0), - ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, dimBehind ? dimBehindAlpha : 0)); + ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, dimBehind ? dimBehindAlpha : 0), + navigationBarAnimation + ); currentSheetAnimation.setDuration(400); currentSheetAnimation.setInterpolator(openInterpolator); currentSheetAnimation.addListener(new AnimatorListenerAdapter() { @@ -1333,7 +1454,7 @@ public class BottomSheet extends Dialog { currentSheetAnimationType = 2; currentSheetAnimation = new AnimatorSet(); currentSheetAnimation.playTogether( - ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, containerView.getMeasuredHeight() + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), + ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0) ); currentSheetAnimation.setDuration(180); @@ -1381,6 +1502,15 @@ public class BottomSheet extends Dialog { return super.dispatchTouchEvent(ev); } + public void onDismissAnimationStart() {} + + public int getContainerViewHeight() { + if (containerView == null) { + return 0; + } + return containerView.getMeasuredHeight(); + } + @Override public void dismiss() { if (delegate != null && !delegate.canDismiss()) { @@ -1395,22 +1525,34 @@ public class BottomSheet extends Dialog { } cancelSheetAnimation(); long duration = 0; + onDismissAnimationStart(); if (!allowCustomAnimation || !onCustomCloseAnimation()) { currentSheetAnimationType = 2; currentSheetAnimation = new AnimatorSet(); - currentSheetAnimation.playTogether( - ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, containerView.getMeasuredHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), - ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0) - ); - if (useFastDismiss) { - int height = containerView.getMeasuredHeight(); - duration = Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height)); - currentSheetAnimation.setDuration(duration); - useFastDismiss = false; - } else { - currentSheetAnimation.setDuration(duration = 250); + if (navigationBarAnimation != null) { + navigationBarAnimation.cancel(); } - currentSheetAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + navigationBarAnimation = ValueAnimator.ofFloat(navigationBarAlpha, 0f); + navigationBarAnimation.addUpdateListener(a -> { + navigationBarAlpha = (float) a.getAnimatedValue(); + if (container != null) { + container.invalidate(); + } + }); + currentSheetAnimation.playTogether( + ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), + ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0), + navigationBarAnimation + ); +// if (useFastDismiss) { +// int height = containerView.getMeasuredHeight(); +// duration = Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height)); +// currentSheetAnimation.setDuration(duration); +// useFastDismiss = false; +// } else { + currentSheetAnimation.setDuration(duration = 250); +// } + currentSheetAnimation.setInterpolator(CubicBezierInterpolator.EASE_OUT); currentSheetAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -1478,12 +1620,27 @@ public class BottomSheet extends Dialog { this(context, false); } + public Builder(Context context, int bgColor) { + this(context, false, null, bgColor); + } + public Builder(Context context, boolean needFocus) { this(context, needFocus, null); } + public Builder(Context context, boolean needFocus, int bgColor) { + this(context, needFocus, null, bgColor); + } + public Builder(Context context, boolean needFocus, Theme.ResourcesProvider resourcesProvider) { bottomSheet = new BottomSheet(context, needFocus, resourcesProvider); + bottomSheet.fixNavigationBar(); + } + + public Builder(Context context, boolean needFocus, Theme.ResourcesProvider resourcesProvider, int bgColor) { + bottomSheet = new BottomSheet(context, needFocus, resourcesProvider); + bottomSheet.setBackgroundColor(bgColor); + bottomSheet.fixNavigationBar(bgColor); } public Builder setItems(CharSequence[] items, final OnClickListener onClickListener) { @@ -1518,6 +1675,11 @@ public class BottomSheet extends Dialog { return this; } + public Builder setTitleMultipleLines(boolean allowMultipleLines) { + bottomSheet.multipleLinesTitle = allowMultipleLines; + return this; + } + public BottomSheet create() { return bottomSheet; } @@ -1575,13 +1737,6 @@ public class BottomSheet extends Dialog { bottomSheet.setOnHideListener(onDismissListener); return this; } - - public Builder fixNavigationBar() { - bottomSheet.drawNavigationBar = true; - bottomSheet.scrollNavBar = true; - bottomSheet.setOverlayNavBarColor(bottomSheet.getThemedColor(Theme.key_dialogBackground)); - return this; - } } public int getLeftInset() { 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 884710841..86c81decd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java @@ -15,7 +15,6 @@ import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; -import org.telegram.messenger.SharedConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ResultCallback; import org.telegram.tgnet.TLRPC; @@ -31,7 +30,7 @@ public class EmojiThemes { public boolean showAsDefaultStub; public String emoji; int currentIndex = 0; - ArrayList items = new ArrayList<>(); + public ArrayList items = new ArrayList<>(); private static final String[] previewColorKeys = new String[]{ Theme.key_chat_inBubble, @@ -364,14 +363,11 @@ public class EmojiThemes { } ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document); ImageReceiver imageReceiver = new ImageReceiver(); + String imageFilter; - if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { - int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; - } else { - imageFilter = (int) (1080 / AndroidUtilities.density) + "_" + (int) (1920 / AndroidUtilities.density) + "_f"; - } + int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; imageReceiver.setImage(imageLocation, imageFilter, null, ".jpg", wallPaper, 1); imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { @@ -424,13 +420,13 @@ public class EmojiThemes { } return; } - final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 120); + final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 140); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document); ImageReceiver imageReceiver = new ImageReceiver(); - imageReceiver.setImage(imageLocation, "120_80", null, null, null, 1); + imageReceiver.setImage(imageLocation, "120_140", null, null, null, 1); imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); - if (!set || holder == null) { + if (!set || holder == null || holder.bitmap.isRecycled()) { return; } Bitmap resultBitmap = holder.bitmap; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java index 0eeefd768..89f17abd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -27,7 +27,9 @@ import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; import android.text.TextUtils; +import android.util.Log; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; @@ -84,6 +86,8 @@ public class SimpleTextView extends View implements Drawable.Callback { private int textWidth; private int totalWidth; private int textHeight; + public int rightDrawableX; + public int rightDrawableY; private boolean wasLayout; private int minWidth; @@ -104,6 +108,11 @@ public class SimpleTextView extends View implements Drawable.Callback { private Stack spoilersPool = new Stack<>(); private Path path = new Path(); private boolean usaAlphaForEmoji; + private boolean canHideRightDrawable; + private boolean rightDrawableHidden; + private OnClickListener rightDrawableOnClickListener; + private boolean maybeClick; + private float touchDownX, touchDownY; public SimpleTextView(Context context) { super(context); @@ -244,6 +253,7 @@ public class SimpleTextView extends View implements Drawable.Callback { protected boolean createLayout(int width) { CharSequence text = this.text; replacingDrawableTextIndex = -1; + rightDrawableHidden = false; if (text != null) { text = Emoji.replaceEmoji(text, textPaint.getFontMetricsInt(), (int) textPaint.getTextSize(), false); try { @@ -251,9 +261,10 @@ public class SimpleTextView extends View implements Drawable.Callback { width -= leftDrawable.getIntrinsicWidth(); width -= drawablePadding; } + int rightDrawableWidth = 0; if (rightDrawable != null) { - int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale); - width -= dw; + rightDrawableWidth = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale); + width -= rightDrawableWidth; width -= drawablePadding; } if (replacedText != null && replacedDrawable != null) { @@ -267,6 +278,14 @@ public class SimpleTextView extends View implements Drawable.Callback { width -= drawablePadding; } } + if (canHideRightDrawable && rightDrawableWidth != 0) { + CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END); + if (!text.equals(string)) { + rightDrawableHidden = true; + width += rightDrawableWidth; + width += drawablePadding; + } + } if (buildFullLayout) { CharSequence string = TextUtils.ellipsize(text, textPaint, width, TextUtils.TruncateAt.END); if (!string.equals(text)) { @@ -621,7 +640,7 @@ public class SimpleTextView extends View implements Drawable.Callback { totalWidth += drawablePadding + replacedDrawable.getIntrinsicWidth(); } } - if (rightDrawable != null) { + if (rightDrawable != null && !rightDrawableHidden && rightDrawableScale > 0) { int x = textOffsetX + textWidth + drawablePadding + (int) -scrollingOffset; if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL) { x += offsetX; @@ -632,6 +651,8 @@ public class SimpleTextView extends View implements Drawable.Callback { int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale); int y = (textHeight - dh) / 2 + rightDrawableTopPadding; rightDrawable.setBounds(x, y, x + dw, y + dh); + rightDrawableX = x + (dw >> 1); + rightDrawableY = y + (dh >> 1); rightDrawable.draw(canvas); totalWidth += drawablePadding + dw; } @@ -832,4 +853,37 @@ public class SimpleTextView extends View implements Drawable.Callback { public int getTextColor() { return textPaint.getColor(); } + + public void setCanHideRightDrawable(boolean b) { + canHideRightDrawable = b; + } + + public void setRightDrawableOnClick(OnClickListener onClickListener) { + rightDrawableOnClickListener = onClickListener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (rightDrawableOnClickListener != null && rightDrawable != null) { + AndroidUtilities.rectTmp.set(rightDrawableX - AndroidUtilities.dp(16), rightDrawableY - AndroidUtilities.dp(16), rightDrawableX + AndroidUtilities.dp(16), rightDrawableY + AndroidUtilities.dp(16)); + if (event.getAction() == MotionEvent.ACTION_DOWN && AndroidUtilities.rectTmp.contains((int) event.getX(), (int) event.getY())) { + maybeClick = true; + touchDownX = event.getX(); + touchDownY = event.getY(); + getParent().requestDisallowInterceptTouchEvent(true); + } else if (event.getAction() == MotionEvent.ACTION_MOVE && maybeClick) { + if (Math.abs(event.getX() - touchDownX) >= AndroidUtilities.touchSlop || Math.abs(event.getY() - touchDownY) >= AndroidUtilities.touchSlop) { + maybeClick = false; + getParent().requestDisallowInterceptTouchEvent(false); + } + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + if (maybeClick && event.getAction() == MotionEvent.ACTION_UP) { + rightDrawableOnClickListener.onClick(this); + } + maybeClick = false; + getParent().requestDisallowInterceptTouchEvent(false); + } + } + return super.onTouchEvent(event) || maybeClick; + } } 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 c934fa3ec..c47d20437 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -8,6 +8,8 @@ package org.telegram.ui.ActionBar; +import static org.telegram.messenger.AndroidUtilities.dp; + import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; @@ -39,6 +41,7 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; +import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.NinePatchDrawable; import android.graphics.drawable.RippleDrawable; import android.graphics.drawable.ShapeDrawable; @@ -55,6 +58,7 @@ import android.os.SystemClock; import android.text.TextPaint; import android.text.TextUtils; import android.util.Base64; +import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; import android.util.SparseBooleanArray; @@ -77,12 +81,12 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.Bitmaps; import org.telegram.messenger.BuildVars; -import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -106,6 +110,7 @@ import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.MsgClockDrawable; import org.telegram.ui.Components.PathAnimator; import org.telegram.ui.Components.PlayingGameDrawable; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RecordStatusDrawable; import org.telegram.ui.Components.RoundStatusDrawable; @@ -133,6 +138,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Locale; import java.util.Map; +import java.util.Set; import java.util.concurrent.CountDownLatch; import tw.nekomimi.nekogram.NekoConfig; @@ -1004,7 +1010,7 @@ public class Theme { } TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; if (wallPaper.pattern) { - File patternPath = FileLoader.getPathToAttach(wallPaper.document, true); + File patternPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(wallPaper.document, true); Boolean exists = null; Bitmap patternBitmap = null; for (int a = 0, N = accents.size(); a < N; a++) { @@ -1136,8 +1142,10 @@ public class Theme { } if (patternBitmap == null) { + int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); if (svg) { - patternBitmap = SvgHelper.getBitmap(patternPath, AndroidUtilities.dp(360), AndroidUtilities.dp(640), false); + patternBitmap = SvgHelper.getBitmap(patternPath, w, h, false); } else { patternBitmap = loadScreenSizedBitmap(new FileInputStream(patternPath), 0); } @@ -1181,7 +1189,7 @@ public class Theme { Utilities.globalQueue.postRunnable(() -> { ArrayList createdAccents = null; TLRPC.TL_wallPaper wallPaper = loadingPattern.pattern; - File patternPath = FileLoader.getPathToAttach(wallPaper.document, true); + File patternPath = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(wallPaper.document, true); Bitmap patternBitmap = null; for (int a = 0, N = loadingPattern.accents.size(); a < N; a++) { ThemeAccent accent = loadingPattern.accents.get(a); @@ -1285,8 +1293,11 @@ public class Theme { boolean isDarkTheme = parentTheme.isDark(); if (accentColor != parentTheme.accentBaseColor || accentColor2 != 0) { - HashSet keys = new HashSet<>(currentColorsNoAccent.keySet()); - keys.addAll(defaultColors.keySet()); + Set currentKeySet = currentColorsNoAccent.keySet(); + Set defaultKeySet = defaultColors.keySet(); + HashSet keys = new HashSet<>(currentKeySet.size() + defaultKeySet.size()); + keys.addAll(currentKeySet); + keys.addAll(defaultKeySet); keys.removeAll(themeAccentExclusionKeys); for (String key : keys) { @@ -1546,9 +1557,11 @@ public class Theme { if (inBubble == null) { inBubble = getColor(key_chat_inBubble); } + + int gradientAverageColor = outBubble; if (info != null && info.emoticon != null && !isDarkTheme) { currentColors.remove(key_chat_selectedBackground); - int gradientAverageColor = averageColor(currentColors, key_chat_wallpaper_gradient_to1, key_chat_wallpaper_gradient_to2, key_chat_wallpaper_gradient_to3); + gradientAverageColor = averageColor(currentColors, key_chat_wallpaper_gradient_to1, key_chat_wallpaper_gradient_to2, key_chat_wallpaper_gradient_to3); if (gradientAverageColor == 0) { gradientAverageColor = averageColor(currentColors, key_chat_wallpaper); } @@ -1566,6 +1579,12 @@ public class Theme { currentColors.put(key_chat_inBubbleSelected, Theme.blendOver(inBubble, inOverlay)); } + if (!isDarkTheme) { + currentColors.put(key_chat_inTextSelectionHighlight, textSelectionBackground(false, inBubble, accentColor)); + currentColors.put(key_chat_outTextSelectionHighlight, textSelectionBackground(true, outBubble, accentColor)); + currentColors.put(key_chat_outTextSelectionCursor, textSelectionHandle(outBubble, accentColor)); + } + Integer inMsgLink = currentColors.get(key_chat_messageLinkIn); if (inMsgLink == null) { inMsgLink = getColor(key_chat_messageLinkIn); @@ -1577,10 +1596,30 @@ public class Theme { currentColors.put(key_chat_linkSelectBackground, linkSelectionBackground(inMsgLink, inBubble, isDarkTheme)); currentColors.put(key_chat_outLinkSelectBackground, linkSelectionBackground(outMsgLink, outBubble, isDarkTheme)); + Integer submenuBackground = currentColors.get(key_actionBarDefaultSubmenuBackground); + if (submenuBackground == null) { + submenuBackground = getColor(key_actionBarDefaultSubmenuBackground); + } + currentColors.put(key_actionBarDefaultSubmenuSeparator, Color.argb( + Color.alpha(submenuBackground), + Math.max(0, Color.red(submenuBackground) - 10), + Math.max(0, Color.green(submenuBackground) - 10), + Math.max(0, Color.blue(submenuBackground) - 10) + )); + return !isMyMessagesGradientColorsNear; } private float[] tempHSV = new float[3]; + private int setHue(int color, int hueFromColor) { + Color.colorToHSV(hueFromColor, tempHSV); + float hue = tempHSV[0]; + Color.colorToHSV(color, tempHSV); + if (tempHSV[1] > 0.02f) { + tempHSV[0] = hue; + } + return Color.HSVToColor(Color.alpha(color), tempHSV); + } private int bubbleSelectedOverlay(int bubble, int accentColor) { Color.colorToHSV(accentColor, tempHSV); float h = tempHSV[0]; @@ -1592,6 +1631,28 @@ public class Theme { tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - .05f)); return Color.HSVToColor(30, tempHSV); } + private int textSelectionBackground(boolean isOut, int bubble, int accentColor) { + Color.colorToHSV(accentColor, tempHSV); + float h = tempHSV[0]; + Color.colorToHSV(bubble, tempHSV); + if (tempHSV[1] <= 0 || tempHSV[0] > 45 && tempHSV[0] < 85) { + tempHSV[0] = h; + } + tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + (tempHSV[2] > .85f ? .25f : .45f))); + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - .15f)); + return Color.HSVToColor(80, tempHSV); + } + private int textSelectionHandle(int bubble, int accentColor) { + Color.colorToHSV(accentColor, tempHSV); + float h = tempHSV[0]; + Color.colorToHSV(bubble, tempHSV); + if (tempHSV[1] <= 0 || tempHSV[0] > 45 && tempHSV[0] < 85) { + tempHSV[0] = h; + } + tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] + .6f)); + tempHSV[2] = Math.max(0, Math.min(1, tempHSV[2] - (tempHSV[2] > .7f ? .25f : .125f))); + return Theme.blendOver(bubble, Color.HSVToColor(255, tempHSV)); + } private int linkSelectionBackground(int linkColor, int bgColor, boolean isDarkTheme) { Color.colorToHSV(ColorUtils.blendARGB(linkColor, bgColor, .25f), tempHSV); tempHSV[1] = Math.max(0, Math.min(1, tempHSV[1] - .1f)); @@ -1714,18 +1775,29 @@ public class Theme { } } - public static int blendOver(int y, int x) { + public static int blendOver(int A, int B) { // B over A // over operator: https://en.wikipedia.org/wiki/Alpha_compositing#Description - float ax = Color.alpha(x) / 255f, - ay = Color.alpha(y) / 255f, - az = (ax + ay * (1 - ax)); - if (az == 0f) + float aB = Color.alpha(B) / 255f, + aA = Color.alpha(A) / 255f, + aC = (aB + aA * (1 - aB)); + if (aC == 0f) return 0; return Color.argb( - (int) (az * 255), - (int) ((Color.red(x) * ax + Color.red(y) * ay * (1 - ax)) / az), - (int) ((Color.green(x) * ax + Color.green(y) * ay * (1 - ax)) / az), - (int) ((Color.blue(x) * ax + Color.blue(y) * ay * (1 - ax)) / az) + (int) (aC * 255), + (int) ((Color.red(B) * aB + Color.red(A) * aA * (1 - aB)) / aC), + (int) ((Color.green(B) * aB + Color.green(A) * aA * (1 - aB)) / aC), + (int) ((Color.blue(B) * aB + Color.blue(A) * aA * (1 - aB)) / aC) + ); + } + + public static int reverseBlendOver(float ax, int y, int z) { + float ay = Color.alpha(y) / 255f, + az = Color.alpha(z) / 255f; + return Color.argb( + (int) (ax * 255), + (int) ((Color.red(y) * ay * (1 - ax) - Color.red(z) * az) / ax), + (int) ((Color.green(y) * ay * (1 - ax) - Color.green(z) * az) / ax), + (int) ((Color.blue(y) * ay * (1 - ax) - Color.blue(z) * az) / ax) ); } @@ -2658,7 +2730,7 @@ public class Theme { } private static final Object sync = new Object(); - private static Runnable wallpaperLoadTask; + public static Runnable wallpaperLoadTask; public static final int ACTION_BAR_PHOTO_VIEWER_COLOR = 0x7f000000; public static final int ACTION_BAR_MEDIA_PICKER_COLOR = 0xff333333; @@ -2802,9 +2874,6 @@ public class Theme { public static Drawable dialogs_errorDrawable; public static Drawable dialogs_reorderDrawable; public static Drawable dialogs_lockDrawable; - public static Drawable dialogs_groupDrawable; - public static Drawable dialogs_broadcastDrawable; - public static Drawable dialogs_botDrawable; public static Drawable dialogs_muteDrawable; public static Drawable dialogs_verifiedDrawable; public static ScamDrawable dialogs_scamDrawable; @@ -2955,11 +3024,7 @@ public class Theme { public static Drawable chat_inlineResultAudio; public static Drawable chat_inlineResultLocation; public static Drawable chat_redLocationIcon; - public static Drawable chat_msgOutBroadcastDrawable; - public static Drawable chat_msgMediaBroadcastDrawable; public static Drawable chat_msgOutLocationDrawable; - public static Drawable chat_msgBroadcastDrawable; - public static Drawable chat_msgBroadcastMediaDrawable; public static Drawable chat_contextResult_shadowUnderSwitchDrawable; public static Drawable chat_shareIconDrawable; public static Drawable chat_replyIconDrawable; @@ -2991,7 +3056,6 @@ public class Theme { public static Drawable[] chat_locationDrawable = new Drawable[2]; public static Drawable[] chat_contactDrawable = new Drawable[2]; public static Drawable[][] chat_fileStatesDrawable = new Drawable[10][2]; - public static CombinedDrawable[][] chat_fileMiniStatesDrawable = new CombinedDrawable[6][2]; public static Drawable[][] chat_photoStatesDrawables = new Drawable[13][2]; public static Drawable calllog_msgCallUpRedDrawable; @@ -3195,6 +3259,7 @@ public class Theme { public static final String key_actionBarDefaultSubmenuItem = "actionBarDefaultSubmenuItem"; public static final String key_actionBarDefaultSubmenuItemIcon = "actionBarDefaultSubmenuItemIcon"; public static final String key_actionBarDefaultSubmenuBackground = "actionBarDefaultSubmenuBackground"; + public static final String key_actionBarDefaultSubmenuSeparator = "actionBarDefaultSubmenuSeparator"; public static final String key_actionBarTabActiveText = "actionBarTabActiveText"; public static final String key_actionBarTabUnactiveText = "actionBarTabUnactiveText"; public static final String key_actionBarTabLine = "actionBarTabLine"; @@ -3579,6 +3644,7 @@ public class Theme { public static final String key_chat_inTextSelectionHighlight = "chat_inTextSelectionHighlight"; public static final String key_chat_recordedVoiceHighlight = "key_chat_recordedVoiceHighlight"; public static final String key_chat_TextSelectionCursor = "chat_TextSelectionCursor"; + public static final String key_chat_outTextSelectionCursor = "chat_outTextSelectionCursor"; public static final String key_chat_BlurAlpha = "chat_BlurAlpha"; public static final String key_voipgroup_listSelector = "voipgroup_listSelector"; @@ -3810,6 +3876,22 @@ public class Theme { public static final String key_chat_inReactionButtonTextSelected = "chat_inReactionButtonTextSelected"; public static final String key_chat_outReactionButtonTextSelected = "chat_outReactionButtonTextSelected"; + public static final String key_premiumGradient1 = "premiumGradient1"; + public static final String key_premiumGradient2 = "premiumGradient2"; + public static final String key_premiumGradient3 = "premiumGradient3"; + public static final String key_premiumGradient4 = "premiumGradient4"; + public static final String key_premiumGradientBackground1 = "premiumGradientBackground1"; + public static final String key_premiumGradientBackground2 = "premiumGradientBackground2"; + public static final String key_premiumGradientBackground3 = "premiumGradientBackground3"; + public static final String key_premiumGradientBackground4 = "premiumGradientBackground4"; + public static final String key_premiumGradientBackgroundOverlay = "premiumGradientBackgroundOverlay"; + public static final String key_premiumStartSmallStarsColor = "premiumStartSmallStarsColor"; + public static final String key_premiumStartGradient1 = "premiumStarGradient1"; + public static final String key_premiumStartGradient2 = "premiumStarGradient2"; + public static final String key_premiumStartSmallStarsColor2 = "premiumStartSmallStarsColor2"; + public static final String key_premiumGradientBottomSheet1 = "premiumGradientBottomSheet1"; + public static final String key_premiumGradientBottomSheet2 = "premiumGradientBottomSheet2"; + public static final String key_premiumGradientBottomSheet3 = "premiumGradientBottomSheet3"; public static final String key_drawable_botInline = "drawableBotInline"; public static final String key_drawable_botLink = "drawableBotLink"; @@ -4066,6 +4148,7 @@ public class Theme { defaultColors.put(key_actionBarDefaultSubmenuItem, 0xff222222); defaultColors.put(key_actionBarDefaultSubmenuItemIcon, 0xff676b70); defaultColors.put(key_actionBarDefaultSubmenuBackground, 0xffffffff); + defaultColors.put(key_actionBarDefaultSubmenuSeparator, 0xfff5f5f5); defaultColors.put(key_actionBarActionModeDefaultSelector, 0xffe2e2e2); defaultColors.put(key_actionBarTabActiveText, 0xffffffff); defaultColors.put(key_actionBarTabUnactiveText, 0xffd5e8f7); @@ -4578,6 +4661,7 @@ public class Theme { defaultColors.put(key_chat_outTextSelectionHighlight, 0x2E3F9923); defaultColors.put(key_chat_inTextSelectionHighlight, 0x5062A9E3); defaultColors.put(key_chat_TextSelectionCursor, 0xFF419FE8); + defaultColors.put(key_chat_outTextSelectionCursor, 0xFF419FE8); defaultColors.put(key_chat_BlurAlpha, 0xFF000000); defaultColors.put(key_statisticChartSignature, 0x7f252529); @@ -4679,6 +4763,23 @@ public class Theme { defaultColors.put(key_chat_inReactionButtonTextSelected, 0xffffffff); defaultColors.put(key_chat_outReactionButtonTextSelected, 0xffffffff); + defaultColors.put(key_premiumGradient1, 0xff55A5FF); + defaultColors.put(key_premiumGradient2, 0xffA767FF); + defaultColors.put(key_premiumGradient3, 0xffDB5C9D); + defaultColors.put(key_premiumGradient4, 0xffF38926); + + defaultColors.put(key_premiumGradientBackground1, 0xff55A5FF); + defaultColors.put(key_premiumGradientBackground2, 0xffA767FF); + defaultColors.put(key_premiumGradientBackground3, 0xffDB5C9D); + defaultColors.put(key_premiumGradientBackground4, 0xffF38926); + defaultColors.put(key_premiumGradientBackgroundOverlay, Color.WHITE); + defaultColors.put(key_premiumStartGradient1, 0xffFFFFFF); + defaultColors.put(key_premiumStartGradient2, 0xffE3ECFA); + defaultColors.put(key_premiumStartSmallStarsColor, ColorUtils.setAlphaComponent(Color.WHITE, 90)); + defaultColors.put(key_premiumStartSmallStarsColor2, ColorUtils.setAlphaComponent(Color.WHITE, 90)); + defaultColors.put(key_premiumGradientBottomSheet1, 0xff5B9DE7); + defaultColors.put(key_premiumGradientBottomSheet2, 0xffAB87DD); + defaultColors.put(key_premiumGradientBottomSheet3, 0xffE794BE); fallbackKeys.put(key_chat_inAdminText, key_chat_inTimeText); fallbackKeys.put(key_chat_inAdminSelectedText, key_chat_inTimeSelectedText); @@ -4714,7 +4815,7 @@ public class Theme { fallbackKeys.put(key_switchTrackBlueChecked, key_switchTrackChecked); fallbackKeys.put(key_switchTrackBlueThumb, key_windowBackgroundWhite); fallbackKeys.put(key_switchTrackBlueThumbChecked, key_windowBackgroundWhite); - fallbackKeys.put(key_windowBackgroundCheckText, key_windowBackgroundWhiteBlackText); + fallbackKeys.put(key_windowBackgroundCheckText, key_windowBackgroundWhite); fallbackKeys.put(key_contextProgressInner4, key_contextProgressInner1); fallbackKeys.put(key_contextProgressOuter4, key_contextProgressOuter1); fallbackKeys.put(key_switchTrackBlueSelector, key_listSelector); @@ -4764,6 +4865,7 @@ public class Theme { fallbackKeys.put(key_profile_status, key_avatar_subtitleInProfileBlue); fallbackKeys.put(key_chats_menuTopBackgroundCats, key_avatar_backgroundActionBarBlue); fallbackKeys.put(key_chat_outLinkSelectBackground, key_chat_linkSelectBackground); + fallbackKeys.put(key_actionBarDefaultSubmenuSeparator, key_windowBackgroundGray); //fallbackKeys.put(key_chat_attachActiveTab, 0xff33a7f5); //fallbackKeys.put(key_chat_attachUnactiveTab, 0xff92999e); fallbackKeys.put(key_chat_attachPermissionImage, key_dialogTextBlack); @@ -4789,6 +4891,7 @@ public class Theme { fallbackKeys.put(key_chat_outTextSelectionHighlight, key_chat_textSelectBackground); fallbackKeys.put(key_chat_inTextSelectionHighlight, key_chat_textSelectBackground); fallbackKeys.put(key_chat_TextSelectionCursor, key_chat_messagePanelCursor); + fallbackKeys.put(key_chat_outTextSelectionCursor, key_chat_TextSelectionCursor); fallbackKeys.put(key_chat_inPollCorrectAnswer, key_chat_attachLocationBackground); fallbackKeys.put(key_chat_outPollCorrectAnswer, key_chat_attachLocationBackground); fallbackKeys.put(key_chat_inPollWrongAnswer, key_chat_attachAudioBackground); @@ -4904,6 +5007,10 @@ public class Theme { themeAccentExclusionKeys.add(key_voipgroup_mutedByAdminMuteButtonDisabled); themeAccentExclusionKeys.add(key_voipgroup_windowBackgroundWhiteInputField); themeAccentExclusionKeys.add(key_voipgroup_windowBackgroundWhiteInputFieldActivated); + themeAccentExclusionKeys.add(key_premiumGradient1); + themeAccentExclusionKeys.add(key_premiumGradient2); + themeAccentExclusionKeys.add(key_premiumGradient3); + themeAccentExclusionKeys.add(key_premiumGradient4); myMessagesBubblesColorKeys.add(key_chat_outBubble); myMessagesBubblesColorKeys.add(key_chat_outBubbleSelected); @@ -5427,36 +5534,6 @@ public class Theme { applyTheme(applyingTheme, false, false, switchToTheme == 2); AndroidUtilities.runOnUIThread(Theme::checkAutoNightThemeConditions); - preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config", Context.MODE_PRIVATE); - int count = preferences.getInt("count", 0); - ArrayList previewItems = new ArrayList<>(); - previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); - for (int i = 0; i < count; ++i) { - String value = preferences.getString("theme_" + i, ""); - SerializedData serializedData = new SerializedData(Utilities.hexToBytes(value)); - try { - TLRPC.TL_theme theme = TLRPC.Theme.TLdeserialize(serializedData, serializedData.readInt32(true), true); - EmojiThemes fullTheme = EmojiThemes.createPreviewFullTheme(theme); - if (fullTheme.items.size() >= 4) { - previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(fullTheme)); - } - - ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { - @Override - public void run() { - for (int i = 0; i < previewItems.size(); i++) { - previewItems.get(i).chatTheme.loadPreviewColors(0); - } - AndroidUtilities.runOnUIThread(() -> { - defaultEmojiThemes.clear(); - defaultEmojiThemes.addAll(previewItems); - }); - } - }); - } catch (Throwable e) { - FileLog.e(e); - } - } } private static void sortAccents(ThemeInfo info) { @@ -5949,23 +6026,6 @@ public class Theme { } } - public static Drawable getRoundRectSelectorWithBackgroundDrawable(int corners, int bgColor, int color) { - if (Build.VERSION.SDK_INT >= 21) { - Drawable maskDrawable = createRoundRectDrawable(corners, 0xffffffff); - ColorStateList colorStateList = new ColorStateList( - new int[][]{StateSet.WILD_CARD}, - new int[]{color} - ); - return new RippleDrawable(colorStateList, createRoundRectDrawable(corners, bgColor), maskDrawable); - } else { - StateListDrawable stateListDrawable = new StateListDrawable(); - stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, createRoundRectDrawable(corners, color)); - stateListDrawable.addState(new int[]{android.R.attr.state_selected}, createRoundRectDrawable(corners, color)); - stateListDrawable.addState(StateSet.WILD_CARD, new ColorDrawable(bgColor)); - return stateListDrawable; - } - } - public static Drawable createSelectorWithBackgroundDrawable(int backgroundColor, int color) { if (Build.VERSION.SDK_INT >= 21) { Drawable maskDrawable = new ColorDrawable(backgroundColor); @@ -6017,20 +6077,33 @@ public class Theme { } public static Drawable createSelectorDrawable(int color) { - return createSelectorDrawable(color, 1, -1); + return createSelectorDrawable(color, RIPPLE_MASK_CIRCLE_20DP, -1); } public static Drawable createSelectorDrawable(int color, int maskType) { return createSelectorDrawable(color, maskType, -1); } + public static final int RIPPLE_MASK_CIRCLE_20DP = 1; + public static final int RIPPLE_MASK_ALL = 2; + public static final int RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE = 3; + public static final int RIPPLE_MASK_CIRCLE_TO_BOUND_CORNER = 4; + public static final int RIPPLE_MASK_CIRCLE_AUTO = 5; + private static final int RIPPLE_MASK_ROUNDRECT_6DP = 7; + public static Drawable createSelectorDrawable(int color, int maskType, int radius) { - Drawable drawable; if (Build.VERSION.SDK_INT >= 21) { Drawable maskDrawable = null; - if ((maskType == 1 || maskType == 5) && Build.VERSION.SDK_INT >= 23) { + if ((maskType == RIPPLE_MASK_CIRCLE_20DP || maskType == 5) && Build.VERSION.SDK_INT >= 23) { maskDrawable = null; - } else if (maskType == 1 || maskType == 3 || maskType == 4 || maskType == 5 || maskType == 6 || maskType == 7) { + } else if ( + maskType == RIPPLE_MASK_CIRCLE_20DP || + maskType == RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE || + maskType == RIPPLE_MASK_CIRCLE_TO_BOUND_CORNER || + maskType == RIPPLE_MASK_CIRCLE_AUTO || + maskType == 6 || + maskType == RIPPLE_MASK_ROUNDRECT_6DP + ) { maskPaint.setColor(0xffffffff); maskDrawable = new Drawable() { @@ -6039,7 +6112,7 @@ public class Theme { @Override public void draw(Canvas canvas) { android.graphics.Rect bounds = getBounds(); - if (maskType == 7) { + if (maskType == RIPPLE_MASK_ROUNDRECT_6DP) { if (rect == null) { rect = new RectF(); } @@ -6047,11 +6120,13 @@ public class Theme { canvas.drawRoundRect(rect, AndroidUtilities.dp(6), AndroidUtilities.dp(6), maskPaint); } else { int rad; - if (maskType == 1 || maskType == 6) { + if (maskType == RIPPLE_MASK_CIRCLE_20DP || maskType == 6) { rad = AndroidUtilities.dp(20); - } else if (maskType == 3) { + } else if (maskType == RIPPLE_MASK_CIRCLE_TO_BOUND_EDGE) { rad = (Math.max(bounds.width(), bounds.height()) / 2); } else { + // RIPPLE_MASK_CIRCLE_AUTO = 5 + // RIPPLE_MASK_CIRCLE_TO_BOUND_CORNER = 4 rad = (int) Math.ceil(Math.sqrt((bounds.left - bounds.centerX()) * (bounds.left - bounds.centerX()) + (bounds.top - bounds.centerY()) * (bounds.top - bounds.centerY()))); } canvas.drawCircle(bounds.centerX(), bounds.centerY(), rad, maskPaint); @@ -6073,18 +6148,18 @@ public class Theme { return PixelFormat.UNKNOWN; } }; - } else if (maskType == 2) { + } else if (maskType == RIPPLE_MASK_ALL) { maskDrawable = new ColorDrawable(0xffffffff); } ColorStateList colorStateList = new ColorStateList( - new int[][]{StateSet.WILD_CARD}, - new int[]{color} + new int[][]{ StateSet.WILD_CARD }, + new int[]{ color } ); RippleDrawable rippleDrawable = new RippleDrawable(colorStateList, null, maskDrawable); if (Build.VERSION.SDK_INT >= 23) { - if (maskType == 1) { + if (maskType == RIPPLE_MASK_CIRCLE_20DP) { rippleDrawable.setRadius(radius <= 0 ? AndroidUtilities.dp(20) : radius); - } else if (maskType == 5) { + } else if (maskType == RIPPLE_MASK_CIRCLE_AUTO) { rippleDrawable.setRadius(RippleDrawable.RADIUS_AUTO); } } @@ -6137,6 +6212,304 @@ public class Theme { } } + /** + * AdaptiveRipple implements methods for creating ripple drawables + * Ripple color is based on background color, shifting saturation and value + * + * There are four public static methods: + * circle(String|int backgroundColor?, float radius?) + * - creates ripple drawable for circle buttons, draws only ripples + * radius (by default) can be RADIUS_TO_BOUNDS (-1): will be calculated to touch bounds edges + * radius can be RADIUS_OUT_BOUNDS (-2): will be calculated to touch bounds corners (fill entire bounds) + * otherwise radius is described in dp + * filledCircle(String|Drawable|int background?, String|int backgroundColor?, float radius?) + * - creates ripple drawable for circle buttons, draws ripples and background + * (!) it's not recommended to use only drawable background, as it would be impossible to get background color + * (there would be an attempt to cast drawable to ColorDrawable to retrieve a color) + * rect(String|int backgroundColor?, ...float radii?) + * - creates ripple drawable for rectangular buttons, draws only ripples + * radii array is allowed to have 0, 1, 2, 3, 4, 8 elements: + * 0 - no rounding + * 1 - all roundings + * 2 - top, bottom roundings + * 3 - top-left, top-right, bottom roundings + * 4 - top-left, top-right, bottom-right, bottom-left roundings + * 8 - top-left-x, top-left-y, top-right-x, top-right-y, + * bottom-right-x, bottom-right-y, bottom-left-x, bottom-left-y roundings + * in case it has more, would be downgraded to nearest (ex.: 5 -> 4, 10 -> 8) + * filledRect(String|Drawable|int background?, String|int backgroundColor?, ...float radii?) + * - creates ripple drawable for rectangular buttons, draws ripples and background + * + * by default, backgroundColor is getColor(Theme.key_windowBackgroundWhite) + */ + public static class AdaptiveRipple { + + public static final float RADIUS_TO_BOUNDS = -1; + public static final float RADIUS_OUT_BOUNDS = -2; + + private static final String defaultBackgroundColorKey = Theme.key_windowBackgroundWhite; + + public static Drawable circle() { + return circle(Theme.getColor(defaultBackgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable circle(String backgroundColorKey) { + return circle(Theme.getColor(backgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable circle(String backgroundColorKey, float radius) { + return circle(Theme.getColor(backgroundColorKey), radius); + } + public static Drawable circle(int backgroundColor) { + return circle(backgroundColor, RADIUS_TO_BOUNDS); + } + public static Drawable circle(int backgroundColor, float radius) { + return createCircle(calcRippleColor(backgroundColor), radius); + } + + public static Drawable filledCircle() { + return filledCircle(null, Theme.getColor(defaultBackgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable filledCircle(Drawable background) { + return filledCircle(background, Theme.getColor(defaultBackgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable filledCircle(String backgroundColorKey) { + return filledCircle(null, Theme.getColor(backgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable filledCircle(Drawable background, String backgroundColorKey) { + return filledCircle(background, Theme.getColor(backgroundColorKey), RADIUS_TO_BOUNDS); + } + public static Drawable filledCircle(String backgroundColorKey, float radius) { + return filledCircle(null, Theme.getColor(backgroundColorKey), radius); + } + public static Drawable filledCircle(Drawable background, String backgroundColorKey, float radius) { + return filledCircle(background, Theme.getColor(backgroundColorKey), radius); + } + public static Drawable filledCircle(int backgroundColor) { + return filledCircle(null, backgroundColor, RADIUS_TO_BOUNDS); + } + public static Drawable filledCircle(int backgroundColor, float radius) { + return filledCircle(null, backgroundColor, radius); + } + public static Drawable filledCircle(Drawable background, int backgroundColor, float radius) { + return createCircle(background, calcRippleColor(backgroundColor), radius); + } + + public static Drawable rect() { + return rect(Theme.getColor(defaultBackgroundColorKey)); + } + public static Drawable rect(String backgroundColorKey) { + return rect(Theme.getColor(backgroundColorKey)); + } + public static Drawable rect(String backgroundColorKey, float ...radii) { + return rect(Theme.getColor(backgroundColorKey), radii); + } + public static Drawable rect(int backgroundColor) { + return rect(backgroundColor, 0); + } + public static Drawable rect(int backgroundColor, float ...radii) { + return createRect(0, calcRippleColor(backgroundColor), radii); + } + + public static Drawable filledRect() { + return filledRect(Theme.getColor(defaultBackgroundColorKey), 0); + } + public static Drawable filledRect(Drawable background) { + int backgroundColor = background instanceof ColorDrawable ? ((ColorDrawable) background).getColor() : Theme.getColor(defaultBackgroundColorKey); + return filledRect(background, backgroundColor, 0); + } + public static Drawable filledRect(String backgroundColorKey) { + return filledRect(Theme.getColor(backgroundColorKey)); + } + public static Drawable filledRect(Drawable background, String backgroundColorKey) { + return filledRect(background, Theme.getColor(backgroundColorKey)); + } + public static Drawable filledRect(String backgroundColorKey, float ...radii) { + return filledRect(Theme.getColor(backgroundColorKey), radii); + } + public static Drawable filledRect(Drawable background, String backgroundColorKey, float ...radii) { + return filledRect(background, Theme.getColor(backgroundColorKey), radii); + } + public static Drawable filledRect(int backgroundColor) { + return createRect(backgroundColor, calcRippleColor(backgroundColor)); + } + public static Drawable filledRect(int backgroundColor, float ...radii) { + return createRect(backgroundColor, calcRippleColor(backgroundColor), radii); + } + public static Drawable filledRect(Drawable background, int backgroundColor, float ...radii) { + return createRect(background, calcRippleColor(backgroundColor), radii); + } + + private static Drawable createRect(int rippleColor, float ...radii) { + return createRect(0, rippleColor, radii); + } + private static Drawable createRect(int backgroundColor, int rippleColor, float ...radii) { + Drawable background = null; + if (backgroundColor != 0) { + if (hasNonzeroRadii(radii)) { + background = new ShapeDrawable(new RoundRectShape(calcRadii(radii), null, null)); + ((ShapeDrawable) background).getPaint().setColor(backgroundColor); + } else { + background = new ColorDrawable(backgroundColor); + } + } + return createRect( + background, + rippleColor, + radii + ); + } + private static Drawable createRect(Drawable background, int rippleColor, float ...radii) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + Drawable maskDrawable = null; + if (hasNonzeroRadii(radii)) { + maskDrawable = new ShapeDrawable(new RoundRectShape(calcRadii(radii), null, null)); + ((ShapeDrawable) maskDrawable).getPaint().setColor(0xffffffff); + } + return new RippleDrawable( + new ColorStateList( + new int[][]{ StateSet.WILD_CARD }, + new int[]{ rippleColor } + ), + background, + maskDrawable + ); + } else { + StateListDrawable stateListDrawable = new StateListDrawable(); + Drawable ripple; + if (hasNonzeroRadii(radii)) { + ripple = new ShapeDrawable(new RoundRectShape(calcRadii(radii), null, null)); + ((ShapeDrawable) ripple).getPaint().setColor(rippleColor); + } else { + ripple = new ColorDrawable(rippleColor); + } + Drawable pressed = new LayerDrawable(new Drawable[] { background, ripple }); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressed); + stateListDrawable.addState(new int[]{android.R.attr.state_selected}, pressed); + stateListDrawable.addState(StateSet.WILD_CARD, background); + return stateListDrawable; + } + } + + private static Drawable createCircle(int rippleColor) { + return createCircle(0, rippleColor, RADIUS_TO_BOUNDS); + } + private static Drawable createCircle(int rippleColor, float radius) { + return createCircle(0, rippleColor, radius); + } + private static Drawable createCircle(int backgroundColor, int rippleColor, float radius) { + return createCircle( + backgroundColor == 0 ? null : new CircleDrawable(radius, backgroundColor), + rippleColor, + radius + ); + } + private static Drawable createCircle(Drawable background, int rippleColor, float radius) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return new RippleDrawable( + new ColorStateList( + new int[][]{ StateSet.WILD_CARD }, + new int[]{ rippleColor } + ), + background, + new CircleDrawable(radius) + ); + } else { + StateListDrawable stateListDrawable = new StateListDrawable(); + Drawable ripple = new CircleDrawable(radius, rippleColor); + Drawable pressed = new LayerDrawable(new Drawable[] { background, ripple }); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, pressed); + stateListDrawable.addState(new int[]{android.R.attr.state_selected}, pressed); + stateListDrawable.addState(StateSet.WILD_CARD, background); + return stateListDrawable; + } + } + + private static class CircleDrawable extends Drawable { + + private static Paint maskPaint; + private Paint paint; + private float radius; + + public CircleDrawable(float radius) { + this.radius = radius; + if (this.maskPaint == null) { + this.maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + this.maskPaint.setColor(0xffffffff); + } + this.paint = this.maskPaint; + } + + public CircleDrawable(float radius, int paintColor) { + this.radius = radius; + this.paint = new Paint(Paint.ANTI_ALIAS_FLAG); + this.paint.setColor(paintColor); + } + + @Override + public void draw(@NonNull Canvas canvas) { + android.graphics.Rect bounds = getBounds(); + float rad; + if (Math.abs(radius - RADIUS_TO_BOUNDS) < 0.01f) { + rad = Math.max(bounds.width(), bounds.height()) / 2; + } else if (Math.abs(radius - RADIUS_OUT_BOUNDS) < 0.01f) { + rad = (int) Math.ceil(Math.sqrt((bounds.left - bounds.centerX()) * (bounds.left - bounds.centerX()) + (bounds.top - bounds.centerY()) * (bounds.top - bounds.centerY()))); + } else { + rad = AndroidUtilities.dp(radius); + } + canvas.drawCircle(bounds.centerX(), bounds.centerY(), rad, paint); + } + + @Override + public void setAlpha(int i) {} + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) {} + @Deprecated @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + } + + private static float[] calcRadii(float ...radii) { + if (radii.length == 0) { + return new float[] { 0, 0, 0, 0, 0, 0, 0, 0 }; + } else if (radii.length == 1) { + return new float[] { dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]) }; + } else if (radii.length == 2) { + return new float[] { dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[0]), dp(radii[1]), dp(radii[1]), dp(radii[1]), dp(radii[1]) }; + } else if (radii.length == 3) { + return new float[] { dp(radii[0]), dp(radii[0]), dp(radii[1]), dp(radii[1]), dp(radii[2]), dp(radii[2]), dp(radii[2]), dp(radii[2]) }; + } else if (radii.length < 8) { + return new float[] { dp(radii[0]), dp(radii[0]), dp(radii[1]), dp(radii[1]), dp(radii[2]), dp(radii[2]), dp(radii[3]), dp(radii[3]) }; + } else { + return new float[] { dp(radii[0]), dp(radii[1]), dp(radii[2]), dp(radii[3]), dp(radii[4]), dp(radii[5]), dp(radii[6]), dp(radii[7]) }; + } + } + private static boolean hasNonzeroRadii(float ...radii) { + for (int i = 0; i < Math.min(8, radii.length); ++i) { + if (radii[i] > 0) { + return true; + } + } + return false; + } + + private static float[] tempHSV; + private static int calcRippleColor(int backgroundColor) { + if (tempHSV == null) { + tempHSV = new float[3]; + } + Color.colorToHSV(backgroundColor, tempHSV); + if (tempHSV[1] > 0.01f) { + // when saturation is too low, hue is ignored + // so changing saturation at that point would reveal ignored hue (usually red, hue=0) + tempHSV[1] = Math.min(1, Math.max(0, tempHSV[1] + (isCurrentThemeDark() ? -.25f : .25f))); + tempHSV[2] = Math.min(1, Math.max(0, tempHSV[2] + (isCurrentThemeDark() ? .05f : -.05f))); + } else { + tempHSV[2] = Math.min(1, Math.max(0, tempHSV[2] + (isCurrentThemeDark() ? .1f : -.1f))); + } + return Color.HSVToColor(127, tempHSV); + } + } + public static class RippleRadMaskDrawable extends Drawable { private Path path = new Path(); private float[] radii = new float[8]; @@ -6480,7 +6853,7 @@ public class Theme { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.putString("theme", themeInfo.getKey()); - editor.commit(); + editor.apply(); } String[] wallpaperLink = new String[1]; if (themeInfo.assetName != null) { @@ -6565,7 +6938,7 @@ public class Theme { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); SharedPreferences.Editor editor = preferences.edit(); editor.remove("theme"); - editor.commit(); + editor.apply(); } currentColorsNoAccent.clear(); themedWallpaperFileOffset = 0; @@ -6692,11 +7065,19 @@ public class Theme { return changeColorAccent(currentTheme, accent != null ? accent.accentColor : 0, color); } + private static float abs(float a) { + return a > 0 ? a : -a; + } + + private static float[] tmpHSV5; public static int changeColorAccent(float[] baseHsv, float[] accentHsv, int color, boolean isDarkTheme) { - float[] colorHsv = getTempHsv(5); + if (tmpHSV5 == null) { + tmpHSV5 = new float[3]; + } + float[] colorHsv = tmpHSV5; Color.colorToHSV(color, colorHsv); - final float diffH = Math.min(Math.abs(colorHsv[0] - baseHsv[0]), Math.abs(colorHsv[0] - baseHsv[0] - 360f)); + final float diffH = Math.min(abs(colorHsv[0] - baseHsv[0]), abs(colorHsv[0] - baseHsv[0] - 360f)); if (diffH > 30f) { return color; } @@ -7440,7 +7821,12 @@ public class Theme { loadingRemoteThemes.put(currentAccount, true); TLRPC.TL_account_getThemes req = new TLRPC.TL_account_getThemes(); req.format = "android"; - req.hash = remoteThemesHash.get(currentAccount); + if (!MediaDataController.getInstance(currentAccount).defaultEmojiThemes.isEmpty()) { + req.hash = remoteThemesHash.get(currentAccount); + } + if (BuildVars.LOGS_ENABLED) { + Log.i("theme", "loading remote themes, hash " + req.hash); + } ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { loadingRemoteThemes.put(currentAccount, false); if (response instanceof TLRPC.TL_account_themes) { @@ -7568,7 +7954,7 @@ public class Theme { if (loadPatterns) { PatternsLoader.createLoader(true); } - generateEmojiPreviewThemes(emojiPreviewThemes, currentAccount); + MediaDataController.getInstance(currentAccount).generateEmojiPreviewThemes(emojiPreviewThemes, currentAccount); } else if (response instanceof TLRPC.TL_account_themesNotModified) { if (defaultEmojiThemes.isEmpty() && !tryToFixMissingEmojiThemes) { // Fix Missing Emoji Themes in v8.3.0-preview01? @@ -7580,48 +7966,6 @@ public class Theme { })); } - private static void generateEmojiPreviewThemes(final ArrayList emojiPreviewThemes, int currentAccount) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("emojithemes_config", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt("count", emojiPreviewThemes.size()); - for (int i = 0; i < emojiPreviewThemes.size(); ++i) { - TLRPC.TL_theme tlChatTheme = emojiPreviewThemes.get(i); - SerializedData data = new SerializedData(tlChatTheme.getObjectSize()); - tlChatTheme.serializeToStream(data); - editor.putString("theme_" + i, Utilities.bytesToHex(data.toByteArray())); - } - editor.apply(); - - if (!emojiPreviewThemes.isEmpty()) { - final ArrayList previewItems = new ArrayList<>(); - previewItems.add(new ChatThemeBottomSheet.ChatThemeItem(EmojiThemes.createHomePreviewTheme())); - for (int i = 0; i < emojiPreviewThemes.size(); i++) { - TLRPC.TL_theme theme = emojiPreviewThemes.get(i); - EmojiThemes chatTheme = EmojiThemes.createPreviewFullTheme(theme); - ChatThemeBottomSheet.ChatThemeItem item = new ChatThemeBottomSheet.ChatThemeItem(chatTheme); - if (chatTheme.items.size() >= 4) { - previewItems.add(item); - } - } - ChatThemeController.chatThemeQueue.postRunnable(new Runnable() { - @Override - public void run() { - for (int i = 0; i < previewItems.size(); i++) { - previewItems.get(i).chatTheme.loadPreviewColors(currentAccount); - } - AndroidUtilities.runOnUIThread(() -> { - defaultEmojiThemes.clear(); - defaultEmojiThemes.addAll(previewItems); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiPreviewThemesChanged); - }); - } - }); - } else { - defaultEmojiThemes.clear(); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.emojiPreviewThemesChanged); - } - } - public static String getBaseThemeKey(TLRPC.ThemeSettings settings) { if (settings.base_theme instanceof TLRPC.TL_baseThemeClassic) { return "Blue"; @@ -7894,7 +8238,8 @@ public class Theme { options.inJustDecodeBounds = true; BitmapFactory.decodeFile(wallpaperPath, options); if (options.outWidth > 0 && options.outHeight > 0) { - float scale = Math.min(options.outWidth / 560.0f, options.outHeight / 560.0f); + float side = 560.0f; + float scale = Math.min(options.outWidth / side, options.outHeight / side); options.inSampleSize = 1; if (scale > 1.0f) { do { @@ -7912,7 +8257,7 @@ public class Theme { } else { Paint bitmapPaint = new Paint(); bitmapPaint.setFilterBitmap(true); - scale = Math.min(wallpaper.getWidth() / 560.0f, wallpaper.getHeight() / 560.0f); + scale = Math.min(wallpaper.getWidth() / side, wallpaper.getHeight() / side); rect.set(0, 0, wallpaper.getWidth() / scale, wallpaper.getHeight() / scale); rect.offset((bitmap.getWidth() - rect.width()) / 2, (bitmap.getHeight() - rect.height()) / 2); canvas.drawBitmap(wallpaper, null, rect, bitmapPaint); @@ -8078,7 +8423,7 @@ public class Theme { public static HashMap getThemeFileValues(File file, String assetName, String[] wallpaperLink) { FileInputStream stream = null; - HashMap stringMap = new HashMap<>(); + HashMap stringMap = new HashMap<>(500); try { byte[] bytes = new byte[1024]; int currentPosition = 0; @@ -8175,15 +8520,15 @@ public class Theme { avatarDrawables[0] = resources.getDrawable(R.drawable.baseline_bookmark_24); avatarDrawables[1] = resources.getDrawable(R.drawable.ghost); - avatarDrawables[2] = resources.getDrawable(R.drawable.folders_private); - avatarDrawables[3] = resources.getDrawable(R.drawable.folders_requests); - avatarDrawables[4] = resources.getDrawable(R.drawable.folders_group); - avatarDrawables[5] = resources.getDrawable(R.drawable.folders_channel); - avatarDrawables[6] = resources.getDrawable(R.drawable.folders_bot); - avatarDrawables[7] = resources.getDrawable(R.drawable.folders_mute); - avatarDrawables[8] = resources.getDrawable(R.drawable.folders_read); - avatarDrawables[9] = resources.getDrawable(R.drawable.folders_archive); - avatarDrawables[10] = resources.getDrawable(R.drawable.folders_private); + avatarDrawables[2] = resources.getDrawable(R.drawable.msg_folders_private); + avatarDrawables[3] = resources.getDrawable(R.drawable.msg_folders_requests); + avatarDrawables[4] = resources.getDrawable(R.drawable.msg_folders_groups); + avatarDrawables[5] = resources.getDrawable(R.drawable.msg_folders_channels); + avatarDrawables[6] = resources.getDrawable(R.drawable.msg_folders_bots); + avatarDrawables[7] = resources.getDrawable(R.drawable.msg_folders_muted); + avatarDrawables[8] = resources.getDrawable(R.drawable.msg_folders_read); + avatarDrawables[9] = resources.getDrawable(R.drawable.msg_folders_archive); + avatarDrawables[10] = resources.getDrawable(R.drawable.msg_folders_private); avatarDrawables[11] = resources.getDrawable(R.drawable.chats_replies); @@ -8278,6 +8623,8 @@ public class Theme { dialogs_unarchiveDrawable.setLayerColor("Box2.**", getNonAnimatedColor(key_chats_archiveIcon)); dialogs_unarchiveDrawable.setLayerColor("Box1.**", getNonAnimatedColor(key_chats_archiveIcon)); dialogs_unarchiveDrawable.commitApplyLayerColors(); + + PremiumGradient.getInstance().checkIconColors(); } public static void createCommonDialogResources(Context context) { @@ -8338,8 +8685,6 @@ public class Theme { dialogs_clockDrawable = new MsgClockDrawable(); dialogs_errorDrawable = resources.getDrawable(R.drawable.list_warning_sign); dialogs_reorderDrawable = resources.getDrawable(R.drawable.list_reorder).mutate(); - dialogs_groupDrawable = resources.getDrawable(R.drawable.list_group); - dialogs_broadcastDrawable = resources.getDrawable(R.drawable.list_broadcast); dialogs_muteDrawable = resources.getDrawable(R.drawable.list_mute).mutate(); dialogs_verifiedDrawable = resources.getDrawable(R.drawable.verified_area).mutate(); dialogs_scamDrawable = new ScamDrawable(11, 0); @@ -8347,9 +8692,8 @@ public class Theme { dialogs_verifiedCheckDrawable = resources.getDrawable(R.drawable.verified_check).mutate(); dialogs_mentionDrawable = resources.getDrawable(R.drawable.mentionchatslist); dialogs_reactionsMentionDrawable = resources.getDrawable(R.drawable.reactionchatslist); - dialogs_botDrawable = resources.getDrawable(R.drawable.list_bot); dialogs_pinnedDrawable = resources.getDrawable(R.drawable.list_pin); - moveUpDrawable = resources.getDrawable(R.drawable.preview_open); + moveUpDrawable = resources.getDrawable(R.drawable.preview_arrow); RectF rect = new RectF(); chat_updatePath[0] = new Path(); @@ -8416,9 +8760,6 @@ public class Theme { setDrawableColorByKey(dialogs_halfCheckDrawable, key_chats_sentReadCheck); setDrawableColorByKey(dialogs_clockDrawable, key_chats_sentClock); setDrawableColorByKey(dialogs_errorDrawable, key_chats_sentErrorIcon); - setDrawableColorByKey(dialogs_groupDrawable, key_chats_nameIcon); - setDrawableColorByKey(dialogs_broadcastDrawable, key_chats_nameIcon); - setDrawableColorByKey(dialogs_botDrawable, key_chats_nameIcon); setDrawableColorByKey(dialogs_pinnedDrawable, key_chats_pinnedIcon); setDrawableColorByKey(dialogs_reorderDrawable, key_chats_pinnedIcon); setDrawableColorByKey(dialogs_muteDrawable, key_chats_muteIcon); @@ -8595,10 +8936,10 @@ public class Theme { playPauseAnimator.addSvgKeyFrame("M 47.641 17.125 C 50.641 18.207 51.09 19.935 51.078 22.653 C 51.07 24.191 51.062 21.23 51.088 23.063 C 51.109 24.886 49.587 27 47.377 27 L 5 27.009 C 2.79 27.009 1 25.219 1 23.009 L 0.983 11.459 C 0.983 8.908 3.414 7.522 5.476 7.838 C 7.138 8.486 47.641 17.125 47.641 17.125 Z", 300); playPauseAnimator.addSvgKeyFrame("M 48 7 C 50.21 7 52 8.79 52 11 C 52 19 52 19 52 19 C 52 21.21 50.21 23 48 23 L 4 23 C 1.79 23 0 21.21 0 19 L 0 11 C 0 8.79 1.79 7 4 7 C 48 7 48 7 48 7 Z", 383); - chat_msgOutCheckDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); - chat_msgOutCheckSelectedDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); - chat_msgOutCheckReadDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); - chat_msgOutCheckReadSelectedDrawable = resources.getDrawable(R.drawable.msg_check).mutate(); + chat_msgOutCheckDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); + chat_msgOutCheckSelectedDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); + chat_msgOutCheckReadDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); + chat_msgOutCheckReadSelectedDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); chat_msgMediaCheckDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); chat_msgStickerCheckDrawable = resources.getDrawable(R.drawable.msg_check_s).mutate(); chat_msgOutHalfCheckDrawable = resources.getDrawable(R.drawable.msg_halfcheck).mutate(); @@ -8634,8 +8975,6 @@ public class Theme { chat_msgErrorDrawable = resources.getDrawable(R.drawable.msg_warning); chat_muteIconDrawable = resources.getDrawable(R.drawable.list_mute).mutate(); chat_lockIconDrawable = resources.getDrawable(R.drawable.ic_lock_header); - chat_msgBroadcastDrawable = resources.getDrawable(R.drawable.broadcast3).mutate(); - chat_msgBroadcastMediaDrawable = resources.getDrawable(R.drawable.broadcast3).mutate(); chat_msgInCallDrawable[0] = resources.getDrawable(R.drawable.chat_calls_voice).mutate(); chat_msgInCallSelectedDrawable[0] = resources.getDrawable(R.drawable.chat_calls_voice).mutate(); chat_msgOutCallDrawable[0] = resources.getDrawable(R.drawable.chat_calls_voice).mutate(); @@ -8650,7 +8989,7 @@ public class Theme { for (int a = 0; a < 2; a++) { chat_pollCheckDrawable[a] = resources.getDrawable(R.drawable.poll_right).mutate(); chat_pollCrossDrawable[a] = resources.getDrawable(R.drawable.poll_wrong).mutate(); - chat_pollHintDrawable[a] = resources.getDrawable(R.drawable.smiles_panel_objects).mutate(); + chat_pollHintDrawable[a] = resources.getDrawable(R.drawable.msg_emoji_objects).mutate(); chat_psaHelpDrawable[a] = resources.getDrawable(R.drawable.baseline_help_24).mutate(); } @@ -8689,19 +9028,6 @@ public class Theme { chat_replyIconDrawable = resources.getDrawable(R.drawable.fast_reply); chat_goIconDrawable = resources.getDrawable(R.drawable.message_arrow); - chat_fileMiniStatesDrawable[0][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_arrow); - chat_fileMiniStatesDrawable[0][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_arrow); - chat_fileMiniStatesDrawable[1][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_cancel); - chat_fileMiniStatesDrawable[1][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_cancel); - chat_fileMiniStatesDrawable[2][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_arrow); - chat_fileMiniStatesDrawable[2][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_arrow); - chat_fileMiniStatesDrawable[3][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_cancel); - chat_fileMiniStatesDrawable[3][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.audio_mini_cancel); - chat_fileMiniStatesDrawable[4][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.video_mini_arrow); - chat_fileMiniStatesDrawable[4][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.video_mini_arrow); - chat_fileMiniStatesDrawable[5][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.video_mini_cancel); - chat_fileMiniStatesDrawable[5][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(22), R.drawable.video_mini_cancel); - int rad = AndroidUtilities.dp(2); RectF rect = new RectF(); chat_filePath[0] = new Path(); @@ -8766,14 +9092,11 @@ public class Theme { chat_photoStatesDrawables[7][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_load_m); chat_photoStatesDrawables[8][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_cancel_m); chat_photoStatesDrawables[8][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_cancel_m); - chat_photoStatesDrawables[9][0] = resources.getDrawable(R.drawable.doc_big).mutate(); - chat_photoStatesDrawables[9][1] = resources.getDrawable(R.drawable.doc_big).mutate(); + chat_photoStatesDrawables[10][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_load_m); chat_photoStatesDrawables[10][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_load_m); chat_photoStatesDrawables[11][0] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_cancel_m); chat_photoStatesDrawables[11][1] = createCircleDrawableWithIcon(AndroidUtilities.dp(48), R.drawable.msg_round_cancel_m); - chat_photoStatesDrawables[12][0] = resources.getDrawable(R.drawable.doc_big).mutate(); - chat_photoStatesDrawables[12][1] = resources.getDrawable(R.drawable.doc_big).mutate(); chat_contactDrawable[0] = createCircleDrawableWithIcon(AndroidUtilities.dp(44), R.drawable.baseline_person_24); chat_contactDrawable[1] = createCircleDrawableWithIcon(AndroidUtilities.dp(44), R.drawable.baseline_person_24); @@ -9000,8 +9323,6 @@ public class Theme { setDrawableColorByKey(chat_msgErrorDrawable, key_chat_sentErrorIcon); setDrawableColorByKey(chat_muteIconDrawable, key_chat_muteIcon); setDrawableColorByKey(chat_lockIconDrawable, key_chat_lockIcon); - setDrawableColorByKey(chat_msgBroadcastDrawable, key_chat_outBroadcast); - setDrawableColorByKey(chat_msgBroadcastMediaDrawable, key_chat_mediaBroadcast); setDrawableColorByKey(chat_inlineResultFile, key_chat_inlineResultIcon); setDrawableColorByKey(chat_inlineResultAudio, key_chat_inlineResultIcon); setDrawableColorByKey(chat_inlineResultLocation, key_chat_inlineResultIcon); @@ -9029,23 +9350,6 @@ public class Theme { setDrawableColorByKey(chat_status_drawables[i], key_chats_actionMessage); } - for (int a = 0; a < 2; a++) { - setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][0], getColor(key_chat_outLoader), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][0], getColor(key_chat_outMediaIcon), true); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][1], getColor(key_chat_outLoaderSelected), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[a][1], getColor(key_chat_outMediaIconSelected), true); - - setCombinedDrawableColor(chat_fileMiniStatesDrawable[2 + a][0], getColor(key_chat_inLoader), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[2 + a][0], getColor(key_chat_inMediaIcon), true); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[2 + a][1], getColor(key_chat_inLoaderSelected), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[2 + a][1], getColor(key_chat_inMediaIconSelected), true); - - setCombinedDrawableColor(chat_fileMiniStatesDrawable[4 + a][0], getColor(key_chat_mediaLoaderPhoto), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[4 + a][0], getColor(key_chat_mediaLoaderPhotoIcon), true); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[4 + a][1], getColor(key_chat_mediaLoaderPhotoSelected), false); - setCombinedDrawableColor(chat_fileMiniStatesDrawable[4 + a][1], getColor(key_chat_mediaLoaderPhotoIconSelected), true); - } - for (int a = 0; a < 5; a++) { setCombinedDrawableColor(chat_fileStatesDrawable[a][0], getColor(key_chat_outLoader), false); setCombinedDrawableColor(chat_fileStatesDrawable[a][0], getColor(key_chat_outMediaIcon), true); @@ -9073,11 +9377,6 @@ public class Theme { setCombinedDrawableColor(chat_photoStatesDrawables[10 + a][1], getColor(key_chat_inLoaderPhotoIconSelected), true); } - setDrawableColorByKey(chat_photoStatesDrawables[9][0], key_chat_outFileIcon); - setDrawableColorByKey(chat_photoStatesDrawables[9][1], key_chat_outFileSelectedIcon); - setDrawableColorByKey(chat_photoStatesDrawables[12][0], key_chat_inFileIcon); - setDrawableColorByKey(chat_photoStatesDrawables[12][1], key_chat_inFileSelectedIcon); - setCombinedDrawableColor(chat_contactDrawable[0], getColor(key_chat_inContactBackground), false); setCombinedDrawableColor(chat_contactDrawable[0], getColor(key_chat_inContactIcon), true); setCombinedDrawableColor(chat_contactDrawable[1], getColor(key_chat_outContactBackground), false); @@ -9861,16 +10160,16 @@ public class Theme { } if (gradientToColor1 != null && gradientToColor2 != null) { MotionBackgroundDrawable motionBackgroundDrawable = new MotionBackgroundDrawable(backgroundColor, gradientToColor1, gradientToColor2, gradientToColor3, false); - Bitmap pattensBitmap = null; + Bitmap patternBitmap = null; if (wallpaperFile != null && wallpaperDocument != null) { - File f = FileLoader.getPathToAttach(wallpaperDocument, true); - pattensBitmap = SvgHelper.getBitmap(f, AndroidUtilities.dp(360), AndroidUtilities.dp(640), false); - if (pattensBitmap != null) { + File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(wallpaperDocument, true); + patternBitmap = SvgHelper.getBitmap(f, AndroidUtilities.dp(360), AndroidUtilities.dp(640), false); + if (patternBitmap != null) { FileOutputStream stream = null; try { stream = new FileOutputStream(wallpaperFile); - pattensBitmap.compress(Bitmap.CompressFormat.PNG, 87, stream); + patternBitmap.compress(Bitmap.CompressFormat.PNG, 90, stream); stream.close(); } catch (Exception e) { FileLog.e(e); @@ -9878,7 +10177,7 @@ public class Theme { } } } - motionBackgroundDrawable.setPatternBitmap(intensity, pattensBitmap); + motionBackgroundDrawable.setPatternBitmap(intensity, patternBitmap); motionBackgroundDrawable.setPhase(previousPhase); settings.wallpaper = motionBackgroundDrawable; } else if (gradientToColor1 == null || gradientToColor1.equals(backgroundColor)) { @@ -9924,6 +10223,7 @@ public class Theme { Bitmap bitmap = loadScreenSizedBitmap(new FileInputStream(file), themedWallpaperFileOffset); if (bitmap != null) { settings.wallpaper = settings.themedWallpaper = wallpaper = new BitmapDrawable(bitmap); + wallpaper.setFilterBitmap(true); settings.isCustomTheme = true; } } catch (Throwable e) { @@ -9975,6 +10275,7 @@ public class Theme { Bitmap bitmap = loadScreenSizedBitmap(new FileInputStream(toFile), 0); if (bitmap != null) { settings.wallpaper = new BitmapDrawable(bitmap); + settings.wallpaper.setFilterBitmap(true); settings.isCustomTheme = true; } } @@ -10022,8 +10323,8 @@ public class Theme { float photoW = opts.outWidth; float photoH = opts.outHeight; float scaleFactor; - int w_filter = AndroidUtilities.dp(360); - int h_filter = AndroidUtilities.dp(640); + int w_filter = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + int h_filter = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); if (w_filter >= h_filter && photoW > photoH) { scaleFactor = Math.max(photoW / w_filter, photoH / h_filter); } else { @@ -10043,7 +10344,16 @@ public class Theme { opts.inSampleSize = (int) scaleFactor; } stream.getChannel().position(offset); - return BitmapFactory.decodeStream(stream, null, opts); + Bitmap bitmap = BitmapFactory.decodeStream(stream, null, opts); + if (bitmap.getWidth() < w_filter || bitmap.getHeight() < h_filter) { + float scale = Math.max((float) w_filter / bitmap.getWidth(), (float) h_filter / bitmap.getHeight()); + if (scale >= 1.02f) { + Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) (bitmap.getWidth() * scale), (int) (bitmap.getHeight() * scale), true); + bitmap.recycle(); + return scaledBitmap; + } + } + return bitmap; } catch (Exception e) { FileLog.e(e); } finally { @@ -10190,12 +10500,7 @@ public class Theme { } public static Drawable getCachedWallpaper() { - Drawable drawable; - if (themedWallpaper != null) { - drawable = themedWallpaper; - } else { - drawable = wallpaper; - } + Drawable drawable = getCachedWallpaperNonBlocking(); if (drawable == null && wallpaperLoadTask != null) { CountDownLatch countDownLatch = new CountDownLatch(1); Utilities.themeQueue.postRunnable(countDownLatch::countDown); @@ -10204,11 +10509,7 @@ public class Theme { } catch (Exception e) { FileLog.e(e); } - if (themedWallpaper != null) { - drawable = themedWallpaper; - } else { - drawable = wallpaper; - } + drawable = getCachedWallpaperNonBlocking(); } return drawable; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionIntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionIntroActivity.java index ca9c940e4..db814ca49 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionIntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionIntroActivity.java @@ -594,7 +594,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl } cellFlickerDrawable.setParentWidth(getMeasuredWidth()); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4)); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null); invalidate(); } } @@ -606,7 +606,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); int buttonRadiusDp = currentType == ACTION_TYPE_SET_PASSCODE || currentType == ACTION_TYPE_CHANGE_PHONE_NUMBER ? 6 : 4; - buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(buttonRadiusDp), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, buttonRadiusDp)); viewGroup.addView(buttonTextView); buttonTextView.setOnClickListener(v -> { if (getParentActivity() == null) { @@ -663,7 +663,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl BottomBuilder builder = new BottomBuilder(getParentActivity()); builder.addTitle(LocaleController.getString("PhoneNumberAlert", R.string.PhoneNumberAlert)); builder.addItem(LocaleController.getString("Change", R.string.Change),R.drawable.baseline_check_circle_24, i -> { - presentFragment(new ChangePhoneActivity(), true); + presentFragment(new LoginActivity().changePhoneNumber(), true); return Unit.INSTANCE; }); builder.addCancelItem(); @@ -687,6 +687,7 @@ public class ActionIntroActivity extends BaseFragment implements LocationControl case ACTION_TYPE_SET_PASSCODE: { imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); imageView.setAnimation(R.raw.utyan_passcode, 200, 200); + imageView.setFocusable(false); imageView.setOnClickListener(v -> { if (!imageView.getAnimatedDrawable().isRunning()) { imageView.getAnimatedDrawable().setCurrentFrame(0, false); 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 6da5f3cd7..fc351bac1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/ContactsAdapter.java @@ -19,6 +19,9 @@ import android.widget.FrameLayout; import androidx.recyclerview.widget.RecyclerView; +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.FileLog; @@ -45,9 +48,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.RecyclerView; - public class ContactsAdapter extends RecyclerListView.SectionsAdapter { private int currentAccount = UserConfig.selectedAccount; @@ -447,9 +447,9 @@ public class ContactsAdapter extends RecyclerListView.SectionsAdapter { } } else if (isAdmin) { if (isChannel) { - textCell.setTextAndIcon(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), R.drawable.profile_link, false); + textCell.setTextAndIcon(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), R.drawable.msg_link2, false); } else { - textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.profile_link, false); + textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.msg_link2, false); } } else { if (position == 0) { 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 f1fd62971..ac5ec4776 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsAdapter.java @@ -28,7 +28,6 @@ import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; -import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; @@ -186,6 +185,9 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { } return (currentCount = 0); } + if (dialogsCount == 0 && messagesController.isLoadingDialogs(folderId)) { + return (currentCount = 0); + } int count = dialogsCount; if (dialogsType == 7 || dialogsType == 8) { if (dialogsCount == 0) { @@ -418,7 +420,11 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { case VIEW_TYPE_CONTACTS_FLICKER: FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); flickerLoadingView.setIsSingleCell(true); - flickerLoadingView.setViewType(viewType == VIEW_TYPE_CONTACTS_FLICKER ? FlickerLoadingView.CONTACT_TYPE : FlickerLoadingView.DIALOG_CELL_TYPE); + int flickerType = viewType == VIEW_TYPE_CONTACTS_FLICKER ? FlickerLoadingView.CONTACT_TYPE : FlickerLoadingView.DIALOG_CELL_TYPE; + flickerLoadingView.setViewType(flickerType); + if (flickerType == FlickerLoadingView.CONTACT_TYPE) { + flickerLoadingView.setIgnoreHeightCheck(true); + } if (viewType == VIEW_TYPE_CONTACTS_FLICKER) { flickerLoadingView.setItemsCount((int) (AndroidUtilities.displaySize.y * 0.5f / AndroidUtilities.dp(64))); } @@ -703,25 +709,17 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { cell.setTextSize(14); cell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); cell.setBackgroundColor(Theme.getColor(Theme.key_graySection)); - try { - MessagesController messagesController = AccountInstance.getInstance(currentAccount).getMessagesController(); - int j = 0; - if (messagesController.dialogsMyChannels.size() > 0) { - if (i == j) { - cell.setText(LocaleController.getString("MyChannels", R.string.MyChannels)); - } - j += 1 + messagesController.dialogsMyChannels.size(); - } - if (messagesController.dialogsMyGroups.size() > 0) { - if (i == j) { - cell.setText(LocaleController.getString("MyGroups", R.string.MyGroups)); - } - j += 1 + messagesController.dialogsMyGroups.size(); - } - if (messagesController.dialogsCanAddUsers.size() > 0 && i == j) { + switch (((DialogsActivity.DialogsHeader) getItem(i)).headerType) { + case DialogsActivity.DialogsHeader.HEADER_TYPE_MY_CHANNELS: + cell.setText(LocaleController.getString("MyChannels", R.string.MyChannels)); + break; + case DialogsActivity.DialogsHeader.HEADER_TYPE_MY_GROUPS: + cell.setText(LocaleController.getString("MyGroups", R.string.MyGroups)); + break; + case DialogsActivity.DialogsHeader.HEADER_TYPE_GROUPS: cell.setText(LocaleController.getString("FilterGroups", R.string.FilterGroups)); - } - } catch (Exception ignore) {} + break; + } break; } case VIEW_TYPE_NEW_CHAT_HINT: { @@ -740,7 +738,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { case VIEW_TYPE_TEXT: { TextCell cell = (TextCell) holder.itemView; cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); - cell.setTextAndIcon(LocaleController.getString("CreateGroupForImport", R.string.CreateGroupForImport), R.drawable.groups_create, dialogsCount != 0); + cell.setTextAndIcon(LocaleController.getString("CreateGroupForImport", R.string.CreateGroupForImport), R.drawable.msg_groups_create, dialogsCount != 0); cell.setIsInDialogs(); cell.setOffsetFromImage(75); break; @@ -839,7 +837,7 @@ public class DialogsAdapter extends RecyclerListView.SelectionAdapter { } else if (i > size) { return VIEW_TYPE_LAST_EMPTY; } - if (dialogsType == 2 && getItem(i) == null) { + if (dialogsType == 2 && getItem(i) instanceof DialogsActivity.DialogsHeader) { return VIEW_TYPE_HEADER_2; } return VIEW_TYPE_DIALOG; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java index bef7b00c8..d02cf2aa9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -9,18 +9,17 @@ package org.telegram.ui.Adapters; import android.content.Context; +import android.os.SystemClock; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; +import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; - -import com.google.android.exoplayer2.util.Log; - import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.SQLite.SQLiteCursor; import org.telegram.SQLite.SQLitePreparedStatement; @@ -43,6 +42,7 @@ import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.DialogCell; import org.telegram.ui.Cells.GraySectionCell; import org.telegram.ui.Cells.HashtagSearchCell; @@ -60,6 +60,7 @@ import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -95,13 +96,21 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private int lastLocalSearchId; private int lastMessagesSearchId; private int dialogsType; + private DefaultItemAnimator itemAnimator; private SearchAdapterHelper searchAdapterHelper; private RecyclerListView innerListView; private long selfUserId; + public int showMoreLastItem; + public boolean showMoreAnimation = false; + private long lastShowMoreUpdate; + public View showMoreHeader; + private Runnable cancelShowMoreAnimation; private int currentAccount = UserConfig.selectedAccount; private ArrayList recentSearchObjects = new ArrayList<>(); + private ArrayList filteredRecentSearchObjects = new ArrayList<>(); + private String filteredRecentQuery = null; private LongSparseArray recentSearchObjectsById = new LongSparseArray<>(); private ArrayList localTipDates = new ArrayList<>(); private boolean localTipArchive; @@ -139,6 +148,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { private final Context mContext; private final int currentAccount; private boolean drawChecked; + private boolean forceDarkTheme; public CategoryAdapterRecycler(Context context, int account, boolean drawChecked) { this.drawChecked = drawChecked; @@ -152,9 +162,9 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = new HintDialogCell(mContext, drawChecked); - view.setLayoutParams(new RecyclerView.LayoutParams(AndroidUtilities.dp(80), AndroidUtilities.dp(86))); - return new RecyclerListView.Holder(view); + HintDialogCell cell = new HintDialogCell(mContext, drawChecked); + cell.setLayoutParams(new RecyclerView.LayoutParams(AndroidUtilities.dp(80), AndroidUtilities.dp(86))); + return new RecyclerListView.Holder(cell); } @Override @@ -197,7 +207,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } } - public DialogsSearchAdapter(Context context, int messagesSearch, int type) { + public DialogsSearchAdapter(Context context, int messagesSearch, int type, DefaultItemAnimator itemAnimator) { + this.itemAnimator = itemAnimator; searchAdapterHelper = new SearchAdapterHelper(false); searchAdapterHelper.setDelegate(new SearchAdapterHelper.SearchAdapterHelperDelegate() { @Override @@ -276,12 +287,16 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { reqId = 0; } if (TextUtils.isEmpty(query)) { + filteredRecentQuery = null; searchResultMessages.clear(); lastReqId = 0; lastMessagesSearchString = null; searchWas = false; notifyDataSetChanged(); return; + } else { + filterRecent(query); + searchAdapterHelper.mergeResults(searchResult, filteredRecentSearchObjects); } final TLRPC.TL_messages_searchGlobal req = new TLRPC.TL_messages_searchGlobal(); @@ -365,6 +380,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { searchAdapterHelper.clear(); } } + searchAdapterHelper.mergeResults(searchResult, filteredRecentSearchObjects); if (delegate != null) { delegate.searchStateChanged(waitingResponseCount > 0, true); delegate.runResultsEnterAnimation(); @@ -380,11 +396,15 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } public boolean hasRecentSearch() { - return dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && dialogsType != 11 && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty()); + return dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && dialogsType != 11 && getRecentItemsCount() > 0; + } + + public boolean isSearchWas() { + return searchWas; } public boolean isRecentSearchDisplayed() { - return needMessagesSearch != 2 && !searchWas && (!recentSearchObjects.isEmpty() || !MediaDataController.getInstance(currentAccount).hints.isEmpty()) && dialogsType != 2 && dialogsType != 4 && dialogsType != 5 && dialogsType != 6 && dialogsType != 11; + return needMessagesSearch != 2 && hasRecentSearch(); } public void loadRecentSearch() { @@ -528,12 +548,36 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } public void clearRecentSearch() { - recentSearchObjectsById = new LongSparseArray<>(); - recentSearchObjects = new ArrayList<>(); + StringBuilder queryFilter = null; + if (searchWas) { + while (filteredRecentSearchObjects.size() > 0) { + RecentSearchObject obj = filteredRecentSearchObjects.remove(0); + recentSearchObjects.remove(obj); + recentSearchObjectsById.remove(obj.did); + if (queryFilter == null) { + queryFilter = new StringBuilder("did IN ("); + queryFilter.append(obj.did); + } else { + queryFilter.append(", ").append(obj.did); + } + } + if (queryFilter == null) { + queryFilter = new StringBuilder("1"); + } else { + queryFilter.append(")"); + } + } else { + filteredRecentSearchObjects.clear(); + recentSearchObjects.clear(); + recentSearchObjectsById.clear(); + queryFilter = new StringBuilder("1"); + } + final StringBuilder finalQueryFilter = queryFilter; notifyDataSetChanged(); MessagesStorage.getInstance(currentAccount).getStorageQueue().postRunnable(() -> { try { - MessagesStorage.getInstance(currentAccount).getDatabase().executeFast("DELETE FROM search_recent WHERE 1").stepThis().dispose(); + finalQueryFilter.insert(0, "DELETE FROM search_recent WHERE "); + MessagesStorage.getInstance(currentAccount).getDatabase().executeFast(finalQueryFilter.toString()).stepThis().dispose(); } catch (Exception e) { FileLog.e(e); } @@ -621,6 +665,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { searchResultMessages.clear(); } searchWas = true; + final int recentCount = filteredRecentSearchObjects.size(); for (int a = 0; a < result.size(); a++) { Object obj = result.get(a); long dialogId = 0; @@ -658,11 +703,25 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { }); } } + + boolean foundInRecent = false; + for (int j = 0; j < recentCount; ++j) { + RecentSearchObject o = filteredRecentSearchObjects.get(j); + if (o != null && o.did == dialogId) { + foundInRecent = true; + break; + } + } + if (foundInRecent) { + result.remove(a); + names.remove(a); + a--; + } } MessagesController.getInstance(currentAccount).putUsers(encUsers, true); searchResult = result; searchResultNames = names; - searchAdapterHelper.mergeResults(searchResult); + searchAdapterHelper.mergeResults(searchResult, filteredRecentSearchObjects); notifyDataSetChanged(); if (delegate != null) { delegate.searchStateChanged(waitingResponseCount > 0, true); @@ -704,11 +763,12 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { query = null; } if (TextUtils.isEmpty(query)) { + filteredRecentQuery = null; searchAdapterHelper.unloadRecentHashtags(); searchResult.clear(); searchResultNames.clear(); searchResultHashtags.clear(); - searchAdapterHelper.mergeResults(null); + searchAdapterHelper.mergeResults(null, null); searchAdapterHelper.queryServerSearch(null, true, true, dialogsType != 11, dialogsType != 11, dialogsType == 2 || dialogsType == 11, 0, dialogsType == 0, 0, 0); searchWas = false; lastSearchId = 0; @@ -726,6 +786,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { filtersDelegate.updateFiltersView(false, null, localTipDates, localTipArchive); } } else { + filterRecent(query); + searchAdapterHelper.mergeResults(searchResult, filteredRecentSearchObjects); if (needMessagesSearch != 2 && (query.startsWith("#") && query.length() == 1)) { messagesSearchEndReached = true; if (searchAdapterHelper.loadRecentHashtags()) { @@ -779,21 +841,36 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } } + public int getRecentItemsCount() { + ArrayList recent = searchWas ? filteredRecentSearchObjects : recentSearchObjects; + return (!recent.isEmpty() ? recent.size() + 1 : 0) + (!searchWas && !MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); + } + + public int getRecentResultsCount() { + ArrayList recent = searchWas ? filteredRecentSearchObjects : recentSearchObjects; + return recent != null ? recent.size() : 0; + } + @Override public int getItemCount() { if (waitingResponseCount == 3) { return 0; } - if (isRecentSearchDisplayed()) { - return (!recentSearchObjects.isEmpty() ? recentSearchObjects.size() + 1 : 0) + (!MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); - } int count = 0; if (!searchResultHashtags.isEmpty()) { count += searchResultHashtags.size() + 1; return count; } - count += searchResult.size(); + if (isRecentSearchDisplayed()) { + count += getRecentItemsCount(); + if (!searchWas) { + return count; + } + } + int resultsCount = searchResult.size(); + count += resultsCount; int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); + count += localServerCount; int globalCount = searchAdapterHelper.getGlobalSearch().size(); if (globalCount > 3 && globalSearchCollapsed) { globalCount = 3; @@ -803,7 +880,9 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { phoneCount = 3; } int messagesCount = searchResultMessages.size(); - count += localServerCount; + if (resultsCount + localServerCount > 0 && getRecentItemsCount() > 0) { + count++; + } if (globalCount != 0) { count += globalCount + 1; } @@ -817,10 +896,18 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } public Object getItem(int i) { + if (!searchResultHashtags.isEmpty()) { + if (i > 0) { + return searchResultHashtags.get(i - 1); + } else { + return null; + } + } if (isRecentSearchDisplayed()) { - int offset = (!MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); - if (i > offset && i - 1 - offset < recentSearchObjects.size()) { - TLObject object = recentSearchObjects.get(i - 1 - offset).object; + int offset = (!searchWas && !MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); + ArrayList recent = searchWas ? filteredRecentSearchObjects : recentSearchObjects; + if (i > offset && i - 1 - offset < recent.size()) { + TLObject object = recent.get(i - 1 - offset).object; if (object instanceof TLRPC.User) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(((TLRPC.User) object).id); if (user != null) { @@ -834,14 +921,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } return object; } else { - return null; - } - } - if (!searchResultHashtags.isEmpty()) { - if (i > 0) { - return searchResultHashtags.get(i - 1); - } else { - return null; + i -= getRecentItemsCount(); } } ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); @@ -849,6 +929,12 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { ArrayList phoneSearch = searchAdapterHelper.getPhoneSearch(); int localCount = searchResult.size(); int localServerCount = localServerSearch.size(); + if (localCount + localServerCount > 0 && getRecentItemsCount() > 0) { + if (i == 0) { + return null; + } + i--; + } int phoneCount = phoneSearch.size(); if (phoneCount > 3 && phoneCollapsed) { phoneCount = 3; @@ -860,37 +946,42 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { int messagesCount = searchResultMessages.isEmpty() ? 0 : searchResultMessages.size() + 1; if (i >= 0 && i < localCount) { return searchResult.get(i); - } else { - i -= localCount; - if (i >= 0 && i < localServerCount) { - return localServerSearch.get(i); - } else { - i -= localServerCount; - if (i >= 0 && i < phoneCount) { - return phoneSearch.get(i); - } else { - i -= phoneCount; - if (i > 0 && i < globalCount) { - return globalSearch.get(i - 1); - } else { - i -= globalCount; - if (i > 0 && i < messagesCount) { - return searchResultMessages.get(i - 1); - } - } - } - } + } + i -= localCount; + if (i >= 0 && i < localServerCount) { + return localServerSearch.get(i); + } + i -= localServerCount; + if (i >= 0 && i < phoneCount) { + return phoneSearch.get(i); + } + i -= phoneCount; + if (i > 0 && i < globalCount) { + return globalSearch.get(i - 1); + } + i -= globalCount; + if (i > 0 && i < messagesCount) { + return searchResultMessages.get(i - 1); } return null; } public boolean isGlobalSearch(int i) { - if (isRecentSearchDisplayed()) { + if (!searchWas) { return false; } if (!searchResultHashtags.isEmpty()) { return false; } + if (isRecentSearchDisplayed()) { + int offset = (!searchWas && !MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); + ArrayList recent = searchWas ? filteredRecentSearchObjects : recentSearchObjects; + if (i > offset && i - 1 - offset < recent.size()) { + return false; + } else { + i -= getRecentItemsCount(); + } + } ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); ArrayList localServerSearch = searchAdapterHelper.getLocalServerSearch(); int localCount = searchResult.size(); @@ -907,26 +998,22 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (i >= 0 && i < localCount) { return false; - } else { - i -= localCount; - if (i >= 0 && i < localServerCount) { - return false; - } else { - i -= localServerCount; - if (i > 0 && i < phoneCount) { - return false; - } else { - i -= phoneCount; - if (i > 0 && i < globalCount) { - return true; - } else { - i -= globalCount; - if (i > 0 && i < messagesCount) { - return false; - } - } - } - } + } + i -= localCount; + if (i >= 0 && i < localServerCount) { + return false; + } + i -= localServerCount; + if (i > 0 && i < phoneCount) { + return false; + } + i -= phoneCount; + if (i > 0 && i < globalCount) { + return true; + } + i -= globalCount; + if (i > 0 && i < messagesCount) { + return false; } return false; } @@ -1020,6 +1107,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { switch (holder.getItemViewType()) { case VIEW_TYPE_PROFILE_CELL: { ProfileSearchCell cell = (ProfileSearchCell) holder.itemView; + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); long oldDialogId = cell.getDialogId(); TLRPC.User user = null; @@ -1046,81 +1134,91 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } if (isRecentSearchDisplayed()) { - isRecent = true; - cell.useSeparator = position != getItemCount() - 1; - } else { - ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); - ArrayList phoneSearch = searchAdapterHelper.getPhoneSearch(); - int localCount = searchResult.size(); - int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); - int phoneCount = phoneSearch.size(); - if (phoneCount > 3 && phoneCollapsed) { - phoneCount = 3; + if (position < getRecentItemsCount()) { + cell.useSeparator = position != getRecentItemsCount() - 1; + isRecent = true; } - int phoneCount2 = phoneCount; - if (phoneCount > 0 && phoneSearch.get(phoneCount - 1) instanceof String) { - phoneCount2 -= 2; - } - int globalCount = globalSearch.isEmpty() ? 0 : globalSearch.size() + 1; - if (globalCount > 4 && globalSearchCollapsed) { - globalCount = 4; - } - cell.useSeparator = (position != getItemCount() - 1 && position != localCount + phoneCount2 + localServerCount - 1 && position != localCount + globalCount + phoneCount + localServerCount - 1); - if (position < searchResult.size()) { - name = searchResultNames.get(position); - if (name != null && name.toString().startsWith("ID: ")) { + position -= getRecentItemsCount(); + } + ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); + ArrayList phoneSearch = searchAdapterHelper.getPhoneSearch(); + int localCount = searchResult.size(); + int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); + if (localCount + localServerCount > 0 && getRecentItemsCount() > 0) { + position--; + } + int phoneCount = phoneSearch.size(); + if (phoneCount > 3 && phoneCollapsed) { + phoneCount = 3; + } + int phoneCount2 = phoneCount; + if (phoneCount > 0 && phoneSearch.get(phoneCount - 1) instanceof String) { + phoneCount2 -= 2; + } + int globalCount = globalSearch.isEmpty() ? 0 : globalSearch.size() + 1; + if (globalCount > 4 && globalSearchCollapsed) { + globalCount = 4; + } + if (!isRecent) { + cell.useSeparator = (position != getItemCount() - getRecentItemsCount() - 1 && position != localCount + phoneCount2 + localServerCount - 1 && position != localCount + globalCount + phoneCount + localServerCount - 1); + } + if (position >= 0 && position < searchResult.size() && user == null) { + name = searchResultNames.get(position); + if (name != null && name.toString().startsWith("ID: ")) { username = name; name = null; if (username instanceof SpannableStringBuilder) { username = new SpannableStringBuilder(username); } } else if (name != null && user != null && user.username != null && user.username.length() > 0) { - if (name.toString().startsWith("@" + user.username)) { - username = name; - name = null; - } + if (name.toString().startsWith("@" + user.username)) { + username = name; + name = null; } - } else { - String foundUserName = searchAdapterHelper.getLastFoundUsername(); - if (!TextUtils.isEmpty(foundUserName)) { - String nameSearch = null; - int index; - if (user != null) { - nameSearch = ContactsController.formatName(user.first_name, user.last_name); - } else if (chat != null) { - nameSearch = chat.title; + } + } + if (username == null) { + String foundUserName = isRecent ? filteredRecentQuery : searchAdapterHelper.getLastFoundUsername(); + if (!TextUtils.isEmpty(foundUserName)) { + String nameSearch = null; + int index; + if (user != null) { + nameSearch = ContactsController.formatName(user.first_name, user.last_name); + } else if (chat != null) { + nameSearch = chat.title; + } + if (nameSearch != null && (index = AndroidUtilities.indexOfIgnoreCase(nameSearch, foundUserName)) != -1) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(nameSearch); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + name = spannableStringBuilder; + } + if (un != null && user == null) { + if (foundUserName.startsWith("@")) { + foundUserName = foundUserName.substring(1); } - if (nameSearch != null && (index = AndroidUtilities.indexOfIgnoreCase(nameSearch, foundUserName)) != -1) { - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(nameSearch); - spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + foundUserName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - name = spannableStringBuilder; - } else if (un != null) { - if (foundUserName.startsWith("@")) { - foundUserName = foundUserName.substring(1); - } - try { - SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); - spannableStringBuilder.append("@"); - spannableStringBuilder.append(un); - if ((index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1) { - int len = foundUserName.length(); - if (index == 0) { - len++; - } else { - index++; - } - spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + try { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append("@"); + spannableStringBuilder.append(un); + boolean hasMatch = (index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1; + if (hasMatch) { + int len = foundUserName.length(); + if (index == 0) { + len++; + } else { + index++; } - username = spannableStringBuilder; - } catch (Exception e) { - username = un; - FileLog.e(e); + spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } + username = spannableStringBuilder; + } catch (Exception e) { + username = un; + FileLog.e(e); } } } - cell.setChecked(false, false); } + cell.setChecked(false, false); boolean savedMessages = false; if (user != null && user.id == selfUserId) { name = LocaleController.getString("SavedMessages", R.string.SavedMessages); @@ -1142,30 +1240,47 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { username = membersString; } } - cell.setData(user != null ? user : chat, encryptedChat, name, username, isRecent, savedMessages); + cell.setData(user != null ? user : chat, encryptedChat, name, username, true, savedMessages); cell.setChecked(delegate.isSelected(cell.getDialogId()), oldDialogId == cell.getDialogId()); break; } case VIEW_TYPE_GRAY_SECTION: { - GraySectionCell cell = (GraySectionCell) holder.itemView; - if (isRecentSearchDisplayed()) { - int offset = (!MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); - if (position < offset) { - cell.setText(LocaleController.getString("ChatHints", R.string.ChatHints)); - } else { - cell.setText(LocaleController.getString("Recent", R.string.Recent), LocaleController.getString("ClearButton", R.string.ClearButton), v -> { - if (delegate != null) { - delegate.needClearList(); - } - }); - } - } else if (!searchResultHashtags.isEmpty()) { + final GraySectionCell cell = (GraySectionCell) holder.itemView; + if (!searchResultHashtags.isEmpty()) { cell.setText(LocaleController.getString("Hashtags", R.string.Hashtags), LocaleController.getString("ClearButton", R.string.ClearButton), v -> { if (delegate != null) { delegate.needClearList(); } }); } else { + int rawPosition = position; + if (isRecentSearchDisplayed()) { + int offset = (!searchWas && !MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); + if (position < offset) { + cell.setText(LocaleController.getString("ChatHints", R.string.ChatHints)); + return; + } else if (position == offset) { + if (!searchWas) { + cell.setText(LocaleController.getString("Recent", R.string.Recent), LocaleController.getString("ClearButton", R.string.ClearButton), v -> { + if (delegate != null) { + delegate.needClearList(); + } + }); + } else { + cell.setText(LocaleController.getString("Recent", R.string.Recent), LocaleController.getString("Clear", R.string.Clear), v -> { + if (delegate != null) { + delegate.needClearList(); + } + }); + } + return; + } else if (position == getRecentItemsCount()) { + cell.setText(LocaleController.getString("SearchAllChatsShort", R.string.SearchAllChatsShort)); + return; + } else { + position -= getRecentItemsCount(); + } + } ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); int localCount = searchResult.size(); int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); @@ -1188,6 +1303,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { showMore = phoneCollapsed; onClick = () -> { phoneCollapsed = !phoneCollapsed; + cell.setRightText(phoneCollapsed ? LocaleController.getString("ShowMore", R.string.ShowMore) : LocaleController.getString("ShowLess", R.string.ShowLess)); notifyDataSetChanged(); }; } @@ -1198,8 +1314,61 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (searchAdapterHelper.getGlobalSearch().size() > 3) { showMore = globalSearchCollapsed; onClick = () -> { + final long now = SystemClock.elapsedRealtime(); + if (now - lastShowMoreUpdate < 300) { + return; + } + lastShowMoreUpdate = now; + + int totalGlobalCount = globalSearch.isEmpty() ? 0 : globalSearch.size(); + boolean disableRemoveAnimation = getItemCount() > rawPosition + Math.min(totalGlobalCount, globalSearchCollapsed ? 4 : Integer.MAX_VALUE) + 1; + if (itemAnimator != null) { + itemAnimator.setAddDuration(disableRemoveAnimation ? 45 : 200); + itemAnimator.setRemoveDuration(disableRemoveAnimation ? 80 : 200); + itemAnimator.setRemoveDelay(disableRemoveAnimation ? 270 : 0); + } globalSearchCollapsed = !globalSearchCollapsed; - notifyDataSetChanged(); + cell.setRightText(globalSearchCollapsed ? LocaleController.getString("ShowMore", R.string.ShowMore) : LocaleController.getString("ShowLess", R.string.ShowLess), globalSearchCollapsed); + showMoreHeader = null; + View parent = (View) cell.getParent(); + if (parent instanceof RecyclerView) { + RecyclerView listView = (RecyclerView) parent; + final int nextGraySectionPosition = !globalSearchCollapsed ? rawPosition + 4 : rawPosition + totalGlobalCount + 1; + for (int i = 0; i < listView.getChildCount(); ++i) { + View child = listView.getChildAt(i); + if (listView.getChildAdapterPosition(child) == nextGraySectionPosition) { + showMoreHeader = child; + break; + } + } + } + if (!globalSearchCollapsed) { + notifyItemChanged(rawPosition + 3); + notifyItemRangeInserted(rawPosition + 4, (totalGlobalCount - 3)); + } else { + notifyItemRangeRemoved(rawPosition + 4, (totalGlobalCount - 3)); + if (disableRemoveAnimation) { + AndroidUtilities.runOnUIThread(() -> notifyItemChanged(rawPosition + 3), 350); + } else { + notifyItemChanged(rawPosition + 3); + } + } + + if (cancelShowMoreAnimation != null) { + AndroidUtilities.cancelRunOnUIThread(cancelShowMoreAnimation); + } + if (disableRemoveAnimation) { + showMoreAnimation = true; + AndroidUtilities.runOnUIThread(cancelShowMoreAnimation = () -> { + showMoreAnimation = false; + showMoreHeader = null; + if (parent != null) { + parent.invalidate(); + } + }, 400); + } else { + showMoreAnimation = false; + } }; } } else { @@ -1218,6 +1387,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } case VIEW_TYPE_DIALOG_CELL: { DialogCell cell = (DialogCell) holder.itemView; + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.useSeparator = (position != getItemCount() - 1); MessageObject messageObject = (MessageObject) getItem(position); cell.setDialog(messageObject.getDialogId(), messageObject, messageObject.messageOwner.date, false); @@ -1225,6 +1395,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { } case VIEW_TYPE_HASHTAG_CELL: { HashtagSearchCell cell = (HashtagSearchCell) holder.itemView; + cell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); cell.setText(searchResultHashtags.get(position - 1)); cell.setNeedDivider(position != searchResultHashtags.size()); break; @@ -1249,22 +1420,31 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { @Override public int getItemViewType(int i) { + if (!searchResultHashtags.isEmpty()) { + return i == 0 ? VIEW_TYPE_GRAY_SECTION : VIEW_TYPE_HASHTAG_CELL; + } if (isRecentSearchDisplayed()) { - int offset = (!MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); + int offset = (!searchWas && !MediaDataController.getInstance(currentAccount).hints.isEmpty() ? 1 : 0); if (i < offset) { return VIEW_TYPE_CATEGORY_LIST; } if (i == offset) { return VIEW_TYPE_GRAY_SECTION; } - return VIEW_TYPE_PROFILE_CELL; - } - if (!searchResultHashtags.isEmpty()) { - return i == 0 ? VIEW_TYPE_GRAY_SECTION : VIEW_TYPE_HASHTAG_CELL; + if (i < getRecentItemsCount()) { + return VIEW_TYPE_PROFILE_CELL; + } + i -= getRecentItemsCount(); } ArrayList globalSearch = searchAdapterHelper.getGlobalSearch(); int localCount = searchResult.size(); int localServerCount = searchAdapterHelper.getLocalServerSearch().size(); + if (localCount + localServerCount > 0 && getRecentItemsCount() > 0) { + if (i == 0) { + return VIEW_TYPE_GRAY_SECTION; + } + i--; + } int phoneCount = searchAdapterHelper.getPhoneSearch().size(); if (phoneCount > 3 && phoneCollapsed) { phoneCount = 3; @@ -1277,43 +1457,39 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (i >= 0 && i < localCount) { return VIEW_TYPE_PROFILE_CELL; - } else { - i -= localCount; - if (i >= 0 && i < localServerCount) { - return VIEW_TYPE_PROFILE_CELL; - } else { - i -= localServerCount; - if (i >= 0 && i < phoneCount) { - Object object = getItem(i); - if (object instanceof String) { - String str = (String) object; - if ("section".equals(str)) { - return VIEW_TYPE_GRAY_SECTION; - } else { - return VIEW_TYPE_ADD_BY_PHONE; - } - } - return VIEW_TYPE_PROFILE_CELL; + } + i -= localCount; + if (i >= 0 && i < localServerCount) { + return VIEW_TYPE_PROFILE_CELL; + } + i -= localServerCount; + if (i >= 0 && i < phoneCount) { + Object object = getItem(i); + if (object instanceof String) { + String str = (String) object; + if ("section".equals(str)) { + return VIEW_TYPE_GRAY_SECTION; } else { - i -= phoneCount; - if (i >= 0 && i < globalCount) { - if (i == 0) { - return VIEW_TYPE_GRAY_SECTION; - } else { - return VIEW_TYPE_PROFILE_CELL; - } - } else { - i -= globalCount; - if (i >= 0 && i < messagesCount) { - if (i == 0) { - return VIEW_TYPE_GRAY_SECTION; - } else { - return VIEW_TYPE_DIALOG_CELL; - } - } - } + return VIEW_TYPE_ADD_BY_PHONE; } } + return VIEW_TYPE_PROFILE_CELL; + } + i -= phoneCount; + if (i >= 0 && i < globalCount) { + if (i == 0) { + return VIEW_TYPE_GRAY_SECTION; + } else { + return VIEW_TYPE_PROFILE_CELL; + } + } + i -= globalCount; + if (i >= 0 && i < messagesCount) { + if (i == 0) { + return VIEW_TYPE_GRAY_SECTION; + } else { + return VIEW_TYPE_DIALOG_CELL; + } } return VIEW_TYPE_LOADING; } @@ -1329,6 +1505,54 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { return currentItemCount; } + public void filterRecent(String query) { + filteredRecentQuery = query; + filteredRecentSearchObjects.clear(); + if (TextUtils.isEmpty(query)) { + return; + } + String lowerCasedQuery = query.toLowerCase(); + final int count = recentSearchObjects.size(); + for (int i = 0; i < count; ++i) { + RecentSearchObject obj = recentSearchObjects.get(i); + if (obj == null || obj.object == null) { + continue; + } + String title = null, username = null; + if (obj.object instanceof TLRPC.Chat) { + title = ((TLRPC.Chat) obj.object).title; + username = ((TLRPC.Chat) obj.object).username; + } else if (obj.object instanceof TLRPC.User) { + title = UserObject.getUserName((TLRPC.User) obj.object); + username = ((TLRPC.User) obj.object).username; + } else if (obj.object instanceof TLRPC.ChatInvite) { + title = ((TLRPC.ChatInvite) obj.object).title; + } + if (title != null && wordStartsWith(title.toLowerCase(), lowerCasedQuery) || + username != null && wordStartsWith(username.toLowerCase(), lowerCasedQuery)) { + filteredRecentSearchObjects.add(obj); + } + if (filteredRecentSearchObjects.size() >= 5) { + break; + } + } + } + + private boolean wordStartsWith(String loweredTitle, String loweredQuery) { + if (loweredQuery == null || loweredTitle == null) { + return false; + } + String[] words = loweredTitle.toLowerCase().split(" "); + boolean found = false; + for (int j = 0; j < words.length; ++j) { + if (words[j] != null && (words[j].startsWith(loweredQuery) || loweredQuery.startsWith(words[j]))) { + found = true; + break; + } + } + return found; + } + public interface OnRecentSearchLoaded { void setRecentSearch(ArrayList arrayList, LongSparseArray hashMap); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java index 0ec21b06e..5a156deea 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DrawerLayoutAdapter.java @@ -16,6 +16,8 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.LocaleController; @@ -24,13 +26,14 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; -import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.DrawerLayoutContainer; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.DividerCell; import org.telegram.ui.Cells.DrawerActionCell; import org.telegram.ui.Cells.DrawerActionCheckCell; +import org.telegram.ui.Cells.DividerCell; +import org.telegram.ui.Cells.DrawerActionCell; import org.telegram.ui.Cells.DrawerAddCell; import org.telegram.ui.Cells.DrawerProfileCell; import org.telegram.ui.Cells.DrawerUserCell; @@ -224,7 +227,7 @@ public class DrawerLayoutAdapter extends RecyclerListView.SelectionAdapter imple } i -= getAccountRowsCount(); } - if (items.get(i) == null) { + if (i < 0 || i >= items.size() || items.get(i) == null) { return 2; } return items.get(i) instanceof CheckItem ? 6 : 3; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java index e89ac3c41..a108fc04f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/FiltersView.java @@ -69,11 +69,11 @@ public class FiltersView extends RecyclerListView { public final static int FILTER_INDEX_VOICE = 4; public final static MediaFilterData[] filters = new MediaFilterData[]{ - new MediaFilterData(R.drawable.search_media, R.drawable.search_media_filled, LocaleController.getString("SharedMediaTab2", R.string.SharedMediaTab2), new TLRPC.TL_inputMessagesFilterPhotoVideo(), FILTER_TYPE_MEDIA), - new MediaFilterData(R.drawable.search_links, R.drawable.search_links_filled, LocaleController.getString("SharedLinksTab2", R.string.SharedLinksTab2), new TLRPC.TL_inputMessagesFilterUrl(), FILTER_TYPE_LINKS), - new MediaFilterData(R.drawable.search_files, R.drawable.search_files_filled, LocaleController.getString("SharedFilesTab2", R.string.SharedFilesTab2), new TLRPC.TL_inputMessagesFilterDocument(), FILTER_TYPE_FILES), - new MediaFilterData(R.drawable.search_music, R.drawable.search_music_filled, LocaleController.getString("SharedMusicTab2", R.string.SharedMusicTab2), new TLRPC.TL_inputMessagesFilterMusic(), FILTER_TYPE_MUSIC), - new MediaFilterData(R.drawable.search_voice, R.drawable.search_voice_filled, LocaleController.getString("SharedVoiceTab2", R.string.SharedVoiceTab2), new TLRPC.TL_inputMessagesFilterRoundVoice(), FILTER_TYPE_VOICE) + new MediaFilterData(R.drawable.search_media_filled, LocaleController.getString("SharedMediaTab2", R.string.SharedMediaTab2), new TLRPC.TL_inputMessagesFilterPhotoVideo(), FILTER_TYPE_MEDIA), + new MediaFilterData(R.drawable.search_links_filled, LocaleController.getString("SharedLinksTab2", R.string.SharedLinksTab2), new TLRPC.TL_inputMessagesFilterUrl(), FILTER_TYPE_LINKS), + new MediaFilterData(R.drawable.search_files_filled, LocaleController.getString("SharedFilesTab2", R.string.SharedFilesTab2), new TLRPC.TL_inputMessagesFilterDocument(), FILTER_TYPE_FILES), + new MediaFilterData(R.drawable.search_music_filled, LocaleController.getString("SharedMusicTab2", R.string.SharedMusicTab2), new TLRPC.TL_inputMessagesFilterMusic(), FILTER_TYPE_MUSIC), + new MediaFilterData(R.drawable.search_voice_filled, LocaleController.getString("SharedVoiceTab2", R.string.SharedVoiceTab2), new TLRPC.TL_inputMessagesFilterRoundVoice(), FILTER_TYPE_VOICE) }; private ArrayList usersFilters = new ArrayList<>(); @@ -235,7 +235,7 @@ public class FiltersView extends RecyclerListView { } else { title = ContactsController.formatName(user.first_name, user.last_name, 10); } - MediaFilterData data = new MediaFilterData(R.drawable.search_users, R.drawable.search_users_filled, title, null, FILTER_TYPE_CHAT); + MediaFilterData data = new MediaFilterData(R.drawable.search_users_filled, title, null, FILTER_TYPE_CHAT); data.setUser(user); usersFilters.add(data); } else if (object instanceof TLRPC.Chat) { @@ -244,7 +244,7 @@ public class FiltersView extends RecyclerListView { if (chat.title.length() > 12) { title = String.format("%s...", title.substring(0, 10)); } - MediaFilterData data = new MediaFilterData(R.drawable.search_users, R.drawable.search_users_filled, title, null, FILTER_TYPE_CHAT); + MediaFilterData data = new MediaFilterData(R.drawable.search_users_filled, title, null, FILTER_TYPE_CHAT); data.setUser(chat); usersFilters.add(data); } @@ -253,13 +253,13 @@ public class FiltersView extends RecyclerListView { if (dates != null) { for (int i = 0; i < dates.size(); i++) { DateData dateData = dates.get(i); - MediaFilterData data = new MediaFilterData(R.drawable.search_date, R.drawable.search_date_filled, dateData.title, null, FILTER_TYPE_DATE); + MediaFilterData data = new MediaFilterData(R.drawable.search_date_filled, dateData.title, null, FILTER_TYPE_DATE); data.setDate(dateData); usersFilters.add(data); } } if (archive) { - FiltersView.MediaFilterData filterData = new FiltersView.MediaFilterData(R.drawable.chats_archive, R.drawable.chats_archive, LocaleController.getString("ArchiveSearchFilter", R.string.ArchiveSearchFilter), null, FiltersView.FILTER_TYPE_ARCHIVE); + FiltersView.MediaFilterData filterData = new FiltersView.MediaFilterData(R.drawable.chats_archive, LocaleController.getString("ArchiveSearchFilter", R.string.ArchiveSearchFilter), null, FiltersView.FILTER_TYPE_ARCHIVE); usersFilters.add(filterData); } if (getAdapter() != null) { @@ -787,7 +787,6 @@ public class FiltersView extends RecyclerListView { public static class MediaFilterData { - public final int iconRes; public final int iconResFilled; public final String title; public final int filterType; @@ -796,8 +795,7 @@ public class FiltersView extends RecyclerListView { public DateData dateData; public boolean removable = true; - public MediaFilterData(int iconRes, int iconResFilled, String title, TLRPC.MessagesFilter filter, int filterType) { - this.iconRes = iconRes; + public MediaFilterData(int iconResFilled, String title, TLRPC.MessagesFilter filter, int filterType) { this.iconResFilled = iconResFilled; this.title = title; this.filter = filter; 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 87d345467..1d34591d3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/MentionsAdapter.java @@ -22,6 +22,9 @@ import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; @@ -29,6 +32,7 @@ import org.telegram.messenger.DialogObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; @@ -61,19 +65,18 @@ import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.Objects; - -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.RecyclerView; public class MentionsAdapter extends RecyclerListView.SelectionAdapter implements NotificationCenter.NotificationCenterDelegate { public interface MentionsAdapterDelegate { void needChangePanelVisibility(boolean show); + void onItemCountUpdate(int oldCount, int newCount); void onContextSearch(boolean searching); void onContextClick(TLRPC.BotInlineResult result); } + private final boolean USE_DIVIDERS = false; + private int currentAccount = UserConfig.selectedAccount; private Context mContext; private long dialog_id; @@ -170,7 +173,6 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement }; public MentionsAdapter(Context context, boolean darkTheme, long did, int threadMessageId, MentionsAdapterDelegate mentionsAdapterDelegate, Theme.ResourcesProvider resourcesProvider) { -// setHasStableIds(true); this.resourcesProvider = resourcesProvider; mContext = context; delegate = mentionsAdapterDelegate; @@ -204,7 +206,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement String fileName = (String) args[0]; stickersToLoad.remove(fileName); if (stickersToLoad.isEmpty()) { - delegate.needChangePanelVisibility(stickers != null && !stickers.isEmpty()); + delegate.needChangePanelVisibility(getItemCountInternal() > 0); } } } @@ -218,10 +220,14 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement if (stickersMap != null && stickersMap.containsKey(key)) { return; } + if (!UserConfig.getInstance(currentAccount).isPremium() && MessageObject.isPremiumSticker(document)) { + return; + } if (stickers == null) { stickers = new ArrayList<>(); stickersMap = new HashMap<>(); } + stickers.add(new StickerResult(document, parent)); stickersMap.put(key, document); if (mentionsStickersActionTracker != null) { @@ -239,9 +245,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement if (stickersMap != null && stickersMap.containsKey(key)) { continue; } - if (stickers == null) { - stickers = new ArrayList<>(); - stickersMap = new HashMap<>(); + if (!UserConfig.getInstance(currentAccount).isPremium() && MessageObject.isPremiumSticker(document)) { + continue; } for (int b = 0, size2 = document.attributes.size(); b < size2; b++) { TLRPC.DocumentAttribute attribute = document.attributes.get(b); @@ -250,46 +255,15 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement break; } } + if (stickers == null) { + stickers = new ArrayList<>(); + stickersMap = new HashMap<>(); + } stickers.add(new StickerResult(document, parent)); stickersMap.put(key, document); } } -// public long getItemIdInternal(int position) { -// try { -// if (stickers != null) { -// return stickers.get(position).sticker.id; -// } else if (foundContextBot != null && !inlineMediaEnabled) { -// return foundContextBot.id; -// } else if (searchResultBotContext != null) { -// if (position == 0 && searchResultBotContextSwitch != null) { -// return -1; -// } -// return searchResultBotContext.get(position - (searchResultBotContextSwitch != null ? 1 : 0)).query_id; -// } else if (searchResultUsernames != null) { -// TLObject obj = searchResultUsernames.get(position); -// if (obj instanceof TLRPC.User) { -// return ((TLRPC.User) obj).id; -// } else if (obj instanceof TLRPC.Chat) { -// return ((TLRPC.Chat) obj).id; -// } -// return obj.hashCode(); -// } else if (searchResultHashtags != null) { -// return searchResultHashtags.get(position).hashCode(); -// } else if (searchResultCommands != null) { -// return searchResultCommands.get(position).hashCode(); -// } else if (searchResultSuggestions != null) { -// return searchResultSuggestions.get(position).emoji.hashCode(); -// } -// } catch (Exception ignore) {} -// return 0; -// } -// -// @Override -// public long getItemId(int position) { -// return Objects.hash(getItemIdInternal(position), getItemCount() < 5 ? getItemCount() - position : position); -// } - private boolean checkStickerFilesExistAndDownload() { if (stickers == null) { return false; @@ -300,7 +274,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement StickerResult result = stickers.get(a); TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(result.sticker.thumbs, 90); if (thumb instanceof TLRPC.TL_photoSize || thumb instanceof TLRPC.TL_photoSizeProgressive) { - File f = FileLoader.getPathToAttach(thumb, "webp", true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(thumb, "webp", true); if (!f.exists()) { stickersToLoad.add(FileLoader.getAttachFileName(thumb, "webp")); FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(thumb, result.sticker), result.parent, "webp", 1, 1); @@ -339,7 +313,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement int newCount = stickers != null ? stickers.size() : 0; if (!visibleByStickersSearch && stickers != null && !stickers.isEmpty()) { checkStickerFilesExistAndDownload(); - delegate.needChangePanelVisibility(stickersToLoad.isEmpty()); + delegate.needChangePanelVisibility(getItemCountInternal() > 0); visibleByStickersSearch = true; } if (oldCount != newCount) { @@ -348,6 +322,69 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement })); } + private Object[] lastData; + + @Override + public void notifyDataSetChanged() { + if (lastItemCount == -1 || lastData == null) { + if (delegate != null) { + delegate.onItemCountUpdate(0, getItemCount()); + } + super.notifyDataSetChanged(); + lastData = new Object[getItemCount()]; + for (int i = 0; i < lastData.length; ++i) { + lastData[i] = getItem(i); + } + } else { + int oldCount = lastItemCount, newCount = getItemCount(); + boolean hadChanges = oldCount != newCount; + int min = Math.min(oldCount, newCount); + Object[] newData = new Object[newCount]; + for (int i = 0; i < newCount; ++i) { + newData[i] = getItem(i); + } + for (int i = 0; i < min; ++i) { + if (i < 0 || i >= lastData.length || i >= newData.length || !itemsEqual(lastData[i], newData[i])) { + notifyItemChanged(i); + hadChanges = true; + } else if ((i == oldCount - 1) != (i == newCount - 1) && USE_DIVIDERS) { + notifyItemChanged(i); // divider update + } + } + notifyItemRangeRemoved(min, oldCount - min); + notifyItemRangeInserted(min, newCount - min); + if (hadChanges && delegate != null) { + delegate.onItemCountUpdate(oldCount, newCount); + } + lastData = newData; + } + + } + + private boolean itemsEqual(Object a, Object b) { + if (a == b) { + return true; + } + if (a instanceof MentionsAdapter.StickerResult && b instanceof MentionsAdapter.StickerResult && ((StickerResult) a).sticker == ((StickerResult) b).sticker) { + return true; + } + if (a instanceof TLRPC.User && b instanceof TLRPC.User && ((TLRPC.User) a).id == ((TLRPC.User) b).id) { + return true; + } + if (a instanceof TLRPC.Chat && b instanceof TLRPC.Chat && ((TLRPC.Chat) a).id == ((TLRPC.Chat) b).id) { + return true; + } + if (a instanceof String && b instanceof String && a.equals(b)) { + return true; + } + if (a instanceof MediaDataController.KeywordResult && b instanceof MediaDataController.KeywordResult && + ((MediaDataController.KeywordResult) a).keyword != null && ((MediaDataController.KeywordResult) a).keyword.equals(((MediaDataController.KeywordResult) b).keyword) && + ((MediaDataController.KeywordResult) a).emoji != null && ((MediaDataController.KeywordResult) a).emoji.equals(((MediaDataController.KeywordResult) b).emoji)) { + return true; + } + return false; + } + private void clearStickers() { lastSticker = null; stickers = null; @@ -518,9 +555,6 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement if (foundContextBot != null && foundContextBot.username != null && foundContextBot.username.equals(username) && searchingContextQuery != null && searchingContextQuery.equals(query)) { return; } - searchResultBotContext = null; - searchResultBotContextSwitch = null; - notifyDataSetChanged(); if (foundContextBot != null) { if (!inlineMediaEnabled && username != null && query != null) { return; @@ -609,6 +643,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement } } processFoundUser(user); + contextUsernameReqid = 0; })); } } @@ -992,7 +1027,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement lastText = text; lastPosition = position; messages = messageObjects; - delegate.needChangePanelVisibility(false); +// delegate.needChangePanelVisibility(false); return; } } else if (a == 0 && botInfo != null && ch == '/') { @@ -1234,7 +1269,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement searchResultCommandsUsers = null; searchResultSuggestions = null; notifyDataSetChanged(); - delegate.needChangePanelVisibility(!newResult.isEmpty()); + delegate.needChangePanelVisibility(!searchResultHashtags.isEmpty()); } else if (foundType == 2) { ArrayList newResult = new ArrayList<>(); ArrayList newResultHelp = new ArrayList<>(); @@ -1290,6 +1325,20 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement } } + private boolean isReversed = false; + public void setIsReversed(boolean isReversed) { + if (this.isReversed != isReversed) { + this.isReversed = isReversed; + int itemCount = getLastItemCount(); + if (itemCount > 0) { + notifyItemChanged(0); + } + if (itemCount > 1) { + notifyItemChanged(itemCount - 1); + } + } + } + private void showUsersResult(ArrayList newResult, LongSparseArray newMap, boolean notify) { searchResultUsernames = newResult; searchResultUsernamesMap = newMap; @@ -1297,6 +1346,8 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement AndroidUtilities.cancelRunOnUIThread(cancelDelayRunnable); cancelDelayRunnable = null; } + searchResultBotContext = null; + stickers = null; if (notify) { notifyDataSetChanged(); delegate.needChangePanelVisibility(!searchResultUsernames.isEmpty()); @@ -1315,14 +1366,24 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement return searchResultBotContext; } + private int lastItemCount = -1; + @Override public int getItemCount() { + return lastItemCount = getItemCountInternal(); + } + + public int getLastItemCount() { + return lastItemCount; + } + + public int getItemCountInternal() { if (foundContextBot != null && !inlineMediaEnabled) { return 1; } if (stickers != null) { return stickers.size(); - }else if (searchResultBotContext != null) { + } else if (searchResultBotContext != null) { return searchResultBotContext.size() + (searchResultBotContextSwitch != null ? 1 : 0); } else if (searchResultUsernames != null) { return searchResultUsernames.size(); @@ -1336,6 +1397,33 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement return 0; } + public void clear(boolean safe) { + if (safe && (channelReqId != 0 || contextQueryReqid != 0 || contextUsernameReqid != 0 || lastReqId != 0)) { + return; + } + foundContextBot = null; + if (stickers != null) { + stickers.clear(); + } + if (searchResultBotContext != null) { + searchResultBotContext.clear(); + } + searchResultBotContextSwitch = null; + if (searchResultUsernames != null) { + searchResultUsernames.clear(); + } + if (searchResultHashtags != null) { + searchResultHashtags.clear(); + } + if (searchResultCommands != null) { + searchResultCommands.clear(); + } + if (searchResultSuggestions != null) { + searchResultSuggestions.clear(); + } + notifyDataSetChanged(); + } + @Override public int getItemViewType(int position) { if (stickers != null) { @@ -1447,7 +1535,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement View view; switch (viewType) { case 0: - view = new MentionCell(mContext); + view = new MentionCell(mContext, resourcesProvider); ((MentionCell) view).setIsDarkTheme(isDarkTheme); break; case 1: @@ -1519,6 +1607,7 @@ public class MentionsAdapter extends RecyclerListView.SelectionAdapter implement } else if (searchResultCommands != null) { ((MentionCell) holder.itemView).setBotCommand(searchResultCommands.get(position), searchResultCommandsHelp.get(position), searchResultCommandsUsers != null ? searchResultCommandsUsers.get(position) : null); } + ((MentionCell) holder.itemView).setDivider(USE_DIVIDERS && (isReversed ? position > 0 : position < getItemCount() - 1)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PaddedListAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PaddedListAdapter.java new file mode 100644 index 000000000..786ee81cc --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PaddedListAdapter.java @@ -0,0 +1,159 @@ +package org.telegram.ui.Adapters; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; +import android.widget.WrapperListAdapter; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.ui.Components.RecyclerListView; + +/** + * PaddedListAdapter wraps list adapter and adds transparent padding view at the start + */ +public class PaddedListAdapter extends RecyclerListView.SelectionAdapter { + + private final int PADDING_VIEW_TYPE = -983904; + + private RecyclerListView.SelectionAdapter wrappedAdapter; + private GetPaddingRunnable getPaddingRunnable; + private Integer padding = null; + public View paddingView; + + public boolean paddingViewAttached = false; + + public PaddedListAdapter(RecyclerListView.SelectionAdapter adapter) { + wrappedAdapter = adapter; + wrappedAdapter.registerAdapterDataObserver(mDataObserver); + } + public PaddedListAdapter(RecyclerListView.SelectionAdapter adapter, GetPaddingRunnable getPaddingRunnable) { + wrappedAdapter = adapter; + wrappedAdapter.registerAdapterDataObserver(mDataObserver); + this.getPaddingRunnable = getPaddingRunnable; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + if (holder.getAdapterPosition() == 0) { + return false; + } + return wrappedAdapter.isEnabled(holder); + } + + public interface GetPaddingRunnable { + public int run(int parentHeight); + } + + public void setPadding(int padding) { + this.padding = padding; + if (paddingView != null) { + paddingView.requestLayout(); + } + } + + public void setPadding(GetPaddingRunnable getPaddingRunnable) { + this.getPaddingRunnable = getPaddingRunnable; + if (paddingView != null) { + paddingView.requestLayout(); + } + } + + private int getPadding(int parentHeight) { + if (padding != null) { + return lastPadding = padding; + } else if (getPaddingRunnable != null) { + return lastPadding = getPaddingRunnable.run(parentHeight); + } else { + return lastPadding = 0; + } + } + + private int lastPadding; + public int getPadding() { + return lastPadding; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == PADDING_VIEW_TYPE) { + return new RecyclerListView.Holder(paddingView = new View(parent.getContext()) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int parentHeight = ((View) getParent()).getMeasuredHeight(); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getPadding(parentHeight), MeasureSpec.EXACTLY)); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + paddingViewAttached = true; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + paddingViewAttached = false; + } + }); + } + return wrappedAdapter.onCreateViewHolder(parent, viewType); + } + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return PADDING_VIEW_TYPE; + } + return wrappedAdapter.getItemViewType(position - 1); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + if (position > 0) { + wrappedAdapter.onBindViewHolder(holder, position - 1); + } + } + + @Override + public int getItemCount() { + return 1 + wrappedAdapter.getItemCount(); + } + + private RecyclerView.AdapterDataObserver mDataObserver = new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + super.onChanged(); + notifyDataSetChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + super.onItemRangeChanged(positionStart, itemCount); + notifyItemRangeChanged(1 + positionStart, itemCount); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + super.onItemRangeInserted(positionStart, itemCount); + notifyItemRangeInserted(1 + positionStart, itemCount); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + super.onItemRangeRemoved(positionStart, itemCount); + notifyItemRangeRemoved(1 + positionStart, itemCount); + } + + @Override + public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { + super.onItemRangeMoved(fromPosition, toPosition, itemCount); + notifyItemRangeChanged(1 + fromPosition, 1 + toPosition + itemCount); + } + }; + + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java index e0376f6c3..642f12472 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapterHelper.java @@ -77,6 +77,7 @@ public class SearchAdapterHelper { private LongSparseArray phoneSearchMap = new LongSparseArray<>(); private ArrayList phonesSearch = new ArrayList<>(); private ArrayList localSearchResults; + private ArrayList localRecentResults; private int currentAccount = UserConfig.selectedAccount; @@ -328,7 +329,7 @@ public class SearchAdapterHelper { } removeGroupSearchFromGlobal(); if (localSearchResults != null) { - mergeResults(localSearchResults); + mergeResults(localSearchResults, localRecentResults); } mergeExcludeResults(); delegate.onDataSetChanged(searchId); @@ -415,13 +416,23 @@ public class SearchAdapterHelper { } public void mergeResults(ArrayList localResults) { + mergeResults(localResults, null); + } + + public void mergeResults(ArrayList localResults, ArrayList recentResults) { localSearchResults = localResults; - if (globalSearchMap.size() == 0 || localResults == null) { + localRecentResults = recentResults; + if (globalSearchMap.size() == 0 || localResults == null && recentResults == null) { return; } - int count = localResults.size(); + final int localResultsCount = localResults == null ? 0 : localResults.size(); + final int recentResultsCount = recentResults == null ? 0 : recentResults.size(); + int count = localResultsCount + recentResultsCount; for (int a = 0; a < count; a++) { - Object obj = localResults.get(a); + Object obj = a < localResultsCount ? localResults.get(a) : recentResults.get(a - localResultsCount); + if (obj instanceof DialogsSearchAdapter.RecentSearchObject) { + obj = ((DialogsSearchAdapter.RecentSearchObject) obj).object; + } if (obj instanceof ShareAlert.DialogSearchResult) { ShareAlert.DialogSearchResult searchResult = (ShareAlert.DialogSearchResult) obj; obj = searchResult.object; 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 a00962659..e75f41b52 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java @@ -12,13 +12,15 @@ import android.content.Context; import android.text.TextUtils; import android.view.ViewGroup; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.UserConfig; -import org.telegram.messenger.FileLoader; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.EmojiReplacementCell; @@ -28,8 +30,6 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; -import androidx.recyclerview.widget.RecyclerView; - public class StickersAdapter extends RecyclerListView.SelectionAdapter implements NotificationCenter.NotificationCenterDelegate { private int currentAccount = UserConfig.selectedAccount; @@ -136,7 +136,7 @@ public class StickersAdapter extends RecyclerListView.SelectionAdapter implement TLRPC.Document animatedSticker = MediaDataController.getInstance(currentAccount).getEmojiAnimatedSticker(emoji); if (animatedSticker != null) { ArrayList sets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_EMOJI); - File f = FileLoader.getPathToAttach(animatedSticker, true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(animatedSticker, true); if (!f.exists()) { FileLoader.getInstance(currentAccount).loadFile(ImageLocation.getForDocument(animatedSticker), sets.get(0), null, 1, 1); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java index ee7898d49..30fe1e118 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ArticleViewer.java @@ -530,6 +530,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); +// sizeBar.setSeparatorsCount(endFontSize - startFontSize); sizeBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { @Override public void onSeekBarDrag(boolean stop, float progress) { @@ -1302,7 +1303,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg popupWindow.dismiss(); } }); - popupLayout.setShownFromBotton(false); + popupLayout.setShownFromBottom(false); deleteView = new TextView(parentActivity); deleteView.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 2)); @@ -4897,13 +4898,13 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (photo != null) { TLRPC.PhotoSize sizeFull = FileLoader.getClosestPhotoSizeWithSize(photo.sizes, AndroidUtilities.getPhotoSize()); if (sizeFull != null) { - return FileLoader.getPathToAttach(sizeFull, true); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(sizeFull, true); } } } else if (block instanceof TLRPC.TL_pageBlockVideo) { TLRPC.Document document = getDocumentWithId(page, ((TLRPC.TL_pageBlockVideo) block).video_id); if (document != null) { - return FileLoader.getPathToAttach(document, true); + return FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); } } return null; @@ -6183,7 +6184,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg if (isGif) { autoDownload = DownloadController.getInstance(currentAccount).canDownloadMedia(DownloadController.AUTODOWNLOAD_TYPE_VIDEO, currentDocument.size); - File path = FileLoader.getPathToAttach(currentDocument, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); if (autoDownload || path.exists()) { imageView.setStrippedLocation(null); imageView.setImage(ImageLocation.getForDocument(currentDocument), ImageLoader.AUTOPLAY_FILTER, null, null, ImageLocation.getForDocument(thumb, currentDocument), "80_80_b", null, currentDocument.size, null, parentAdapter.currentPage, 1); @@ -6281,7 +6282,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public void updateButtonState(boolean animated) { String fileName = FileLoader.getAttachFileName(currentDocument); - File path = FileLoader.getPathToAttach(currentDocument, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); boolean fileExists = path.exists(); if (TextUtils.isEmpty(fileName)) { radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, false); @@ -6689,7 +6690,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public void updateButtonState(boolean animated) { String fileName = FileLoader.getAttachFileName(currentDocument); - File path = FileLoader.getPathToAttach(currentDocument, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentDocument, true); boolean fileExists = path.exists(); if (TextUtils.isEmpty(fileName)) { radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, false); @@ -9925,7 +9926,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg isFirst = first; channelCell.setVisibility(INVISIBLE); if (!TextUtils.isEmpty(currentBlock.url)) { - linkDrawable = getResources().getDrawable(R.drawable.instant_link); + linkDrawable = getResources().getDrawable(R.drawable.msg_instant_link); } if (currentBlock != null) { TLRPC.Photo photo = parentAdapter.getPhotoWithId(currentBlock.photo_id); @@ -10061,7 +10062,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg currentThumbFilter = "80_80_b"; autoDownload = (DownloadController.getInstance(currentAccount).getCurrentDownloadMask() & DownloadController.AUTODOWNLOAD_TYPE_PHOTO) != 0; - File path = FileLoader.getPathToAttach(currentPhotoObject, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentPhotoObject, true); if (autoDownload || path.exists()) { imageView.setStrippedLocation(null); imageView.setImage(ImageLocation.getForPhoto(currentPhotoObject, currentPhoto), currentFilter, ImageLocation.getForPhoto(currentPhotoObjectThumb, currentPhoto), currentThumbFilter, currentPhotoObject.size, null, parentAdapter.currentPage, 1); @@ -10177,7 +10178,7 @@ public class ArticleViewer implements NotificationCenter.NotificationCenterDeleg public void updateButtonState(boolean animated) { String fileName = FileLoader.getAttachFileName(currentPhotoObject); - File path = FileLoader.getPathToAttach(currentPhotoObject, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(currentPhotoObject, true); boolean fileExists = path.exists(); if (TextUtils.isEmpty(fileName)) { radialProgress.setIcon(MediaActionDrawable.ICON_NONE, false, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java index b979d6559..eef8f315e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/AvatarPreviewer.java @@ -387,6 +387,7 @@ public class AvatarPreviewer { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); + imageReceiver.onAttachedToWindow(); NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(UserConfig.selectedAccount).addObserver(this, NotificationCenter.fileLoadProgressChanged); } @@ -394,6 +395,7 @@ public class AvatarPreviewer { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + imageReceiver.onDetachedFromWindow(); NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoaded); NotificationCenter.getInstance(UserConfig.selectedAccount).removeObserver(this, NotificationCenter.fileLoadProgressChanged); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index a0bf6adb9..099e9156c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -43,6 +43,7 @@ import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; @@ -154,10 +155,12 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe return; } documentsSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), 1); + documentsSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), 1); if (canceled) { return; } musicSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), 2); + musicSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), 2); if (canceled) { return; } @@ -348,6 +351,13 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false); } } + if (type == FileLoader.MEDIA_DIR_DOCUMENT) { + file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES); + if (file != null) { + Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false); + } + } + if (type == FileLoader.MEDIA_DIR_CACHE) { cacheSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE), documentsMusicType); imagesCleared = true; @@ -366,8 +376,10 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } else if (type == FileLoader.MEDIA_DIR_DOCUMENT) { if (documentsMusicType == 1) { documentsSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), documentsMusicType); + documentsSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), documentsMusicType); } else { musicSize = getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_DOCUMENT), documentsMusicType); + musicSize += getDirectorySize(FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES), documentsMusicType); } } else if (type == FileLoader.MEDIA_DIR_IMAGE) { imagesCleared = true; @@ -427,8 +439,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe getMediaDataController().ringtoneDataStore.checkRingtoneSoundsLoaded(); cacheRemovedTooltip.setInfoText(LocaleController.formatString("CacheWasCleared", R.string.CacheWasCleared, AndroidUtilities.formatFileSize(finalClearedSize))); cacheRemovedTooltip.showWithAction(0, UndoView.ACTION_CACHE_WAS_CLEARED, null, null); - - getMediaDataController().loadAttachMenuBots(false, true); + MediaDataController.getInstance(currentAccount).chekAllMedia(true); }); }); } @@ -481,6 +492,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe return false; } }; + bottomSheet.fixNavigationBar(); bottomSheet.setAllowNestedScroll(true); bottomSheet.setApplyBottomPadding(false); LinearLayout linearLayout = new LinearLayout(getParentActivity()); @@ -807,7 +819,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } if (actionTextView != null) { - actionTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + actionTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); } }; ArrayList arrayList = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java index dc9c3f422..8ff67b7c7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CalendarActivity.java @@ -640,7 +640,7 @@ public class CalendarActivity extends BaseFragment { } } else { PeriodDay day = getDayAtCoord(e.getX(), e.getY()); - if (parentLayout.fragmentsStack.size() >= 2) { + if (day != null && parentLayout.fragmentsStack.size() >= 2) { BaseFragment fragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2); if (fragment instanceof ChatActivity) { finishFragment(); @@ -777,7 +777,6 @@ public class CalendarActivity extends BaseFragment { prepareBlurBitmap(); presentFragmentAsPreviewWithMenu(chatActivity, previewMenu); - } } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java index 4069be915..86258b500 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CallLogActivity.java @@ -93,8 +93,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. private boolean firstLoaded; private boolean endReached; - private ProgressButton waitingForLoadButton; - private ArrayList activeGroupCalls; private ArrayList selectedIds = new ArrayList<>(); @@ -281,9 +279,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. if (chatFull.id == waitingForCallChatId) { ChatObject.Call groupCall = getMessagesController().getGroupCall(waitingForCallChatId, true); if (groupCall != null) { - if (waitingForLoadButton != null) { - waitingForLoadButton.setDrawProgress(false, false); - } VoIPHelper.startCall(lastCallChat, null, null, false, getParentActivity(), CallLogActivity.this, getAccountInstance()); waitingForCallChatId = null; } @@ -294,9 +289,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. } Long chatId = (Long) args[0]; if (waitingForCallChatId.equals(chatId)) { - if (waitingForLoadButton != null) { - waitingForLoadButton.setDrawProgress(false, false); - } VoIPHelper.startCall(lastCallChat, null, null, false, getParentActivity(), CallLogActivity.this, getAccountInstance()); waitingForCallChatId = null; } @@ -369,14 +361,13 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. addView(profileSearchCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); button.setText(text); + button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); button.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); button.setProgressColor(Theme.getColor(Theme.key_featuredStickers_buttonProgress)); - button.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed)); - addView(button, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 18, 14, 0)); + button.setBackgroundRoundRect(Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed), 16); + button.setPadding(AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14), 0); + addView(button, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.END, 0, 16, 14, 0)); button.setOnClickListener(v -> { - if (waitingForLoadButton != null) { - waitingForLoadButton.setDrawProgress(false, true); - } Long tag = (Long) v.getTag(); ChatObject.Call call = getMessagesController().getGroupCall(tag, false); lastCallChat = getMessagesController().getChat(tag); @@ -385,8 +376,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. } else { waitingForCallChatId = tag; getMessagesController().loadFullChat(tag, 0, true); - button.setDrawProgress(true, true); - waitingForLoadButton = button; + } }); } @@ -1005,7 +995,7 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; case 3: - view = new HeaderCell(mContext); + view = new HeaderCell(mContext, Theme.key_windowBackgroundWhiteBlueHeader, 21, 15, 2, false, getResourceProvider()); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; case 4: @@ -1023,15 +1013,6 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. if (holder.itemView instanceof CallCell) { CallLogRow row = calls.get(holder.getAdapterPosition() - callsStartRow); ((CallCell) holder.itemView).setChecked(isSelected(row.calls), false); - } else if (holder.itemView instanceof GroupCallCell) { - GroupCallCell cell = (GroupCallCell) holder.itemView; - TLRPC.Chat chat = cell.profileSearchCell.getChat(); - if (waitingForCallChatId != null && chat.id == waitingForCallChatId) { - waitingForLoadButton = cell.button; - cell.button.setDrawProgress(true, false); - } else { - cell.button.setDrawProgress(false, false); - } } } @@ -1102,8 +1083,8 @@ public class CallLogActivity extends BaseFragment implements NotificationCenter. text = LocaleController.getString("MegaPublic", R.string.MegaPublic).toLowerCase(); } } + cell.profileSearchCell.useSeparator = position != activeGroupCalls.size() - 1 && !endReached; cell.profileSearchCell.setData(chat, null, null, text, false, false); - cell.profileSearchCell.useSeparator = position != activeGroupCalls.size() - 1 || !endReached; break; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java index 755348df6..1e58b4fb5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CameraScanActivity.java @@ -103,6 +103,7 @@ public class CameraScanActivity extends BaseFragment { private ImageView flashButton; private AnimatorSet flashAnimator; private float backShadowAlpha = .5f; + protected boolean shownAsBottomSheet = false; private SpringAnimation qrAppearing = null; private float qrAppearingValue = 0; @@ -119,7 +120,7 @@ public class CameraScanActivity extends BaseFragment { private int recognizeIndex = 0; private String recognizedText; - private int sps; // samples per second (already when recognized) + private int sps; // samples per second (when already recognized) private boolean qrLoading = false; private boolean qrLoaded = false; @@ -176,6 +177,7 @@ public class CameraScanActivity extends BaseFragment { dismiss(); } }; + fragment.shownAsBottomSheet = true; fragment.needGalleryButton = gallery; fragment.any = any; actionBarLayout[0].addFragmentToStack(fragment); @@ -210,9 +212,8 @@ public class CameraScanActivity extends BaseFragment { }; bottomSheet.setUseLightStatusBar(false); AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - bottomSheet.getWindow().setNavigationBarColor(0xff000000); - } + AndroidUtilities.setNavigationBarColor(bottomSheet.getWindow(), 0xff000000, false); + bottomSheet.setUseLightStatusBar(false); bottomSheet.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); bottomSheet.show(); return actionBarLayout; @@ -260,8 +261,15 @@ public class CameraScanActivity extends BaseFragment { @Override public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); - actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarWhiteSelector), false); + if (shownAsBottomSheet) { + actionBar.setItemsColor(0xffffffff, false); + actionBar.setItemsBackgroundColor(0xffffffff, false); + actionBar.setTitleColor(0xffffffff); + } else { + actionBar.setItemsColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_actionBarWhiteSelector), false); + actionBar.setTitleColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); + } actionBar.setCastShadows(false); if (!AndroidUtilities.isTablet() && !isQr()) { actionBar.showActionModeTop(); @@ -431,7 +439,7 @@ public class CameraScanActivity extends BaseFragment { fragmentView = viewGroup; if (currentType == TYPE_QR || currentType == TYPE_QR_LOGIN) { - fragmentView.postDelayed(this::initCameraView, 350); + fragmentView.postDelayed(this::initCameraView, 450); } else { initCameraView(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java index edb9a7195..8cd94c6d9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AboutLinkCell.java @@ -27,6 +27,7 @@ import android.text.StaticLayout; import android.text.TextUtils; import android.text.style.ClickableSpan; import android.text.style.URLSpan; +import android.text.util.Linkify; import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; @@ -81,13 +82,19 @@ public class AboutLinkCell extends FrameLayout { private LinkPath urlPath = new LinkPath(true); private BaseFragment parentFragment; + private Theme.ResourcesProvider resourcesProvider; private FrameLayout container; private Drawable rippleBackground; public AboutLinkCell(Context context, BaseFragment fragment) { + this(context, fragment, null); + } + + public AboutLinkCell(Context context, BaseFragment fragment, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; parentFragment = fragment; container = new FrameLayout(context) { @@ -140,24 +147,26 @@ public class AboutLinkCell extends FrameLayout { return result || super.onTouchEvent(event); } }; + container.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); links = new LinkSpanDrawable.LinkCollector(container); container.setClickable(true); - rippleBackground = Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector), 0, 0); + rippleBackground = Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), 0, 0); valueTextView = new EmojiTextView(context); valueTextView.setVisibility(GONE); - valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); valueTextView.setLines(1); valueTextView.setMaxLines(1); valueTextView.setSingleLine(true); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); valueTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); + valueTextView.setFocusable(false); container.addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.BOTTOM, 23, 0, 23, 10)); bottomShadow = new FrameLayout(context); Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.gradient_bottom).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhite), PorterDuff.Mode.SRC_ATOP)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider), PorterDuff.Mode.SRC_ATOP)); bottomShadow.setBackground(shadowDrawable); addView(bottomShadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 12, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, 0)); @@ -188,7 +197,7 @@ public class AboutLinkCell extends FrameLayout { super.onDraw(canvas); } }; - showMoreTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText)); + showMoreTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider)); showMoreTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); showMoreTextView.setLines(1); showMoreTextView.setMaxLines(1); @@ -200,7 +209,7 @@ public class AboutLinkCell extends FrameLayout { showMoreTextView.setPadding(AndroidUtilities.dp(2), 0, AndroidUtilities.dp(2), 0); showMoreTextBackgroundView = new FrameLayout(context); showMoreBackgroundDrawable = context.getResources().getDrawable(R.drawable.gradient_left).mutate(); - showMoreBackgroundDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhite), PorterDuff.Mode.MULTIPLY)); + showMoreBackgroundDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider), PorterDuff.Mode.MULTIPLY)); showMoreTextBackgroundView.setBackground(showMoreBackgroundDrawable); showMoreTextBackgroundView.setPadding( showMoreTextBackgroundView.getPaddingLeft() + AndroidUtilities.dp(4), @@ -210,7 +219,7 @@ public class AboutLinkCell extends FrameLayout { ); showMoreTextBackgroundView.addView(showMoreTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); addView(showMoreTextBackgroundView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.BOTTOM, 22 - showMoreTextBackgroundView.getPaddingLeft() / AndroidUtilities.density, 0, 22 - showMoreTextBackgroundView.getPaddingRight() / AndroidUtilities.density, 6)); - backgroundPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + backgroundPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); setWillNotDraw(false); } @@ -421,7 +430,7 @@ public class AboutLinkCell extends FrameLayout { if (left <= x && left + textLayout.getLineWidth(line) >= x && y >= 0 && y <= textLayout.getHeight()) { Spannable buffer = (Spannable) textLayout.getText(); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); - if (link.length != 0) { + if (link.length != 0 && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { resetPressedLink(); pressedLink = new LinkSpanDrawable(link[0], parentFragment.getResourceProvider(), ex, ey); links.addLink(pressedLink); @@ -467,7 +476,7 @@ public class AboutLinkCell extends FrameLayout { private static final int COLLAPSED_HEIGHT = AndroidUtilities.dp(8 + 20 * 3 + 8); private static final int MAX_OPEN_HEIGHT = COLLAPSED_HEIGHT;// + AndroidUtilities.dp(20); - private class SpringInterpolator { + public class SpringInterpolator { public float tension; public float friction; public SpringInterpolator(float tension, float friction) { @@ -713,8 +722,9 @@ public class AboutLinkCell extends FrameLayout { public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); if (textLayout != null) { - final CharSequence text = textLayout.getText(); + final CharSequence text = stringBuilder; final CharSequence valueText = valueTextView.getText(); + info.setClassName("android.widget.TextView"); if (TextUtils.isEmpty(valueText)) { info.setText(text); } else { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java index 79d6e736e..0780942da 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AdminedChannelCell.java @@ -14,12 +14,10 @@ import android.graphics.PorterDuffColorFilter; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.view.Gravity; -import android.view.View; import android.widget.FrameLayout; import android.widget.ImageView; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -29,6 +27,7 @@ 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.CheckBox2; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.URLSpanNoUnderline; @@ -42,35 +41,47 @@ public class AdminedChannelCell extends FrameLayout { private TLRPC.Chat currentChannel; private boolean isLast; private int currentAccount = UserConfig.selectedAccount; + CheckBox2 checkBox; - public AdminedChannelCell(Context context, View.OnClickListener onClickListener) { + public AdminedChannelCell(Context context, OnClickListener onClickListener, boolean needCheck, int padding) { super(context); avatarDrawable = new AvatarDrawable(); - avatarImageView = new BackupImageView(context); avatarImageView.setRoundRadius(AndroidUtilities.dp(24)); - addView(avatarImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12, 12, LocaleController.isRTL ? 12 : 0, 0)); + addView(avatarImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 12 + padding, 6, LocaleController.isRTL ? 12 + padding : 0, 6)); + if (needCheck) { + checkBox = new CheckBox2(context, 21); + checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); + checkBox.setDrawUnchecked(false); + checkBox.setDrawBackgroundAsArc(3); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 42 + padding, 32, LocaleController.isRTL ? 42 + padding: 0, 0)); + } + + int leftPadding = onClickListener == null ? 24 : 62; nameTextView = new SimpleTextView(context); nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); nameTextView.setTextSize(17); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 62 : 73, 15.5f, LocaleController.isRTL ? 73 : 62, 0)); + addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? leftPadding : 73 + padding, 9.5f, LocaleController.isRTL ? 73 + padding: leftPadding, 0)); statusTextView = new SimpleTextView(context); statusTextView.setTextSize(14); statusTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); statusTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); statusTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); - addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 62 : 73, 38.5f, LocaleController.isRTL ? 73 : 62, 0)); + addView(statusTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? leftPadding : 73 + padding, 32.5f, LocaleController.isRTL ? 73 + padding : leftPadding, 6)); - deleteButton = new ImageView(context); - deleteButton.setScaleType(ImageView.ScaleType.CENTER); - deleteButton.setImageResource(R.drawable.msg_panel_clear); - deleteButton.setOnClickListener(onClickListener); - deleteButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.SRC_IN)); - addView(deleteButton, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 7 : 0, 12, LocaleController.isRTL ? 0 : 7, 0)); + if (onClickListener != null) { + deleteButton = new ImageView(context); + deleteButton.setScaleType(ImageView.ScaleType.CENTER); + deleteButton.setImageResource(R.drawable.msg_panel_clear); + deleteButton.setOnClickListener(onClickListener); + deleteButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector))); + deleteButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText), PorterDuff.Mode.SRC_IN)); + addView(deleteButton, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 7 : 0, 6, LocaleController.isRTL ? 0 : 7, 0)); + } } public void setChannel(TLRPC.Chat channel, boolean last) { @@ -115,4 +126,8 @@ public class AdminedChannelCell extends FrameLayout { public ImageView getDeleteButton() { return deleteButton; } + + public void setChecked(boolean checked, boolean animated) { + checkBox.setChecked(checked, animated); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AppIconsSelectorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AppIconsSelectorCell.java new file mode 100644 index 000000000..1c1272095 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AppIconsSelectorCell.java @@ -0,0 +1,343 @@ +package org.telegram.ui.Cells; + +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.Path; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.text.Spannable; +import android.text.SpannableString; +import android.util.DisplayMetrics; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.LinearSmoothScroller; +import androidx.recyclerview.widget.RecyclerView; + +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.UserConfig; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Bulletin; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.Easings; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.LauncherIconController; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class AppIconsSelectorCell extends RecyclerListView implements NotificationCenter.NotificationCenterDelegate { + public final static float ICONS_ROUND_RADIUS = 18; + + private List availableIcons = new ArrayList<>(); + private LinearLayoutManager linearLayoutManager; + private int currentAccount; + + public AppIconsSelectorCell(Context context, BaseFragment fragment, int currentAccount) { + super(context); + this.currentAccount = currentAccount; + setPadding(0, AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12)); + + setFocusable(false); + setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + setItemAnimator(null); + setLayoutAnimation(null); + + setLayoutManager(linearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); + setAdapter(new Adapter() { + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new RecyclerListView.Holder(new IconHolderView(parent.getContext())); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + IconHolderView holderView = (IconHolderView) holder.itemView; + LauncherIconController.LauncherIcon icon = availableIcons.get(position); + holderView.bind(icon); + holderView.iconView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(ICONS_ROUND_RADIUS), Color.TRANSPARENT, Theme.getColor(Theme.key_listSelector), Color.BLACK)); + holderView.iconView.setForeground(icon.foreground); + } + + @Override + public int getItemCount() { + return availableIcons.size(); + } + }); + addItemDecoration(new ItemDecoration() { + @Override + public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull State state) { + int pos = parent.getChildViewHolder(view).getAdapterPosition(); + if (pos == 0) { + outRect.left = AndroidUtilities.dp(18); + } + if (pos == getAdapter().getItemCount() - 1) { + outRect.right = AndroidUtilities.dp(18); + } else { + int itemCount = getAdapter().getItemCount(); + if (itemCount == 4) { + outRect.right = (getWidth() - AndroidUtilities.dp(36) - AndroidUtilities.dp(58) * itemCount) / (itemCount - 1); + } else { + outRect.right = AndroidUtilities.dp(24); + } + } + } + }); + setOnItemClickListener((view, position) -> { + IconHolderView holderView = (IconHolderView) view; + LauncherIconController.LauncherIcon icon = availableIcons.get(position); + if (icon.premium && !UserConfig.hasPremiumOnAccounts()) { + fragment.showDialog(new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS, true)); + return; + } + + if (LauncherIconController.isEnabled(icon)) { + return; + } + + LinearSmoothScroller smoothScroller = new LinearSmoothScroller(context) { + @Override + public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) { + return boxStart - viewStart + AndroidUtilities.dp(16); + } + + @Override + protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) { + return super.calculateSpeedPerPixel(displayMetrics) * 3f; + } + }; + smoothScroller.setTargetPosition(position); + linearLayoutManager.startSmoothScroll(smoothScroller); + + LauncherIconController.setIcon(icon); + holderView.setSelected(true, true); + + for (int i = 0; i < getChildCount(); i++) { + IconHolderView otherView = (IconHolderView) getChildAt(i); + if (otherView != holderView) { + otherView.setSelected(false, true); + } + } + + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_APP_ICON, icon); + }); + updateIconsVisibility(); + } + + @SuppressLint("NotifyDataSetChanged") + private void updateIconsVisibility() { + availableIcons.clear(); + availableIcons.addAll(Arrays.asList(LauncherIconController.LauncherIcon.values())); + if (MessagesController.getInstance(currentAccount).premiumLocked) { + for (int i = 0; i < availableIcons.size(); i++) { + if (availableIcons.get(i).premium) { + availableIcons.remove(i); + i--; + } + } + } + getAdapter().notifyDataSetChanged(); + invalidateItemDecorations(); + + for (int i = 0; i < availableIcons.size(); i++) { + LauncherIconController.LauncherIcon icon = availableIcons.get(i); + if (LauncherIconController.isEnabled(icon)) { + linearLayoutManager.scrollToPositionWithOffset(i, AndroidUtilities.dp(16)); + break; + } + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + invalidateItemDecorations(); + } + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthSpec), MeasureSpec.EXACTLY), heightSpec); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.premiumStatusChangedGlobal); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.premiumStatusChangedGlobal); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.premiumStatusChangedGlobal) { + updateIconsVisibility(); + } + } + + private final static class IconHolderView extends LinearLayout { + private Paint outlinePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private AdaptiveIconImageView iconView; + private TextView titleView; + + private float progress; + + private IconHolderView(@NonNull Context context) { + super(context); + + setOrientation(VERTICAL); + + setWillNotDraw(false); + iconView = new AdaptiveIconImageView(context); + iconView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + addView(iconView, LayoutHelper.createLinear(58, 58, Gravity.CENTER_HORIZONTAL)); + + titleView = new TextView(context); + titleView.setSingleLine(); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 4, 0, 0)); + + outlinePaint.setStyle(Paint.Style.STROKE); + outlinePaint.setStrokeWidth(Math.max(2, AndroidUtilities.dp(0.5f))); + } + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + + float stroke = outlinePaint.getStrokeWidth(); + AndroidUtilities.rectTmp.set(iconView.getLeft() + stroke, iconView.getTop() + stroke, iconView.getRight() - stroke, iconView.getBottom() - stroke); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(ICONS_ROUND_RADIUS), AndroidUtilities.dp(ICONS_ROUND_RADIUS), outlinePaint); + } + + private void setProgress(float progress) { + this.progress = progress; + + titleView.setTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), Theme.getColor(Theme.key_windowBackgroundWhiteValueText), progress)); + outlinePaint.setColor(ColorUtils.blendARGB(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_switchTrack), 0x3F), Theme.getColor(Theme.key_windowBackgroundWhiteValueText), progress)); + outlinePaint.setStrokeWidth(Math.max(2, AndroidUtilities.dp(AndroidUtilities.lerp(0.5f, 2f, progress)))); + invalidate(); + } + + private void setSelected(boolean selected, boolean animate) { + float to = selected ? 1 : 0; + if (to == progress && animate) { + return; + } + + if (animate) { + ValueAnimator animator = ValueAnimator.ofFloat(progress, to).setDuration(250); + animator.setInterpolator(Easings.easeInOutQuad); + animator.addUpdateListener(animation -> setProgress((Float) animation.getAnimatedValue())); + animator.start(); + } else { + setProgress(to); + } + } + + private void bind(LauncherIconController.LauncherIcon icon) { + iconView.setImageResource(icon.background); + + MarginLayoutParams params = (MarginLayoutParams) titleView.getLayoutParams(); + if (icon.premium && !UserConfig.hasPremiumOnAccounts()) { + SpannableString str = new SpannableString("d " + LocaleController.getString(icon.title)); + ColoredImageSpan span = new ColoredImageSpan(R.drawable.msg_mini_premiumlock); + span.setTopOffset(1); + span.setSize(AndroidUtilities.dp(13)); + str.setSpan(span, 0, 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + + params.rightMargin = AndroidUtilities.dp(4); + titleView.setText(str); + } else { + params.rightMargin = 0; + titleView.setText(LocaleController.getString(icon.title)); + } + setSelected(LauncherIconController.isEnabled(icon), false); + } + } + + public static class AdaptiveIconImageView extends ImageView { + private Drawable foreground; + private Path path = new Path(); + private int outerPadding = AndroidUtilities.dp(5); + private int backgroundOuterPadding = AndroidUtilities.dp(42); + + public AdaptiveIconImageView(Context context) { + super(context); + } + + public void setForeground(int res) { + foreground = ContextCompat.getDrawable(getContext(), res); + invalidate(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + updatePath(); + } + + public void setPadding(int padding) { + setPadding(padding, padding, padding, padding); + } + + public void setOuterPadding(int outerPadding) { + this.outerPadding = outerPadding; + } + + public void setBackgroundOuterPadding(int backgroundOuterPadding) { + this.backgroundOuterPadding = backgroundOuterPadding; + } + + @Override + public void draw(Canvas canvas) { + canvas.save(); + canvas.clipPath(path); + canvas.scale(1f + backgroundOuterPadding / (float) getWidth(), 1f + backgroundOuterPadding / (float) getHeight(), getWidth() / 2f, getHeight() / 2f); + super.draw(canvas); + canvas.restore(); + + if (foreground != null) { + foreground.setBounds(-outerPadding, -outerPadding, getWidth() + outerPadding, getHeight() + outerPadding); + foreground.draw(canvas); + } + } + + private void updatePath() { + path.rewind(); + path.addCircle(getWidth() / 2f, getHeight() / 2f, Math.min(getWidth() - getPaddingLeft() - getPaddingRight(), getHeight() - getPaddingTop() - getPaddingBottom()) / 2f, Path.Direction.CW); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java index fd323a858..c195b6d9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioPlayerCell.java @@ -316,7 +316,7 @@ public class AudioPlayerCell extends View implements DownloadController.FileDown } } if (cacheFile == null) { - cacheFile = FileLoader.getPathToAttach(currentMessageObject.getDocument()); + cacheFile = FileLoader.getInstance(currentAccount).getPathToAttach(currentMessageObject.getDocument()); } if (TextUtils.isEmpty(fileName)) { return; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AvailableReactionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AvailableReactionCell.java index cd114d622..d805ab524 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AvailableReactionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AvailableReactionCell.java @@ -6,6 +6,7 @@ import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -43,7 +44,7 @@ public class AvailableReactionCell extends FrameLayout { textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity(LayoutHelper.getAbsoluteGravityStart() | Gravity.CENTER_VERTICAL); - addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 81, 0, 91, 0)); + addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 81, 0, 61, 0)); imageView = new BackupImageView(context); imageView.setAspectFit(true); @@ -85,7 +86,7 @@ public class AvailableReactionCell extends FrameLayout { this.react = react; textView.setText(react.title); SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(react.static_icon, Theme.key_windowBackgroundGray, 1.0f); - imageView.setImage(ImageLocation.getForDocument(react.static_icon), "50_50", "webp", svgThumb, react); + imageView.setImage(ImageLocation.getForDocument(react.center_icon), "40_40_lastframe", "webp", svgThumb, react); setChecked(checked, animated); } @@ -111,6 +112,16 @@ public class AvailableReactionCell extends FrameLayout { } } + public boolean isChecked() { + if (switchView != null) { + return switchView.isChecked(); + } + if (checkBox != null) { + return checkBox.isChecked(); + } + return false; + } + @Override protected void onDraw(Canvas canvas) { canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -125,4 +136,19 @@ public class AvailableReactionCell extends FrameLayout { canvas.drawLine(getPaddingLeft() + l, getHeight() - w, getWidth() - getPaddingRight() - r, getHeight() - w, Theme.dividerPaint); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + info.setClickable(true); + if (switchView != null) { + info.setCheckable(true); + info.setChecked(isChecked()); + info.setClassName("android.widget.Switch"); + } else if (isChecked()) { + info.setSelected(true); + } + info.setContentDescription(textView.getText()); + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java index c3b5970b8..918a9bfcd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BaseCell.java @@ -36,7 +36,7 @@ public abstract class BaseCell extends ViewGroup { if (checkingForLongPress && getParent() != null && currentPressCount == pressCount) { checkingForLongPress = false; if (!NekoConfig.disableVibration.Bool()) { - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); } if (onLongPress()) { MotionEvent event = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java index 8128e5b5c..3730df322 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java @@ -10,12 +10,14 @@ package org.telegram.ui.Cells; import android.content.Context; import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; 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.ClickableSpan; import android.text.style.URLSpan; import android.view.MotionEvent; @@ -24,20 +26,32 @@ import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.FileRefController; +import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; -import org.telegram.messenger.FileLog; import org.telegram.messenger.R; -import org.telegram.ui.Components.LinkPath; +import org.telegram.messenger.SharedConfig; +import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LinkPath; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanNoUnderline; +import java.util.Objects; + public class BotHelpCell extends View { private StaticLayout textLayout; private String oldText; + private String currentPhotoKey; + private int width; private int height; private int textX; @@ -48,7 +62,13 @@ public class BotHelpCell extends View { private LinkPath urlPath = new LinkPath(); private BotHelpCellDelegate delegate; - private final Theme.ResourcesProvider resourcesProvider; + private Theme.ResourcesProvider resourcesProvider; + + private int photoHeight; + private ImageReceiver imageReceiver; + private boolean isPhotoVisible; + private boolean isTextVisible; + private int imagePadding = AndroidUtilities.dp(4); private boolean animating; @@ -59,6 +79,11 @@ public class BotHelpCell extends View { public BotHelpCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; + + imageReceiver = new ImageReceiver(this); + imageReceiver.setInvalidateAll(true); + imageReceiver.setCrossfadeWithOldImage(true); + imageReceiver.setCrossfadeDuration(300); } public void setDelegate(BotHelpCellDelegate botHelpCellDelegate) { @@ -73,13 +98,52 @@ public class BotHelpCell extends View { } public void setText(boolean bot, String text) { - if (text == null || text.length() == 0) { + setText(bot, text, null, null); + } + + public void setText(boolean bot, String text, TLObject imageOrAnimation, TLRPC.BotInfo botInfo) { + boolean photoVisible = imageOrAnimation != null; + boolean textVisible = !TextUtils.isEmpty(text); + if ((text == null || text.length() == 0) && !photoVisible) { setVisibility(GONE); return; } - if (text != null && text.equals(oldText)) { + if (text == null) { + text = ""; + } + if (text != null && text.equals(oldText) && isPhotoVisible == photoVisible) { return; } + isPhotoVisible = photoVisible; + isTextVisible = textVisible; + if (isPhotoVisible) { + String photoKey = FileRefController.getKeyForParentObject(botInfo); + if (!Objects.equals(currentPhotoKey, photoKey)) { + currentPhotoKey = photoKey; + if (imageOrAnimation instanceof TLRPC.TL_photo) { + TLRPC.Photo photo = (TLRPC.Photo) imageOrAnimation; + imageReceiver.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 400), photo), "400_400", null, "jpg", botInfo, 0); + } else if (imageOrAnimation instanceof TLRPC.Document) { + TLRPC.Document doc = (TLRPC.Document) imageOrAnimation; + TLRPC.PhotoSize photoThumb = FileLoader.getClosestPhotoSizeWithSize(doc.thumbs, 400); + BitmapDrawable strippedThumb = null; + if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW) { + for (TLRPC.PhotoSize photoSize : doc.thumbs) { + if (photoSize instanceof TLRPC.TL_photoStrippedSize) { + strippedThumb = new BitmapDrawable(getResources(), ImageLoader.getStrippedPhotoBitmap(photoSize.bytes, "b")); + } + } + } + imageReceiver.setImage(ImageLocation.getForDocument(doc), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(MessageObject.getDocumentVideoThumb(doc), doc), null, ImageLocation.getForDocument(photoThumb, doc), "86_86_b", strippedThumb, doc.size, "mp4", botInfo, 0); + } + + int topRadius = AndroidUtilities.dp(SharedConfig.bubbleRadius) - AndroidUtilities.dp(2), bottomRadius = AndroidUtilities.dp(4); + if (!isTextVisible) { + bottomRadius = topRadius; + } + imageReceiver.setRoundRadius(topRadius, topRadius, bottomRadius, bottomRadius); + } + } oldText = AndroidUtilities.getSafeString(text); setVisibility(VISIBLE); int maxWidth; @@ -88,39 +152,47 @@ public class BotHelpCell extends View { } else { maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); } - String[] lines = text.split("\n"); - SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); - String help = LocaleController.getString("BotInfoTitle", R.string.BotInfoTitle); - if (bot) { - stringBuilder.append(help); - stringBuilder.append("\n\n"); - } - for (int a = 0; a < lines.length; a++) { - stringBuilder.append(lines[a].trim()); - if (a != lines.length - 1) { - stringBuilder.append("\n"); + if (isTextVisible) { + String[] lines = text.split("\n"); + SpannableStringBuilder stringBuilder = new SpannableStringBuilder(); + String help = LocaleController.getString(R.string.BotInfoTitle); + if (bot) { + stringBuilder.append(help); + stringBuilder.append("\n\n"); } - } - MessageObject.addLinks(false, stringBuilder); - if (bot) { - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - } - Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); - try { - textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); - width = 0; - height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18); - int count = textLayout.getLineCount(); - for (int a = 0; a < count; a++) { - width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) + textLayout.getLineLeft(a))); + for (int a = 0; a < lines.length; a++) { + stringBuilder.append(lines[a].trim()); + if (a != lines.length - 1) { + stringBuilder.append("\n"); + } } - if (width > maxWidth) { - width = maxWidth; + MessageObject.addLinks(false, stringBuilder); + if (bot) { + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } - } catch (Exception e) { - FileLog.e(e); + Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + try { + textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth - (isPhotoVisible ? AndroidUtilities.dp(5) : 0), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + width = 0; + height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18); + int count = textLayout.getLineCount(); + for (int a = 0; a < count; a++) { + width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) + textLayout.getLineLeft(a))); + } + if (width > maxWidth || isPhotoVisible) { + width = maxWidth; + } + } catch (Exception e) { + FileLog.e(e); + } + } else if (isPhotoVisible) { + width = maxWidth; } width += AndroidUtilities.dp(4 + 18); + + if (isPhotoVisible) { + height += (photoHeight = (int) (width * 0.5625)) + AndroidUtilities.dp(4); // 16:9 + } } @Override @@ -136,10 +208,10 @@ public class BotHelpCell extends View { try { int x2 = (int) (x - textX); int y2 = (int) (y - textY); - final int line = textLayout.getLineForVertical(y2); - final int off = textLayout.getOffsetForHorizontal(line, x2); + int line = textLayout.getLineForVertical(y2); + int off = textLayout.getOffsetForHorizontal(line, x2); - final float left = textLayout.getLineLeft(line); + float left = textLayout.getLineLeft(line); if (left <= x2 && left + textLayout.getLineWidth(line) >= x2) { Spannable buffer = (Spannable) textLayout.getText(); ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class); @@ -203,7 +275,8 @@ public class BotHelpCell extends View { @Override protected void onDraw(Canvas canvas) { int x = (getWidth() - width) / 2; - int y = AndroidUtilities.dp(2); + int y = photoHeight; + y += AndroidUtilities.dp(2); Drawable shadowDrawable = Theme.chat_msgInMediaDrawable.getShadowDrawable(); if (shadowDrawable != null) { shadowDrawable.setBounds(x, y, width + x, height + y); @@ -218,12 +291,16 @@ public class BotHelpCell extends View { } Theme.MessageDrawable drawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgInMedia); drawable.setTop((int) getY(), w, h, false, false); - drawable.setBounds(x, y, width + x, height + y); + drawable.setBounds(x, 0, width + x, height); drawable.draw(canvas); + + imageReceiver.setImageCoords(x + imagePadding, imagePadding, width - imagePadding * 2, photoHeight - imagePadding); + imageReceiver.draw(canvas); + Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn)); Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn); canvas.save(); - canvas.translate(textX = AndroidUtilities.dp(2 + 9) + x, textY = AndroidUtilities.dp(2 + 9) + y); + canvas.translate(textX = AndroidUtilities.dp(isPhotoVisible ? 14 : 11) + x, textY = AndroidUtilities.dp(11) + y); if (pressedLink != null) { canvas.drawPath(urlPath, Theme.chat_urlPaint); } @@ -234,10 +311,16 @@ public class BotHelpCell extends View { wasDraw = true; } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + imageReceiver.onAttachedToWindow(); + } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); + imageReceiver.onDetachedFromWindow(); wasDraw = false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BrightnessControlCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BrightnessControlCell.java index 32f75ddee..343e66e94 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BrightnessControlCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BrightnessControlCell.java @@ -34,7 +34,7 @@ public class BrightnessControlCell extends FrameLayout { super(context); leftImageView = new ImageView(context); - leftImageView.setImageResource(R.drawable.brightness_low); + leftImageView.setImageResource(R.drawable.msg_brightness_low); addView(leftImageView, LayoutHelper.createFrame(24, 24, Gravity.LEFT | Gravity.TOP, 17, 12, 0, 0)); seekBarView = new SeekBarView(context, /* inPercents = */ true, null) { @@ -66,7 +66,7 @@ public class BrightnessControlCell extends FrameLayout { addView(seekBarView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 54, 5, 54, 0)); rightImageView = new ImageView(context); - rightImageView.setImageResource(R.drawable.brightness_high); + rightImageView.setImageResource(R.drawable.msg_brightness_high); addView(rightImageView, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.TOP, 0, 12, 17, 0)); } 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 df47f8b6d..930415ace 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java @@ -14,14 +14,20 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; +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.TextPaint; import android.text.TextUtils; +import android.text.style.CharacterStyle; +import android.text.style.ClickableSpan; import android.text.style.URLSpan; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; @@ -47,6 +53,7 @@ import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.spoilers.SpoilerEffect; import org.telegram.ui.PhotoViewer; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Stack; @@ -185,6 +192,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD return; } customText = newText; + accessibilityText = null; updateTextInternal(inLayout); } @@ -220,7 +228,11 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD if (currentMessageObject == messageObject && (textLayout == null || TextUtils.equals(textLayout.getText(), messageObject.messageText)) && (hasReplyMessage || messageObject.replyMessageObject == null)) { return; } + accessibilityText = null; currentMessageObject = messageObject; + if (currentMessageObject != null && currentMessageObject.viewRef != null && (currentMessageObject.viewRef.get() == null || currentMessageObject.viewRef.get().get() != this)) { + currentMessageObject.viewRef.set(new WeakReference<>(this)); + } hasReplyMessage = messageObject.replyMessageObject != null; DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); previousWidth = 0; @@ -366,43 +378,7 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD result = true; } else { if (link[0] == pressedLink) { - if (delegate != null) { - String url = link[0].getURL(); - if (url.startsWith("invite") && pressedLink instanceof URLSpanNoUnderline) { - URLSpanNoUnderline spanNoUnderline = (URLSpanNoUnderline) pressedLink; - TLObject object = spanNoUnderline.getObject(); - if (object instanceof TLRPC.TL_chatInviteExported) { - TLRPC.TL_chatInviteExported invite = (TLRPC.TL_chatInviteExported) object; - delegate.needOpenInviteLink(invite); - } - } else if (url.startsWith("game")) { - delegate.didPressReplyMessage(this, currentMessageObject.getReplyMsgId()); - /*TLRPC.KeyboardButton gameButton = null; - MessageObject messageObject = currentMessageObject.replyMessageObject; - if (messageObject != null && messageObject.messageOwner.reply_markup != null) { - for (int a = 0; a < messageObject.messageOwner.reply_markup.rows.size(); a++) { - TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(a); - for (int b = 0; b < row.buttons.size(); b++) { - TLRPC.KeyboardButton button = row.buttons.get(b); - if (button instanceof TLRPC.TL_keyboardButtonGame && button.game_id == currentMessageObject.messageOwner.action.game_id) { - gameButton = button; - break; - } - } - if (gameButton != null) { - break; - } - } - } - if (gameButton != null) { - delegate.didPressBotButton(messageObject, gameButton); - }*/ - } else if (url.startsWith("http")) { - Browser.openUrl(getContext(), url); - } else { - delegate.needOpenUserProfile(Long.parseLong(url)); - } - } + openLink(pressedLink); result = true; } } @@ -425,6 +401,46 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD return result; } + private void openLink(CharacterStyle link) { + if (delegate != null && link instanceof URLSpan) { + String url = ((URLSpan) link).getURL(); + if (url.startsWith("invite") && pressedLink instanceof URLSpanNoUnderline) { + URLSpanNoUnderline spanNoUnderline = (URLSpanNoUnderline) pressedLink; + TLObject object = spanNoUnderline.getObject(); + if (object instanceof TLRPC.TL_chatInviteExported) { + TLRPC.TL_chatInviteExported invite = (TLRPC.TL_chatInviteExported) object; + delegate.needOpenInviteLink(invite); + } + } else if (url.startsWith("game")) { + delegate.didPressReplyMessage(this, currentMessageObject.getReplyMsgId()); + /*TLRPC.KeyboardButton gameButton = null; + MessageObject messageObject = currentMessageObject.replyMessageObject; + if (messageObject != null && messageObject.messageOwner.reply_markup != null) { + for (int a = 0; a < messageObject.messageOwner.reply_markup.rows.size(); a++) { + TLRPC.TL_keyboardButtonRow row = messageObject.messageOwner.reply_markup.rows.get(a); + for (int b = 0; b < row.buttons.size(); b++) { + TLRPC.KeyboardButton button = row.buttons.get(b); + if (button instanceof TLRPC.TL_keyboardButtonGame && button.game_id == currentMessageObject.messageOwner.action.game_id) { + gameButton = button; + break; + } + } + if (gameButton != null) { + break; + } + } + } + if (gameButton != null) { + delegate.didPressBotButton(messageObject, gameButton); + }*/ + } else if (url.startsWith("http")) { + Browser.openUrl(getContext(), url); + } else { + delegate.needOpenUserProfile(Long.parseLong(url)); + } + } + } + private void createLayout(CharSequence text, int width) { int maxWidth = width - AndroidUtilities.dp(30); invalidatePath = true; @@ -757,13 +773,40 @@ public class ChatActionCell extends BaseCell implements DownloadController.FileD return TAG; } + private SpannableStringBuilder accessibilityText; + @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); if (TextUtils.isEmpty(customText) && currentMessageObject == null) { return; } - info.setText(!TextUtils.isEmpty(customText) ? customText : currentMessageObject.messageText); + if (accessibilityText == null) { + CharSequence text = !TextUtils.isEmpty(customText) ? customText : currentMessageObject.messageText; + SpannableStringBuilder sb = new SpannableStringBuilder(text); + CharacterStyle[] links = sb.getSpans(0, sb.length(), ClickableSpan.class); + for (CharacterStyle link : links) { + int start = sb.getSpanStart(link); + int end = sb.getSpanEnd(link); + sb.removeSpan(link); + + ClickableSpan underlineSpan = new ClickableSpan() { + @Override + public void onClick(View view) { + if (delegate != null) { + openLink(link); + } + } + }; + sb.setSpan(underlineSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + accessibilityText = sb; + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + info.setContentDescription(accessibilityText.toString()); + } else { + info.setText(accessibilityText); + } info.setEnabled(true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java index 1a7b6a83d..b597329e1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatListCell.java @@ -7,6 +7,7 @@ import android.graphics.Paint; import android.graphics.RectF; import android.text.TextPaint; import android.view.Gravity; +import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -96,6 +97,7 @@ public class ChatListCell extends LinearLayout { info.setClassName(RadioButton.class.getName()); info.setChecked(button.isChecked()); info.setCheckable(true); + info.setContentDescription(isThreeLines ? LocaleController.getString("ChatListExpanded", R.string.ChatListExpanded) : LocaleController.getString("ChatListDefault", R.string.ChatListDefault)); } } 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 da5c4a569..1a64de5d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -43,6 +43,7 @@ import android.os.Bundle; import android.os.SystemClock; import android.text.Layout; import android.text.Spannable; +import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.StaticLayout; @@ -59,6 +60,7 @@ import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.SoundEffectConstants; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewStructure; import android.view.accessibility.AccessibilityEvent; @@ -68,6 +70,7 @@ import android.view.accessibility.AccessibilityNodeProvider; import android.view.animation.Interpolator; import android.widget.Toast; +import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; import org.telegram.PhoneFormat.PhoneFormat; @@ -134,6 +137,7 @@ import org.telegram.ui.Components.SlotsDrawable; import org.telegram.ui.Components.StaticLayoutEx; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.TimerParticles; +import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanBotCommand; import org.telegram.ui.Components.URLSpanBrowser; @@ -146,6 +150,7 @@ import org.telegram.ui.PinchToZoomHelper; import org.telegram.ui.SecretMediaViewer; import java.io.File; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -161,6 +166,7 @@ import tw.nekomimi.nekogram.NekoXConfig; public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate, ImageReceiver.ImageReceiverDelegate, DownloadController.FileDownloadProgressListener, TextSelectionHelper.SelectableView, NotificationCenter.NotificationCenterDelegate { public boolean clipToGroupBounds; + private boolean flipImage; public RadialProgress2 getRadialProgress() { return radialProgress; @@ -333,6 +339,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { } + default void didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { + } + default void didPressReaction(ChatMessageCell cell, TLRPC.TL_reactionCount reaction, boolean longpress) { } @@ -348,6 +357,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate default void didPressHint(ChatMessageCell cell, int type) { } + default void needShowPremiumFeatures(String source) { + } + default String getAdminRank(long uid) { return null; } @@ -360,6 +372,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return false; } + default boolean onAccessibilityAction(int action, Bundle arguments) { + return false; + } + default void videoTimerReached() { } @@ -570,7 +586,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private int instantTextX; private int instantTextLeftX; private int instantWidth; - private boolean insantTextNewLine; + private boolean instantTextNewLine; private boolean instantPressed; private boolean instantButtonPressed; private Drawable[] selectorDrawable = new Drawable[2]; @@ -656,13 +672,17 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private Path rectPath = new Path(); private static float[] radii = new float[8]; - private boolean useSeekBarWaweform; + private boolean useSeekBarWaveform; private SeekBar seekBar; private SeekBarWaveform seekBarWaveform; private SeekBarAccessibilityDelegate seekBarAccessibilityDelegate; private int seekBarX; private int seekBarY; + private boolean useTranscribeButton; + private TranscribeButton transcribeButton; + private float transcribeX, transcribeY; + private StaticLayout durationLayout; private int lastTime; private int timeWidthAudio; @@ -1034,11 +1054,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isMusic()) { return seekBar.getProgress(); } else if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo()) { - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { return seekBarWaveform.getProgress(); } else { return seekBar.getProgress(); } + } else if (currentMessageObject.isRoundVideo()) { + return currentMessageObject.audioProgress; } else { return 0f; } @@ -1049,11 +1071,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessageObject.isMusic()) { seekBar.setProgress(progress); } else if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo()) { - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { seekBarWaveform.setProgress(progress); } else { seekBar.setProgress(progress); } + } else if (currentMessageObject.isRoundVideo()) { + currentMessageObject.audioProgress = progress; } else { return; } @@ -1192,7 +1216,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } - if (!ignore) { + if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); @@ -1304,7 +1328,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } - if (!ignore) { + if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); @@ -1369,7 +1393,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } - if (!ignore) { + if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); @@ -1429,6 +1453,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return false; } + private boolean checkTranscribeButtonMotionEvent(MotionEvent event) { + return useTranscribeButton && transcribeButton != null && transcribeButton.onTouch(event.getAction(), event.getX() - transcribeX, event.getY() - transcribeY); + } + private boolean checkLinkPreviewMotionEvent(MotionEvent event) { if (currentMessageObject.type != 0 || !hasLinkPreview) { return false; @@ -1454,7 +1482,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) { ignore = true; } - if (!ignore) { + if (!ignore && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { if (pressedLink == null || pressedLink.getSpan() != link[0]) { links.removeLink(pressedLink); pressedLink = new LinkSpanDrawable(link[0], resourcesProvider, x, y, spanSupportsLongPress(link[0])); @@ -2105,11 +2133,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (documentAttachType != DOCUMENT_ATTACH_TYPE_AUDIO && documentAttachType != DOCUMENT_ATTACH_TYPE_MUSIC) { return false; } + if (AndroidUtilities.isAccessibilityScreenReaderEnabled()) { + return false; + } int x = (int) event.getX(); int y = (int) event.getY(); boolean result; - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { result = seekBarWaveform.onTouch(event.getAction(), event.getX() - seekBarX - AndroidUtilities.dp(13), event.getY() - seekBarY); } else { if (MediaController.getInstance().isPlayingMessage(currentMessageObject)) { @@ -2119,9 +2150,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } if (result) { - if (!useSeekBarWaweform && event.getAction() == MotionEvent.ACTION_DOWN) { + if (!useSeekBarWaveform && event.getAction() == MotionEvent.ACTION_DOWN) { getParent().requestDisallowInterceptTouchEvent(true); - } else if (useSeekBarWaweform && !seekBarWaveform.isStartDraging() && event.getAction() == MotionEvent.ACTION_UP) { + } else if (useSeekBarWaveform && !seekBarWaveform.isStartDraging() && event.getAction() == MotionEvent.ACTION_UP) { didPressButton(true, false); } disallowLongPress = true; @@ -2186,9 +2217,32 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return result; } - private boolean checkSpoilersMotionEvent(MotionEvent event) { - if (isSpoilerRevealing) + public boolean checkSpoilersMotionEvent(MotionEvent event) { + if (currentMessageObject.hasValidGroupId() && currentMessagesGroup != null && !currentMessagesGroup.isDocuments) { + ViewGroup parent = (ViewGroup) getParent(); + for (int i = 0; i < parent.getChildCount(); i++) { + View v = parent.getChildAt(i); + if (v instanceof ChatMessageCell) { + ChatMessageCell cell = (ChatMessageCell) v; + MessageObject.GroupedMessages group = cell.getCurrentMessagesGroup(); + MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); + if (group != null && group.groupId == currentMessagesGroup.groupId && + (position.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && + (position.flags & MessageObject.POSITION_FLAG_LEFT) != 0) { + if (cell != this) { + event.offsetLocation(this.getLeft() - cell.getLeft(), this.getTop() - cell.getTop()); + boolean result = cell.checkSpoilersMotionEvent(event); + event.offsetLocation(-(this.getLeft() - cell.getLeft()), -(this.getTop() - cell.getTop())); + return result; + } + } + } + } + } + + if (isSpoilerRevealing) { return false; + } int x = (int) event.getX(); int y = (int) event.getY(); @@ -2319,6 +2373,20 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate pressedBotButton = a; invalidate(); result = true; + final int longPressedBotButton = pressedBotButton; + postDelayed(() -> { + if (longPressedBotButton == pressedBotButton) { + if (!currentMessageObject.scheduled) { + BotButton button2 = botButtons.get(pressedBotButton); + if (button2.button != null) { + cancelCheckLongPress(); + delegate.didLongPressBotButton(this, button2.button); + } + } + pressedBotButton = -1; + invalidate(); + } + }, ViewConfiguration.getLongPressTimeout() - 1); break; } } @@ -2395,6 +2463,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (!result) { result = checkCaptionMotionEvent(event); } + if (!result) { + result = checkTranscribeButtonMotionEvent(event); + } if (!result) { result = checkAudioMotionEvent(event); } @@ -2863,7 +2934,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } invalidate(); } else if (documentAttach != null) { - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { if (!seekBarWaveform.isDragging()) { seekBarWaveform.setProgress(currentMessageObject.audioProgress, true); } @@ -3081,6 +3152,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (buttonState == -1) { delegate.didPressImage(this, lastTouchX, lastTouchY); } + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // open message options then + if (delegate != null) { + if (currentMessageObject.type == 16) { + delegate.didLongPress(this, 0, 0); + } else { + delegate.didPressOther(this, otherX, otherY); + } + } } } @@ -3132,7 +3212,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentPhotoObject == null || currentPhotoObject.location instanceof TLRPC.TL_fileLocationUnavailable) { return object.type == MessageObject.TYPE_PHOTO || object.type == MessageObject.TYPE_ROUND_VIDEO || object.type == MessageObject.TYPE_VIDEO || object.type == 8 || object.isAnyKindOfSticker(); } else if (currentMessageObject != null && photoNotSet) { - File cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + File cacheFile = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); return cacheFile.exists(); } return false; @@ -3372,8 +3452,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate radialProgress.onAttachedToWindow(); videoRadialProgress.onAttachedToWindow(); - avatarImage.onAttachedToWindow(); avatarImage.setParentView((View) getParent()); + avatarImage.onAttachedToWindow(); if (pollAvatarImages != null) { for (int a = 0; a < pollAvatarImages.length; a++) { pollAvatarImages[a].onAttachedToWindow(); @@ -3439,10 +3519,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate newReply != lastReplyMessage; boolean groupChanged = groupedMessages != currentMessagesGroup; boolean pollChanged = false; - if (dataChanged || messageChanged || messageIdChanged) { - accessibilityText = null; - } - if (drawCommentButton || drawSideButton == 3 && !((hasDiscussion && messageObject.isLinkedToChat(linkedChatId) || isRepliesChat) && (currentPosition == null || currentPosition.siblingHeights == null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 || currentPosition.siblingHeights != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0))) { + accessibilityText = null; + if (drawCommentButton || useTranscribeButton || drawSideButton == 3 && !((hasDiscussion && messageObject.isLinkedToChat(linkedChatId) || isRepliesChat) && (currentPosition == null || currentPosition.siblingHeights == null && (currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 || currentPosition.siblingHeights != null && (currentPosition.flags & MessageObject.POSITION_FLAG_TOP) == 0))) { dataChanged = true; } if (!messageChanged && messageObject.isDice()) { @@ -3479,6 +3557,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } animatePollAvatars = lastPollResultsVoters == 0 || lastPollResultsVoters != 0 && newVoters == 0; } + if (!messageIdChanged && newPoll != null && lastPoll.quiz && newPoll.quiz && currentMessageObject != null && !pollVoted && messageObject != null && messageObject.isVoted()) { + TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; + if (mediaPoll.results != null && !mediaPoll.results.results.isEmpty()) { + TLRPC.TL_pollAnswerVoters chosenAnswer = null; + int a; + final int count = mediaPoll.results.results.size(); + for (a = 0; a < count; a++) { + TLRPC.TL_pollAnswerVoters answer = mediaPoll.results.results.get(a); + if (answer.chosen) { + chosenAnswer = answer; + break; + } + } + if (chosenAnswer != null) { + sendAccessibilityEventForVirtualView(MessageAccessibilityNodeProvider.POLL_BUTTONS_START + a, AccessibilityEvent.TYPE_VIEW_SELECTED, chosenAnswer.correct ? LocaleController.getString("AccDescrQuizCorrectAnswer", R.string.AccDescrQuizCorrectAnswer) : LocaleController.getString("AccDescrQuizIncorrectAnswer", R.string.AccDescrQuizIncorrectAnswer)); + } + } + } } if (!groupChanged && groupedMessages != null) { MessageObject.GroupedMessagePosition newPosition; @@ -3529,11 +3625,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate lastDeleteDate = messageObject.messageOwner.destroyTime; lastViewsCount = messageObject.messageOwner.views; lastRepliesCount = getRepliesCount(); - isPressed = false; + if (messageIdChanged) { + isPressed = false; + isCheckPressed = true; + } gamePreviewPressed = false; sideButtonPressed = false; - isCheckPressed = true; hasNewLineForTime = false; + flipImage = false; isThreadPost = isThreadChat && messageObject.messageOwner.fwd_from != null && messageObject.messageOwner.fwd_from.channel_post != 0; isAvatarVisible = !isThreadPost && isChat && !messageObject.isOutOwner() && messageObject.needDrawAvatar() && (currentPosition == null || currentPosition.edge); boolean drawAvatar = isChat && !isThreadPost && !messageObject.isOutOwner() && messageObject.needDrawAvatar(); @@ -3643,7 +3742,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoNotSet = false; drawBackground = true; drawName = false; - useSeekBarWaweform = false; + useSeekBarWaveform = false; + useTranscribeButton = false; drawInstantView = false; drawInstantViewType = 0; drawForwardedName = false; @@ -3662,6 +3762,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate imageBackgroundSideColor = 0; mediaBackground = false; isMedia = false; + photoImage.animatedFileDrawableRepeatMaxCount = 0; hasPsaHint = messageObject.messageOwner.fwd_from != null && !TextUtils.isEmpty(messageObject.messageOwner.fwd_from.psa_type); if (hasPsaHint) { createSelectorDrawable(0); @@ -4040,7 +4141,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } String site_name; String title; - String author; + CharSequence author; String description; TLRPC.Photo photo; TLRPC.Document document; @@ -4229,6 +4330,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate linkPreviewHeight += AndroidUtilities.dp(2); totalHeight += AndroidUtilities.dp(2); } + try { + author = Emoji.replaceEmoji(author, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + } catch (Exception ignore) {} if (restLinesCount == 3 && (!isSmallImage || description == null)) { authorLayout = new StaticLayout(author, Theme.chat_replyNamePaint, linkPreviewMaxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } else { @@ -4563,6 +4667,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate maxPhotoWidth = AndroidUtilities.roundMessageSize; photoImage.setAllowDecodeSingleFrame(true); } + if (hasInvoicePreview && maxPhotoWidth < messageObject.textWidth) { + maxPhotoWidth = messageObject.textWidth + AndroidUtilities.dp(22); + } maxChildWidth = Math.max(maxChildWidth, maxPhotoWidth - (hasInvoicePreview ? AndroidUtilities.dp(12) : 0) + additinalWidth); if (currentPhotoObject != null) { @@ -4674,6 +4781,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } 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 { @@ -4715,7 +4825,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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); + 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); // TODO: Here } 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); } @@ -5322,7 +5432,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawPinnedTop) { namesOffset -= AndroidUtilities.dp(1); } - insantTextNewLine = false; + instantTextNewLine = false; if (media.poll.public_voters || media.poll.multiple_choice) { int instantTextWidth = 0; for (int a = 0; a < 3; a++) { @@ -5339,7 +5449,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int timeWidthTotal = timeWidth + (messageObject.isOutOwner() ? AndroidUtilities.dp(20) : 0) + getExtraTimeX(); if (!reactionsLayoutInBubble.isSmall && reactionsLayoutInBubble.isEmpty && timeWidthTotal >= (backgroundWidth - AndroidUtilities.dp(76) - instantTextWidth) / 2) { totalHeight += AndroidUtilities.dp(18); - insantTextNewLine = true; + instantTextNewLine = true; } } if (!reactionsLayoutInBubble.isSmall) { @@ -5752,8 +5862,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setRoundRadius(0); canChangeRadius = false; + if (!messageObject.isOutOwner() && MessageObject.isPremiumSticker(messageObject.getDocument())) { + flipImage = true; + } if (messageObject.isVideoSticker()) { - // photoImage.setAspectFit(true); + if (!SharedConfig.loopStickers) { + photoImage.animatedFileDrawableRepeatMaxCount = 1; + } photoImage.setImage(ImageLocation.getForDocument(messageObject.getDocument()), ImageLoader.AUTOPLAY_FILTER, null, null, messageObject.pathThumb, @@ -6411,20 +6526,35 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate // if ((currentPosition == null || currentMessageObject.isMusic() || currentMessageObject.isDocument()) && !messageObject.isAnyKindOfSticker() && addedCaptionHeight == 0) { - if (!messageObject.isRestrictedMessage && captionLayout == null && messageObject.caption != null) { + 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) { + currentCaption += " "; + if (!(currentCaption instanceof Spannable)) { + currentCaption = new SpannableString(currentCaption); + } + ((SpannableString) currentCaption).setSpan(new TranscribeButton.LoadingPointsSpan(), currentCaption.length() - 1, currentCaption.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } try { - currentCaption = messageObject.caption; - int width = backgroundWidth - AndroidUtilities.dp(31); - int widthForCaption = width - AndroidUtilities.dp(10) - getExtraTextX() * 2; + int width = backgroundWidth; + if (messageObject.isVoiceTranscriptionOpen()) { + if (AndroidUtilities.isTablet()) { + width = AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(drawAvatar ? 102 : 50); + } else { + width = getParentWidth() - AndroidUtilities.dp(drawAvatar ? 102 : 50); + } + } + int widthForCaption = width - AndroidUtilities.dp(31) - AndroidUtilities.dp(10) - getExtraTextX() * 2; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - captionLayout = StaticLayout.Builder.obtain(messageObject.caption, 0, messageObject.caption.length(), Theme.chat_msgTextPaint, widthForCaption) + 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(messageObject.caption, Theme.chat_msgTextPaint, widthForCaption, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + captionLayout = new StaticLayout(currentCaption, Theme.chat_msgTextPaint, widthForCaption, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } + updateSeekBarWaveformWidth(); updateCaptionSpoilers(); } catch (Exception e) { FileLog.e(e); @@ -6432,6 +6562,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } if (captionLayout != null) { try { + if (messageObject.isVoiceTranscriptionOpen()) { + 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; + } + } + backgroundWidth += maxWidth - startMaxWidth; + } int width = backgroundWidth - AndroidUtilities.dp(31); if (captionLayout != null && captionLayout.getLineCount() > 0) { captionWidth = width; @@ -6620,7 +6760,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (b == row.buttons.size() - 1) { maxButtonsWidth = Math.max(maxButtonsWidth, botButton.x + botButton.width); } - if (messageObject.isFromUser() && botButton.button instanceof TLRPC.TL_keyboardButtonUrl) { // TODO(dkaraush): or instanceof TLRPC.TL_keyboardButtonInvite in the future + if (messageObject.isFromUser() && botButton.button instanceof TLRPC.TL_keyboardButtonUrl) { try { final Uri uri = Uri.parse(botButton.button.url); final String host = uri.getHost().toLowerCase(); @@ -6735,6 +6875,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } photoImage.setRoundRadius(tl, tr, br, bl); } + if (currentMessageObject != null && currentMessageObject.viewRef != null && (currentMessageObject.viewRef.get() == null || currentMessageObject.viewRef.get().get() != this)) { + currentMessageObject.viewRef.set(new WeakReference<>(this)); + } } if (messageIdChanged) { currentUrl = null; @@ -6779,8 +6922,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawBackground = false; isAvatarVisible = false; } + if (transcribeButton != null) { + transcribeButton.setOpen(currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.voiceTranscriptionOpen && currentMessageObject.messageOwner.voiceTranscriptionFinal, !messageIdChanged); + transcribeButton.setLoading(TranscribeButton.isTranscribing(currentMessageObject), !messageIdChanged); + } updateWaveform(); - updateButtonState(false, dataChanged && !messageObject.cancelEditing, true); + updateButtonState(false, !messageIdChanged && !messageObject.cancelEditing, true); if (!currentMessageObject.loadingCancelled && buttonState == 2 && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO && DownloadController.getInstance(currentAccount).canDownloadMedia(messageObject)) { FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, 0); @@ -7002,7 +7149,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate isCheckPressed = value; isPressed = pressed; updateRadialProgressBackground(); - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { seekBar.setSelected(isDrawSelectionBackground()); @@ -7084,7 +7231,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } updateRadialProgressBackground(); - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { seekBar.setSelected(isDrawSelectionBackground()); @@ -7099,7 +7246,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public void setPressed(boolean pressed) { super.setPressed(pressed); updateRadialProgressBackground(); - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { seekBarWaveform.setSelected(isDrawSelectionBackground()); } else { seekBar.setSelected(isDrawSelectionBackground()); @@ -7153,11 +7300,27 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (attribute.waveform == null || attribute.waveform.length == 0) { MediaController.getInstance().generateWaveform(currentMessageObject); } - useSeekBarWaweform = attribute.waveform != null; + useSeekBarWaveform = attribute.waveform != null; seekBarWaveform.setWaveform(attribute.waveform); break; } } + useTranscribeButton = currentMessageObject.isVoice() && useSeekBarWaveform && currentMessageObject.messageOwner != null && !(currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage) && UserConfig.getInstance(currentAccount).isPremium(); + updateSeekBarWaveformWidth(); + } + + private void updateSeekBarWaveformWidth() { + if (seekBarWaveform != null) { + int offset = -AndroidUtilities.dp(92 + (hasLinkPreview ? 10 : 0)) - AndroidUtilities.dp(useTranscribeButton ? 34 : 0); + if (transitionParams.animateBackgroundBoundsInner && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + int fromBackgroundWidth = this.backgroundWidth; + int toBackgroundWidth = (int) (this.backgroundWidth - transitionParams.toDeltaLeft + transitionParams.toDeltaRight); + int backgroundWidth = (int) (this.backgroundWidth - transitionParams.deltaLeft + transitionParams.deltaRight); + seekBarWaveform.setSize(backgroundWidth + offset, AndroidUtilities.dp(30), fromBackgroundWidth + offset, toBackgroundWidth + offset); + } else { + seekBarWaveform.setSize(backgroundWidth + offset, AndroidUtilities.dp(30)); + } + } } private int createDocumentLayout(int maxWidth, MessageObject messageObject) { @@ -7309,6 +7472,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate int lastLineWidth = (reactionsLayoutInBubble.isEmpty || reactionsLayoutInBubble.isSmall) ? currentMessageObject.lastLineWidth : reactionsLayoutInBubble.lastLineX; if (!reactionsLayoutInBubble.isEmpty && !reactionsLayoutInBubble.isSmall) { newLineForTime = maxWidth - lastLineWidth < timeMore || currentMessageObject.hasRtl; + if (hasInvoicePreview) { + totalHeight += AndroidUtilities.dp(14); + } } else { newLineForTime = hasLinkPreview || hasOldCaptionPreview || hasGamePreview || hasInvoicePreview || maxWidth - lastLineWidth < timeMore || currentMessageObject.hasRtl; } @@ -7429,7 +7595,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override public void invalidateDrawable(Drawable drawable) { super.invalidateDrawable(drawable); - if (currentMessagesGroup != null && drawable == selectorDrawable[1]) { + if (currentMessagesGroup != null) { invalidateWithParent(); } } @@ -7518,7 +7684,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate path.reset(); boolean out = currentMessageObject != null && currentMessageObject.isOutOwner(); for (int a = 0; a < 4; a++) { - if (!insantTextNewLine) { + if (!instantTextNewLine) { if (a == 2 && !out) { radii[a * 2] = radii[a * 2 + 1] = AndroidUtilities.dp(SharedConfig.bubbleRadius); continue; @@ -7802,7 +7968,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonX += AndroidUtilities.dp(10); timeAudioX += AndroidUtilities.dp(10); } - seekBarWaveform.setSize(backgroundWidth - AndroidUtilities.dp(92 + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); + updateSeekBarWaveformWidth(); seekBar.setSize(backgroundWidth - AndroidUtilities.dp(72 + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); seekBarY = AndroidUtilities.dp(13) + namesOffset + mediaOffsetY; buttonY = AndroidUtilities.dp(13) + namesOffset + mediaOffsetY; @@ -8120,11 +8286,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate buttonY = (transitionParams.animateFromButtonY * (1f - transitionParams.animateChangeProgress) + this.buttonY * (transitionParams.animateChangeProgress)); radialProgress.setProgressRect((int) buttonX, (int) buttonY, (int) buttonX + AndroidUtilities.dp(44), (int) buttonY + AndroidUtilities.dp(44)); } - if (transitionParams.animateBackgroundBoundsInner && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { - int backgroundWidth = (int) (this.backgroundWidth - transitionParams.deltaLeft + transitionParams.deltaRight); - seekBarWaveform.setSize(backgroundWidth - AndroidUtilities.dp(92 + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); - seekBar.setSize(backgroundWidth - AndroidUtilities.dp(72 + (hasLinkPreview ? 10 : 0)), AndroidUtilities.dp(30)); - } + updateSeekBarWaveformWidth(); forceNotDrawTime = currentMessagesGroup != null; photoImage.setPressed((isHighlightedAnimated || isHighlighted) && currentPosition != null ? 2 : 0); photoImage.setVisible(!PhotoViewer.isShowingImage(currentMessageObject) && !SecretMediaViewer.getInstance().isShowingImage(currentMessageObject), false); @@ -8272,10 +8434,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.setSideClip(0); } if (delegate == null || delegate.getPinchToZoomHelper() == null || !delegate.getPinchToZoomHelper().isInOverlayModeFor(this)) { - imageDrawn = photoImage.draw(canvas); + if (flipImage) { + canvas.save(); + canvas.scale(-1f, 1, photoImage.getCenterX(), photoImage.getCenterY()); + photoImage.draw(canvas); + canvas.restore(); + } else { + imageDrawn = photoImage.draw(canvas); + } } boolean drawTimeOld = drawTime; - drawTime = photoImage.getVisible(); + boolean groupPhotoVisible = photoImage.getVisible(); + drawTime = groupPhotoVisible || currentMessageObject.shouldDrawReactionsInLayout() && currentMessageObject.hasReactions(); if (currentPosition != null && drawTimeOld != drawTime) { ViewGroup viewGroup = (ViewGroup) getParent(); if (viewGroup != null) { @@ -8291,7 +8461,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (cell.getCurrentMessagesGroup() == currentMessagesGroup) { MessageObject.GroupedMessagePosition position = cell.getCurrentPosition(); if (position.last && position.maxY == currentPosition.maxY && cell.timeX - AndroidUtilities.dp(4) + cell.getLeft() < getRight()) { - cell.groupPhotoInvisible = !drawTime; + cell.groupPhotoInvisible = !groupPhotoVisible; cell.invalidate(); viewGroup.invalidate(); } @@ -8464,7 +8634,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate timeAudioX -= offset; } canvas.save(); - if (useSeekBarWaweform) { + if (useSeekBarWaveform) { canvas.translate(seekBarX + AndroidUtilities.dp(13), seekBarY); seekBarWaveform.draw(canvas, this); } else { @@ -8473,6 +8643,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } canvas.restore(); + if (useTranscribeButton) { + canvas.save(); + int backgroundWidth = this.backgroundWidth; + if (transitionParams.animateBackgroundBoundsInner && documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + backgroundWidth = (int) (this.backgroundWidth - transitionParams.deltaLeft + transitionParams.deltaRight); + } + int seekBarWidth = backgroundWidth - AndroidUtilities.dp(92 + (hasLinkPreview ? 10 : 0) + 36); + canvas.translate(transcribeX = seekBarX + AndroidUtilities.dp(13 + 8) + seekBarWidth, transcribeY = seekBarY); + if (transcribeButton == null) { + transcribeButton = new TranscribeButton(this, seekBarWaveform); + transcribeButton.setOpen(currentMessageObject.messageOwner != null && currentMessageObject.messageOwner.voiceTranscriptionOpen && currentMessageObject.messageOwner.voiceTranscriptionFinal, false); + transcribeButton.setLoading(TranscribeButton.isTranscribing(currentMessageObject), false); + } + transcribeButton.setColor(currentMessageObject.isOut(), getThemedColor(currentMessageObject.isOutOwner() ? Theme.key_chat_outReactionButtonBackground : Theme.key_chat_inReactionButtonBackground), getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + transcribeButton.draw(canvas); + canvas.restore(); + } + canvas.save(); canvas.translate(timeAudioX, AndroidUtilities.dp(44) + namesOffset + mediaOffsetY); durationLayout.draw(canvas); @@ -8642,6 +8830,7 @@ 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); @@ -9207,7 +9396,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } try { Emoji.emojiDrawingYOffset = -transitionYOffsetForDrawables; - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, 0, block.spoilersPatchedTextLayout, block.textLayout, block.spoilers, canvas); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, 0, block.spoilersPatchedTextLayout, block.textLayout, block.spoilers, canvas, false); Emoji.emojiDrawingYOffset = 0; } catch (Exception e) { FileLog.e(e); @@ -9798,7 +9987,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (miniButtonState == 0) { miniButtonState = 1; radialProgress.setProgress(0, false); - currentMessageObject.putInDownloadsStore = true; + if (currentMessageObject != null && !currentMessageObject.isAnyKindOfSticker()) { + currentMessageObject.putInDownloadsStore = true; + } if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { FileLoader.getInstance(currentAccount).loadFile(documentAttach, currentMessageObject, 1, 0); currentMessageObject.loadingCancelled = false; @@ -9824,7 +10015,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void didPressButton(boolean animated, boolean video) { - if (currentMessageObject != null) { + if (currentMessageObject != null && !currentMessageObject.isAnyKindOfSticker()) { currentMessageObject.putInDownloadsStore = true; } if (buttonState == 0 && (!drawVideoImageButton || video)) { @@ -10095,7 +10286,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { if (!lottieDrawable.hasBaseDice() && stickerSet.documents.size() > 0) { TLRPC.Document document = stickerSet.documents.get(0); - File path = FileLoader.getPathToAttach(document, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(document, true); if (lottieDrawable.setBaseDice(path)) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } else { @@ -10112,7 +10303,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } TLRPC.Document document = stickerSet.documents.get(Math.max(value, 0)); - File path = FileLoader.getPathToAttach(document, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(document, true); if (lottieDrawable.setDiceNumber(path, instant)) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); } else { @@ -10257,6 +10448,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate w = (int) Math.ceil(Theme.chat_infoPaint.measureText(str)); } loadingProgressLayout = new StaticLayout(str, Theme.chat_infoPaint, w, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); +// if (loadingProgressLayout != null) { +// loadingProgressLayout.copyStylesFrom(Theme.chat_infoPaint); +// loadingProgressLayout.setBounds(0, 0, w, (int) Theme.chat_infoPaint.getTextSize()); +// loadingProgressLayout.setText(str, true); +// } else { +// loadingProgressLayout = new AnimatedTextView.AnimatedTextDrawable(false, true, true); +// loadingProgressLayout.setAnimationProperties(0.3f, 0, 140, CubicBezierInterpolator.EASE_OUT); +// loadingProgressLayout.setCallback(this); +// loadingProgressLayout.copyStylesFrom(Theme.chat_infoPaint); +// loadingProgressLayout.setBounds(0, 0, w, (int) Theme.chat_infoPaint.getTextSize()); +// loadingProgressLayout.setText(str, false); +// } } @@ -10521,7 +10724,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentPhoto = null; } avatarDrawable.setInfo(currentUser); - avatarImage.setForUserOrChat(currentUser, avatarDrawable); + avatarImage.setForUserOrChat(currentUser, avatarDrawable, null, true); } else if (currentChat != null) { if (currentChat.photo != null) { currentPhoto = currentChat.photo.photo_small; @@ -10649,7 +10852,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } nameStringFinal = TextUtils.ellipsize(nameStringFinal, Theme.chat_namePaint, nameWidth, TextUtils.TruncateAt.END); } - nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.chat_namePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + try { + nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.chat_namePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + } catch (Exception ignore) {} try { nameLayout = new StaticLayout(nameStringFinal, Theme.chat_namePaint, nameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); if (nameLayout.getLineCount() > 0) { @@ -10747,7 +10952,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } lastLine = stringBuilder; lastLine = TextUtils.ellipsize(lastLine, Theme.chat_forwardNamePaint, forwardedNameWidth, TextUtils.TruncateAt.END); - lastLine = Emoji.replaceEmoji(lastLine, Theme.chat_forwardNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + try { + lastLine = Emoji.replaceEmoji(lastLine, Theme.chat_forwardNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + } catch (Exception ignore) {}; try { forwardedNameLayout[1] = new StaticLayout(lastLine, Theme.chat_forwardNamePaint, forwardedNameWidth + AndroidUtilities.dp(2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); lastLine = TextUtils.ellipsize(AndroidUtilities.replaceTags(forwardedString), Theme.chat_forwardNamePaint, forwardedNameWidth, TextUtils.TruncateAt.END); @@ -10939,8 +11146,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } CharSequence stringFinalName = name == null ? "" : TextUtils.ellipsize(name.replace('\n', ' '), Theme.chat_replyNamePaint, maxWidth, TextUtils.TruncateAt.END); - stringFinalName = Emoji.replaceEmoji(stringFinalName, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); - + try { + stringFinalName = Emoji.replaceEmoji(stringFinalName, Theme.chat_replyNamePaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + } catch (Exception ignore) {} try { replyNameWidth = AndroidUtilities.dp(4 + (needReplyImage ? 44 : 0)); if (stringFinalName != null) { @@ -11624,6 +11832,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentBackgroundSelectedDrawable.drawCached(canvas, backgroundCacheParams); } } else if (selectedBackgroundProgress != 0 && !(currentMessagesGroup != null && currentMessagesGroup.isDocuments)) { + currentBackgroundDrawable.setAlpha((int) (255 * alphaInternal)); currentBackgroundDrawable.drawCached(canvas, backgroundCacheParams); currentSelectedBackgroundAlpha = selectedBackgroundProgress; currentBackgroundSelectedDrawable.setAlpha((int) (currentSelectedBackgroundAlpha * alphaInternal * 255)); @@ -12413,7 +12622,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate canvas.translate(forwardNameX, replyStartY + AndroidUtilities.dp(19)); int spoilersColor = currentMessageObject.isOut() && !ChatObject.isChannelAndNotMegaGroup(currentMessageObject.getChatId(), currentAccount) ? getThemedColor(Theme.key_chat_outTimeText) : replyTextLayout.getPaint().getColor(); - SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, replyTextLayout, replySpoilers, canvas); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, -AndroidUtilities.dp(2), spoilersPatchedReplyTextLayout, replyTextLayout, replySpoilers, canvas, false); canvas.restore(); } } @@ -12534,6 +12743,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate drawCaptionLayout(canvas, captionLayout, selectionOnly, alpha); } + if (currentMessageObject != null && currentMessageObject.messageOwner != null && currentMessageObject.isVoiceTranscriptionOpen() && !currentMessageObject.messageOwner.voiceTranscriptionFinal && TranscribeButton.isTranscribing(currentMessageObject)) { + invalidate(); + } + if (!selectionOnly && (currentPosition == null || ((currentPosition.flags & MessageObject.POSITION_FLAG_BOTTOM) != 0 && (currentPosition.flags & MessageObject.POSITION_FLAG_LEFT) != 0)) && !reactionsLayoutInBubble.isSmall) { if (reactionsLayoutInBubble.drawServiceShaderBackground) { applyServiceShaderMatrix(); @@ -12546,7 +12759,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate reactionsLayoutInBubble.draw(canvas, transitionParams.animateChange ? transitionParams.animateChangeProgress : 1f, null); canvas.restore(); } - } } @@ -12646,6 +12858,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (currentMessagesGroup.transitionParams.backgroundChangeBounds) { ly -= getTranslationY(); } + } else { + int backgroundWidth = (int) (this.backgroundWidth - transitionParams.deltaLeft + transitionParams.deltaRight); + endX = x + backgroundWidth - AndroidUtilities.dp(12); } canvas.drawLine(x, ly, endX - AndroidUtilities.dp(14), ly, Theme.chat_replyLinePaint); } @@ -12815,7 +13030,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (transitionParams.moveCaption) { captionX = this.captionX * transitionParams.animateChangeProgress + transitionParams.captionFromX * (1f - transitionParams.animateChangeProgress); captionY = this.captionY * transitionParams.animateChangeProgress + transitionParams.captionFromY * (1f - transitionParams.animateChangeProgress); - } else { + } else if (!currentMessageObject.isVoice() || !TextUtils.isEmpty(currentMessageObject.caption)) { captionX += transitionParams.deltaLeft; } } @@ -12826,16 +13041,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate restore = canvas.saveLayerAlpha(rect, (int) (255 * renderingAlpha), Canvas.ALL_SAVE_FLAG); } if (transitionParams.animateBackgroundBoundsInner && currentBackgroundDrawable != null && currentMessagesGroup == null) { - Rect r = currentBackgroundDrawable.getBounds(); + int bottomoffset = (drawCommentButton && commentButtonRect != null ? commentButtonRect.height() : 0) + (reactionsLayoutInBubble != null && !reactionsLayoutInBubble.isSmall ? reactionsLayoutInBubble.height : 0); if (currentMessageObject.isOutOwner() && !mediaBackground && !pinnedBottom) { canvas.clipRect( getBackgroundDrawableLeft() + transitionParams.deltaLeft + AndroidUtilities.dp(4), getBackgroundDrawableTop() + transitionParams.deltaTop + AndroidUtilities.dp(4), - getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(10), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) + getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(10), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) - bottomoffset ); } else { canvas.clipRect( getBackgroundDrawableLeft() + transitionParams.deltaLeft + AndroidUtilities.dp(4), getBackgroundDrawableTop() + transitionParams.deltaTop + AndroidUtilities.dp(4), - getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(4), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) + getBackgroundDrawableRight() + transitionParams.deltaRight - AndroidUtilities.dp(4), getBackgroundDrawableBottom() + transitionParams.deltaBottom - AndroidUtilities.dp(4) - bottomoffset ); } } @@ -12857,7 +13072,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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); + SpoilerEffect.renderWithRipple(this, invalidateSpoilersParent, spoilersColor, 0, captionPatchedSpoilersLayout, captionLayout, captionSpoilers, canvas, currentMessagesGroup != null); Emoji.emojiDrawingYOffset = 0; } catch (Exception e) { @@ -12886,7 +13101,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return; } for (int i = 0; i < 2; i++) { - float curentAplha = alpha; + float currentAlpha = alpha; if (i == 0 && isDrawSelectionBackground() && currentSelectedBackgroundAlpha == 1f && !shouldDrawTimeOnMedia()) { continue; } else if (i == 1 && ((!isDrawSelectionBackground() && currentSelectedBackgroundAlpha == 0) || shouldDrawTimeOnMedia())) { @@ -12894,21 +13109,21 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } boolean drawSelectionBackground = i == 1; if (i == 1) { - curentAplha *= currentSelectedBackgroundAlpha; + currentAlpha *= currentSelectedBackgroundAlpha; } else if (!shouldDrawTimeOnMedia()) { - curentAplha *= (1f - currentSelectedBackgroundAlpha); + currentAlpha *= (1f - currentSelectedBackgroundAlpha); } if (transitionParams.animateShouldDrawTimeOnMedia && transitionParams.animateChangeProgress != 1f) { if (shouldDrawTimeOnMedia()) { overideShouldDrawTimeOnMedia = 1; - drawTimeInternal(canvas, curentAplha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); + drawTimeInternal(canvas, currentAlpha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); overideShouldDrawTimeOnMedia = 2; - drawTimeInternal(canvas, curentAplha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); + drawTimeInternal(canvas, currentAlpha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); } else { overideShouldDrawTimeOnMedia = 2; - drawTimeInternal(canvas, curentAplha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); + drawTimeInternal(canvas, currentAlpha * transitionParams.animateChangeProgress, fromParent, this.timeX, timeLayout, timeWidth, drawSelectionBackground); overideShouldDrawTimeOnMedia = 1; - drawTimeInternal(canvas, curentAplha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); + drawTimeInternal(canvas, currentAlpha * (1f - transitionParams.animateChangeProgress), fromParent, transitionParams.animateFromTimeX, transitionParams.animateTimeLayout, transitionParams.animateTimeWidth, drawSelectionBackground); } overideShouldDrawTimeOnMedia = 0; } else { @@ -12921,7 +13136,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate timeX = this.timeX + transitionParams.deltaRight; timeWidth = this.timeWidth; } - drawTimeInternal(canvas, curentAplha, fromParent, timeX, timeLayout, timeWidth, drawSelectionBackground); + drawTimeInternal(canvas, currentAlpha, fromParent, timeX, timeLayout, timeWidth, drawSelectionBackground); } } @@ -13193,7 +13408,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean drawCheck2 = (currentStatus & 2) != 0; boolean drawClock = (currentStatus & 4) != 0; boolean drawError = (currentStatus & 8) != 0; - boolean isBroadcast = (currentStatus & 16) != 0; boolean needRestore = false; if (transitionYOffsetForDrawables != 0) { needRestore = true; @@ -13205,15 +13419,14 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate boolean outDrawCheck2 = (animateFromStatusDrawableParams & 2) != 0; boolean outDrawClock = (animateFromStatusDrawableParams & 4) != 0; boolean outDrawError = (animateFromStatusDrawableParams & 8) != 0; - boolean outIsBroadcast = (animateFromStatusDrawableParams & 16) != 0; - if (!outDrawClock && !isBroadcast && !outIsBroadcast && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1) { - drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, true, drawSelectionBackground); + if (!outDrawClock && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1) { + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, true, drawSelectionBackground); } else { - drawStatusDrawable(canvas, outDrawCheck1, outDrawCheck2, outDrawClock, outDrawError, outIsBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, 1f - statusDrawableProgress, false, drawSelectionBackground); - drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, false, drawSelectionBackground); + drawStatusDrawable(canvas, outDrawCheck1, outDrawCheck2, outDrawClock, outDrawError, alpha, bigRadius, timeYOffset, layoutHeight, 1f - statusDrawableProgress, false, drawSelectionBackground); + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, alpha, bigRadius, timeYOffset, layoutHeight, statusDrawableProgress, false, drawSelectionBackground); } } else { - drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, isBroadcast, alpha, bigRadius, timeYOffset, layoutHeight, 1, false, drawSelectionBackground); + drawStatusDrawable(canvas, drawCheck1, drawCheck2, drawClock, drawError, alpha, bigRadius, timeYOffset, layoutHeight, 1, false, drawSelectionBackground); } if (needRestore) { canvas.restore(); @@ -13229,14 +13442,12 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate private void createStatusDrawableAnimator(int lastStatusDrawableParams, int currentStatus, boolean fromParent) { boolean drawCheck1 = (currentStatus & 1) != 0; boolean drawCheck2 = (currentStatus & 2) != 0; - boolean isBroadcast = (currentStatus & 16) != 0; boolean outDrawCheck1 = (lastStatusDrawableParams & 1) != 0; boolean outDrawCheck2 = (lastStatusDrawableParams & 2) != 0; boolean outDrawClock = (lastStatusDrawableParams & 4) != 0; - boolean outIsBroadcast = (lastStatusDrawableParams & 16) != 0; - boolean moveCheckTransition = !outDrawClock && !isBroadcast && !outIsBroadcast && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1; + boolean moveCheckTransition = !outDrawClock && outDrawCheck2 && drawCheck2 && !outDrawCheck1 && drawCheck1; if (transitionParams.messageEntering && !moveCheckTransition) { return; @@ -13540,7 +13751,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } } - private void drawStatusDrawable(Canvas canvas, boolean drawCheck1, boolean drawCheck2, boolean drawClock, boolean drawError, boolean isBroadcast, float alpha, boolean bigRadius, float timeYOffset, float layoutHeight, float progress, boolean moveCheck, boolean drawSelectionBackground) { + private void drawStatusDrawable(Canvas canvas, boolean drawCheck1, boolean drawCheck2, boolean drawClock, boolean drawError, float alpha, boolean bigRadius, float timeYOffset, float layoutHeight, float progress, boolean moveCheck, boolean drawSelectionBackground) { final boolean useScale = progress != 1f && !moveCheck; float scale = 0.5f + 0.5f * progress; if (useScale) { @@ -13578,17 +13789,34 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } invalidate(); } - if (isBroadcast) { - if (drawCheck1 || drawCheck2) { + if (drawCheck2) { + if (shouldDrawTimeOnMedia()) { Drawable drawable; - if (shouldDrawTimeOnMedia()) { - setDrawableBounds(Theme.chat_msgBroadcastMediaDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 26 : 24) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(14.0f) - Theme.chat_msgBroadcastMediaDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgBroadcastMediaDrawable.setAlpha((int) (255 * alpha)); - drawable = Theme.chat_msgBroadcastMediaDrawable; + if (moveCheck) { + canvas.save(); + } + if (currentMessageObject.shouldDrawWithoutBackground()) { + drawable = getThemedDrawable(Theme.key_drawable_msgStickerCheck); + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); + } + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); + } else { + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); + } + drawable.setAlpha((int) (255 * timeAlpha * alpha)); } else { - setDrawableBounds(Theme.chat_msgBroadcastDrawable, layoutWidth - AndroidUtilities.dp(20.5f) - Theme.chat_msgBroadcastDrawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(8.0f) - Theme.chat_msgBroadcastDrawable.getIntrinsicHeight() + timeYOffset); - Theme.chat_msgBroadcastDrawable.setAlpha((int) (255 * alpha)); - drawable = Theme.chat_msgBroadcastDrawable; + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); + } + setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); + } else { + setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); + } + Theme.chat_msgMediaCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); + drawable = Theme.chat_msgMediaCheckDrawable; } if (useScale) { canvas.save(); @@ -13598,115 +13826,67 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (useScale) { canvas.restore(); } + if (moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); + } else { + Drawable drawable; + if (moveCheck) { + canvas.save(); + } + if (drawCheck1) { + if (moveCheck) { + canvas.translate(AndroidUtilities.dp(4) * (1f - progress), 0); + } + drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckReadSelected : Theme.key_drawable_msgOutCheckRead); + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + } else { + drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckSelected : Theme.key_drawable_msgOutCheck); + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + } + drawable.setAlpha((int) (255 * alpha)); + if (useScale) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale) { + canvas.restore(); + } + if (moveCheck) { + canvas.restore(); + } drawable.setAlpha(255); } - } else { - if (drawCheck2) { - if (shouldDrawTimeOnMedia()) { - Drawable drawable; - if (moveCheck) { - canvas.save(); - } - if (currentMessageObject.shouldDrawWithoutBackground()) { - drawable = getThemedDrawable(Theme.key_drawable_msgStickerCheck); - if (drawCheck1) { - if (moveCheck) { - canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); - } - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); - } else { - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); - } - drawable.setAlpha((int) (255 * timeAlpha * alpha)); - } else { - if (drawCheck1) { - if (moveCheck) { - canvas.translate(AndroidUtilities.dp(4.8f) * (1f - progress), 0); - } - setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 28.3f : 26.3f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); - } else { - setDrawableBounds(Theme.chat_msgMediaCheckDrawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - Theme.chat_msgMediaCheckDrawable.getIntrinsicWidth(), timeY - Theme.chat_msgMediaCheckDrawable.getIntrinsicHeight() + timeYOffset); - } - Theme.chat_msgMediaCheckDrawable.setAlpha((int) (255 * timeAlpha * alpha)); - drawable = Theme.chat_msgMediaCheckDrawable; - } - if (useScale) { - canvas.save(); - canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); - } - drawable.draw(canvas); - if (useScale) { - canvas.restore(); - } - if (moveCheck) { - canvas.restore(); - } - drawable.setAlpha(255); - } else { - Drawable drawable; - if (moveCheck) { - canvas.save(); - } - if (drawCheck1) { - if (moveCheck) { - canvas.translate(AndroidUtilities.dp(4) * (1f - progress), 0); - } - drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckReadSelected : Theme.key_drawable_msgOutCheckRead); - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(22.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - } else { - drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutCheckSelected : Theme.key_drawable_msgOutCheck); - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18.5f) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - } - drawable.setAlpha((int) (255 * alpha)); - if (useScale) { - canvas.save(); - canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); - } - drawable.draw(canvas); - if (useScale) { - canvas.restore(); - } - if (moveCheck) { - canvas.restore(); - } - drawable.setAlpha(255); + } + if (drawCheck1) { + if (shouldDrawTimeOnMedia()) { + Drawable drawable = currentMessageObject.shouldDrawWithoutBackground() ? getThemedDrawable(Theme.key_drawable_msgStickerHalfCheck) : Theme.chat_msgMediaHalfCheckDrawable; + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); + drawable.setAlpha((int) (255 * timeAlpha * alpha)); + if (useScale || moveCheck) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); } - } - if (drawCheck1) { - if (shouldDrawTimeOnMedia()) { - Drawable drawable; - if (currentMessageObject.shouldDrawWithoutBackground()) { - drawable = getThemedDrawable(Theme.key_drawable_msgStickerHalfCheck); - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); - drawable.setAlpha((int) (255 * timeAlpha * alpha)); - } else { - drawable = Theme.chat_msgMediaHalfCheckDrawable; - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(bigRadius ? 23.5f : 21.5f) - drawable.getIntrinsicWidth(), timeY - drawable.getIntrinsicHeight() + timeYOffset); - drawable.setAlpha((int) (255 * timeAlpha * alpha)); - } - if (useScale || moveCheck) { - canvas.save(); - canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); - } - drawable.draw(canvas); - if (useScale || moveCheck) { - canvas.restore(); - } - drawable.setAlpha(255); - } else { - Drawable drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutHalfCheckSelected : Theme.key_drawable_msgOutHalfCheck); - setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); - drawable.setAlpha((int) (255 * alpha)); - if (useScale || moveCheck) { - canvas.save(); - canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); - } - drawable.draw(canvas); - if (useScale || moveCheck) { - canvas.restore(); - } - drawable.setAlpha(255); + drawable.draw(canvas); + if (useScale || moveCheck) { + canvas.restore(); } + drawable.setAlpha(255); + } else { + Drawable drawable = getThemedDrawable(drawSelectionBackground ? Theme.key_drawable_msgOutHalfCheckSelected : Theme.key_drawable_msgOutHalfCheck); + setDrawableBounds(drawable, layoutWidth - AndroidUtilities.dp(18) - drawable.getIntrinsicWidth(), layoutHeight - AndroidUtilities.dp(pinnedBottom || pinnedTop ? 9 : 8) - drawable.getIntrinsicHeight() + timeYOffset); + drawable.setAlpha((int) (255 * alpha)); + if (useScale || moveCheck) { + canvas.save(); + canvas.scale(scale, scale, drawable.getBounds().centerX(), drawable.getBounds().centerY()); + } + drawable.draw(canvas); + if (useScale || moveCheck) { + canvas.restore(); + } + drawable.setAlpha(255); } } if (drawError) { @@ -13828,6 +14008,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (drawLoadingProgress && loadingProgressLayout != null) { imageW = 0; infoW = (int) loadingProgressLayout.getLineWidth(0); +// infoW = loadingProgressLayout.getCurrentWidth(); } else { infoW = infoWidth; } @@ -13873,6 +14054,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate 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) { @@ -14672,9 +14854,10 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate @Override public boolean performAccessibilityAction(int action, Bundle arguments) { - if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) { - currentFocusedVirtualView = -1; - } else if (action == AccessibilityNodeInfo.ACTION_CLICK) { + if (delegate != null && delegate.onAccessibilityAction(action, arguments)) { + return false; + } + if (action == AccessibilityNodeInfo.ACTION_CLICK) { int icon = getIconForCurrentState(); if (icon != MediaActionDrawable.ICON_NONE && icon != MediaActionDrawable.ICON_FILE) { didPressButton(true, false); @@ -14694,6 +14877,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate delegate.didPressOther(this, otherX, otherY); } } + } else if (action == R.id.acc_action_open_forwarded_origin) { + if (delegate != null) { + if (currentForwardChannel != null) { + delegate.didPressChannelAvatar(ChatMessageCell.this, currentForwardChannel, currentMessageObject.messageOwner.fwd_from.channel_post, lastTouchX, lastTouchY); + } else if (currentForwardUser != null) { + delegate.didPressUserAvatar(ChatMessageCell.this, currentForwardUser, lastTouchX, lastTouchY); + } else if (currentForwardName != null) { + delegate.didPressHiddenForward(ChatMessageCell.this); + } + } } if (currentMessageObject.isVoice() || currentMessageObject.isRoundVideo() || currentMessageObject.isMusic() && MediaController.getInstance().isPlayingMessage(currentMessageObject)) { if (seekBarAccessibilityDelegate.performAccessibilityActionInternal(action, arguments)) { @@ -14748,11 +14941,18 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private void sendAccessibilityEventForVirtualView(int viewId, int eventType) { + sendAccessibilityEventForVirtualView(viewId, eventType, null); + } + + private void sendAccessibilityEventForVirtualView(int viewId, int eventType, String text) { AccessibilityManager am = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); if (am.isTouchExplorationEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain(eventType); event.setPackageName(getContext().getPackageName()); event.setSource(ChatMessageCell.this, viewId); + if (text != null) { + event.getText().add(text); + } if (getParent() != null) { getParent().requestSendAccessibilityEvent(ChatMessageCell.this, event); } @@ -14956,22 +15156,41 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate return seekBar; } + public SeekBarWaveform getSeekBarWaveform() { + return seekBarWaveform; + } + private class MessageAccessibilityNodeProvider extends AccessibilityNodeProvider { - private final int LINK_IDS_START = 2000; - private final int LINK_CAPTION_IDS_START = 3000; - private final int BOT_BUTTONS_START = 1000; - private final int POLL_BUTTONS_START = 500; - private final int INSTANT_VIEW = 499; - private final int SHARE = 498; - private final int REPLY = 497; - private final int COMMENT = 496; - private final int POLL_HINT = 495; - private final int FORWARD = 494; + public static final int PROFILE = 5000; + public static final int LINK_IDS_START = 2000; + public static final int LINK_CAPTION_IDS_START = 3000; + public static final int BOT_BUTTONS_START = 1000; + public static final int POLL_BUTTONS_START = 500; + public static final int INSTANT_VIEW = 499; + public static final int SHARE = 498; + public static final int REPLY = 497; + public static final int COMMENT = 496; + public static final int POLL_HINT = 495; + public static final int FORWARD = 494; + public static final int TRANSCRIBE = 493; private Path linkPath = new Path(); private RectF rectF = new RectF(); private Rect rect = new Rect(); + private class ProfileSpan extends ClickableSpan { + private TLRPC.User user; + public ProfileSpan(TLRPC.User user) { + this.user = user; + } + @Override + public void onClick(@NonNull View view) { + if (delegate != null) { + delegate.didPressUserAvatar(ChatMessageCell.this, user, 0, 0); + } + } + } + @Override public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { int[] pos = {0, 0}; @@ -14983,6 +15202,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate SpannableStringBuilder sb = new SpannableStringBuilder(); if (isChat && currentUser != null && !currentMessageObject.isOut()) { sb.append(UserObject.getUserName(currentUser)); + sb.setSpan(new ProfileSpan(currentUser), 0, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); sb.append('\n'); } if (drawForwardedName) { @@ -15003,13 +15223,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate final String key = sending ? "AccDescrUploadProgress" : "AccDescrDownloadProgress"; final int resId = sending ? R.string.AccDescrUploadProgress : R.string.AccDescrDownloadProgress; sb.append(LocaleController.formatString(key, resId, AndroidUtilities.formatFileSize(currentMessageObject.loadedFileSize), AndroidUtilities.formatFileSize(lastLoadingSizeTotal))); - } else if (buttonState == 0 || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { - sb.append(", "); - sb.append(AndroidUtilities.formatFileSize(documentAttach.size)); - } - if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { - sb.append(", "); - sb.append(LocaleController.formatDuration(currentMessageObject.getDuration())); } } if (currentMessageObject.isMusic()) { @@ -15020,9 +15233,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (currentMessageObject.isVoice() || isRoundVideo) { sb.append(", "); sb.append(LocaleController.formatDuration(currentMessageObject.getDuration())); + sb.append(", "); if (currentMessageObject.isContentUnread()) { - sb.append(", "); sb.append(LocaleController.getString("AccDescrMsgNotPlayed", R.string.AccDescrMsgNotPlayed)); + } else { + sb.append(LocaleController.getString("AccDescrMsgPlayed", R.string.AccDescrMsgPlayed)); } } if (lastPoll != null) { @@ -15047,9 +15262,24 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } sb.append(title); } - if (currentMessageObject.messageOwner.media != null && !TextUtils.isEmpty(currentMessageObject.caption)) { + if (currentMessageObject.isVoiceTranscriptionOpen()) { sb.append("\n"); - sb.append(currentMessageObject.caption); + sb.append(currentMessageObject.getVoiceTranscription()); + } else { + if (currentMessageObject.messageOwner.media != null && !TextUtils.isEmpty(currentMessageObject.caption)) { + sb.append("\n"); + sb.append(currentMessageObject.caption); + } + } + if (documentAttach != null) { + if (documentAttachType == DOCUMENT_ATTACH_TYPE_VIDEO) { + sb.append(", "); + sb.append(LocaleController.formatDuration(currentMessageObject.getDuration())); + } + if (buttonState == 0 || documentAttachType == DOCUMENT_ATTACH_TYPE_DOCUMENT) { + sb.append(", "); + sb.append(AndroidUtilities.formatFileSize(documentAttach.size)); + } } if (currentMessageObject.isOut()) { if (currentMessageObject.isSent()) { @@ -15076,6 +15306,51 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate sb.append("\n"); sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, LocaleController.getString("TodayAt", R.string.TodayAt) + " " + currentTimeString)); } + if (getRepliesCount() > 0 && !hasCommentLayout()) { + sb.append("\n"); + sb.append(LocaleController.formatPluralString("AccDescrNumberOfReplies", getRepliesCount())); + } + if (currentMessageObject.messageOwner.reactions != null && currentMessageObject.messageOwner.reactions.results != null) { + if (currentMessageObject.messageOwner.reactions.results.size() == 1) { + TLRPC.TL_reactionCount reaction = currentMessageObject.messageOwner.reactions.results.get(0); + if (reaction.count == 1) { + sb.append("\n"); + boolean isMe = false; + String userName = ""; + if (currentMessageObject.messageOwner.reactions.recent_reactions != null && currentMessageObject.messageOwner.reactions.recent_reactions.size() == 1) { + TLRPC.TL_messagePeerReaction recentReaction = currentMessageObject.messageOwner.reactions.recent_reactions.get(0); + if (recentReaction != null) { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(MessageObject.getPeerId(recentReaction.peer_id)); + isMe = UserObject.isUserSelf(user); + if (user != null) { + userName = UserObject.getFirstName(user); + } + } + } + if (isMe) { + sb.append(LocaleController.formatString("AccDescrYouReactedWith", R.string.AccDescrYouReactedWith, reaction.reaction)); + } else { + sb.append(LocaleController.formatString("AccDescrReactedWith", R.string.AccDescrReactedWith, userName, reaction.reaction)); + } + } else if (reaction.count > 1) { + sb.append("\n"); + sb.append(LocaleController.formatPluralString("AccDescrNumberOfPeopleReactions", reaction.count, reaction.reaction)); + } + } else { + sb.append(LocaleController.getString("Reactions", R.string.Reactions)).append((": ")); + final int count = currentMessageObject.messageOwner.reactions.results.size(); + for (int i = 0; i < count; ++i) { + TLRPC.TL_reactionCount reactionCount = currentMessageObject.messageOwner.reactions.results.get(i); + if (reactionCount != null) { + sb.append(reactionCount.reaction).append(" ").append(reactionCount.count + ""); + if (i + 1 < count) { + sb.append(", "); + } + } + } + sb.append("\n"); + } + } if ((currentMessageObject.messageOwner.flags & TLRPC.MESSAGE_FLAG_HAS_VIEWS) != 0) { sb.append("\n"); sb.append(LocaleController.formatPluralString("AccDescrNumberOfViews", currentMessageObject.messageOwner.views)); @@ -15092,7 +15367,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate ClickableSpan underlineSpan = new ClickableSpan() { @Override public void onClick(View view) { - if (delegate != null) { + if (link instanceof ProfileSpan) { + ((ProfileSpan) link).onClick(view); + } else if (delegate != null) { delegate.didPressUrl(ChatMessageCell.this, link, false); } } @@ -15159,8 +15436,15 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate info.addChild(ChatMessageCell.this, FORWARD); } + if (useTranscribeButton && transcribeButton != null) { + info.addChild(ChatMessageCell.this, TRANSCRIBE); + } + int i; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + if (isChat && currentUser != null && !currentMessageObject.isOut()) { + info.addChild(ChatMessageCell.this, PROFILE); + } if (currentMessageObject.messageText instanceof Spannable) { Spannable buffer = (Spannable) currentMessageObject.messageText; CharacterStyle[] links = buffer.getSpans(0, buffer.length(), ClickableSpan.class); @@ -15205,6 +15489,13 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (replyNameLayout != null) { info.addChild(ChatMessageCell.this, REPLY); } + if (forwardedNameLayout[0] != null && forwardedNameLayout[1] != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_open_forwarded_origin, LocaleController.getString("AccActionOpenForwardedOrigin", R.string.AccActionOpenForwardedOrigin))); + } else { + info.addChild(ChatMessageCell.this, FORWARD); + } + } if (drawSelectionBackground || getBackground() != null) { info.setSelected(true); } @@ -15214,7 +15505,26 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate info.setSource(ChatMessageCell.this, virtualViewId); info.setParent(ChatMessageCell.this); info.setPackageName(getContext().getPackageName()); - if (virtualViewId >= LINK_CAPTION_IDS_START) { + if (virtualViewId == PROFILE) { + if (currentUser == null) { + return null; + } + String content = UserObject.getUserName(currentUser); + info.setText(content); + rect.set((int) nameX, (int) nameY, (int) (nameX + nameWidth), (int) (nameY + (nameLayout != null ? nameLayout.getHeight() : 10))); + info.setBoundsInParent(rect); + if (accessibilityVirtualViewBounds.get(virtualViewId) == null) { + accessibilityVirtualViewBounds.put(virtualViewId, new Rect(rect)); + } + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + info.setClassName("android.widget.TextView"); + info.setEnabled(true); + info.setClickable(true); + info.setLongClickable(true); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); + } else if (virtualViewId >= LINK_CAPTION_IDS_START) { if (!(currentMessageObject.caption instanceof Spannable) || captionLayout == null) { return null; } @@ -15319,8 +15629,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { info.setSelected(button.chosen); sb.append(", ").append(button.percent).append("%"); - if (lastPoll != null && lastPoll.quiz && button.correct) { - sb.append(", ").append(LocaleController.getString("AccDescrQuizCorrectAnswer", R.string.AccDescrQuizCorrectAnswer)); + if (lastPoll != null && lastPoll.quiz && (button.chosen || button.correct)) { + sb.append(", ").append(button.correct ? LocaleController.getString("AccDescrQuizCorrectAnswer", R.string.AccDescrQuizCorrectAnswer) : LocaleController.getString("AccDescrQuizIncorrectAnswer", R.string.AccDescrQuizIncorrectAnswer)); } } info.setText(sb); @@ -15423,10 +15733,19 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else if (virtualViewId == COMMENT) { info.setClassName("android.widget.Button"); info.setEnabled(true); - if (commentLayout != null) { - //commentLayout not give for us text information about number of comments,so we shouldn't use text of layout for viryual node. - int commentCount = getRepliesCount(); - info.setText(isRepliesChat ? LocaleController.getString("ViewInChat", R.string.ViewInChat) : commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.formatPluralString("CommentsCount", commentCount)); + int commentCount = getRepliesCount(); + String comment = null; + if (currentMessageObject != null && !currentMessageObject.shouldDrawWithoutBackground() && !currentMessageObject.isAnimatedEmoji()) { + if (isRepliesChat) { + comment = LocaleController.getString("ViewInChat", R.string.ViewInChat); + } else { + comment = commentCount == 0 ? LocaleController.getString("LeaveAComment", R.string.LeaveAComment) : LocaleController.formatPluralString("CommentsCount", commentCount); + } + } else if (!isRepliesChat && commentCount > 0) { + comment = LocaleController.formatShortNumber(commentCount, null); + } + if (comment != null) { + info.setText(comment); } info.addAction(AccessibilityNodeInfo.ACTION_CLICK); rect.set(commentButtonRect); @@ -15437,6 +15756,16 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate rect.offset(pos[0], pos[1]); info.setBoundsInScreen(rect); info.setClickable(true); + } else if (virtualViewId == TRANSCRIBE) { + info.setClassName("android.widget.Button"); + info.setEnabled(true); + info.setText(currentMessageObject.isVoiceTranscriptionOpen() ? LocaleController.getString("AccActionCloseTranscription", R.string.AccActionCloseTranscription) : LocaleController.getString("AccActionOpenTranscription", R.string.AccActionOpenTranscription)); + info.addAction(AccessibilityNodeInfo.ACTION_CLICK); + rect.set((int) transcribeX, (int) transcribeY, (int) (transcribeX + AndroidUtilities.dp(30)), (int) (transcribeY + AndroidUtilities.dp(30))); + info.setBoundsInParent(rect); + rect.offset(pos[0], pos[1]); + info.setBoundsInScreen(rect); + info.setClickable(true); } info.setFocusable(true); info.setVisibleToUser(true); @@ -15453,7 +15782,11 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate currentFocusedVirtualView = virtualViewId; sendAccessibilityEventForVirtualView(virtualViewId, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); } else if (action == AccessibilityNodeInfo.ACTION_CLICK) { - if (virtualViewId >= LINK_CAPTION_IDS_START) { + if (virtualViewId == PROFILE) { + if (delegate != null) { + delegate.didPressUserAvatar(ChatMessageCell.this, currentUser, 0, 0); + } + } else if (virtualViewId >= LINK_CAPTION_IDS_START) { ClickableSpan link = getLinkById(virtualViewId, true); if (link != null) { delegate.didPressUrl(ChatMessageCell.this, link, false); @@ -15523,6 +15856,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate delegate.didPressCommentButton(ChatMessageCell.this); } } + } else if (virtualViewId == TRANSCRIBE && transcribeButton != null) { + transcribeButton.onTap(); } } else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK) { ClickableSpan link = getLinkById(virtualViewId, virtualViewId >= LINK_CAPTION_IDS_START); @@ -15536,6 +15871,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } private ClickableSpan getLinkById(int id, boolean caption) { + if (id == PROFILE) { + return null; + } if (caption) { id -= LINK_CAPTION_IDS_START; if (!(currentMessageObject.caption instanceof Spannable) || id < 0) { @@ -15698,6 +16036,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public float deltaBottom; public float deltaTop; + // in animation, describe to what values deltaLeft and deltaRight moves to + public float toDeltaLeft, toDeltaRight; + public float animateToImageX, animateToImageY, animateToImageW, animateToImageH; public float captionFromX, captionFromY; private boolean moveCaption; @@ -15925,7 +16266,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (captionLayout != lastDrawingCaptionLayout) { String oldCaption = lastDrawingCaptionLayout == null ? null : lastDrawingCaptionLayout.getText().toString(); String currentCaption = captionLayout == null ? null : captionLayout.getText().toString(); - if (currentCaption != null && (oldCaption == null || !oldCaption.equals(currentCaption))) { + if ((currentCaption == null) != (oldCaption == null) || (oldCaption != null && !oldCaption.equals(currentCaption))) { animateReplaceCaptionLayout = true; animateOutCaptionLayout = lastDrawingCaptionLayout; changed = true; @@ -16106,6 +16447,8 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate deltaRight = 0; deltaBottom = 0; deltaTop = 0; + toDeltaLeft = 0; + toDeltaRight = 0; if (imageChangeBoundsTransition && animateToImageW != 0 && animateToImageH != 0) { photoImage.setImageCoords(animateToImageX, animateToImageY, animateToImageW, animateToImageH); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java index af1c53c74..a3f3f72a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ContextLinkCell.java @@ -81,6 +81,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F private LetterDrawable letterDrawable; private int currentAccount = UserConfig.selectedAccount; private Object parentObject; + private Theme.ResourcesProvider resourcesProvider; private boolean needDivider; private boolean buttonPressed; @@ -129,25 +130,30 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F private ContextLinkCellDelegate delegate; public ContextLinkCell(Context context) { - this(context, false); + this(context, false, null); } public ContextLinkCell(Context context, boolean needsCheckBox) { + this(context, needsCheckBox, null); + } + + public ContextLinkCell(Context context, boolean needsCheckBox, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; linkImageView = new ImageReceiver(this); linkImageView.setLayerNum(1); linkImageView.setUseSharedAnimationQueue(true); - letterDrawable = new LetterDrawable(); + letterDrawable = new LetterDrawable(resourcesProvider); radialProgress = new RadialProgress2(this); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); setFocusable(true); if (needsCheckBox) { backgroundPaint = new Paint(); - backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder)); + backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder, resourcesProvider)); - checkBox = new CheckBox2(context, 21); + checkBox = new CheckBox2(context, 21, resourcesProvider); checkBox.setVisibility(INVISIBLE); checkBox.setColor(null, Theme.key_sharedMedia_photoPlaceholder, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); @@ -503,6 +509,10 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; } requestLayout(); + fileName = null; + cacheFile = null; + fileExist = false; + resolvingFileName = false; updateButtonState(false, false); } @@ -531,6 +541,10 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F setAttachType(); documentAttachType = DOCUMENT_ATTACH_TYPE_GIF; requestLayout(); + fileName = null; + cacheFile = null; + fileExist = false; + resolvingFileName = false; updateButtonState(false, false); } @@ -718,7 +732,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F } if (descriptionLayout != null) { - Theme.chat_contextResult_descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + Theme.chat_contextResult_descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); descriptionLayout.draw(canvas); @@ -726,7 +740,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F } if (linkLayout != null) { - Theme.chat_contextResult_descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); + Theme.chat_contextResult_descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), linkY); linkLayout.draw(canvas); @@ -740,7 +754,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F letterDrawable.setAlpha(255); } if (documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO || documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC) { - radialProgress.setProgressColor(Theme.getColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress)); + radialProgress.setProgressColor(Theme.getColor(buttonPressed ? Theme.key_chat_inAudioSelectedProgress : Theme.key_chat_inAudioProgress, resourcesProvider)); radialProgress.draw(canvas); } else if (inlineResult != null && inlineResult.type.equals("file")) { int w = Theme.chat_inlineResultFile.getIntrinsicWidth(); @@ -839,93 +853,126 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F return buttonState == 1 ? MediaActionDrawable.ICON_EMPTY : MediaActionDrawable.ICON_NONE; } + boolean resolvingFileName; + String fileName; + File cacheFile = null; + int resolveFileNameId; + boolean fileExist; + private static int resolveFileIdPointer; + public void updateButtonState(boolean ifSame, boolean animated) { - String fileName = null; - File cacheFile = null; - if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { - if (documentAttach != null) { - fileName = FileLoader.getAttachFileName(documentAttach); - cacheFile = FileLoader.getPathToAttach(documentAttach); - } else if (inlineResult.content instanceof TLRPC.TL_webDocument) { - fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? "mp3" : "ogg"); - cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); - } - } else if (mediaWebpage) { - if (inlineResult != null) { - if (inlineResult.document instanceof TLRPC.TL_document) { - fileName = FileLoader.getAttachFileName(inlineResult.document); - cacheFile = FileLoader.getPathToAttach(inlineResult.document); - } else if (inlineResult.photo instanceof TLRPC.TL_photo) { - currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.getPhotoSize(), true); - fileName = FileLoader.getAttachFileName(currentPhotoObject); - cacheFile = FileLoader.getPathToAttach(currentPhotoObject); - } else if (inlineResult.content instanceof TLRPC.TL_webDocument) { - fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, FileLoader.getMimeTypePart(inlineResult.content.mime_type)); - cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); - if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && inlineResult.thumb instanceof TLRPC.TL_webDocument && "video/mp4".equals(inlineResult.thumb.mime_type)) { - fileName = null; + if (fileName == null && !resolvingFileName) { + resolvingFileName = true; + int localId = resolveFileNameId = resolveFileNameId++; + Utilities.searchQueue.postRunnable(new Runnable() { + @Override + public void run() { + String fileName = null; + File cacheFile = null; + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + if (documentAttach != null) { + fileName = FileLoader.getAttachFileName(documentAttach); + cacheFile = FileLoader.getInstance(currentAccount).getPathToAttach(documentAttach); + } else if (inlineResult.content instanceof TLRPC.TL_webDocument) { + fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC ? "mp3" : "ogg"); + cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + } + } else if (mediaWebpage) { + if (inlineResult != null) { + if (inlineResult.document instanceof TLRPC.TL_document) { + fileName = FileLoader.getAttachFileName(inlineResult.document); + cacheFile = FileLoader.getInstance(currentAccount).getPathToAttach(inlineResult.document); + } else if (inlineResult.photo instanceof TLRPC.TL_photo) { + currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.getPhotoSize(), true); + fileName = FileLoader.getAttachFileName(currentPhotoObject); + cacheFile = FileLoader.getInstance(currentAccount).getPathToAttach(currentPhotoObject); + } else if (inlineResult.content instanceof TLRPC.TL_webDocument) { + fileName = Utilities.MD5(inlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.content.url, FileLoader.getMimeTypePart(inlineResult.content.mime_type)); + cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && inlineResult.thumb instanceof TLRPC.TL_webDocument && "video/mp4".equals(inlineResult.thumb.mime_type)) { + fileName = null; + } + } else if (inlineResult.thumb instanceof TLRPC.TL_webDocument) { + fileName = Utilities.MD5(inlineResult.thumb.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.thumb.url, FileLoader.getMimeTypePart(inlineResult.thumb.mime_type)); + cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + } + } else if (documentAttach != null) { + fileName = FileLoader.getAttachFileName(documentAttach); + cacheFile = FileLoader.getInstance(currentAccount).getPathToAttach(documentAttach); + } + + if (documentAttach != null && documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.getDocumentVideoThumb(documentAttach) != null) { + fileName = null; + } } - } else if (inlineResult.thumb instanceof TLRPC.TL_webDocument) { - fileName = Utilities.MD5(inlineResult.thumb.url) + "." + ImageLoader.getHttpUrlExtension(inlineResult.thumb.url, FileLoader.getMimeTypePart(inlineResult.thumb.mime_type)); - cacheFile = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), fileName); + String fileNameFinal = fileName; + File cacheFileFinal = cacheFile; + boolean fileExist = !TextUtils.isEmpty(fileName) && cacheFile.exists(); + AndroidUtilities.runOnUIThread(() -> { + resolvingFileName = false; + if (resolveFileNameId == localId) { + ContextLinkCell.this.fileName = fileNameFinal; + if (ContextLinkCell.this.fileName == null) { + ContextLinkCell.this.fileName = ""; + } + ContextLinkCell.this.cacheFile = cacheFileFinal; + ContextLinkCell.this.fileExist = fileExist; + } + updateButtonState(ifSame, true); + }); } - } else if (documentAttach != null) { - fileName = FileLoader.getAttachFileName(documentAttach); - cacheFile = FileLoader.getPathToAttach(documentAttach); - } - - if (documentAttach != null && documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && MessageObject.getDocumentVideoThumb(documentAttach) != null) { - fileName = null; - } - } - - if (TextUtils.isEmpty(fileName)) { - buttonState = -1; + }); radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false); - return; - } - if (!cacheFile.exists()) { - DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, this); - if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { - boolean isLoading; - if (documentAttach != null) { - isLoading = FileLoader.getInstance(currentAccount).isLoadingFile(fileName); - } else { - isLoading = ImageLoader.getInstance().isLoadingHttpFile(fileName); - } - if (!isLoading) { - buttonState = 2; - } else { - buttonState = 4; - Float progress = ImageLoader.getInstance().getFileProgress(fileName); - if (progress != null) { - radialProgress.setProgress(progress, animated); - } else { - radialProgress.setProgress(0, animated); - } - } - } else { - buttonState = 1; - Float progress = ImageLoader.getInstance().getFileProgress(fileName); - float setProgress = progress != null ? progress : 0; - radialProgress.setProgress(setProgress, false); - } } else { - DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); - if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { - boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); - if (!playing || playing && MediaController.getInstance().isMessagePaused()) { - buttonState = 0; + if (TextUtils.isEmpty(fileName)) { + buttonState = -1; + radialProgress.setIcon(MediaActionDrawable.ICON_NONE, ifSame, false); + return; + } + + boolean isLoading; + if (documentAttach != null) { + isLoading = FileLoader.getInstance(currentAccount).isLoadingFile(fileName); + } else { + isLoading = ImageLoader.getInstance().isLoadingHttpFile(fileName); + } + if (isLoading || !fileExist) { + DownloadController.getInstance(currentAccount).addLoadingFileObserver(fileName, this); + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + if (!isLoading) { + buttonState = 2; + } else { + buttonState = 4; + Float progress = ImageLoader.getInstance().getFileProgress(fileName); + if (progress != null) { + radialProgress.setProgress(progress, animated); + } else { + radialProgress.setProgress(0, animated); + } + } } else { buttonState = 1; + Float progress = ImageLoader.getInstance().getFileProgress(fileName); + float setProgress = progress != null ? progress : 0; + radialProgress.setProgress(setProgress, false); } - radialProgress.setProgress(1, animated); } else { - buttonState = -1; + DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); + if (documentAttachType == DOCUMENT_ATTACH_TYPE_MUSIC || documentAttachType == DOCUMENT_ATTACH_TYPE_AUDIO) { + boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); + if (!playing || playing && MediaController.getInstance().isMessagePaused()) { + buttonState = 0; + } else { + buttonState = 1; + } + radialProgress.setProgress(1, animated); + } else { + buttonState = -1; + } } + radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); + invalidate(); } - radialProgress.setIcon(getIconForCurrentState(), ifSame, animated); - invalidate(); } public void setDelegate(ContextLinkCellDelegate contextLinkCellDelegate) { @@ -943,6 +990,7 @@ public class ContextLinkCell extends FrameLayout implements DownloadController.F @Override public void onSuccessDownload(String fileName) { + fileExist = true; radialProgress.setProgress(1, true); updateButtonState(false, true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CreationTextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CreationTextCell.java index 458abdb8f..219c3d651 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/CreationTextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/CreationTextCell.java @@ -20,12 +20,16 @@ public class CreationTextCell extends FrameLayout { public int startPadding = 70; public CreationTextCell(Context context) { + this(context, null); + } + + public CreationTextCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); textView = new SimpleTextView(context); textView.setTextSize(16); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText2, resourcesProvider)); textView.setTag(Theme.key_windowBackgroundWhiteBlueText2); addView(textView); 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 5c2ac03d4..edf65f874 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -19,6 +19,7 @@ import android.graphics.RectF; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Bundle; import android.os.SystemClock; import android.text.Layout; import android.text.Spannable; @@ -31,6 +32,7 @@ import android.text.style.CharacterStyle; import android.text.style.ClickableSpan; import android.text.style.ReplacementSpan; import android.text.style.StyleSpan; +import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -66,6 +68,7 @@ import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EmptyStubSpan; import org.telegram.ui.Components.ForegroundColorSpanThemable; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.Components.PullForegroundDrawable; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.StaticLayoutEx; @@ -220,9 +223,6 @@ public class DialogCell extends BaseCell { private int nameLeft; private StaticLayout nameLayout; private boolean drawNameLock; - private boolean drawNameGroup; - private boolean drawNameBroadcast; - private boolean drawNameBot; private int nameMuteLeft; private int nameLockLeft; private int nameLockTop; @@ -291,6 +291,7 @@ public class DialogCell extends BaseCell { private StaticLayout mentionLayout; private boolean drawVerified; + private boolean drawPremium; private int drawScam; @@ -348,7 +349,7 @@ public class DialogCell extends BaseCell { currentAccount = account; if (needCheck) { - checkBox = new CheckBox2(context, 21); + checkBox = new CheckBox2(context, 21, resourcesProvider); checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); checkBox.setDrawBackgroundAsArc(3); @@ -555,6 +556,18 @@ public class DialogCell extends BaseCell { return (unreadCount != 0 || markUnread) && !dialogMuted; } + public boolean getHasUnread() { + return (unreadCount != 0 || markUnread); + } + + public boolean getIsMuted() { + return dialogMuted; + } + + public boolean getIsPinned() { + return drawPin; + } + private CharSequence formatArchivedDialogNames() { ArrayList dialogs = MessagesController.getInstance(currentAccount).getDialogs(currentDialogFolderId); currentDialogFolderDialogsCount = dialogs.size(); @@ -640,11 +653,9 @@ public class DialogCell extends BaseCell { TextPaint currentMessagePaint = Theme.dialogs_messagePaint[paintIndex]; boolean checkMessage = true; - drawNameGroup = false; - drawNameBroadcast = false; drawNameLock = false; - drawNameBot = false; drawVerified = false; + drawPremium = false; drawScam = 0; drawPinBackground = false; hasMessageThumb = false; @@ -652,7 +663,7 @@ public class DialogCell extends BaseCell { boolean showChecks = !UserObject.isUserSelf(user) && !useMeForMyMessages; boolean drawTime = true; printingStringType = -1; - int printigStingReplaceIndex = -1; + int printingStringReplaceIndex = -1; String messageFormat; boolean hasNameInMessage; @@ -709,40 +720,17 @@ public class DialogCell extends BaseCell { } } else { drawVerified = customDialog.verified; - if (SharedConfig.drawDialogIcons && customDialog.type == 1) { - drawNameGroup = true; - if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { - nameLockTop = AndroidUtilities.dp(13.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(72 + 6); - nameLeft = AndroidUtilities.dp(72 + 10) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(22); - } + if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(72 + 6); } else { - if (!LocaleController.isRTL) { - nameLockTop = AndroidUtilities.dp(17.5f); - nameLockLeft = AndroidUtilities.dp(72 + 4); - nameLeft = AndroidUtilities.dp(72 + 8) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(18); - } + nameLeft = AndroidUtilities.dp(22); } } else { - if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { - if (!LocaleController.isRTL) { - nameLeft = AndroidUtilities.dp(72 + 6); - } else { - nameLeft = AndroidUtilities.dp(22); - } + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(72 + 4); } else { - if (!LocaleController.isRTL) { - nameLeft = AndroidUtilities.dp(72 + 4); - } else { - nameLeft = AndroidUtilities.dp(18); - } + nameLeft = AndroidUtilities.dp(18); } } } @@ -843,41 +831,6 @@ public class DialogCell extends BaseCell { } else { drawVerified = chat.verifiedExtended(); } - if (SharedConfig.drawDialogIcons) { - if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { - if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(12.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(13.5f); - } - - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(72 + 6); - nameLeft = AndroidUtilities.dp(72 + 10) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(22); - } - } else { - if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(16.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - } - - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(72 + 4); - nameLeft = AndroidUtilities.dp(72 + 8) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(18); - } - } - } } else if (user != null) { if (user.scam) { drawScam = 1; @@ -888,28 +841,7 @@ public class DialogCell extends BaseCell { } else { drawVerified = user.verifiedExtended(); } - if (SharedConfig.drawDialogIcons && user.bot) { - drawNameBot = true; - if (useForceThreeLines || SharedConfig.useThreeLinesLayout) { - nameLockTop = AndroidUtilities.dp(12.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(72 + 6); - nameLeft = AndroidUtilities.dp(72 + 10) + Theme.dialogs_botDrawable.getIntrinsicWidth(); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 6) - Theme.dialogs_botDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(22); - } - } else { - nameLockTop = AndroidUtilities.dp(16.5f); - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(72 + 4); - nameLeft = AndroidUtilities.dp(72 + 8) + Theme.dialogs_botDrawable.getIntrinsicWidth(); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(72 + 4) - Theme.dialogs_botDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(18); - } - } - } + drawPremium = MessagesController.getInstance(currentAccount).isPremiumUser(user) && UserConfig.getInstance(currentAccount).clientUserId != user.id && user.id != 0; } } } @@ -942,10 +874,10 @@ public class DialogCell extends BaseCell { printingString = TextUtils.replace(printingString, new String[]{"..."}, new String[]{""}); if (printingStringType == 5) { - printigStingReplaceIndex = printingString.toString().indexOf("**oo**"); + printingStringReplaceIndex = printingString.toString().indexOf("**oo**"); } - if (printigStingReplaceIndex >= 0) { - spannableStringBuilder.append(printingString).setSpan(new FixedWidthSpan(Theme.getChatStatusDrawable(printingStringType).getIntrinsicWidth()), printigStingReplaceIndex, printigStingReplaceIndex + 6, 0); + if (printingStringReplaceIndex >= 0) { + spannableStringBuilder.append(printingString).setSpan(new FixedWidthSpan(Theme.getChatStatusDrawable(printingStringType).getIntrinsicWidth()), printingStringReplaceIndex, printingStringReplaceIndex + 6, 0); } else { spannableStringBuilder.append(" ").append(printingString).setSpan(new FixedWidthSpan(startPadding), 0, 1, 0); } @@ -1120,9 +1052,6 @@ public class DialogCell extends BaseCell { stringBuilder = SpannableStringBuilder.valueOf(String.format(messageFormat, restrictionReason, messageNameString)); } else if (message.caption != null) { CharSequence mess = message.caption.toString(); - if (mess.length() > 150) { - mess = mess.subSequence(0, 150); - } String emoji; if (!needEmoji) { emoji = ""; @@ -1137,10 +1066,31 @@ public class DialogCell extends BaseCell { } else { emoji = "\uD83D\uDCCE "; } - SpannableStringBuilder msgBuilder = new SpannableStringBuilder(mess); - if (!NekoConfig.showSpoilersDirectly.Bool()) - MediaDataController.addTextStyleRuns(message.messageOwner.entities, message.caption, msgBuilder, TextStyleSpan.FLAG_STYLE_SPOILER); - stringBuilder = AndroidUtilities.formatSpannable(messageFormat, new SpannableStringBuilder(emoji).append(AndroidUtilities.replaceNewLines(msgBuilder)), messageNameString); + if (message.hasHighlightedWords() && !TextUtils.isEmpty(message.messageOwner.message)) { + String str = message.messageTrimmedToHighlight; + if (message.messageTrimmedToHighlight != null) { + str = message.messageTrimmedToHighlight; + } + int w = getMeasuredWidth() - AndroidUtilities.dp(72 + 23 + 24); + if (hasNameInMessage) { + if (!TextUtils.isEmpty(messageNameString)) { + w -= currentMessagePaint.measureText(messageNameString.toString()); + } + w -= currentMessagePaint.measureText(": "); + } + if (w > 0) { + str = AndroidUtilities.ellipsizeCenterEnd(str, message.highlightedWords.get(0), w, currentMessagePaint, 130).toString(); + } + stringBuilder = new SpannableStringBuilder(emoji).append(str); + } else { + if (mess.length() > 150) { + mess = mess.subSequence(0, 150); + } + SpannableStringBuilder msgBuilder = new SpannableStringBuilder(mess); + if (!NekoConfig.showSpoilersDirectly.Bool()) + MediaDataController.addTextStyleRuns(message.messageOwner.entities, mess, msgBuilder, TextStyleSpan.FLAG_STYLE_SPOILER); + stringBuilder = AndroidUtilities.formatSpannable(messageFormat, new SpannableStringBuilder(emoji).append(AndroidUtilities.replaceNewLines(msgBuilder)), messageNameString); + } } else if (message.messageOwner.media != null && !message.isMediaEmpty()) { currentMessagePaint = Theme.dialogs_messagePrintingPaint[paintIndex]; String innerMessage; @@ -1226,8 +1176,13 @@ public class DialogCell extends BaseCell { } checkMessage = false; SpannableStringBuilder builder = (SpannableStringBuilder) messageString; - builder.insert(thumbInsertIndex, " "); - builder.setSpan(new FixedWidthSpan(AndroidUtilities.dp(thumbSize + 6)), thumbInsertIndex, thumbInsertIndex + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (thumbInsertIndex >= builder.length()) { + builder.append(" "); + builder.setSpan(new FixedWidthSpan(AndroidUtilities.dp(thumbSize + 6)), builder.length() - 1, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + builder.insert(thumbInsertIndex, " "); + builder.setSpan(new FixedWidthSpan(AndroidUtilities.dp(thumbSize + 6)), thumbInsertIndex, thumbInsertIndex + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } } } else { if (!TextUtils.isEmpty(restrictionReason)) { @@ -1498,12 +1453,6 @@ public class DialogCell extends BaseCell { } if (drawNameLock) { nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); - } else if (drawNameGroup) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_groupDrawable.getIntrinsicWidth(); - } else if (drawNameBroadcast) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_broadcastDrawable.getIntrinsicWidth(); - } else if (drawNameBot) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_botDrawable.getIntrinsicWidth(); } if (drawClock) { int w = Theme.dialogs_clockDrawable.getIntrinsicWidth() + AndroidUtilities.dp(5); @@ -1549,6 +1498,12 @@ public class DialogCell extends BaseCell { if (LocaleController.isRTL) { nameLeft += w; } + } else if (drawPremium) { + int w = AndroidUtilities.dp(6) + PremiumGradient.getInstance().premiumStarDrawableMini.getIntrinsicWidth(); + nameWidth -= w; + if (LocaleController.isRTL) { + nameLeft += w; + } } else if (drawScam != 0) { int w = AndroidUtilities.dp(6) + (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth(); nameWidth -= w; @@ -1556,10 +1511,13 @@ public class DialogCell extends BaseCell { nameLeft += w; } } - - nameWidth = Math.max(AndroidUtilities.dp(12), nameWidth); try { - CharSequence nameStringFinal = TextUtils.ellipsize(nameString.replace('\n', ' '), Theme.dialogs_namePaint[paintIndex], nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + int ellipsizeWidth = nameWidth - AndroidUtilities.dp(12); + if (ellipsizeWidth < 0) { + ellipsizeWidth = 0; + } + CharSequence nameStringFinal = TextUtils.ellipsize(nameString.replace('\n', ' '), Theme.dialogs_namePaint[paintIndex], ellipsizeWidth, TextUtils.TruncateAt.END); + nameStringFinal = Emoji.replaceEmoji(nameStringFinal, Theme.dialogs_namePaint[paintIndex].getFontMetricsInt(), AndroidUtilities.dp(20), false); if (message != null && message.hasHighlightedWords()) { CharSequence s = AndroidUtilities.highlightText(nameStringFinal, message.highlightedWords, resourcesProvider); if (s != null) { @@ -1670,14 +1628,28 @@ public class DialogCell extends BaseCell { messageNameLeft += w; } drawMention = true; + } else { + mentionWidth = 0; } if (drawReactionMention) { int w = AndroidUtilities.dp(24); messageWidth -= w; if (!LocaleController.isRTL) { - reactionMentionLeft = getMeasuredWidth() - AndroidUtilities.dp(32) - (mentionWidth != 0 ? (mentionWidth + AndroidUtilities.dp(18)) : 0) - (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + reactionMentionLeft = getMeasuredWidth() - AndroidUtilities.dp(32); + if (drawMention) { + reactionMentionLeft -= (mentionWidth != 0 ? (mentionWidth + AndroidUtilities.dp(18)) : 0); + } + if (drawCount) { + reactionMentionLeft -= (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + } } else { - reactionMentionLeft = AndroidUtilities.dp(20) + (countWidth != 0 ? countWidth + AndroidUtilities.dp(18) : 0); + reactionMentionLeft = AndroidUtilities.dp(20); + if (drawMention) { + reactionMentionLeft += (mentionWidth != 0 ? (mentionWidth + AndroidUtilities.dp(18)) : 0); + } + if (drawCount) { + reactionMentionLeft += (countWidth != 0 ? (countWidth + AndroidUtilities.dp(18)) : 0); + } messageLeft += w; messageNameLeft += w; } @@ -1798,6 +1770,8 @@ public class DialogCell extends BaseCell { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth()); } else if (drawVerified) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth()); + } else if (drawPremium) { + nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - PremiumGradient.getInstance().premiumStarDrawableMini.getIntrinsicWidth()); } else if (drawScam != 0) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth()); } @@ -1844,7 +1818,7 @@ public class DialogCell extends BaseCell { nameLeft -= (nameWidth - widthpx); } } - if (dialogMuted || drawVerified || drawScam != 0) { + if (dialogMuted || drawVerified || drawPremium || drawScam != 0) { nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6)); } } @@ -1881,9 +1855,9 @@ public class DialogCell extends BaseCell { } if (messageLayout != null && printingStringType >= 0) { float x1, x2; - if (printigStingReplaceIndex >= 0 && printigStingReplaceIndex + 1 < messageLayout.getText().length() ){ - x1 = messageLayout.getPrimaryHorizontal(printigStingReplaceIndex); - x2 = messageLayout.getPrimaryHorizontal(printigStingReplaceIndex + 1); + if (printingStringReplaceIndex >= 0 && printingStringReplaceIndex + 1 < messageLayout.getText().length() ){ + x1 = messageLayout.getPrimaryHorizontal(printingStringReplaceIndex); + x2 = messageLayout.getPrimaryHorizontal(printingStringReplaceIndex + 1); } else { x1 = messageLayout.getPrimaryHorizontal(0); x2 = messageLayout.getPrimaryHorizontal(1); @@ -2295,7 +2269,7 @@ public class DialogCell extends BaseCell { avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); avatarImage.setImage(null, null, avatarDrawable, null, user, 0); } else { - avatarImage.setForUserOrChat(user, avatarDrawable); + avatarImage.setForUserOrChat(user, avatarDrawable, null, true); } } else if (chat != null) { avatarDrawable.setInfo(chat); @@ -2701,15 +2675,6 @@ public class DialogCell extends BaseCell { if (drawNameLock) { setDrawableBounds(Theme.dialogs_lockDrawable, nameLockLeft, nameLockTop); Theme.dialogs_lockDrawable.draw(canvas); - } else if (drawNameGroup) { - setDrawableBounds(Theme.dialogs_groupDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_groupDrawable.draw(canvas); - } else if (drawNameBroadcast) { - setDrawableBounds(Theme.dialogs_broadcastDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_broadcastDrawable.draw(canvas); - } else if (drawNameBot) { - setDrawableBounds(Theme.dialogs_botDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_botDrawable.draw(canvas); } if (nameLayout != null) { @@ -2829,7 +2794,7 @@ public class DialogCell extends BaseCell { lastStatusDrawableParams = (this.drawClock ? 1 : 0) + (this.drawCheck1 ? 2 : 0) + (this.drawCheck2 ? 4 : 0); } - if (dialogsType != 2 && (dialogMuted || dialogMutedProgress > 0) && !drawVerified && drawScam == 0) { + if (dialogsType != 2 && (dialogMuted || dialogMutedProgress > 0) && !drawVerified && drawScam == 0 && !drawPremium) { if (dialogMuted && dialogMutedProgress != 1f) { dialogMutedProgress += 16 / 150f; if (dialogMutedProgress > 1f) { @@ -2858,10 +2823,14 @@ public class DialogCell extends BaseCell { } } else if (drawVerified) { - setDrawableBounds(Theme.dialogs_verifiedDrawable, nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 16.5f)); - setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 16.5f)); + setDrawableBounds(Theme.dialogs_verifiedDrawable, nameMuteLeft - AndroidUtilities.dp(1), AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 13.5f : 16.5f)); + setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, nameMuteLeft - AndroidUtilities.dp(1), AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 13.5f : 16.5f)); Theme.dialogs_verifiedDrawable.draw(canvas); Theme.dialogs_verifiedCheckDrawable.draw(canvas); + } else if (drawPremium) { + Drawable premiumDrawable = PremiumGradient.getInstance().premiumStarDrawableMini; + setDrawableBounds(premiumDrawable, nameMuteLeft - AndroidUtilities.dp(1), AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12.5f : 15.5f)); + premiumDrawable.draw(canvas); } else if (drawScam != 0) { setDrawableBounds((drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable), nameMuteLeft, AndroidUtilities.dp(useForceThreeLines || SharedConfig.useThreeLinesLayout ? 12 : 15)); (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).draw(canvas); @@ -3360,6 +3329,16 @@ public class DialogCell extends BaseCell { public boolean hasOverlappingRendering() { return false; } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (action == R.id.acc_action_chat_preview && parentFragment != null) { + parentFragment.showChatPreview(this); + return true; + } + return super.performAccessibilityAction(action, arguments); + } + @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); @@ -3368,76 +3347,114 @@ public class DialogCell extends BaseCell { } else { info.addAction(AccessibilityNodeInfo.ACTION_CLICK); info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); - if (checkBox != null) info.setSelected(checkBox.isChecked()); - StringBuilder sb = new StringBuilder(); - if (currentDialogFolderId == 1) { - sb.append(LocaleController.getString("ArchivedChats", R.string.ArchivedChats)); - sb.append(". "); - } else { - if (encryptedChat != null) { - sb.append(LocaleController.getString("AccDescrSecretChat", R.string.AccDescrSecretChat)); - sb.append(". "); - } - if (user != null) { - if (UserObject.isReplyUser(user)) { - sb.append(LocaleController.getString("RepliesTitle", R.string.RepliesTitle)); - } else { - if (user.bot) { - sb.append(LocaleController.getString("Bot", R.string.Bot)); - sb.append(". "); - } - if (user.self) { - sb.append(LocaleController.getString("SavedMessages", R.string.SavedMessages)); - } else { - sb.append(ContactsController.formatName(user.first_name, user.last_name)); - } - } - sb.append(". "); - } else if (chat != null) { - if (chat.broadcast) { - sb.append(LocaleController.getString("AccDescrChannel", R.string.AccDescrChannel)); - } else { - sb.append(LocaleController.getString("AccDescrGroup", R.string.AccDescrGroup)); - } - sb.append(". "); - sb.append(chat.title); - sb.append(". "); - } - } - if (unreadCount > 0) { - sb.append(LocaleController.formatPluralString("NewMessages", unreadCount)); - sb.append(". "); - } - if (message == null || currentDialogFolderId != 0) { - info.setContentDescription(sb.toString()); - return; - } - int lastDate = lastMessageDate; - if (lastMessageDate == 0) { - lastDate = message.messageOwner.date; - } - String date = LocaleController.formatDateAudio(lastDate, true); - if (message.isOut()) { - sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, date)); - } else { - sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, date)); + if (!isFolderCell() && parentFragment != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(R.id.acc_action_chat_preview, LocaleController.getString("AccActionChatPreview", R.string.AccActionChatPreview))); } + } + if (checkBox != null && checkBox.isChecked()) { + info.setClassName("android.widget.CheckBox"); + info.setCheckable(true); + info.setChecked(true); + } + } + + @Override + public void onPopulateAccessibilityEvent(AccessibilityEvent event) { + super.onPopulateAccessibilityEvent(event); + StringBuilder sb = new StringBuilder(); + if (currentDialogFolderId == 1) { + sb.append(LocaleController.getString("ArchivedChats", R.string.ArchivedChats)); sb.append(". "); - if (chat != null && !message.isOut() && message.isFromUser() && message.messageOwner.action == null) { - TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(message.getSenderId()); - if (fromUser != null) { - sb.append(ContactsController.formatName(fromUser.first_name, fromUser.last_name)); - sb.append(". "); - } + } else { + if (encryptedChat != null) { + sb.append(LocaleController.getString("AccDescrSecretChat", R.string.AccDescrSecretChat)); + sb.append(". "); } - if (encryptedChat == null) { - sb.append(message.messageText); - if (!message.isMediaEmpty()) { - if (!TextUtils.isEmpty(message.caption)) { + if (user != null) { + if (UserObject.isReplyUser(user)) { + sb.append(LocaleController.getString("RepliesTitle", R.string.RepliesTitle)); + } else { + if (user.bot) { + sb.append(LocaleController.getString("Bot", R.string.Bot)); sb.append(". "); - sb.append(message.caption); + } + if (user.self) { + sb.append(LocaleController.getString("SavedMessages", R.string.SavedMessages)); + } else { + sb.append(ContactsController.formatName(user.first_name, user.last_name)); } } + sb.append(". "); + } else if (chat != null) { + if (chat.broadcast) { + sb.append(LocaleController.getString("AccDescrChannel", R.string.AccDescrChannel)); + } else { + sb.append(LocaleController.getString("AccDescrGroup", R.string.AccDescrGroup)); + } + sb.append(". "); + sb.append(chat.title); + sb.append(". "); + } + } + if (drawVerified) { + sb.append(LocaleController.getString("AccDescrVerified", R.string.AccDescrVerified)); + sb.append(". "); + } + if (unreadCount > 0) { + sb.append(LocaleController.formatPluralString("NewMessages", unreadCount)); + sb.append(". "); + } + if (mentionCount > 0) { + sb.append(LocaleController.formatPluralString("AccDescrMentionCount", mentionCount)); + sb.append(". "); + } + if (reactionMentionCount > 0) { + sb.append(LocaleController.getString("AccDescrMentionReaction", R.string.AccDescrMentionReaction)); + sb.append(". "); + } + if (message == null || currentDialogFolderId != 0) { + event.setContentDescription(sb.toString()); + return; + } + int lastDate = lastMessageDate; + if (lastMessageDate == 0) { + lastDate = message.messageOwner.date; + } + String date = LocaleController.formatDateAudio(lastDate, true); + if (message.isOut()) { + sb.append(LocaleController.formatString("AccDescrSentDate", R.string.AccDescrSentDate, date)); + } else { + sb.append(LocaleController.formatString("AccDescrReceivedDate", R.string.AccDescrReceivedDate, date)); + } + sb.append(". "); + if (chat != null && !message.isOut() && message.isFromUser() && message.messageOwner.action == null) { + TLRPC.User fromUser = MessagesController.getInstance(currentAccount).getUser(message.messageOwner.from_id.user_id); + if (fromUser != null) { + sb.append(ContactsController.formatName(fromUser.first_name, fromUser.last_name)); + sb.append(". "); + } + } + if (encryptedChat == null) { + StringBuilder messageString = new StringBuilder(); + messageString.append(message.messageText); + if (!message.isMediaEmpty()) { + if (!TextUtils.isEmpty(message.caption)) { + messageString.append(". "); + messageString.append(message.caption); + } + } + int len = messageLayout == null ? -1 : messageLayout.getText().length(); + if (len > 0) { + int index = messageString.length(), b; + if ((b = messageString.indexOf("\n", len)) < index && b >= 0) + index = b; + if ((b = messageString.indexOf("\t", len)) < index && b >= 0) + index = b; + if ((b = messageString.indexOf(" ", len)) < index && b >= 0) + index = b; + sb.append(messageString.substring(0, index)); + } else { + sb.append(messageString); } info.setContentDescription(sb.toString()); } @@ -3468,6 +3485,10 @@ public class DialogCell extends BaseCell { return currentDialogFolderId; } + public boolean isDialogFolder() { + return currentDialogFolderId > 0; + } + public MessageObject getMessage() { return message; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java index f150f2401..aa6d81088 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogMeUrlCell.java @@ -16,7 +16,6 @@ import android.text.TextPaint; import android.text.TextUtils; import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; @@ -42,9 +41,6 @@ public class DialogMeUrlCell extends BaseCell { private int nameLeft; private StaticLayout nameLayout; private boolean drawNameLock; - private boolean drawNameGroup; - private boolean drawNameBroadcast; - private boolean drawNameBot; private int nameMuteLeft; private int nameLockLeft; private int nameLockTop; @@ -103,28 +99,18 @@ public class DialogMeUrlCell extends BaseCell { TextPaint currentNamePaint = Theme.dialogs_namePaint[0]; TextPaint currentMessagePaint = Theme.dialogs_messagePaint[0]; - drawNameGroup = false; - drawNameBroadcast = false; drawNameLock = false; - drawNameBot = false; drawVerified = false; if (recentMeUrl instanceof TLRPC.TL_recentMeUrlChat) { TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(recentMeUrl.chat_id); - if (chat.id < 0 || ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(16.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - } drawVerified = chat.verifiedExtended(); if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(14); } nameString = chat.title; @@ -139,13 +125,12 @@ public class DialogMeUrlCell extends BaseCell { } if (user != null) { if (user.bot) { - drawNameBot = true; nameLockTop = AndroidUtilities.dp(16.5f); if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_botDrawable.getIntrinsicWidth(); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - Theme.dialogs_botDrawable.getIntrinsicWidth(); + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(14); } } @@ -172,33 +157,19 @@ public class DialogMeUrlCell extends BaseCell { if (recentMeUrl.chat_invite.chat != null) { avatarDrawable.setInfo(recentMeUrl.chat_invite.chat); nameString = recentMeUrl.chat_invite.chat.title; - if (recentMeUrl.chat_invite.chat.id < 0 || ChatObject.isChannel(recentMeUrl.chat_invite.chat) && !recentMeUrl.chat_invite.chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(16.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - } drawVerified = recentMeUrl.chat_invite.chat.verifiedExtended(); avatarImage.setForUserOrChat(recentMeUrl.chat_invite.chat, avatarDrawable, recentMeUrl); } else { nameString = recentMeUrl.chat_invite.title; avatarDrawable.setInfo(5, recentMeUrl.chat_invite.title, null); - if (recentMeUrl.chat_invite.broadcast || recentMeUrl.chat_invite.channel) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(16.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(17.5f); - } TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(recentMeUrl.chat_invite.photo.sizes, 50); avatarImage.setImage(ImageLocation.getForPhoto(size, recentMeUrl.chat_invite.photo), "50_50", avatarDrawable, null, recentMeUrl, 0); } if (!LocaleController.isRTL) { nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4); } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); + nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline); nameLeft = AndroidUtilities.dp(14); } } else if (recentMeUrl instanceof TLRPC.TL_recentMeUrlUnknown) { @@ -227,12 +198,6 @@ public class DialogMeUrlCell extends BaseCell { } if (drawNameLock) { nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); - } else if (drawNameGroup) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_groupDrawable.getIntrinsicWidth(); - } else if (drawNameBroadcast) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_broadcastDrawable.getIntrinsicWidth(); - } else if (drawNameBot) { - nameWidth -= AndroidUtilities.dp(4) + Theme.dialogs_botDrawable.getIntrinsicWidth(); } if (drawVerified) { @@ -335,15 +300,6 @@ public class DialogMeUrlCell extends BaseCell { if (drawNameLock) { setDrawableBounds(Theme.dialogs_lockDrawable, nameLockLeft, nameLockTop); Theme.dialogs_lockDrawable.draw(canvas); - } else if (drawNameGroup) { - setDrawableBounds(Theme.dialogs_groupDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_groupDrawable.draw(canvas); - } else if (drawNameBroadcast) { - setDrawableBounds(Theme.dialogs_broadcastDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_broadcastDrawable.draw(canvas); - } else if (drawNameBot) { - setDrawableBounds(Theme.dialogs_botDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_botDrawable.draw(canvas); } if (nameLayout != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java index efd3a9d76..e796560b4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DividerCell.java @@ -23,9 +23,15 @@ public class DividerCell extends View { private boolean forceDarkTheme; private Paint paint = new Paint(); + private Theme.ResourcesProvider resourcesProvider; public DividerCell(Context context) { + this(context, null); + } + + public DividerCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); } @@ -37,9 +43,9 @@ public class DividerCell extends View { @Override protected void onDraw(Canvas canvas) { if (forceDarkTheme) { - paint.setColor(ColorUtils.blendARGB(Color.BLACK, Theme.getColor(Theme.key_voipgroup_dialogBackground), 0.2f)); + paint.setColor(ColorUtils.blendARGB(Color.BLACK, Theme.getColor(Theme.key_voipgroup_dialogBackground, resourcesProvider), 0.2f)); } else { - paint.setColor(Theme.getColor(Theme.key_divider)); + paint.setColor(Theme.getColor(Theme.key_divider, resourcesProvider)); } canvas.drawLine(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getPaddingTop(), paint); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerAddCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerAddCell.java index f8e60f176..151dbd0ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerAddCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerAddCell.java @@ -39,7 +39,7 @@ public class DrawerAddCell extends FrameLayout { textView.setSingleLine(true); textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); textView.setCompoundDrawablePadding(AndroidUtilities.dp(29)); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 23, 0, 16, 0)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 19, 0, 16, 0)); } @Override @@ -52,7 +52,7 @@ public class DrawerAddCell extends FrameLayout { super.onAttachedToWindow(); textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText)); textView.setText(LocaleController.getString("AddAccount", R.string.AddAccount)); - Drawable drawable = getResources().getDrawable(R.drawable.account_add); + Drawable drawable = getResources().getDrawable(R.drawable.msg_add); if (drawable != null) { drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_menuItemIcon), PorterDuff.Mode.SRC_IN)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java index c31ca7991..a397fe4d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerProfileCell.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.RippleDrawable; import android.os.Build; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -35,12 +36,16 @@ import android.widget.Toast; import androidx.palette.graphics.Palette; +import androidx.core.content.ContextCompat; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; @@ -52,12 +57,16 @@ import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.ActionBar.ActionBarLayout; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; +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.CubicBezierInterpolator; import org.telegram.ui.Components.EmojiTextView; import org.telegram.ui.Components.FireworksEffect; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; +import org.telegram.ui.Components.Premium.StarParticlesView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.SnowflakesEffect; @@ -65,7 +74,7 @@ import org.telegram.ui.ThemeActivity; import tw.nekomimi.nekogram.NekoConfig; -public class DrawerProfileCell extends FrameLayout { +public class DrawerProfileCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private BackupImageView avatarImageView; private TextView nameTextView; @@ -87,6 +96,11 @@ public class DrawerProfileCell extends FrameLayout { private boolean accountsShown; private int darkThemeBackgroundColor; public static boolean switchingTheme; + public boolean drawPremium; + public float drawPremiumProgress; + + StarParticlesView.Drawable starParticlesDrawable; + PremiumGradient.GradientTools gradientTools; private Bitmap lastBitmap; private TLRPC.User user; @@ -177,7 +191,7 @@ public class DrawerProfileCell extends FrameLayout { arrowView = new ImageView(context); arrowView.setScaleType(ImageView.ScaleType.CENTER); - arrowView.setImageResource(R.drawable.menu_expand); + arrowView.setImageResource(R.drawable.msg_expand); addView(arrowView, LayoutHelper.createFrame(59, 59, Gravity.RIGHT | Gravity.BOTTOM)); setArrowState(false); @@ -193,13 +207,14 @@ public class DrawerProfileCell extends FrameLayout { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); - if (sunDrawable.getCustomEndFrame() != 0) { - info.setText(LocaleController.getString("AccDescrSwitchToNightTheme", R.string.AccDescrSwitchToNightTheme)); - } else { + if (Theme.isCurrentThemeDark()) { info.setText(LocaleController.getString("AccDescrSwitchToDayTheme", R.string.AccDescrSwitchToDayTheme)); + } else { + info.setText(LocaleController.getString("AccDescrSwitchToNightTheme", R.string.AccDescrSwitchToNightTheme)); } } }; + darkThemeView.setFocusable(true); darkThemeView.setBackground(Theme.createCircleSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0, 0)); sunDrawable.beginApplyLayerColors(); int color = Theme.getColor(Theme.key_chats_menuName); @@ -283,6 +298,13 @@ public class DrawerProfileCell extends FrameLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); updateColors(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); } @Override @@ -305,6 +327,22 @@ public class DrawerProfileCell extends FrameLayout { return NekoConfig.largeAvatarInDrawer.Int() > 0 && ImageLocation.isUserHasPhoto(user); } + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + if (drawPremium) { + if (starParticlesDrawable == null) { + starParticlesDrawable = new StarParticlesView.Drawable(15); + starParticlesDrawable.init(); + starParticlesDrawable.speedScale = 0.8f; + starParticlesDrawable.minLifeTime = 3000; + } + starParticlesDrawable.rect.set(avatarImageView.getLeft(), avatarImageView.getTop(), avatarImageView.getRight(), avatarImageView.getBottom()); + starParticlesDrawable.rect.inset(-AndroidUtilities.dp(20), -AndroidUtilities.dp(20)); + starParticlesDrawable.resetPositions(); + } + } + @Override protected void onDraw(Canvas canvas) { Drawable backgroundDrawable = Theme.getCachedWallpaper(); @@ -367,6 +405,43 @@ public class DrawerProfileCell extends FrameLayout { shadowView.setVisibility(visibility); } super.onDraw(canvas); + darkBackColor = Theme.getColor(Theme.key_listSelector); + } + + +// if (darkBackColor != 0) { +// if (darkBackColor != darkThemeBackgroundColor) { +// backPaint.setColor(darkThemeBackgroundColor = darkBackColor); +// if (Build.VERSION.SDK_INT >= 21) { +// Theme.setSelectorDrawableColor(darkThemeView.getBackground(), darkThemeBackgroundColor = darkBackColor, true); +// } +// } +// if (useImageBackground && backgroundDrawable instanceof BitmapDrawable) { +// canvas.drawCircle(darkThemeView.getX() + darkThemeView.getMeasuredWidth() / 2, darkThemeView.getY() + darkThemeView.getMeasuredHeight() / 2, AndroidUtilities.dp(17), backPaint); +// } +// } + if (drawPremium && drawPremiumProgress != 1f) { + drawPremiumProgress += 16 / 220f; + } else if (!drawPremium && drawPremiumProgress != 0) { + drawPremiumProgress -= 16 / 220f; + } + drawPremiumProgress = Utilities.clamp(drawPremiumProgress, 1f, 0); + if (drawPremiumProgress != 0) { + if (gradientTools == null) { + gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradientBottomSheet1, Theme.key_premiumGradientBottomSheet2, Theme.key_premiumGradientBottomSheet3, null); + gradientTools.x1 = 0; + gradientTools.y1 = 1.1f; + gradientTools.x2 = 1.5f; + gradientTools.y2 = -0.2f; + gradientTools.exactly = true; + } + gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), 0, 0); + gradientTools.paint.setAlpha((int) (drawPremiumProgress * 255)); + canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), gradientTools.paint); + if (starParticlesDrawable != null) { + starParticlesDrawable.onDraw(canvas, drawPremiumProgress); + } + invalidate(); } if (snowflakesEffect != null) { @@ -408,7 +483,20 @@ public class DrawerProfileCell extends FrameLayout { this.user = user; accountsShown = accounts; setArrowState(false); - nameTextView.setText(UserObject.getUserName(user)); + CharSequence text = UserObject.getUserName(user); + try { + text = Emoji.replaceEmoji(text, nameTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(22), false); + } catch (Exception ignore) {} + + drawPremium = user.premium; + // NekoX: test during merge, official value: false + if (text != null && drawPremium) { + SpannableStringBuilder spannableStringBuilder = SpannableStringBuilder.valueOf(text); + spannableStringBuilder.append(" d"); + spannableStringBuilder.setSpan(new ColoredImageSpan(ContextCompat.getDrawable(getContext(), R.drawable.msg_premium_liststar)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); + text = spannableStringBuilder; + } + nameTextView.setText(text); if (!NekoConfig.hidePhone.Bool()) { phoneTextView.setText(PhoneFormat.getInstance().format("+" + user.phone)); } else if (!TextUtils.isEmpty(user.username)) { @@ -440,6 +528,7 @@ public class DrawerProfileCell extends FrameLayout { } applyBackground(true); + } public String applyBackground(boolean force) { @@ -475,7 +564,9 @@ public class DrawerProfileCell extends FrameLayout { } @Override - public void invalidate(int l, int t, int r, int b) { - if (allowInvalidate) super.invalidate(l, t, r, b); + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + nameTextView.invalidate(); + } } -} \ No newline at end of file +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java index 8c484c778..a35d9df83 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DrawerUserCell.java @@ -11,32 +11,34 @@ package org.telegram.ui.Cells; import android.content.Context; import android.graphics.Canvas; import android.graphics.RectF; -import android.text.TextUtils; -import android.util.TypedValue; import android.view.Gravity; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; -import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ContactsController; import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; +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.EmojiTextView; import org.telegram.ui.Components.GroupCreateCheckBox; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; -public class DrawerUserCell extends FrameLayout { +public class DrawerUserCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { - private TextView textView; + private SimpleTextView textView; private BackupImageView imageView; private AvatarDrawable avatarDrawable; private GroupCreateCheckBox checkBox; @@ -54,16 +56,13 @@ public class DrawerUserCell extends FrameLayout { imageView.setRoundRadius(AndroidUtilities.dp(18)); addView(imageView, LayoutHelper.createFrame(36, 36, Gravity.LEFT | Gravity.TOP, 14, 6, 0, 0)); - textView = new EmojiTextView(context); + textView = new SimpleTextView(context); textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTextSize(15); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - textView.setLines(1); textView.setMaxLines(1); - textView.setSingleLine(true); textView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - textView.setEllipsize(TextUtils.TruncateAt.END); - addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 72, 0, 60, 0)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 72, 0, 60, 0)); checkBox = new GroupCreateCheckBox(context); checkBox.setChecked(true, false); @@ -84,6 +83,30 @@ public class DrawerUserCell extends FrameLayout { protected void onAttachedToWindow() { super.onAttachedToWindow(); textView.setTextColor(Theme.getColor(Theme.key_chats_menuItemText)); + for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ + NotificationCenter.getInstance(i).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (int i = 0; i < UserConfig.MAX_ACCOUNT_COUNT; i++){ + NotificationCenter.getInstance(i).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.currentUserPremiumStatusChanged) { + if (account == accountNumber) { + setAccount(accountNumber); + } + } else if (id == NotificationCenter.emojiLoaded) { + textView.invalidate(); + } } public void setAccount(int account) { @@ -93,7 +116,17 @@ public class DrawerUserCell extends FrameLayout { return; } avatarDrawable.setInfo(user); - textView.setText(UserObject.getUserName(user)); + CharSequence text = ContactsController.formatName(user.first_name, user.last_name); + try { + text = Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false); + } catch (Exception ignore) {} + textView.setText(text); + if (MessagesController.getInstance(account).isPremiumUser(user)) { + textView.setDrawablePadding(AndroidUtilities.dp(6)); + textView.setRightDrawable(PremiumGradient.getInstance().premiumStarDrawableMini); + } else { + textView.setRightDrawable(null); + } imageView.getImageReceiver().setCurrentAccount(account); imageView.setForUserOrChat(user, avatarDrawable); checkBox.setVisibility(account == UserConfig.selectedAccount ? VISIBLE : INVISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell2.java index b310a1b3b..0c35a0b5b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FeaturedStickerSetCell2.java @@ -108,6 +108,10 @@ public class FeaturedStickerSetCell2 extends FrameLayout { updateColors(); } + public TextView getTextView() { + return textView; + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(64) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/FixedHeightEmptyCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FixedHeightEmptyCell.java new file mode 100644 index 000000000..120c76cf5 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/FixedHeightEmptyCell.java @@ -0,0 +1,21 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.view.View; + +import org.telegram.messenger.AndroidUtilities; + +public class FixedHeightEmptyCell extends View { + + int heightInDp; + + public FixedHeightEmptyCell(Context context, int heightInDp) { + super(context); + this.heightInDp = heightInDp; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(heightInDp), MeasureSpec.EXACTLY)); + } +} 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 0abe3ab1c..198e87f00 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GraySectionCell.java @@ -21,6 +21,8 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Components.AnimatedTextView; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -29,7 +31,7 @@ import java.util.List; public class GraySectionCell extends FrameLayout { private TextView textView; - private TextView rightTextView; + private AnimatedTextView rightTextView; private final Theme.ResourcesProvider resourcesProvider; public GraySectionCell(Context context) { @@ -49,15 +51,17 @@ public class GraySectionCell extends FrameLayout { 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)); - rightTextView = new TextView(getContext()) { + rightTextView = new AnimatedTextView(getContext(), true, true, true) { @Override public CharSequence getAccessibilityClassName() { return Button.class.getName(); } }; - rightTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + rightTextView.setPadding(AndroidUtilities.dp(2), 0, AndroidUtilities.dp(2), 0); + rightTextView.setAnimationProperties(1f, 0, 400, CubicBezierInterpolator.EASE_OUT_QUINT); + rightTextView.setTextSize(AndroidUtilities.dp(14)); rightTextView.setTextColor(getThemedColor(Theme.key_graySectionText)); - rightTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); + rightTextView.setGravity(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); addView(rightTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 16, 0, 16, 0)); ViewCompat.setAccessibilityHeading(this, true); @@ -74,18 +78,32 @@ public class GraySectionCell extends FrameLayout { rightTextView.setTextColor(color); } + public CharSequence getText() { + return textView.getText(); + } + public void setText(String text) { textView.setText(text); rightTextView.setVisibility(GONE); + rightTextView.setOnClickListener(null); } public void setText(String left, String right, OnClickListener onClickListener) { textView.setText(left); - rightTextView.setText(right); + rightTextView.setText(right, false); rightTextView.setOnClickListener(onClickListener); rightTextView.setVisibility(VISIBLE); } + public void setRightText(String right) { + setRightText(right, true); + } + + public void setRightText(String right, boolean moveDown) { + rightTextView.setText(right, true, moveDown); + rightTextView.setVisibility(VISIBLE); + } + public static void createThemeDescriptions(List descriptions, RecyclerListView listView) { descriptions.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText)); descriptions.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"rightTextView"}, null, null, null, Theme.key_graySectionText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java index 355437b76..e1d42eab4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/GroupCreateUserCell.java @@ -16,11 +16,11 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.text.TextUtils; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; -import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; @@ -103,7 +103,7 @@ public class GroupCreateUserCell extends FrameLayout { checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); checkBox.setDrawBackgroundAsArc(3); - addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 40, 33, LocaleController.isRTL ? 39 : 0, 0)); + addView(checkBox, LayoutHelper.createFrame(24, 24, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 40 + padding, 33, LocaleController.isRTL ? 39 + padding : 0, 0)); } else if (checkBoxType == 2) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Paint.Style.STROKE); @@ -254,11 +254,11 @@ public class GroupCreateUserCell extends FrameLayout { } avatarImageView.getLayoutParams().width = avatarImageView.getLayoutParams().height = AndroidUtilities.dp(46); if (checkBox != null) { - ((LayoutParams) checkBox.getLayoutParams()).topMargin = AndroidUtilities.dp(33); + ((LayoutParams) checkBox.getLayoutParams()).topMargin = AndroidUtilities.dp(33) + padding; if (LocaleController.isRTL) { - ((LayoutParams) checkBox.getLayoutParams()).rightMargin = AndroidUtilities.dp(39); + ((LayoutParams) checkBox.getLayoutParams()).rightMargin = AndroidUtilities.dp(39) + padding; } else { - ((LayoutParams) checkBox.getLayoutParams()).leftMargin = AndroidUtilities.dp(40); + ((LayoutParams) checkBox.getLayoutParams()).leftMargin = AndroidUtilities.dp(40) + padding; } } @@ -426,4 +426,13 @@ public class GroupCreateUserCell extends FrameLayout { public boolean hasOverlappingRendering() { return false; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (isChecked()) { + info.setCheckable(true); + info.setChecked(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java index 66c4fbbd3..a2fe1d14b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HeaderCell.java @@ -17,6 +17,7 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.LinearLayout; import android.widget.TextView; @@ -49,6 +50,10 @@ public class HeaderCell extends LinearLayout { this(context, Theme.key_windowBackgroundWhiteBlueHeader, padding, 15, false, false, null); } + public HeaderCell(Context context, int padding, Theme.ResourcesProvider resourcesProvider) { + this(context, Theme.key_windowBackgroundWhiteBlueHeader, padding, 15, false, resourcesProvider); + } + public HeaderCell(Context context, String textColorKey, int padding, int topMargin, boolean text2) { this(context, textColorKey, padding, topMargin, text2, false, null); } @@ -59,6 +64,10 @@ public class HeaderCell extends LinearLayout { public HeaderCell(Context context, String textColorKey, int padding, int topMargin, boolean text2, boolean bigTitle, Theme.ResourcesProvider resourcesProvider) { + this(context, textColorKey, padding, topMargin, 0, text2, resourcesProvider); + } + + public HeaderCell(Context context, String textColorKey, int padding, int topMargin, int bottomMargin, boolean text2, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; @@ -74,13 +83,13 @@ public class HeaderCell extends LinearLayout { textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); textView.setTextColor(getThemedColor(textColorKey)); textView.setTag(textColorKey); - addView(textView, LayoutHelper.createLinear(-1, -2)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, topMargin, padding, text2 ? 0 : bottomMargin)); textView2 = new TextView(getContext()); textView2.setTextSize(13); textView2.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); textView2.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); - addView(textView2, LayoutHelper.createLinear(-2, -2, 0, 4, 0, 0)); + addView(textView2, LayoutHelper.createLinear(-2, -2, 0, 4, 0, bottomMargin)); if (!text2) textView2.setVisibility(View.GONE); @@ -99,7 +108,7 @@ public class HeaderCell extends LinearLayout { public void setEnabled(boolean value, ArrayList animators) { if (animators != null) { - animators.add(ObjectAnimator.ofFloat(textView, "alpha", value ? 1.0f : 0.5f)); + animators.add(ObjectAnimator.ofFloat(textView, View.ALPHA, value ? 1.0f : 0.5f)); } else { textView.setAlpha(value ? 1.0f : 0.5f); } @@ -140,12 +149,15 @@ public class HeaderCell extends LinearLayout { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + info.setHeading(true); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { AccessibilityNodeInfo.CollectionItemInfo collection = info.getCollectionItemInfo(); if (collection != null) { info.setCollectionItemInfo(AccessibilityNodeInfo.CollectionItemInfo.obtain(collection.getRowIndex(), collection.getRowSpan(), collection.getColumnIndex(), collection.getColumnSpan(), true)); } } + info.setEnabled(true); } private int getThemedColor(String key) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java index 6d4b10164..44772c36a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/HintDialogCell.java @@ -85,7 +85,7 @@ public class HintDialogCell extends FrameLayout { invalidate(); }); addView(checkBox, LayoutHelper.createFrame(24, 24, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 19, 42, 0, 0)); - checkBox.setChecked(true, false); + checkBox.setChecked(false, false); setWillNotDraw(false); } } @@ -130,6 +130,12 @@ public class HintDialogCell extends FrameLayout { } } + public void setColors(String textColorKey, String backgroundColorKey) { + nameTextView.setTextColor(Theme.getColor(textColorKey)); + this.backgroundColorKey = backgroundColorKey; + checkBox.setColor(Theme.key_dialogRoundCheckBox, backgroundColorKey, Theme.key_dialogRoundCheckBoxCheck); + } + public void setDialog(long uid, boolean counter, CharSequence name) { if (dialogId != uid) { wasDraw = false; @@ -165,6 +171,8 @@ public class HintDialogCell extends FrameLayout { } } + private String backgroundColorKey = Theme.key_windowBackgroundWhite; + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result = super.drawChild(canvas, child, drawingTime); @@ -191,7 +199,7 @@ public class HintDialogCell extends FrameLayout { int left = AndroidUtilities.dp(59); canvas.save(); canvas.scale(showOnlineProgress, showOnlineProgress, left, top); - Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(backgroundColorKey)); canvas.drawCircle(left, top, AndroidUtilities.dp(7), Theme.dialogs_onlineCirclePaint); Theme.dialogs_onlineCirclePaint.setColor(Theme.getColor(Theme.key_chats_onlineCircle)); canvas.drawCircle(left, top, AndroidUtilities.dp(5), Theme.dialogs_onlineCirclePaint); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationDirectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationDirectionCell.java index 9a7d4ec63..f60b6e743 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationDirectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/LocationDirectionCell.java @@ -23,7 +23,7 @@ public class LocationDirectionCell extends FrameLayout { this.resourcesProvider = resourcesProvider; frameLayout = new FrameLayout(context); - frameLayout.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), getThemedColor(Theme.key_featuredStickers_addButton), getThemedColor(Theme.key_featuredStickers_addButtonPressed))); + frameLayout.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 4)); addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 16, 10, 16, 0)); buttonTextView = new SimpleTextView(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java index c1043a24b..5c31853d6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ManageChatUserCell.java @@ -40,6 +40,7 @@ public class ManageChatUserCell extends FrameLayout { private SimpleTextView statusTextView; private ImageView optionsButton; private ImageView customImageView; + private Theme.ResourcesProvider resourcesProvider; private AvatarDrawable avatarDrawable; private Object currentObject; @@ -70,10 +71,15 @@ public class ManageChatUserCell extends FrameLayout { } public ManageChatUserCell(Context context, int avatarPadding, int nPadding, boolean needOption) { - super(context); + this(context, avatarPadding, nPadding, needOption, null); + } - statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText); - statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText); + public ManageChatUserCell(Context context, int avatarPadding, int nPadding, boolean needOption, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider); + statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider); namePadding = nPadding; @@ -84,7 +90,7 @@ public class ManageChatUserCell extends FrameLayout { addView(avatarImageView, LayoutHelper.createFrame(46, 46, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 7 + avatarPadding, 8, LocaleController.isRTL ? 7 + avatarPadding : 0, 0)); nameTextView = new SimpleTextView(context); - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); nameTextView.setTextSize(17); nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); @@ -98,9 +104,9 @@ public class ManageChatUserCell extends FrameLayout { if (needOption) { optionsButton = new ImageView(context); optionsButton.setFocusable(false); - optionsButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + optionsButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector, resourcesProvider))); optionsButton.setImageResource(R.drawable.ic_ab_other); - optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.SRC_IN)); + optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu, resourcesProvider), PorterDuff.Mode.SRC_IN)); optionsButton.setScaleType(ImageView.ScaleType.CENTER); addView(optionsButton, LayoutHelper.createFrame(60, 64, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP)); optionsButton.setOnClickListener(v -> delegate.onOptionsButtonCheck(ManageChatUserCell.this, true)); @@ -112,7 +118,7 @@ public class ManageChatUserCell extends FrameLayout { customImageView = new ImageView(getContext()); customImageView.setImageResource(resId); customImageView.setScaleType(ImageView.ScaleType.CENTER); - customImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_mutedIconUnscrolled), PorterDuff.Mode.MULTIPLY)); + customImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_mutedIconUnscrolled, resourcesProvider), PorterDuff.Mode.MULTIPLY)); addView(customImageView, LayoutHelper.createFrame(52, 64, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP)); } @@ -348,7 +354,7 @@ public class ManageChatUserCell extends FrameLayout { protected void onDraw(Canvas canvas) { if (needDivider) { if (dividerColor != null) { - Theme.dividerExtraPaint.setColor(Theme.getColor(dividerColor)); + Theme.dividerExtraPaint.setColor(Theme.getColor(dividerColor, resourcesProvider)); } canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(68), getMeasuredHeight() - 1, getMeasuredWidth() - (LocaleController.isRTL ? AndroidUtilities.dp(68) : 0), getMeasuredHeight() - 1, dividerColor != null ? Theme.dividerExtraPaint : Theme.dividerPaint); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MaxFileSizeCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MaxFileSizeCell.java index 020a31935..d5970db50 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MaxFileSizeCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MaxFileSizeCell.java @@ -95,7 +95,7 @@ public class MaxFileSizeCell extends FrameLayout { progress -= 0.25f; size += 90 * 1024 * 1024; - size += (FileLoader.MAX_FILE_SIZE - size) * (progress / 0.25f); + size += (FileLoader.DEFAULT_MAX_FILE_SIZE - size) * (progress / 0.25f); } } } @@ -196,7 +196,7 @@ public class MaxFileSizeCell extends FrameLayout { progress += 0.25f; size -= 90 * 1024 * 1024; - progress += Math.max(0, size / (float) (FileLoader.MAX_FILE_SIZE - 100 * 1024 * 1024)) * 0.25f; + progress += Math.max(0, size / (float) (FileLoader.DEFAULT_MAX_FILE_SIZE - 100 * 1024 * 1024)) * 0.25f; } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java index 03ce557bd..31faf8f37 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MemberRequestCell.java @@ -53,7 +53,7 @@ public class MemberRequestCell extends FrameLayout { int btnPadding = AndroidUtilities.dp(17); TextView addButton = new TextView(getContext()); - addButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + addButton.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addButton.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); addButton.setMaxLines(1); addButton.setPadding(btnPadding, 0, btnPadding, 0); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java index dafc71e6b..e9320a894 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/MentionCell.java @@ -9,6 +9,7 @@ package org.telegram.ui.Cells; import android.content.Context; +import android.graphics.Canvas; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -33,8 +34,9 @@ public class MentionCell extends LinearLayout { private TextView nameTextView; private TextView usernameTextView; private AvatarDrawable avatarDrawable; + private Theme.ResourcesProvider resourcesProvider; - public MentionCell(Context context) { + public MentionCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); setOrientation(HORIZONTAL); @@ -47,7 +49,7 @@ public class MentionCell extends LinearLayout { addView(imageView, LayoutHelper.createLinear(28, 28, 12, 4, 0, 0)); nameTextView = new EmojiTextView(context); - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); nameTextView.setSingleLine(true); nameTextView.setGravity(Gravity.LEFT); @@ -55,7 +57,7 @@ public class MentionCell extends LinearLayout { addView(nameTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 12, 0, 0, 0)); usernameTextView = new EmojiTextView(context); - usernameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); + usernameTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); usernameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); usernameTextView.setSingleLine(true); usernameTextView.setGravity(Gravity.LEFT); @@ -91,6 +93,23 @@ public class MentionCell extends LinearLayout { usernameTextView.setVisibility(VISIBLE); } + private boolean needsDivider = false; + public void setDivider(boolean enabled) { + if (enabled != needsDivider) { + needsDivider = enabled; + setWillNotDraw(!needsDivider); + invalidate(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (needsDivider) { + canvas.drawLine(AndroidUtilities.dp(52), getHeight() - 1, getWidth() - AndroidUtilities.dp(8), getHeight() - 1, Theme.dividerPaint); + } + } + public void setChat(TLRPC.Chat chat) { if (chat == null) { nameTextView.setText(""); @@ -158,8 +177,13 @@ public class MentionCell extends LinearLayout { nameTextView.setTextColor(0xffffffff); usernameTextView.setTextColor(0xffbbbbbb); } else { - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - usernameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); + nameTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + usernameTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); } } + + private int getThemedColor(String key) { + Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; + return color != null ? color : Theme.getColor(key); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java index 55471056f..874b4876f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/NotificationsCheckCell.java @@ -15,6 +15,7 @@ import android.graphics.PorterDuffColorFilter; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -38,13 +39,24 @@ public class NotificationsCheckCell extends FrameLayout { private boolean isMultiline; private int currentHeight; private boolean animationsEnabled; + private Theme.ResourcesProvider resourcesProvider; public NotificationsCheckCell(Context context) { - this(context, 21, 70, false); + this(context, 21, 70, false, null); + } + + public NotificationsCheckCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, 21, 70, false, resourcesProvider); } public NotificationsCheckCell(Context context, int padding, int height, boolean reorder) { + this(context, padding, height, reorder, null); + } + + public NotificationsCheckCell(Context context, int padding, int height, boolean reorder, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; + setWillNotDraw(false); currentHeight = height; @@ -53,12 +65,12 @@ public class NotificationsCheckCell extends FrameLayout { moveImageView.setFocusable(false); moveImageView.setScaleType(ImageView.ScaleType.CENTER); moveImageView.setImageResource(R.drawable.poll_reorder); - moveImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + moveImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon, resourcesProvider), PorterDuff.Mode.SRC_IN)); addView(moveImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 6, 0, 6, 0)); } textView = new TextView(context); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setLines(1); textView.setMaxLines(1); @@ -68,7 +80,7 @@ public class NotificationsCheckCell extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (reorder ? 64 : padding), 13 + (currentHeight - 70) / 2, LocaleController.isRTL ? (reorder ? 64 : padding) : 80, 0)); valueTextView = new TextView(context); - valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); valueTextView.setLines(1); @@ -78,10 +90,10 @@ public class NotificationsCheckCell extends FrameLayout { valueTextView.setEllipsize(TextUtils.TruncateAt.END); addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : (reorder ? 64 : padding), 38 + (currentHeight - 70) / 2, LocaleController.isRTL ? (reorder ? 64 : padding) : 80, 0)); - checkBox = new Switch(context); + checkBox = new Switch(context, resourcesProvider); checkBox.setColors(Theme.key_switchTrack, Theme.key_switchTrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite); addView(checkBox, LayoutHelper.createFrame(37, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0)); - checkBox.setFocusable(true); + checkBox.setFocusable(false); } @Override @@ -156,4 +168,19 @@ public class NotificationsCheckCell extends FrameLayout { public void setAnimationsEnabled(boolean animationsEnabled) { this.animationsEnabled = animationsEnabled; } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Switch"); + StringBuilder sb = new StringBuilder(); + sb.append(textView.getText()); + if (valueTextView != null && !TextUtils.isEmpty(valueTextView.getText())) { + sb.append("\n"); + sb.append(valueTextView.getText()); + } + info.setContentDescription(sb); + info.setCheckable(true); + info.setChecked(checkBox.isChecked()); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java index 05306832d..3cdf2402e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PatternCell.java @@ -35,6 +35,8 @@ import java.io.File; public class PatternCell extends BackupImageView implements DownloadController.FileDownloadProgressListener { + private final int SIZE = 100; + private RectF rect = new RectF(); private RadialProgress2 radialProgress; private boolean wasSelected; @@ -76,7 +78,7 @@ public class PatternCell extends BackupImageView implements DownloadController.F radialProgress = new RadialProgress2(this); radialProgress.setProgressRect(AndroidUtilities.dp(30), AndroidUtilities.dp(30), AndroidUtilities.dp(70), AndroidUtilities.dp(70)); - backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); TAG = DownloadController.getInstance(currentAccount).generateObserverTag(); @@ -94,8 +96,8 @@ public class PatternCell extends BackupImageView implements DownloadController.F public void setPattern(TLRPC.TL_wallPaper wallPaper) { currentPattern = wallPaper; if (wallPaper != null) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100); - setImage(ImageLocation.getForDocument(thumb, wallPaper.document), "100_100", null, null, "jpg", 0, 1, wallPaper); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, AndroidUtilities.dp(SIZE)); + setImage(ImageLocation.getForDocument(thumb, wallPaper.document), SIZE + "_" + SIZE, null, null, "png", 0, 1, wallPaper); } else { setImageDrawable(null); } @@ -135,12 +137,12 @@ public class PatternCell extends BackupImageView implements DownloadController.F if (TextUtils.isEmpty(fileName)) { return; } - path = FileLoader.getPathToAttach(wallPaper.document, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(wallPaper.document, true); } else { MediaController.SearchImage wallPaper = (MediaController.SearchImage) image; if (wallPaper.photo != null) { TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); - path = FileLoader.getPathToAttach(photoSize, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(photoSize, true); fileName = FileLoader.getAttachFileName(photoSize); } else { path = ImageLoader.getHttpFilePath(wallPaper.imageUrl, "jpg"); @@ -245,7 +247,7 @@ public class PatternCell extends BackupImageView implements DownloadController.F @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(AndroidUtilities.dp(100), AndroidUtilities.dp(100)); + setMeasuredDimension(AndroidUtilities.dp(SIZE), AndroidUtilities.dp(SIZE)); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java index 66fb58991..1c23e9d23 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PaymentInfoCell.java @@ -37,6 +37,7 @@ public class PaymentInfoCell extends FrameLayout { super(context); imageView = new BackupImageView(context); + imageView.getImageReceiver().setRoundRadius(AndroidUtilities.dp(8)); addView(imageView, LayoutHelper.createFrame(100, 100, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), 10, 10, 10, 0)); nameTextView = new TextView(context); @@ -83,9 +84,9 @@ public class PaymentInfoCell extends FrameLayout { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), h); } - public void setInvoice(TLRPC.TL_messageMediaInvoice invoice, String botname) { - nameTextView.setText(invoice.title); - detailTextView.setText(invoice.description); + public void setInfo(String title, String description, TLRPC.WebDocument photo, String botname, Object parentObject) { + nameTextView.setText(title); + detailTextView.setText(description); detailExTextView.setText(botname); int maxPhotoWidth; @@ -99,13 +100,13 @@ public class PaymentInfoCell extends FrameLayout { float scale = width / (float) (maxPhotoWidth - AndroidUtilities.dp(2)); width /= scale; height /= scale; - if (invoice.photo != null && invoice.photo.mime_type.startsWith("image/")) { + if (photo != null && photo.mime_type.startsWith("image/")) { nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 9, LocaleController.isRTL ? 123 : 10, 0)); detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 33, LocaleController.isRTL ? 123 : 10, 0)); detailExTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 90, LocaleController.isRTL ? 123 : 10, 0)); imageView.setVisibility(VISIBLE); String filter = String.format(Locale.US, "%d_%d", width, height); - imageView.getImageReceiver().setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(invoice.photo)), filter, null, null, -1, null, invoice, 1); + imageView.getImageReceiver().setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(photo)), filter, null, null, -1, null, parentObject, 1); } else { nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 9, 17, 0)); detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 33, 17, 0)); @@ -114,34 +115,11 @@ public class PaymentInfoCell extends FrameLayout { } } + public void setInvoice(TLRPC.TL_messageMediaInvoice invoice, String botname) { + setInfo(invoice.title, invoice.description, invoice.photo, botname, invoice); + } + public void setReceipt(TLRPC.TL_payments_paymentReceipt receipt, String botname) { - nameTextView.setText(receipt.title); - detailTextView.setText(receipt.description); - detailExTextView.setText(botname); - - int maxPhotoWidth; - if (AndroidUtilities.isTablet()) { - maxPhotoWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f); - } else { - maxPhotoWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f); - } - int width = 640; - int height = 360; - float scale = width / (float) (maxPhotoWidth - AndroidUtilities.dp(2)); - width /= scale; - height /= scale; - if (receipt.photo != null && receipt.photo.mime_type.startsWith("image/")) { - nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 9, LocaleController.isRTL ? 123 : 10, 0)); - detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 33, LocaleController.isRTL ? 123 : 10, 0)); - detailExTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 10 : 123, 90, LocaleController.isRTL ? 123 : 10, 0)); - imageView.setVisibility(VISIBLE); - String filter = String.format(Locale.US, "%d_%d", width, height); - imageView.getImageReceiver().setImage(ImageLocation.getForWebFile(WebFile.createWithWebDocument(receipt.photo)), filter, null, null, -1, null, receipt, 1); - } else { - nameTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 9, 17, 0)); - detailTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 33, 17, 0)); - detailExTextView.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 17, 90, 17, 9)); - imageView.setVisibility(GONE); - } + setInfo(receipt.title, receipt.description, receipt.photo, botname, receipt); } } 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 91816123d..6a37477ee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ProfileSearchCell.java @@ -11,6 +11,7 @@ package org.telegram.ui.Cells; import android.content.Context; import android.graphics.Canvas; import android.graphics.RectF; +import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -21,29 +22,31 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.UserObject; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; -import org.telegram.messenger.UserConfig; -import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.CheckBox2; -import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.NotificationsSettingsActivity; -public class ProfileSearchCell extends BaseCell { +public class ProfileSearchCell extends BaseCell implements NotificationCenter.NotificationCenterDelegate { private CharSequence currentName; private ImageReceiver avatarImage; private AvatarDrawable avatarDrawable; private CharSequence subLabel; + private Theme.ResourcesProvider resourcesProvider; private TLRPC.User user; private TLRPC.Chat chat; @@ -64,9 +67,6 @@ public class ProfileSearchCell extends BaseCell { private int nameTop; private StaticLayout nameLayout; private boolean drawNameLock; - private boolean drawNameBroadcast; - private boolean drawNameGroup; - private boolean drawNameBot; private int nameLockLeft; private int nameLockTop; private int nameWidth; @@ -80,8 +80,10 @@ public class ProfileSearchCell extends BaseCell { private int countLeft; private int countWidth; private StaticLayout countLayout; + private boolean[] isOnline; private boolean drawCheck; + private boolean drawPremium; private int statusLeft; private StaticLayout statusLayout; @@ -91,13 +93,18 @@ public class ProfileSearchCell extends BaseCell { CheckBox2 checkBox; public ProfileSearchCell(Context context) { + this(context, null); + } + + public ProfileSearchCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; avatarImage = new ImageReceiver(this); avatarImage.setRoundRadius(AndroidUtilities.dp(23)); avatarDrawable = new AvatarDrawable(); - checkBox = new CheckBox2(context, 21); + checkBox = new CheckBox2(context, 21, resourcesProvider); checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); checkBox.setDrawBackgroundAsArc(3); @@ -188,12 +195,21 @@ public class ProfileSearchCell extends BaseCell { protected void onDetachedFromWindow() { super.onDetachedFromWindow(); avatarImage.onDetachedFromWindow(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); avatarImage.onAttachedToWindow(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + invalidate(); + } } @Override @@ -236,11 +252,9 @@ public class ProfileSearchCell extends BaseCell { CharSequence nameString; TextPaint currentNamePaint; - drawNameBroadcast = false; drawNameLock = false; - drawNameGroup = false; drawCheck = false; - drawNameBot = false; + drawPremium = false; if (encryptedChat != null) { drawNameLock = true; @@ -256,30 +270,11 @@ public class ProfileSearchCell extends BaseCell { } else { if (chat != null) { dialog_id = -chat.id; - if (SharedConfig.drawDialogIcons) { - if (ChatObject.isChannel(chat) && !chat.megagroup) { - drawNameBroadcast = true; - nameLockTop = AndroidUtilities.dp(22.5f); - } else { - drawNameGroup = true; - nameLockTop = AndroidUtilities.dp(24); - } - } drawCheck = chat.verifiedExtended(); - if (SharedConfig.drawDialogIcons) { - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - (drawNameGroup ? Theme.dialogs_groupDrawable.getIntrinsicWidth() : Theme.dialogs_broadcastDrawable.getIntrinsicWidth()); - nameLeft = AndroidUtilities.dp(11); - } + if (!LocaleController.isRTL) { + nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); } else { - if (!LocaleController.isRTL) { - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - } else { - nameLeft = AndroidUtilities.dp(11); - } + nameLeft = AndroidUtilities.dp(11); } } else if (user != null) { dialog_id = user.id; @@ -288,20 +283,9 @@ public class ProfileSearchCell extends BaseCell { } else { nameLeft = AndroidUtilities.dp(11); } - if (SharedConfig.drawDialogIcons && user.bot && !MessagesController.isSupportUser(user)) { - drawNameBot = true; - if (!LocaleController.isRTL) { - nameLockLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline); - nameLeft = AndroidUtilities.dp(AndroidUtilities.leftBaseline + 4) + Theme.dialogs_botDrawable.getIntrinsicWidth(); - } else { - nameLockLeft = getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline + 2) - Theme.dialogs_botDrawable.getIntrinsicWidth(); - nameLeft = AndroidUtilities.dp(11); - } - nameLockTop = AndroidUtilities.dp(20.5f); - } else { - nameLockTop = AndroidUtilities.dp(21); - } + nameLockTop = AndroidUtilities.dp(21); drawCheck = user.verifiedExtended(); + drawPremium = !user.self && MessagesController.getInstance(currentAccount).isPremiumUser(user); } } @@ -337,12 +321,6 @@ public class ProfileSearchCell extends BaseCell { } if (drawNameLock) { nameWidth -= AndroidUtilities.dp(6) + Theme.dialogs_lockDrawable.getIntrinsicWidth(); - } else if (drawNameBroadcast) { - nameWidth -= AndroidUtilities.dp(6) + Theme.dialogs_broadcastDrawable.getIntrinsicWidth(); - } else if (drawNameGroup) { - nameWidth -= AndroidUtilities.dp(6) + Theme.dialogs_groupDrawable.getIntrinsicWidth(); - } else if (drawNameBot) { - nameWidth -= AndroidUtilities.dp(6) + Theme.dialogs_botDrawable.getIntrinsicWidth(); } nameWidth -= getPaddingLeft() + getPaddingRight(); @@ -357,6 +335,7 @@ public class ProfileSearchCell extends BaseCell { countLayout = new StaticLayout(countString, Theme.dialogs_countTextPaint, countWidth, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); int w = countWidth + AndroidUtilities.dp(18); nameWidth -= w; + statusWidth -= w; if (!LocaleController.isRTL) { countLeft = getMeasuredWidth() - countWidth - AndroidUtilities.dp(19); } else { @@ -376,6 +355,9 @@ public class ProfileSearchCell extends BaseCell { nameWidth = 0; } CharSequence nameStringFinal = TextUtils.ellipsize(nameString, currentNamePaint, nameWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END); + if (nameStringFinal != null) { + nameStringFinal = Emoji.replaceEmoji(nameStringFinal, currentNamePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false); + } nameLayout = new StaticLayout(nameStringFinal, currentNamePaint, nameWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); CharSequence statusString = null; @@ -397,7 +379,14 @@ public class ProfileSearchCell extends BaseCell { } else if (user.id == 333000 || user.id == 777000) { statusString = LocaleController.getString("ServiceNotifications", R.string.ServiceNotifications); } else { - statusString = LocaleController.formatUserStatus(currentAccount, user); + if (isOnline == null) { + isOnline = new boolean[1]; + } + isOnline[0] = false; + statusString = LocaleController.formatUserStatus(currentAccount, user, isOnline); + if (isOnline[0]) { + currentStatusPaint = Theme.dialogs_onlinePaint; + } if (user != null && (user.id == UserConfig.getInstance(currentAccount).getClientUserId() || user.status != null && user.status.expires > ConnectionsManager.getInstance(currentAccount).getCurrentTime())) { currentStatusPaint = Theme.dialogs_onlinePaint; statusString = LocaleController.getString("Online", R.string.Online); @@ -512,17 +501,25 @@ public class ProfileSearchCell extends BaseCell { avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); avatarImage.setImage(null, null, avatarDrawable, null, null, 0); } else { + Drawable thumb = avatarDrawable; if (user.photo != null) { photo = user.photo.photo_small; + if (user.photo.strippedBitmap != null) { + thumb = user.photo.strippedBitmap; + } } - avatarImage.setImage(ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_STRIPPED), "50_50", avatarDrawable, user, 0); + avatarImage.setImage(ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_STRIPPED), "50_50", thumb, user, 0); } } else if (chat != null) { + Drawable thumb = avatarDrawable; if (chat.photo != null) { photo = chat.photo.photo_small; + if (chat.photo.strippedBitmap != null) { + thumb = chat.photo.strippedBitmap; + } } avatarDrawable.setInfo(chat); - avatarImage.setImage(ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_STRIPPED), "50_50", avatarDrawable, chat, 0); + avatarImage.setImage(ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(chat, ImageLocation.TYPE_STRIPPED), "50_50", thumb, chat, 0); } else { avatarDrawable.setInfo(0, null, null); avatarImage.setImage(null, null, avatarDrawable, null, null, 0); @@ -605,15 +602,6 @@ public class ProfileSearchCell extends BaseCell { if (drawNameLock) { setDrawableBounds(Theme.dialogs_lockDrawable, nameLockLeft, nameLockTop); Theme.dialogs_lockDrawable.draw(canvas); - } else if (drawNameGroup) { - setDrawableBounds(Theme.dialogs_groupDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_groupDrawable.draw(canvas); - } else if (drawNameBroadcast) { - setDrawableBounds(Theme.dialogs_broadcastDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_broadcastDrawable.draw(canvas); - } else if (drawNameBot) { - setDrawableBounds(Theme.dialogs_botDrawable, nameLockLeft, nameLockTop); - Theme.dialogs_botDrawable.draw(canvas); } if (nameLayout != null) { @@ -621,22 +609,28 @@ public class ProfileSearchCell extends BaseCell { canvas.translate(nameLeft, nameTop); nameLayout.draw(canvas); canvas.restore(); - if (drawCheck) { + if (drawCheck || drawPremium) { int x; + Drawable drawable = drawCheck ? Theme.dialogs_verifiedDrawable : PremiumGradient.getInstance().premiumStarDrawableMini; if (LocaleController.isRTL) { if (nameLayout.getLineLeft(0) == 0) { - x = nameLeft - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth(); + x = nameLeft - AndroidUtilities.dp(6) - drawable.getIntrinsicWidth(); } else { float w = nameLayout.getLineWidth(0); - x = (int) (nameLeft + nameWidth - Math.ceil(w) - AndroidUtilities.dp(6) - Theme.dialogs_verifiedDrawable.getIntrinsicWidth()); + x = (int) (nameLeft + nameWidth - Math.ceil(w) - AndroidUtilities.dp(6) - drawable.getIntrinsicWidth()); } } else { x = (int) (nameLeft + nameLayout.getLineRight(0) + AndroidUtilities.dp(6)); } - setDrawableBounds(Theme.dialogs_verifiedDrawable, x, nameTop + AndroidUtilities.dp(3)); - setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, x, nameTop + AndroidUtilities.dp(3)); - Theme.dialogs_verifiedDrawable.draw(canvas); - Theme.dialogs_verifiedCheckDrawable.draw(canvas); + if (drawCheck) { + setDrawableBounds(Theme.dialogs_verifiedDrawable, x, nameTop + AndroidUtilities.dp(3)); + setDrawableBounds(Theme.dialogs_verifiedCheckDrawable, x, nameTop + AndroidUtilities.dp(3)); + Theme.dialogs_verifiedDrawable.draw(canvas); + Theme.dialogs_verifiedCheckDrawable.draw(canvas); + } else if (drawPremium) { + setDrawableBounds(drawable, x, nameTop + AndroidUtilities.dp(1.5f)); + drawable.draw(canvas); + } } } @@ -667,6 +661,9 @@ public class ProfileSearchCell extends BaseCell { if (nameLayout != null) { builder.append(nameLayout.getText()); } + if (drawCheck) { + builder.append(", ").append(LocaleController.getString("AccDescrVerified", R.string.AccDescrVerified)).append("\n"); + } if (statusLayout != null) { if (builder.length() > 0) { builder.append(", "); @@ -675,6 +672,11 @@ public class ProfileSearchCell extends BaseCell { } info.setText(builder.toString()); if (checkBox != null) info.setSelected(checkBox.isChecked()); +// if (checkBox.isChecked()) { +// info.setCheckable(true); +// info.setChecked(checkBox.isChecked()); +// info.setClassName("android.widget.CheckBox"); +// } } public long getDialogId() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java index fd19e844b..12b5ae046 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RadioCell.java @@ -30,6 +30,7 @@ import java.util.ArrayList; public class RadioCell extends FrameLayout { + private Theme.ResourcesProvider resourcesProvider; private TextView textView; private RadioButton radioButton; private boolean needDivider; @@ -38,14 +39,23 @@ public class RadioCell extends FrameLayout { this(context, false, 21); } + public RadioCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, false, 21, resourcesProvider); + } + public RadioCell(Context context, boolean dialog, int padding) { + this(context, dialog, padding, null); + } + + public RadioCell(Context context, boolean dialog, int padding, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; textView = new TextView(context); if (dialog) { - textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); } else { - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); } textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setLines(1); @@ -58,9 +68,9 @@ public class RadioCell extends FrameLayout { radioButton = new RadioButton(context); radioButton.setSize(AndroidUtilities.dp(20)); if (dialog) { - radioButton.setColor(Theme.getColor(Theme.key_dialogRadioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + radioButton.setColor(Theme.getColor(Theme.key_dialogRadioBackground, resourcesProvider), Theme.getColor(Theme.key_dialogRadioBackgroundChecked, resourcesProvider)); } else { - radioButton.setColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_radioBackgroundChecked)); + radioButton.setColor(Theme.getColor(Theme.key_radioBackground, resourcesProvider), Theme.getColor(Theme.key_radioBackgroundChecked, resourcesProvider)); } addView(radioButton, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? padding + 1 : 0), 14, (LocaleController.isRTL ? 0 : padding + 1), 0)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java new file mode 100644 index 000000000..27d397506 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/RecurrentPaymentsAcceptCell.java @@ -0,0 +1,70 @@ +package org.telegram.ui.Cells; + +import android.content.Context; +import android.graphics.Canvas; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CheckBoxSquare; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; + +public class RecurrentPaymentsAcceptCell extends FrameLayout { + private LinkSpanDrawable.LinkCollector links; + + private TextView textView; + private CheckBoxSquare checkBox; + + public RecurrentPaymentsAcceptCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + + checkBox = new CheckBoxSquare(context, false); + checkBox.setDuplicateParentStateEnabled(false); + checkBox.setFocusable(false); + checkBox.setFocusableInTouchMode(false); + checkBox.setClickable(false); + addView(checkBox, LayoutHelper.createFrame(18, 18, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0)); + + textView = new LinkSpanDrawable.LinksTextView(context, links = new LinkSpanDrawable.LinkCollector(this), resourcesProvider); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); + textView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setMaxLines(2); + textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); + textView.setEllipsize(TextUtils.TruncateAt.END); + addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 16 : 58, 21, LocaleController.isRTL ? 58 : 16, 21)); + + setWillNotDraw(false); + } + + public TextView getTextView() { + return textView; + } + + public void setText(CharSequence text) { + textView.setText(text); + } + + public void setChecked(boolean checked) { + checkBox.setChecked(checked, true); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + if (links != null) { + canvas.save(); + canvas.translate(textView.getLeft(), textView.getTop()); + if (links.draw(canvas)) { + invalidate(); + } + canvas.restore(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java index b6e5819ef..956d51912 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SendLocationCell.java @@ -57,6 +57,8 @@ public class SendLocationCell extends FrameLayout { imageView = new ImageView(context); + setBackground(Theme.AdaptiveRipple.rect()); + imageView.setTag(live ? Theme.key_location_sendLiveLocationBackground + Theme.key_location_sendLiveLocationIcon : Theme.key_location_sendLocationBackground + Theme.key_location_sendLocationIcon); Drawable circle = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(42), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground), getThemedColor(live ? Theme.key_location_sendLiveLocationBackground : Theme.key_location_sendLocationBackground)); if (live) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java index 4ca39d676..9b95379b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SessionCell.java @@ -15,6 +15,7 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.text.SpannableStringBuilder; import android.text.TextUtils; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -36,9 +37,11 @@ import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.AnimatedFloat; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.DotDividerSpan; import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; @@ -51,10 +54,12 @@ public class SessionCell extends FrameLayout { private TextView onlineTextView; private TextView detailTextView; private TextView detailExTextView; + private BackupImageView placeholderImageView; private BackupImageView imageView; private AvatarDrawable avatarDrawable; private boolean needDivider; private boolean showStub; + private AnimatedFloat showStubValue = new AnimatedFloat(this); FlickerLoadingView globalGradient; LinearLayout linearLayout; @@ -72,10 +77,15 @@ public class SessionCell extends FrameLayout { avatarDrawable = new AvatarDrawable(); avatarDrawable.setTextSize(AndroidUtilities.dp(10)); + imageView = new BackupImageView(context); imageView.setRoundRadius(AndroidUtilities.dp(10)); addView(imageView, LayoutHelper.createFrame(20, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 0 : 21), 13, (LocaleController.isRTL ? 21 : 0), 0)); } else { + placeholderImageView = new BackupImageView(context); + placeholderImageView.setRoundRadius(AndroidUtilities.dp(10)); + addView(placeholderImageView, LayoutHelper.createFrame(42, 42, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 0 : 16), 13, (LocaleController.isRTL ? 16 : 0), 0)); + imageView = new BackupImageView(context); imageView.setRoundRadius(AndroidUtilities.dp(10)); addView(imageView, LayoutHelper.createFrame(42, 42, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, (LocaleController.isRTL ? 0 : 16), 13, (LocaleController.isRTL ? 16 : 0), 0)); @@ -137,6 +147,30 @@ public class SessionCell extends FrameLayout { addView(detailExTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, leftMargin, 59, rightMargin, 0)); } + private void setContentAlpha(float alpha) { + if (detailExTextView != null) { + detailExTextView.setAlpha(alpha); + } + if (detailTextView != null) { + detailTextView.setAlpha(alpha); + } + if (nameTextView != null) { + nameTextView.setAlpha(alpha); + } + if (onlineTextView != null) { + onlineTextView.setAlpha(alpha); + } + if (imageView != null) { + imageView.setAlpha(alpha); + } + if (placeholderImageView != null) { + placeholderImageView.setAlpha(1f - alpha); + } + if (linearLayout != null) { + linearLayout.setAlpha(alpha); + } + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(90) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY)); @@ -313,7 +347,13 @@ public class SessionCell extends FrameLayout { @Override protected void onDraw(Canvas canvas) { - if (showStub && globalGradient != null) { + float stubAlpha = showStubValue.set(showStub ? 1 : 0); + setContentAlpha(1f - stubAlpha); + if (stubAlpha > 0 && globalGradient != null) { + if (stubAlpha < 1f) { + AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); + canvas.saveLayerAlpha(AndroidUtilities.rectTmp, (int) (255 * stubAlpha), Canvas.ALL_SAVE_FLAG); + } globalGradient.updateColors(); globalGradient.updateGradient(); if (getParent() != null) { @@ -338,6 +378,10 @@ public class SessionCell extends FrameLayout { AndroidUtilities.rectTmp.set(x, y - AndroidUtilities.dp(4), x + getMeasuredWidth() * 0.3f, y + AndroidUtilities.dp(4)); canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(4), AndroidUtilities.dp(4), globalGradient.getPaint()); invalidate(); + + if (stubAlpha < 1f) { + canvas.restore(); + } } if (needDivider) { canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint); @@ -351,7 +395,11 @@ public class SessionCell extends FrameLayout { Drawable iconDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, AndroidUtilities.isTablet() ? R.drawable.device_tablet_android : R.drawable.device_phone_android).mutate(); iconDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_avatar_text), PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(Theme.createCircleDrawable(AndroidUtilities.dp(42), Theme.getColor(Theme.key_avatar_backgroundGreen)), iconDrawable); - imageView.setImageDrawable(combinedDrawable); + if (placeholderImageView != null) { + placeholderImageView.setImageDrawable(combinedDrawable); + } else { + imageView.setImageDrawable(combinedDrawable); + } invalidate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java index e4619a392..19146b46c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SettingsSuggestionCell.java @@ -30,13 +30,15 @@ public class SettingsSuggestionCell extends LinearLayout { private TextView detailTextView; private TextView yesButton; private TextView noButton; + private Theme.ResourcesProvider resourcesProvider; private int currentType; private int currentAccount = UserConfig.selectedAccount; - public SettingsSuggestionCell(Context context) { + public SettingsSuggestionCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; setOrientation(VERTICAL); textView = new TextView(context); @@ -44,14 +46,14 @@ public class SettingsSuggestionCell extends LinearLayout { textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader, resourcesProvider)); addView(textView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 21, 15, 21, 0)); detailTextView = new TextView(context); - detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + detailTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); detailTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); - detailTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); - detailTextView.setHighlightColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection)); + detailTextView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); + detailTextView.setHighlightColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkSelection, resourcesProvider)); detailTextView.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); detailTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); addView(detailTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 21, 8, 21, 0)); @@ -62,13 +64,13 @@ public class SettingsSuggestionCell extends LinearLayout { for (int a = 0; a < 2; a++) { TextView textView = new TextView(context); - textView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + textView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); textView.setLines(1); textView.setSingleLine(true); textView.setGravity(Gravity.CENTER_HORIZONTAL); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity(Gravity.CENTER); - textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + textView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); linearLayout.addView(textView, LayoutHelper.createLinear(0, 40, 0.5f, a == 0 ? 0 : 4, 0, a == 0 ? 4 : 0, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java index 15f79a7a8..dbdc917ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java @@ -23,18 +23,30 @@ public class ShadowSectionCell extends View { private int size; public ShadowSectionCell(Context context) { - this(context, 12); + this(context, 12, null); } - public ShadowSectionCell(Context context, int s) { + public ShadowSectionCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, 12, resourcesProvider); + } + + public ShadowSectionCell(Context context, int s) { + this(context, s, null); + } + + public ShadowSectionCell(Context context, int s, Theme.ResourcesProvider resourcesProvider) { super(context); - setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider))); size = s; } public ShadowSectionCell(Context context, int s, int backgroundColor) { + this(context, s, backgroundColor, null); + } + + public ShadowSectionCell(Context context, int s, int backgroundColor, Theme.ResourcesProvider resourcesProvider) { super(context); - Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow); + Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); Drawable background = new ColorDrawable(backgroundColor); CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); combinedDrawable.setFullsize(true); 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 4a038a467..3846c84c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShareDialogCell.java @@ -15,6 +15,7 @@ import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -205,4 +206,12 @@ public class ShareDialogCell extends FrameLayout { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (checkBox.isChecked()) { + info.setSelected(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java index 4fe9e6251..4115c62ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedAudioCell.java @@ -4,6 +4,9 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Rect; +import android.os.Build; +import android.os.Bundle; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; @@ -12,7 +15,11 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.MotionEvent; import android.view.SoundEffectConstants; +import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeProvider; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; @@ -28,6 +35,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.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.CheckBox2; @@ -38,6 +46,8 @@ import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.RadialProgress2; import org.telegram.ui.FilteredSearchView; +import java.util.Locale; + public class SharedAudioCell extends FrameLayout implements DownloadController.FileDownloadProgressListener, NotificationCenter.NotificationCenterDelegate { private SpannableStringBuilder dotSpan; @@ -94,6 +104,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F this.resourcesProvider = resourcesProvider; this.viewType = viewType; setFocusable(true); + setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); radialProgress = new RadialProgress2(this, resourcesProvider); radialProgress.setColors(Theme.key_chat_inLoader, Theme.key_chat_inLoaderSelected, Theme.key_chat_inMediaIcon, Theme.key_chat_inMediaIconSelected); @@ -523,6 +534,7 @@ public class SharedAudioCell extends FrameLayout implements DownloadController.F @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); if (currentMessageObject.isMusic()) { info.setText(LocaleController.formatString("AccDescrMusicInfo", R.string.AccDescrMusicInfo, currentMessageObject.getMusicAuthor(), currentMessageObject.getMusicTitle())); } else if (titleLayout != null && descriptionLayout != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java index becfc98ff..650ac29cf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java @@ -31,12 +31,12 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DownloadController; +import org.telegram.messenger.FileLoader; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; -import org.telegram.messenger.FileLoader; import org.telegram.messenger.R; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; @@ -400,7 +400,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle if (!messageObject.isVideo() && !(messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaPhoto) && !MessageObject.isGifDocument(document)) { fileName = FileLoader.getDocumentFileName(document); } - if (TextUtils.isEmpty(fileName)) { + if (TextUtils.isEmpty(fileName) && document.mime_type != null) { if (document.mime_type.startsWith("video")) { if (MessageObject.isGifDocument(document)) { fileName = LocaleController.getString("AttachGif", R.string.AttachGif); @@ -408,7 +408,11 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle fileName = LocaleController.getString("AttachVideo", R.string.AttachVideo); } } else if (document.mime_type.startsWith("image")) { - fileName = LocaleController.getString("AttachPhoto", R.string.AttachPhoto); + if (MessageObject.isGifDocument(document)) { + fileName = LocaleController.getString("AttachGif", R.string.AttachGif); + } else { + fileName = LocaleController.getString("AttachPhoto", R.string.AttachPhoto); + } } else if (document.mime_type.startsWith("audio")) { fileName = LocaleController.getString("AttachAudio", R.string.AttachAudio); } else { @@ -682,7 +686,7 @@ public class SharedDocumentCell extends FrameLayout implements DownloadControlle super.onInitializeAccessibilityNodeInfo(info); if (checkBox.isChecked()) { info.setCheckable(true); - info.setChecked(true); + info.setChecked(checkBox.isChecked()); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java index 44b737e47..322b531c2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedLinkCell.java @@ -11,6 +11,7 @@ package org.telegram.ui.Cells; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; +import android.graphics.CornerPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Rect; @@ -174,16 +175,22 @@ public class SharedLinkCell extends FrameLayout { private int fromInfoLayoutY = AndroidUtilities.dp(30); private StaticLayout fromInfoLayout; + private Theme.ResourcesProvider resourcesProvider; private int viewType; public final static int VIEW_TYPE_DEFAULT = 0; public final static int VIEW_TYPE_GLOBAL_SEARCH = 1; public SharedLinkCell(Context context) { - this(context, VIEW_TYPE_DEFAULT); + this(context, VIEW_TYPE_DEFAULT, null); } public SharedLinkCell(Context context, int viewType) { + this(context, viewType, null); + } + + public SharedLinkCell(Context context, int viewType, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; this.viewType = viewType; setFocusable(true); @@ -192,7 +199,7 @@ public class SharedLinkCell extends FrameLayout { titleTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); titleTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + titleTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); descriptionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -202,9 +209,9 @@ public class SharedLinkCell extends FrameLayout { setWillNotDraw(false); linkImageView = new ImageReceiver(this); linkImageView.setRoundRadius(AndroidUtilities.dp(4)); - letterDrawable = new LetterDrawable(); + letterDrawable = new LetterDrawable(resourcesProvider); - checkBox = new CheckBox2(context, 21); + checkBox = new CheckBox2(context, 21, resourcesProvider); checkBox.setVisibility(INVISIBLE); checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); @@ -748,10 +755,12 @@ public class SharedLinkCell extends FrameLayout { checkBox.setChecked(checked, animated); } + private Paint urlPaint; + @Override protected void onDraw(Canvas canvas) { if (viewType == VIEW_TYPE_GLOBAL_SEARCH) { - description2TextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); + description2TextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3, resourcesProvider)); } if (dateLayout != null) { canvas.save(); @@ -771,30 +780,30 @@ public class SharedLinkCell extends FrameLayout { } if (captionLayout != null) { - captionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + captionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), captionY); captionLayout.draw(canvas); canvas.restore(); } if (descriptionLayout != null) { - descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), descriptionY); - SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout, descriptionLayout, descriptionLayoutSpoilers, canvas); + SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout, descriptionLayout, descriptionLayoutSpoilers, canvas, false); canvas.restore(); } if (descriptionLayout2 != null) { - descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); canvas.save(); canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline), description2Y); - SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout2, descriptionLayout2, descriptionLayout2Spoilers, canvas); + SpoilerEffect.renderWithRipple(this, false, descriptionTextPaint.getColor(), -AndroidUtilities.dp(2), patchedDescriptionLayout2, descriptionLayout2, descriptionLayout2Spoilers, canvas, false); canvas.restore(); } if (!linkLayout.isEmpty()) { - descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); + descriptionTextPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText, resourcesProvider)); int offset = 0; for (int a = 0; a < linkLayout.size(); a++) { StaticLayout layout = linkLayout.get(a); @@ -810,10 +819,15 @@ public class SharedLinkCell extends FrameLayout { path.addRect(b.left, b.top, b.right, b.bottom, Path.Direction.CW); } } + if (urlPaint == null) { + urlPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + urlPaint.setPathEffect(new CornerPathEffect(AndroidUtilities.dp(4))); + } + urlPaint.setColor(Theme.getColor(Theme.key_chat_linkSelectBackground, resourcesProvider)); canvas.save(); canvas.clipPath(path, Region.Op.DIFFERENCE); if (pressedLink == a) { - canvas.drawPath(urlPath, Theme.linkSelectionPaint); + canvas.drawPath(urlPath, urlPaint); } layout.draw(canvas); canvas.restore(); @@ -826,7 +840,7 @@ public class SharedLinkCell extends FrameLayout { canvas.clipPath(path); if (pressedLink == a) { - canvas.drawPath(urlPath, Theme.linkSelectionPaint); + canvas.drawPath(urlPath, urlPaint); } layout.draw(canvas); canvas.restore(); 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 13086c2d6..04cc5a2af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedPhotoVideoCell2.java @@ -440,13 +440,13 @@ public class SharedPhotoVideoCell2 extends View { Paint highlightPaint = new Paint(); SparseArray imageFilters = new SparseArray<>(); - public SharedResources(Context context) { + public SharedResources(Context context, Theme.ResourcesProvider resourcesProvider) { textPaint.setTextSize(AndroidUtilities.dp(12)); textPaint.setColor(Color.WHITE); textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); playDrawable = ContextCompat.getDrawable(context, R.drawable.play_mini_video); playDrawable.setBounds(0, 0, playDrawable.getIntrinsicWidth(), playDrawable.getIntrinsicHeight()); - backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder)); + backgroundPaint.setColor(Theme.getColor(Theme.key_sharedMedia_photoPlaceholder, resourcesProvider)); } public String getFilterString(int width) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java index d929030c7..ee3b9b912 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java @@ -10,6 +10,8 @@ package org.telegram.ui.Cells; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Vibrator; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -27,6 +29,7 @@ import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SvgHelper; @@ -36,10 +39,12 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.EmojiTextView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumLockIconView; -public class StickerEmojiCell extends FrameLayout { +public class StickerEmojiCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private BackupImageView imageView; + private PremiumLockIconView premiumIconView; private TLRPC.Document sticker; private SendMessagesHelper.ImportingSticker stickerPath; private Object parentObject; @@ -55,6 +60,11 @@ public class StickerEmojiCell extends FrameLayout { private static AccelerateInterpolator interpolator = new AccelerateInterpolator(0.5f); private int currentAccount = UserConfig.selectedAccount; private boolean fromEmojiPanel; + private boolean isPremiumSticker; + private float premiumAlpha = 1f; + private boolean showPremiumLock; + + int stickerColor; public StickerEmojiCell(Context context, boolean isEmojiPanel) { super(context); @@ -68,7 +78,16 @@ public class StickerEmojiCell extends FrameLayout { emojiTextView = new EmojiTextView(context); emojiTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - addView(emojiTextView, LayoutHelper.createFrame(28, 28, Gravity.BOTTOM | Gravity.RIGHT)); + // addView(emojiTextView, LayoutHelper.createFrame(28, 28, Gravity.BOTTOM | Gravity.RIGHT)); + + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setColor(Theme.getColor(Theme.key_featuredStickers_addButton)); + + premiumIconView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_STICKERS_PREMIUM_LOCKED); + premiumIconView.setImageReceiver(imageView.getImageReceiver()); + premiumIconView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4)); + premiumIconView.setImageReceiver(imageView.getImageReceiver()); + addView(premiumIconView, LayoutHelper.createFrame(24, 24, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0 ,0, 0, 0)); setFocusable(true); } @@ -121,6 +140,11 @@ public class StickerEmojiCell extends FrameLayout { public void setSticker(TLRPC.Document document, SendMessagesHelper.ImportingSticker path, Object parent, String emoji, boolean showEmoji) { currentEmoji = emoji; + isPremiumSticker = MessageObject.isPremiumSticker(document); + if (isPremiumSticker) { + premiumIconView.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + premiumIconView.setWaitingImage(); + } if (path != null) { stickerPath = path; if (path.validated) { @@ -185,13 +209,39 @@ public class StickerEmojiCell extends FrameLayout { emojiTextView.setVisibility(INVISIBLE); } } + updatePremiumStatus(false); + imageView.getImageReceiver().setAlpha(alpha * premiumAlpha); + } + + private void updatePremiumStatus(boolean animated) { + if (isPremiumSticker) { + showPremiumLock = true; + } else { + showPremiumLock = false; + } + FrameLayout.LayoutParams layoutParams = (LayoutParams) premiumIconView.getLayoutParams(); + if (!UserConfig.getInstance(currentAccount).isPremium()) { + layoutParams.height = layoutParams.width = AndroidUtilities.dp(24); + layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; + layoutParams.bottomMargin = layoutParams.rightMargin = 0; + premiumIconView.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4)); + } else { + layoutParams.height = layoutParams.width = AndroidUtilities.dp(16); + layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; + layoutParams.bottomMargin = AndroidUtilities.dp(8); + layoutParams.rightMargin = AndroidUtilities.dp(8); + premiumIconView.setPadding(AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1)); + } + premiumIconView.setLocked(!UserConfig.getInstance(currentAccount).isPremium()); + AndroidUtilities.updateViewVisibilityAnimated(premiumIconView, showPremiumLock, 0.9f, animated); + invalidate(); } public void disable() { changingAlpha = true; alpha = 0.5f; time = 0; - imageView.getImageReceiver().setAlpha(alpha); + imageView.getImageReceiver().setAlpha(alpha * premiumAlpha); imageView.invalidate(); lastUpdateTime = System.currentTimeMillis(); invalidate(); @@ -221,6 +271,28 @@ public class StickerEmojiCell extends FrameLayout { super.invalidate(); } + @Override + protected void dispatchDraw(Canvas canvas) { +// if (showPremiumLock && premiumAlpha > 0.5f) { +// premiumAlpha -= 16 / 150f; +// if (premiumAlpha < 0.5f) { +// premiumAlpha = 0.5f; +// } +// invalidate(); +// imageView.invalidate(); +// } else if (!showPremiumLock && premiumAlpha < 1f) { +// premiumAlpha += 16 / 150f; +// if (premiumAlpha > 1f) { +// premiumAlpha = 1f; +// } +// invalidate(); +// imageView.invalidate(); +// } + imageView.getImageReceiver().setAlpha(alpha * premiumAlpha); + + super.dispatchDraw(canvas); + } + @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean result = super.drawChild(canvas, child, drawingTime); @@ -238,7 +310,7 @@ public class StickerEmojiCell extends FrameLayout { changingAlpha = false; alpha = 1.0f; } - imageView.getImageReceiver().setAlpha(alpha); + imageView.getImageReceiver().setAlpha(alpha * premiumAlpha); } else if (scaled && scale != 0.8f) { scale -= dt / 400.0f; if (scale < 0.8f) { @@ -277,4 +349,33 @@ public class StickerEmojiCell extends FrameLayout { info.setContentDescription(descr); info.setEnabled(true); } + + public void showRequirePremiumAnimation() { + if (premiumIconView != null) { + Vibrator v = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(200); + } + AndroidUtilities.shakeView(premiumIconView, 2, 0); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.currentUserPremiumStatusChanged) { + updatePremiumStatus(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java index 99ae135ae..75e73cc46 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetCell.java @@ -8,6 +8,8 @@ package org.telegram.ui.Cells; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; @@ -15,10 +17,12 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.os.Build; +import android.text.SpannableString; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -38,15 +42,18 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CheckBox2; import org.telegram.ui.Components.Easings; +import org.telegram.ui.Components.ForegroundColorSpanThemable; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RadialProgressView; import java.util.ArrayList; +import java.util.Locale; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.ui.PinnedStickerHelper; public class StickerSetCell extends FrameLayout { + private final static String LINK_PREFIX = "t.me/addstickers/"; private final int option; @@ -103,10 +110,13 @@ public class StickerSetCell extends FrameLayout { optionsButton = new ImageView(context); optionsButton.setFocusable(false); optionsButton.setScaleType(ImageView.ScaleType.CENTER); - optionsButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + if (option != 3) { + optionsButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_stickers_menuSelector))); + } if (option == 1) { optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.SRC_IN)); optionsButton.setImageResource(R.drawable.msg_actions); + optionsButton.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL)); // NekoX: Pinned Sticker Mark @@ -130,7 +140,7 @@ public class StickerSetCell extends FrameLayout { addView(checkBox, LayoutHelper.createFrameRelatively(24, 24, Gravity.START, 34, 30, 0, 0)); } else if (option == 3) { optionsButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_featuredStickers_addedIcon), PorterDuff.Mode.SRC_IN)); - optionsButton.setImageResource(R.drawable.sticker_added); + optionsButton.setImageResource(R.drawable.floating_check); addView(optionsButton, LayoutHelper.createFrame(40, 40, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, (LocaleController.isRTL ? 10 : 0), 9, (LocaleController.isRTL ? 0 : 10), 0)); } } @@ -170,6 +180,28 @@ public class StickerSetCell extends FrameLayout { } public void setStickersSet(TLRPC.TL_messages_stickerSet set, boolean divider) { + setStickersSet(set, divider, false); + } + + public void setSearchQuery(TLRPC.TL_messages_stickerSet tlSet, String query, Theme.ResourcesProvider resourcesProvider) { + TLRPC.StickerSet set = tlSet.set; + int titleIndex = set.title.toLowerCase(Locale.ROOT).indexOf(query); + if (titleIndex != -1) { + SpannableString spannableString = new SpannableString(set.title); + spannableString.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider), titleIndex, titleIndex + query.length(), 0); + textView.setText(spannableString); + } + int linkIndex = set.short_name.toLowerCase(Locale.ROOT).indexOf(query); + if (linkIndex != -1) { + linkIndex += LINK_PREFIX.length(); + SpannableString spannableString = new SpannableString(LINK_PREFIX + set.short_name); + spannableString.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4, resourcesProvider), linkIndex, linkIndex + query.length(), 0); + valueTextView.setText(spannableString); + } + } + + @SuppressLint("SetTextI18n") + public void setStickersSet(TLRPC.TL_messages_stickerSet set, boolean divider, boolean groupSearch) { needDivider = divider; stickersSet = set; @@ -232,6 +264,9 @@ public class StickerSetCell extends FrameLayout { valueTextView.setText(LocaleController.formatPluralString("Stickers", 0)); imageView.setImageDrawable(null); } + if (groupSearch) { + valueTextView.setText(LINK_PREFIX + set.set.short_name); + } } // NekoX: Pinned Sticker Mark -> Change Visibility @@ -251,13 +286,40 @@ public class StickerSetCell extends FrameLayout { setChecked(checked, true); } + public boolean isChecked() { + return option == 1 ? checkBox.isChecked() : option == 3 && optionsButton.getVisibility() == VISIBLE; + } + public void setChecked(boolean checked, boolean animated) { switch (option) { case 1: checkBox.setChecked(checked, animated); break; case 3: - optionsButton.setVisibility(checked ? VISIBLE : INVISIBLE); + if (animated) { + optionsButton.animate().cancel(); + optionsButton.animate().setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (!checked) { + optionsButton.setVisibility(INVISIBLE); + } + } + + @Override + public void onAnimationStart(Animator animation) { + if (checked) { + optionsButton.setVisibility(VISIBLE); + } + } + }).alpha(checked ? 1 : 0).scaleX(checked ? 1 : 0.1f).scaleY(checked ? 1 : 0.1f).setDuration(150).start(); + } else { + optionsButton.setVisibility(checked ? VISIBLE : INVISIBLE); + if (!checked) { + optionsButton.setScaleX(0.1f); + optionsButton.setScaleY(0.1f); + } + } break; } } @@ -345,7 +407,16 @@ public class StickerSetCell extends FrameLayout { @Override protected void onDraw(Canvas canvas) { if (needDivider) { - canvas.drawLine(0, getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); + canvas.drawLine(LocaleController.isRTL ? 0 : AndroidUtilities.dp(71), getHeight() - 1, getWidth() - getPaddingRight() - (LocaleController.isRTL ? AndroidUtilities.dp(71) : 0), getHeight() - 1, Theme.dividerPaint); + } + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (checkBox != null && checkBox.isChecked()) { + info.setCheckable(true); + info.setChecked(true); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetGroupInfoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetGroupInfoCell.java index 12704d16a..cc6445b2d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetGroupInfoCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetGroupInfoCell.java @@ -42,7 +42,7 @@ public class StickerSetGroupInfoCell extends LinearLayout { addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); addButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); addButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + addButton.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addButton.setText(LocaleController.getString("ChooseStickerSet", R.string.ChooseStickerSet).toUpperCase()); addView(addButton, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | Gravity.LEFT, 17, 10, 14, 8)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java index 7812d3e8a..7859a53b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerSetNameCell.java @@ -118,7 +118,11 @@ public class StickerSetNameCell extends FrameLayout { } public void setText(CharSequence text, int resId) { - setText(text, resId, 0, 0); + setText(text, resId, null, 0, 0); + } + + public void setText(CharSequence text, int resId, CharSequence iconAccDescr) { + setText(text, resId, iconAccDescr, 0, 0); } public void setTitleColor(int color) { @@ -126,6 +130,10 @@ public class StickerSetNameCell extends FrameLayout { } public void setText(CharSequence text, int resId, int index, int searchLength) { + setText(text, resId, null, index, searchLength); + } + + public void setText(CharSequence text, int resId, CharSequence iconAccDescr, int index, int searchLength) { stickerSetName = text; stickerSetNameSearchIndex = index; stickerSetNameSearchLength = searchLength; @@ -141,6 +149,7 @@ public class StickerSetNameCell extends FrameLayout { } if (resId != 0) { buttonView.setImageResource(resId); + buttonView.setContentDescription(iconAccDescr); buttonView.setVisibility(VISIBLE); } else { buttonView.setVisibility(INVISIBLE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java index 7beff5dc8..3b83ff8c3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCell.java @@ -23,6 +23,7 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; @@ -37,25 +38,36 @@ public class TextCell extends FrameLayout { private int offsetFromImage = 71; public int imageLeft = 21; private boolean inDialogs; + private boolean prioritizeTitleOverValue; + private Theme.ResourcesProvider resourcesProvider; public TextCell(Context context) { - this(context, 23, false); + this(context, 23, false, null); + } + + public TextCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, 23, false, resourcesProvider); } public TextCell(Context context, int left, boolean dialog) { + this(context, left, dialog, null); + } + + public TextCell(Context context, int left, boolean dialog, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; leftPadding = left; textView = new SimpleTextView(context); - textView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(16); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); textView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); - addView(textView); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); valueTextView = new SimpleTextView(context); - valueTextView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlue2 : Theme.key_windowBackgroundWhiteValueText)); + valueTextView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlue2 : Theme.key_windowBackgroundWhiteValueText, resourcesProvider)); valueTextView.setTextSize(16); valueTextView.setGravity(LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT); valueTextView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); @@ -63,7 +75,7 @@ public class TextCell extends FrameLayout { imageView = new RLottieImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(dialog ? Theme.key_dialogIcon : Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(dialog ? Theme.key_dialogIcon : Theme.key_windowBackgroundWhiteGrayIcon, resourcesProvider), PorterDuff.Mode.SRC_IN)); addView(imageView); valueImageView = new ImageView(context); @@ -93,13 +105,23 @@ public class TextCell extends FrameLayout { return valueImageView; } + public void setPrioritizeTitleOverValue(boolean prioritizeTitleOverValue) { + this.prioritizeTitleOverValue = prioritizeTitleOverValue; + requestLayout(); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec); int height = AndroidUtilities.dp(48); - valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(leftPadding), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); - textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding) - valueTextView.getTextWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + if (prioritizeTitleOverValue) { + textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(103 + leftPadding) - textView.getTextWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + } else { + valueTextView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(leftPadding), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + textView.measure(MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(71 + leftPadding) - valueTextView.getTextWidth(), MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(20), MeasureSpec.EXACTLY)); + } if (imageView.getVisibility() == VISIBLE) { imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST)); } @@ -116,6 +138,9 @@ public class TextCell extends FrameLayout { int viewTop = (height - valueTextView.getTextHeight()) / 2; int viewLeft = LocaleController.isRTL ? AndroidUtilities.dp(leftPadding) : 0; + if (prioritizeTitleOverValue && !LocaleController.isRTL) { + viewLeft = width - valueTextView.getMeasuredWidth() - AndroidUtilities.dp(leftPadding); + } valueTextView.layout(viewLeft, viewTop, viewLeft + valueTextView.getMeasuredWidth(), viewTop + valueTextView.getMeasuredHeight()); viewTop = (height - textView.getTextHeight()) / 2; @@ -144,10 +169,10 @@ public class TextCell extends FrameLayout { } public void setColors(String icon, String text) { - textView.setTextColor(Theme.getColor(text)); + textView.setTextColor(Theme.getColor(text, resourcesProvider)); textView.setTag(text); if (icon != null) { - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(icon), PorterDuff.Mode.SRC_IN)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(icon, resourcesProvider), PorterDuff.Mode.SRC_IN)); imageView.setTag(icon); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java index 04980a371..5ef27140e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell.java @@ -24,6 +24,7 @@ import android.util.Property; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -58,6 +59,7 @@ public class TextCheckCell extends FrameLayout { private float lastTouchX; private ObjectAnimator animator; private boolean drawCheckRipple; + private Theme.ResourcesProvider resourcesProvider; public static final Property ANIMATION_PROGRESS = new AnimationProperties.FloatProperty("animationProgress") { @Override @@ -77,20 +79,29 @@ public class TextCheckCell extends FrameLayout { } public TextCheckCell(Context context, int padding) { - this(context, padding, false); + this(context, padding, false, null); + } + + public TextCheckCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, 21, false, resourcesProvider); } public TextCheckCell(Context context, int padding, boolean dialog) { + this(context, padding, dialog, null); + } + + public TextCheckCell(Context context, int padding, boolean dialog, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; textView = new TextView(context); - textView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogTextBlack : Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); 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, LocaleController.isRTL ? 70 : padding, 0, LocaleController.isRTL ? padding : 70, 0)); valueTextView = new TextView(context); - valueTextView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogIcon : Theme.key_windowBackgroundWhiteGrayText2)); + valueTextView.setTextColor(Theme.getColor(dialog ? Theme.key_dialogIcon : Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); valueTextView.setLines(1); @@ -102,7 +113,7 @@ public class TextCheckCell extends FrameLayout { if (!dialog) { - checkBox = new Switch(context); + checkBox = new Switch(context, resourcesProvider); checkBox.setColors(Theme.key_switchTrack, Theme.key_switchTrackChecked, Theme.key_windowBackgroundWhite, Theme.key_windowBackgroundWhite); addView(checkBox, LayoutHelper.createFrame(37, 20, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, 22, 0, 22, 0)); @@ -116,6 +127,12 @@ public class TextCheckCell extends FrameLayout { setClipChildren(false); } + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + checkBox.setEnabled(enabled); + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (isMultiline) { @@ -154,7 +171,7 @@ public class TextCheckCell extends FrameLayout { } public void setColors(String key, String switchKey, String switchKeyChecked, String switchThumb, String switchThumbChecked) { - textView.setTextColor(Theme.getColor(key)); + textView.setTextColor(Theme.getColor(key, resourcesProvider)); checkBox.setColors(switchKey, switchKeyChecked, switchThumb, switchThumbChecked); textView.setTag(key); } @@ -213,14 +230,14 @@ public class TextCheckCell extends FrameLayout { public void setEnabled(boolean value, ArrayList animators) { super.setEnabled(value); if (animators != null) { - animators.add(ObjectAnimator.ofFloat(textView, "alpha", value ? 1.0f : 0.5f)); + animators.add(ObjectAnimator.ofFloat(textView, View.ALPHA, value ? 1.0f : 0.5f)); if (checkBox != null) { - animators.add(ObjectAnimator.ofFloat(checkBox, "alpha", value ? 1.0f : 0.5f)); + animators.add(ObjectAnimator.ofFloat(checkBox, View.ALPHA, value ? 1.0f : 0.5f)); } else { animators.add(ObjectAnimator.ofFloat(checkBoxSquare, "alpha", value ? 1.0f : 0.5f)); } if (valueTextView.getVisibility() == VISIBLE) { - animators.add(ObjectAnimator.ofFloat(valueTextView, "alpha", value ? 1.0f : 0.5f)); + animators.add(ObjectAnimator.ofFloat(valueTextView, View.ALPHA, value ? 1.0f : 0.5f)); } } else { textView.setAlpha(value ? 1.0f : 0.5f); @@ -344,7 +361,13 @@ public class TextCheckCell extends FrameLayout { super.onInitializeAccessibilityNodeInfo(info); info.setClassName("android.widget.Switch"); info.setCheckable(true); - info.setChecked(isChecked()); - info.setContentDescription(isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + info.setChecked(checkBox.isChecked()); + StringBuilder sb = new StringBuilder(); + sb.append(textView.getText()); + if (!TextUtils.isEmpty(valueTextView.getText())) { + sb.append('\n'); + sb.append(valueTextView.getText()); + } + info.setContentDescription(sb); } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java index 38b7a41ba..c81f338ff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckCell2.java @@ -178,6 +178,5 @@ public class TextCheckCell2 extends FrameLayout { info.setClassName("android.widget.Switch"); info.setCheckable(true); info.setChecked(checkBox.isChecked()); - info.setContentDescription(checkBox.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckbox2Cell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckbox2Cell.java index 7c0c5f9cc..230269127 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckbox2Cell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextCheckbox2Cell.java @@ -295,6 +295,12 @@ public class TextCheckbox2Cell extends FrameLayout { info.setClassName("android.widget.checkbox"); info.setCheckable(true); info.setChecked(checkbox.isChecked()); - info.setContentDescription(checkbox.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + StringBuilder sb = new StringBuilder(); + sb.append(textView.getText()); + if (valueTextView != null) { + sb.append("\n"); + sb.append(valueTextView.getText()); + } + info.setText(sb); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java index 2360e8aee..09d90fbb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextColorCell.java @@ -29,6 +29,7 @@ import java.util.ArrayList; public class TextColorCell extends FrameLayout { + private Theme.ResourcesProvider resourcesProvider; private TextView textView; private boolean needDivider; private int currentColor; @@ -40,14 +41,19 @@ public class TextColorCell extends FrameLayout { public final static int[] colorsToSave = new int[] {0xffff0000, 0xffff8e01, 0xffffff00, 0xff00ff00, 0xff00ffff, 0xff0000ff, 0xffd274f9, 0xffff00ff, 0xffffffff}; public TextColorCell(Context context) { + this(context, null); + } + + public TextColorCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; if (colorPaint == null) { colorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } textView = new TextView(context); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setLines(1); textView.setMaxLines(1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java index 3c838b97c..785529dab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java @@ -37,11 +37,18 @@ public class TextDetailCell extends FrameLayout { private boolean needDivider; private boolean contentDescriptionValueFirst; + private Theme.ResourcesProvider resourcesProvider; + public TextDetailCell(Context context) { + this(context, null); + } + + public TextDetailCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; textView = new EmojiTextView(context); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); textView.setLines(1); @@ -52,7 +59,7 @@ public class TextDetailCell extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 23, 8, 23, 0)); valueTextView = new EmojiTextView(context); - valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); valueTextView.setLines(1); valueTextView.setMaxLines(1); @@ -62,6 +69,7 @@ public class TextDetailCell extends FrameLayout { addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 23, 33, 23, 0)); imageView = new ImageView(context); + imageView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); imageView.setScaleType(ImageView.ScaleType.CENTER); addView(imageView, LayoutHelper.createFrameRelatively(48, 48, Gravity.END | Gravity.CENTER_VERTICAL, 0, 0, 12, 0)); } @@ -82,11 +90,19 @@ public class TextDetailCell extends FrameLayout { } public void setImage(Drawable drawable) { + setImage(drawable, null); + } + + public void setImage(Drawable drawable, CharSequence imageContentDescription) { imageView.setImageDrawable(drawable); + imageView.setFocusable(drawable != null); + imageView.setContentDescription(imageContentDescription); if (drawable == null) { imageView.setBackground(null); + imageView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); } else { - imageView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(48), Color.TRANSPARENT, Theme.getColor(Theme.key_listSelector))); + imageView.setBackground(Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(48), Color.TRANSPARENT, Theme.getColor(Theme.key_listSelector, resourcesProvider))); + imageView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); } int margin = AndroidUtilities.dp(23) + (drawable == null ? 0 : AndroidUtilities.dp(48)); if (LocaleController.isRTL) { @@ -101,7 +117,7 @@ public class TextDetailCell extends FrameLayout { imageView.setOnClickListener(clickListener); } - public void setTextWithEmojiAndValue(String text, CharSequence value, boolean divider) { + public void setTextWithEmojiAndValue(CharSequence text, CharSequence value, boolean divider) { textView.setText(Emoji.replaceEmoji(text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false)); valueTextView.setText(value); needDivider = divider; 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 583d7c54c..cb222380e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextInfoPrivacyCell.java @@ -18,6 +18,7 @@ import android.text.method.LinkMovementMethod; import android.text.style.AbsoluteSizeSpan; import android.util.TypedValue; import android.view.Gravity; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; @@ -26,12 +27,14 @@ import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LinkSpanDrawable; import java.util.ArrayList; public class TextInfoPrivacyCell extends FrameLayout { private TextView textView; + private LinkSpanDrawable.LinkCollector links; private String linkTextColorKey = Theme.key_windowBackgroundWhiteLinkText; private int topPadding = 10; private int bottomPadding = 17; @@ -56,7 +59,7 @@ public class TextInfoPrivacyCell extends FrameLayout { super(context); this.resourcesProvider = resourcesProvider; - textView = new TextView(context) { + textView = new LinkSpanDrawable.LinksTextView(context, links = new LinkSpanDrawable.LinkCollector(this), resourcesProvider) { @Override protected void onDraw(Canvas canvas) { onTextDraw(); @@ -74,6 +77,19 @@ public class TextInfoPrivacyCell extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, 0, padding, 0)); } + @Override + protected void onDraw(Canvas canvas) { + if (links != null) { + canvas.save(); + canvas.translate(textView.getLeft(), textView.getTop()); + if (links.draw(canvas)) { + invalidate(); + } + canvas.restore(); + } + super.onDraw(canvas); + } + protected void onTextDraw() { } @@ -149,7 +165,7 @@ public class TextInfoPrivacyCell extends FrameLayout { public void setEnabled(boolean value, ArrayList animators) { if (animators != null) { - animators.add(ObjectAnimator.ofFloat(textView, "alpha", value ? 1.0f : 0.5f)); + animators.add(ObjectAnimator.ofFloat(textView, View.ALPHA, value ? 1.0f : 0.5f)); } else { textView.setAlpha(value ? 1.0f : 0.5f); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextRadioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextRadioCell.java index 1e0d4f668..90c53c11e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextRadioCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextRadioCell.java @@ -264,9 +264,16 @@ public class TextRadioCell extends FrameLayout { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); - info.setClassName("android.widget.RadioButton"); info.setCheckable(true); info.setChecked(radioButton.isChecked()); info.setContentDescription(radioButton.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff)); + StringBuilder sb = new StringBuilder(); + sb.append(textView.getText()); + if (!TextUtils.isEmpty(valueTextView.getText())) { + sb.append("\n"); + sb.append(valueTextView.getText()); + } + info.setContentDescription(sb); + info.setClassName("android.widget.RadioButton"); } } 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 0a07fcee5..d1419403f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSelectionHelper.java @@ -92,9 +92,10 @@ public abstract class TextSelectionHelper 0 && magnifierYanimated > magnifierY) { - magnifierYanimated = magnifierY; - } else if (magnifierDy < 0 && magnifierYanimated < magnifierY) { - magnifierYanimated = magnifierY; - } - int startLine; int endLine; if (selectedView instanceof ArticleViewer.BlockTableCell) { @@ -420,24 +404,65 @@ public abstract class TextSelectionHelper endLine) { x = endLine; } + + if (magnifierY != newY) { + magnifierY = newY; + magnifierDy = (newY - magnifierYanimated) / 200f; + } + if (magnifierX != x) { + magnifierX = x; + magnifierDx = (x - magnifierXanimated) / 100f; + } + + if (magnifier == null) { + magnifier = new Magnifier(textSelectionOverlay); + magnifierYanimated = magnifierY; + magnifierXanimated = magnifierX; + } + + if (magnifierYanimated != magnifierY) { + magnifierYanimated += magnifierDy * 16; + } + + if (magnifierDy > 0 && magnifierYanimated > magnifierY) { + magnifierYanimated = magnifierY; + } else if (magnifierDy < 0 && magnifierYanimated < magnifierY) { + magnifierYanimated = magnifierY; + } + + if (magnifierXanimated != magnifierX) { + magnifierXanimated += magnifierDx * 16; + } + + if (magnifierDx > 0 && magnifierXanimated > magnifierX) { + magnifierXanimated = magnifierX; + } else if (magnifierDx < 0 && magnifierXanimated < magnifierX) { + magnifierXanimated = magnifierX; + } + magnifier.show( - x, magnifierYanimated + lineHeight * 1.5f + AndroidUtilities.dp(8) + magnifierXanimated, magnifierYanimated + lineHeight * 1.5f + AndroidUtilities.dp(8) ); magnifier.update(); } } + private ValueAnimator handleViewAnimator; + protected void showHandleViews() { if (handleViewProgress == 1f || textSelectionOverlay == null) { return; } - ValueAnimator animator = ValueAnimator.ofFloat(0, 1f); - animator.addUpdateListener(animation -> { + if (handleViewAnimator != null) { + handleViewAnimator.cancel(); + } + handleViewAnimator = ValueAnimator.ofFloat(handleViewProgress, 1f); + handleViewAnimator.addUpdateListener(animation -> { handleViewProgress = (float) animation.getAnimatedValue(); textSelectionOverlay.invalidate(); }); - animator.setDuration(250); - animator.start(); + handleViewAnimator.setDuration((long) (Math.abs(1f - handleViewProgress) * 250)); + handleViewAnimator.start(); } public boolean isSelectionMode() { @@ -488,7 +513,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } else if (Layout.DIR_RIGHT_TO_LEFT == layoutNew.getParagraphDirection(layoutNew.getLineForOffset(newSelection)) || layoutNew.isRtlCharAt(newSelection) || nextWhitespaceLine != currentLine || newSelectionLine != nextWhitespaceLine) { @@ -856,7 +882,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } else { @@ -907,7 +933,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } @@ -945,7 +971,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } else if (Layout.DIR_RIGHT_TO_LEFT == layoutNew.getParagraphDirection(layoutNew.getLineForOffset(newSelection)) || layoutNew.isRtlCharAt(newSelection) || currentLine != nextWhitespaceLine || newSelectionLine != nextWhitespaceLine) { @@ -957,7 +983,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } else { @@ -989,7 +1015,7 @@ public abstract class TextSelectionHelper= Build.VERSION_CODES.O_MR1 && !NekoConfig.disableVibration.Bool()) { - textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); + textSelectionOverlay.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } TextSelectionHelper.this.invalidate(); } @@ -1036,8 +1062,12 @@ public abstract class TextSelectionHelper 0) { end--; CharSequence text = layout.getText(); @@ -1484,63 +1520,100 @@ public abstract class TextSelectionHelper 0 && end < text.length() && !Character.isWhitespace(text.charAt(end - 1))) { - selectionPath.addRect(l, layout.getLineTop(startLine), r, layout.getLineBottom(startLine), Path.Direction.CW); + rect = new Rect(l, layout.getLineTop(startLine), r + halfR, layout.getLineBottom(startLine)); } } - drawLine(layout, startLine, selectionStart, end); - drawLine(layout, endLine, layout.getLineStart(endLine), selectionEnd); + drawLine(layout, startLine, selectionStart, end, !hasStart, true); + if (rect != null) { + AndroidUtilities.rectTmp.set(rect); + selectionPath.addRect(AndroidUtilities.rectTmp, Path.Direction.CW); + } for (int i = startLine + 1; i < endLine; i++) { int s = (int) layout.getLineLeft(i); int e = (int) layout.getLineRight(i); int l = Math.min(s, e); int r = Math.max(s, e); + selectionPath.addRect(l - halfR, layout.getLineTop(i), r + halfR, layout.getLineBottom(i) + 1, Path.Direction.CW); + } + drawLine(layout, endLine, layout.getLineStart(endLine), selectionEnd, true, !hasEnd); + } + boolean restore = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; + if (restore) { + canvas.save(); + } - selectionPath.addRect(l, layout.getLineTop(i) - 1, r, layout.getLineBottom(i) + 1, Path.Direction.CW); + float startLeft = layout.getPrimaryHorizontal(selectionStart), + endRight = layout.getPrimaryHorizontal(selectionEnd); + float startBottom = layout.getLineBottom(startLine), + endBottom = layout.getLineBottom(endLine); + + if (hasStart && hasEnd && startBottom == endBottom && Math.abs(endRight - startLeft) < R) { + float left = Math.min(startLeft, endRight), right = Math.max(startLeft, endRight); + AndroidUtilities.rectTmp2.set((int) left, (int) (startBottom - R), (int) right, (int) startBottom); + AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); + selectionHandlePath.addRect(AndroidUtilities.rectTmp, Path.Direction.CW); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + canvas.clipOutRect(AndroidUtilities.rectTmp2); + } + } else { + if (hasStart) { + AndroidUtilities.rectTmp2.set((int) startLeft, (int) (startBottom - R), (int) Math.min(startLeft + R, layout.getLineRight(startLine)), (int) startBottom); + AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); + selectionHandlePath.addRect(AndroidUtilities.rectTmp, Path.Direction.CW); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AndroidUtilities.rectTmp2.set(AndroidUtilities.rectTmp2.left - (int) R, AndroidUtilities.rectTmp2.top, AndroidUtilities.rectTmp2.right, AndroidUtilities.rectTmp2.bottom); + canvas.clipOutRect(AndroidUtilities.rectTmp2); + } + } + + if (hasEnd) { + AndroidUtilities.rectTmp2.set((int) Math.max(endRight - R, layout.getLineLeft(endLine)), (int) (endBottom - R), (int) endRight, (int) endBottom); + AndroidUtilities.rectTmp.set(AndroidUtilities.rectTmp2); + selectionHandlePath.addRect(AndroidUtilities.rectTmp, Path.Direction.CW); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + canvas.clipOutRect(AndroidUtilities.rectTmp2); + } } } + canvas.drawPath(selectionPath, selectionPaint); - - final float R = cornerRadius * 1.9f; - float startLeft = layout.getPrimaryHorizontal(selectionStart), - endLeft = layout.getPrimaryHorizontal(selectionEnd); - float x, b; - if (selectionStart + 1 < layout.getLineEnd(startLine) && (startLine == endLine || startLine + 1 == endLine && startLeft > endLeft)) { - x = startLeft; - b = layout.getLineBottom(startLine); - tempPath.reset(); - tempPath.moveTo(x + R, b); - tempPath.lineTo(x, b); - tempPath.lineTo(x, b - R); - AndroidUtilities.rectTmp.set(x, b - R, x + R, b); - tempPath.arcTo(AndroidUtilities.rectTmp, 180, -90); - canvas.drawPath(tempPath, selectionHandlePaint); - } - - if (layout.getLineStart(endLine) < selectionEnd) { - x = endLeft; - b = layout.getLineBottom(endLine); - tempPath.reset(); - tempPath.moveTo(x - R, b); - tempPath.lineTo(x, b); - tempPath.lineTo(x, b - R); - AndroidUtilities.rectTmp.set(x - R, b - R, x, b); - tempPath.arcTo(AndroidUtilities.rectTmp, 0, 90); - canvas.drawPath(tempPath, selectionHandlePaint); + if (restore) { + canvas.restore(); + canvas.drawPath(selectionHandlePath, selectionHandlePaint); } } private final ScalablePath tempPath2 = new ScalablePath(); - private void drawLine(StaticLayout layout, int line, int start, int end) { + private void drawLine(StaticLayout layout, int line, int start, int end, boolean padAtStart, boolean padAtEnd) { tempPath2.reset(); layout.getSelectionPath(start, end, tempPath2); + + float sy = 1, cy = 0; if (tempPath2.lastBottom < layout.getLineBottom(line)) { int lineTop = layout.getLineTop(line); int lineBottom = layout.getLineBottom(line); float lineH = lineBottom - lineTop; float lineHWithoutSpacing = tempPath2.lastBottom - lineTop; - tempPath2.scaleY(lineH / lineHWithoutSpacing, lineTop, selectionPath); - } else { - tempPath2.scaleY(1f, 0, selectionPath); + sy = lineH / lineHWithoutSpacing; + cy = lineTop; + } + + for (int i = 0; i < tempPath2.rectsCount; ++i) { + RectF rect = tempPath2.rects.get(i); + rect.set( + (int) (rect.left - (padAtStart ? cornerRadius / 2 : 0)), + (int) ((rect.top - cy) * sy + cy), + (int) (rect.right + (padAtEnd ? cornerRadius / 2 : 0)), + (int) ((rect.bottom - cy) * sy + cy) + ); + selectionPath.addRect(rect.left, rect.top, rect.right, rect.bottom, Path.Direction.CW); + } + + if (tempPath2.rectsCount == 0 && !padAtEnd) { + int left = (int) layout.getPrimaryHorizontal(start), + right = (int) layout.getPrimaryHorizontal(end); + int top = layout.getLineTop(line), bottom = layout.getLineBottom(line); + selectionPath.addRect(left - cornerRadius / 2, top, right + cornerRadius / 4, bottom, Path.Direction.CW); } } @@ -1651,6 +1724,11 @@ public abstract class TextSelectionHelper startViewChildPosition && i < endViewChildPosition) { - drawSelection(canvas, layoutBlock.getLayout(), 0, textLen); + drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false); } } else if (position == startViewPosition && startViewChildPosition == i) { - drawSelection(canvas, layoutBlock.getLayout(), startViewOffset, textLen); + drawSelection(canvas, layoutBlock.getLayout(), startViewOffset, textLen, true, false); } else if (position == endViewPosition && endViewChildPosition == i) { - drawSelection(canvas, layoutBlock.getLayout(), 0, endOffset); + drawSelection(canvas, layoutBlock.getLayout(), 0, endOffset, false, true); } else if (position > startViewPosition && position < endViewPosition || (position == startViewPosition && i > startViewChildPosition) || (position == endViewPosition && i < endViewChildPosition)) { - drawSelection(canvas, layoutBlock.getLayout(), 0, textLen); + drawSelection(canvas, layoutBlock.getLayout(), 0, textLen, false, false); } } } @@ -2765,12 +2850,17 @@ public abstract class TextSelectionHelper recycled; private ArrayList rects = new ArrayList<>(1); private int rectsCount = 0; @Override public void reset() { super.reset(); + if (recycled == null) { + recycled = new ArrayList<>(rects.size()); + } + recycled.addAll(rects); rects.clear(); rectsCount = 0; lastBottom = 0; @@ -2778,28 +2868,20 @@ public abstract class TextSelectionHelper 0) { + rectF = recycled.remove(0); + } else { + rectF = new RectF(); + } + rectF.set(left, top, right, bottom); + rects.add(rectF); rectsCount++; super.addRect(left, top, right, bottom, dir); if (bottom > lastBottom) { lastBottom = bottom; } } - - public void scaleY(float sy, float cy, Path copyTo) { - if (copyTo != null) { - for (int i = 0; i < rectsCount; ++i) { - RectF rect = rects.get(i); - copyTo.addRect(rect.left, (rect.top - cy) * sy + cy, rect.right, (rect.bottom - cy) * sy + cy, Path.Direction.CW); - } - } else { - super.reset(); - for (int i = 0; i < rectsCount; ++i) { - RectF rect = rects.get(i); - super.addRect(rect.left, (rect.top - cy) * sy + cy, rect.right, (rect.bottom - cy) * sy + cy, Path.Direction.CW); - } - } - } } public void setKeyboardSize(int keyboardSize) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java index d2c18c14c..feba18103 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextSettingsCell.java @@ -27,15 +27,20 @@ import android.widget.TextView; 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.BackupImageView; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieImageView; import java.util.ArrayList; public class TextSettingsCell extends FrameLayout { + private Theme.ResourcesProvider resourcesProvider; private TextView textView; - private TextView valueTextView; + private AnimatedTextView valueTextView; + private ImageView imageView; private BackupImageView valueBackupImageView; private ImageView valueImageView; private boolean needDivider; @@ -56,8 +61,17 @@ public class TextSettingsCell extends FrameLayout { this(context, 21); } + public TextSettingsCell(Context context, Theme.ResourcesProvider resourcesProvider) { + this(context, 21, resourcesProvider); + } + public TextSettingsCell(Context context, int padding) { + this(context, padding, null); + } + + public TextSettingsCell(Context context, int padding, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; this.padding = padding; textView = new TextView(context); @@ -67,19 +81,22 @@ public class TextSettingsCell extends FrameLayout { textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, padding, 0, padding, 0)); - valueTextView = new TextView(context); - valueTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - valueTextView.setLines(1); - valueTextView.setMaxLines(1); - valueTextView.setSingleLine(true); - valueTextView.setEllipsize(TextUtils.TruncateAt.END); + valueTextView = new AnimatedTextView(context, true, true, !LocaleController.isRTL); + valueTextView.setAnimationProperties(.55f, 0, 320, CubicBezierInterpolator.EASE_OUT_QUINT); + valueTextView.setTextSize(AndroidUtilities.dp(16)); valueTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL); - valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText)); + valueTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteValueText, resourcesProvider)); addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, padding, 0, padding, 0)); + imageView = new RLottieImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.MULTIPLY)); + imageView.setVisibility(GONE); + addView(imageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 21, 0, 21, 0)); + valueImageView = new ImageView(context); valueImageView.setScaleType(ImageView.ScaleType.CENTER); valueImageView.setVisibility(INVISIBLE); @@ -97,6 +114,10 @@ public class TextSettingsCell extends FrameLayout { valueImageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY)); } + if (imageView.getVisibility() == VISIBLE) { + imageView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); + } + if (valueBackupImageView != null) { valueBackupImageView.measure(MeasureSpec.makeMeasureSpec(valueBackupImageView.getLayoutParams().height, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(valueBackupImageView.getLayoutParams().width, MeasureSpec.EXACTLY)); } @@ -125,7 +146,7 @@ public class TextSettingsCell extends FrameLayout { canDisable = value; } - public TextView getValueTextView() { + public AnimatedTextView getValueTextView() { return valueTextView; } @@ -146,10 +167,14 @@ public class TextSettingsCell extends FrameLayout { } public void setTextAndValue(CharSequence text, CharSequence value, boolean divider) { + setTextAndValue(text, value, false, divider); + } + + public void setTextAndValue(CharSequence text, CharSequence value, boolean animated, boolean divider) { textView.setText(text); valueImageView.setVisibility(INVISIBLE); if (value != null) { - valueTextView.setText(value); + valueTextView.setText(value, animated); valueTextView.setVisibility(VISIBLE); } else { valueTextView.setVisibility(INVISIBLE); @@ -172,6 +197,18 @@ public class TextSettingsCell extends FrameLayout { setWillNotDraw(!divider); } + public void setIcon(int resId) { + MarginLayoutParams params = (MarginLayoutParams) textView.getLayoutParams(); + if (resId == 0) { + imageView.setVisibility(GONE); + params.leftMargin = 0; + } else { + imageView.setImageResource(resId); + imageView.setVisibility(VISIBLE); + params.leftMargin = AndroidUtilities.dp(71); + } + } + public void setEnabled(boolean value, ArrayList animators) { setEnabled(value); if (animators != null) { @@ -210,7 +247,7 @@ public class TextSettingsCell extends FrameLayout { if (drawLoading || drawLoadingProgress != 0) { if (paint == null) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); - paint.setColor(Theme.getColor(Theme.key_dialogSearchBackground)); + paint.setColor(Theme.getColor(Theme.key_dialogSearchBackground, resourcesProvider)); } //LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT; if (incrementLoadingProgress) { @@ -264,6 +301,7 @@ public class TextSettingsCell extends FrameLayout { @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); + info.setText(textView.getText() + (valueTextView != null && valueTextView.getVisibility() == View.VISIBLE ? "\n" + valueTextView.getText() : "")); info.setEnabled(isEnabled()); } 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 35e6e2789..9730f8f99 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ThemePreviewMessagesCell.java @@ -258,6 +258,9 @@ public class ThemePreviewMessagesCell extends LinearLayout { @Override protected void onDraw(Canvas canvas) { Drawable newDrawable = Theme.getCachedWallpaperNonBlocking(); + if (Theme.wallpaperLoadTask != null) { + invalidate(); + } if (newDrawable != backgroundDrawable && newDrawable != null) { if (Theme.isAnimatingColor()) { oldBackgroundDrawable = backgroundDrawable; @@ -274,11 +277,16 @@ public class ThemePreviewMessagesCell extends LinearLayout { if (drawable == null) { continue; } + int alpha; if (a == 1 && oldBackgroundDrawable != null && parentLayout != null) { - drawable.setAlpha((int) (255 * themeAnimationValue)); + alpha = (int) (255 * themeAnimationValue); } else { - drawable.setAlpha(255); + alpha = 255; } + if (alpha <= 0) { + continue; + } + drawable.setAlpha(alpha); if (drawable instanceof ColorDrawable || drawable instanceof GradientDrawable || drawable instanceof MotionBackgroundDrawable) { drawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight()); if (drawable instanceof BackgroundGradientDrawable) { @@ -289,6 +297,7 @@ public class ThemePreviewMessagesCell extends LinearLayout { } } else if (drawable instanceof BitmapDrawable) { BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; + bitmapDrawable.setFilterBitmap(true); if (bitmapDrawable.getTileModeX() == Shader.TileMode.REPEAT) { canvas.save(); float scale = 2.0f / AndroidUtilities.density; 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 74f43465d..81e68b6cc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell.java @@ -23,24 +23,26 @@ import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.DialogObject; -import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.Emoji; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; -import org.telegram.messenger.UserObject; +import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; -import org.telegram.messenger.UserConfig; +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.CheckBox; import org.telegram.ui.Components.CheckBoxSquare; import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.NotificationsSettingsActivity; -public class UserCell extends FrameLayout { +public class UserCell extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { private BackupImageView avatarImageView; private SimpleTextView nameTextView; @@ -50,6 +52,7 @@ public class UserCell extends FrameLayout { private CheckBoxSquare checkBoxBig; private TextView adminTextView; private TextView addButton; + private Theme.ResourcesProvider resourcesProvider; private AvatarDrawable avatarDrawable; private Object currentObject; @@ -74,20 +77,29 @@ public class UserCell extends FrameLayout { private boolean needDivider; public UserCell(Context context, int padding, int checkbox, boolean admin) { - this(context, padding, checkbox, admin, false); + this(context, padding, checkbox, admin, false, null); + } + + public UserCell(Context context, int padding, int checkbox, boolean admin, Theme.ResourcesProvider resourcesProvider) { + this(context, padding, checkbox, admin, false, resourcesProvider); } public UserCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton) { + this(context, padding, checkbox, admin, needAddButton, null); + } + + public UserCell(Context context, int padding, int checkbox, boolean admin, boolean needAddButton, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; int additionalPadding; if (needAddButton) { addButton = new TextView(context); addButton.setGravity(Gravity.CENTER); - addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + addButton.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText, resourcesProvider)); addButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); addButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - addButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + addButton.setBackgroundDrawable(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addButton.setText(LocaleController.getString("Add", R.string.Add)); addButton.setPadding(AndroidUtilities.dp(17), 0, AndroidUtilities.dp(17), 0); addView(addButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 28, Gravity.TOP | (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT), LocaleController.isRTL ? 14 : 0, 15, LocaleController.isRTL ? 0 : 14, 0)); @@ -96,8 +108,8 @@ public class UserCell extends FrameLayout { additionalPadding = 0; } - statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText); - statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText); + statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider); + statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider); avatarDrawable = new AvatarDrawable(); @@ -106,7 +118,7 @@ public class UserCell extends FrameLayout { addView(avatarImageView, LayoutHelper.createFrame(46, 46, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 7 + padding, 6, LocaleController.isRTL ? 7 + padding : 0, 0)); nameTextView = new SimpleTextView(context); - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); nameTextView.setTextSize(16); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); @@ -119,7 +131,7 @@ public class UserCell extends FrameLayout { imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon, resourcesProvider), PorterDuff.Mode.SRC_IN)); imageView.setVisibility(GONE); addView(imageView, LayoutHelper.createFrame(LayoutParams.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 16, 0, LocaleController.isRTL ? 16 : 0, 0)); @@ -129,14 +141,14 @@ public class UserCell extends FrameLayout { } else if (checkbox == 1) { checkBox = new CheckBox(context, R.drawable.round_check2); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); + checkBox.setColor(Theme.getColor(Theme.key_checkbox, resourcesProvider), Theme.getColor(Theme.key_checkboxCheck, resourcesProvider)); addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 37 + padding, 40, LocaleController.isRTL ? 37 + padding : 0, 0)); } if (admin) { adminTextView = new TextView(context); adminTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon)); + adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon, resourcesProvider)); addView(adminTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 23 : 0, 10, LocaleController.isRTL ? 0 : 23, 0)); } @@ -210,6 +222,11 @@ public class UserCell extends FrameLayout { } encryptedChat = ec; currentStatus = status; + try { + if (name != null && nameTextView != null) { + name = Emoji.replaceEmoji(name, nameTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + } + } catch (Exception ignore) {} currentName = name; currentObject = object; currentDrawable = resId; @@ -448,7 +465,20 @@ public class UserCell extends FrameLayout { } else { lastName = ""; } - nameTextView.setText(lastName); + CharSequence name = lastName; + if (name != null) { + try { + name = Emoji.replaceEmoji(lastName, nameTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(18), false); + } catch (Exception ignore) {} + } + nameTextView.setText(name); + } + if (currentUser != null && MessagesController.getInstance(currentAccount).isPremiumUser(currentUser)) { + nameTextView.setRightDrawable(PremiumGradient.getInstance().premiumStarDrawableMini); + nameTextView.setRightDrawableTopPadding(-AndroidUtilities.dp(0.5f)); + } else { + nameTextView.setRightDrawable(null); + nameTextView.setRightDrawableTopPadding(0); } if (currentStatus != null) { statusTextView.setTextColor(statusColor); @@ -486,9 +516,9 @@ public class UserCell extends FrameLayout { avatarImageView.setImageDrawable(avatarDrawable); } - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); if (adminTextView != null) { - adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon)); + adminTextView.setTextColor(Theme.getColor(Theme.key_profile_creatorIcon, resourcesProvider)); } } @@ -521,4 +551,23 @@ public class UserCell extends FrameLayout { info.setClassName("android.widget.CheckBox"); } } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.emojiLoaded) { + nameTextView.invalidate(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java index ff6ef5c23..b3dde2efa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/UserCell2.java @@ -38,6 +38,7 @@ import org.telegram.ui.Components.LayoutHelper; public class UserCell2 extends FrameLayout { + private Theme.ResourcesProvider resourcesProvider; private BackupImageView avatarImageView; private SimpleTextView nameTextView; private SimpleTextView statusTextView; @@ -63,10 +64,15 @@ public class UserCell2 extends FrameLayout { private int statusOnlineColor; public UserCell2(Context context, int padding, int checkbox) { - super(context); + this(context, padding, checkbox, null); + } - statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText); - statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText); + public UserCell2(Context context, int padding, int checkbox, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + statusColor = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText, resourcesProvider); + statusOnlineColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText, resourcesProvider); avatarDrawable = new AvatarDrawable(); @@ -75,7 +81,7 @@ public class UserCell2 extends FrameLayout { addView(avatarImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 7 + padding, 11, LocaleController.isRTL ? 7 + padding : 0, 0)); nameTextView = new SimpleTextView(context); - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); nameTextView.setTextSize(17); nameTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP); addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 20, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 28 + (checkbox == 2 ? 18 : 0) : (68 + padding), 14.5f, LocaleController.isRTL ? (68 + padding) : 28 + (checkbox == 2 ? 18 : 0), 0)); @@ -87,17 +93,17 @@ public class UserCell2 extends FrameLayout { imageView = new ImageView(context); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); + imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon, resourcesProvider), PorterDuff.Mode.SRC_IN)); imageView.setVisibility(GONE); addView(imageView, LayoutHelper.createFrame(LayoutParams.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 0 : 16, 0, LocaleController.isRTL ? 16 : 0, 0)); if (checkbox == 2) { - checkBoxBig = new CheckBoxSquare(context, false); + checkBoxBig = new CheckBoxSquare(context, false, resourcesProvider); addView(checkBoxBig, LayoutHelper.createFrame(18, 18, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.CENTER_VERTICAL, LocaleController.isRTL ? 19 : 0, 0, LocaleController.isRTL ? 0 : 19, 0)); } else if (checkbox == 1) { checkBox = new CheckBox(context, R.drawable.round_check2); checkBox.setVisibility(INVISIBLE); - checkBox.setColor(Theme.getColor(Theme.key_checkbox), Theme.getColor(Theme.key_checkboxCheck)); + checkBox.setColor(Theme.getColor(Theme.key_checkbox, resourcesProvider), Theme.getColor(Theme.key_checkboxCheck, resourcesProvider)); addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 37 + padding, 41, LocaleController.isRTL ? 37 + padding : 0, 0)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java index 7d9a3419a..8d61e086a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/WallpaperCell.java @@ -116,14 +116,16 @@ public class WallpaperCell extends FrameLayout { imageView.getImageReceiver().setBlendMode(null); imageView.getImageReceiver().setGradientBitmap(null); isSelected = object == selectedWallpaper; + int thumbSide = 100, imageSide = 180; + String imageFilter = imageSide + "_" + imageSide, thumbFilter = thumbSide + "_" + thumbSide + "_b"; if (object instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 100); - TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, 320); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, AndroidUtilities.dp(thumbSide)); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.document.thumbs, AndroidUtilities.dp(imageSide)); if (image == thumb) { image = null; } - int size = image != null ? image.size : wallPaper.document.size; + long size = image != null ? image.size : wallPaper.document.size; if (wallPaper.pattern) { int patternColor; if (wallPaper.settings.third_background_color != 0) { @@ -145,16 +147,16 @@ public class WallpaperCell extends FrameLayout { imageView.getImageReceiver().setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(patternColor), PorterDuff.Mode.SRC_IN)); } if (image != null) { - imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), null, "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), imageFilter, ImageLocation.getForDocument(thumb, wallPaper.document), null, "jpg", size, 1, wallPaper); } else { - imageView.setImage(ImageLocation.getForDocument(thumb, wallPaper.document), "100_100", null, null, "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForDocument(thumb, wallPaper.document), imageFilter, null, null, "jpg", size, 1, wallPaper); } imageView.getImageReceiver().setAlpha(Math.abs(wallPaper.settings.intensity) / 100.0f); } else { if (image != null) { - imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), "100_100_b", "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForDocument(image, wallPaper.document), imageFilter, ImageLocation.getForDocument(thumb, wallPaper.document), thumbFilter, "jpg", size, 1, wallPaper); } else { - imageView.setImage(ImageLocation.getForDocument(wallPaper.document), "100_100", ImageLocation.getForDocument(thumb, wallPaper.document), "100_100_b", "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForDocument(wallPaper.document), imageFilter, ImageLocation.getForDocument(thumb, wallPaper.document), thumbFilter, "jpg", size, 1, wallPaper); } } } else if (object instanceof WallpapersListActivity.ColorWallpaper) { @@ -182,11 +184,11 @@ public class WallpaperCell extends FrameLayout { imageView.setImageBitmap(wallPaper.defaultCache); imageView.getImageReceiver().setAlpha(Math.abs(wallPaper.intensity)); } else if (wallPaper.path != null) { - imageView.setImage(wallPaper.path.getAbsolutePath(), "100_100", null); + imageView.setImage(wallPaper.path.getAbsolutePath(), imageFilter, null); } else { TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.pattern.document.thumbs, 100); - int size = thumb != null ? thumb.size : wallPaper.pattern.document.size; - imageView.setImage(ImageLocation.getForDocument(thumb, wallPaper.pattern.document), "100_100", null, null, "jpg", size, 1, wallPaper.pattern); + long size = thumb != null ? thumb.size : wallPaper.pattern.document.size; + imageView.setImage(ImageLocation.getForDocument(thumb, wallPaper.pattern.document), imageFilter, null, null, "jpg", size, 1, wallPaper.pattern); imageView.getImageReceiver().setAlpha(Math.abs(wallPaper.intensity)); if (Build.VERSION.SDK_INT < 29 || wallPaper.gradientColor2 == 0) { imageView.getImageReceiver().setColorFilter(new PorterDuffColorFilter(AndroidUtilities.getPatternColor(patternColor), PorterDuff.Mode.SRC_IN)); @@ -205,9 +207,9 @@ public class WallpaperCell extends FrameLayout { } else if (object instanceof WallpapersListActivity.FileWallpaper) { WallpapersListActivity.FileWallpaper wallPaper = (WallpapersListActivity.FileWallpaper) object; if (wallPaper.originalPath != null) { - imageView.setImage(wallPaper.originalPath.getAbsolutePath(), "100_100", null); + imageView.setImage(wallPaper.originalPath.getAbsolutePath(), imageFilter, null); } else if (wallPaper.path != null) { - imageView.setImage(wallPaper.path.getAbsolutePath(), "100_100", null); + imageView.setImage(wallPaper.path.getAbsolutePath(), imageFilter, null); } else if (Theme.THEME_BACKGROUND_SLUG.equals(wallPaper.slug)) { imageView.setImageDrawable(Theme.getThemedWallpaper(true, imageView)); } else { @@ -216,15 +218,15 @@ public class WallpaperCell extends FrameLayout { } else if (object instanceof MediaController.SearchImage) { MediaController.SearchImage wallPaper = (MediaController.SearchImage) object; if (wallPaper.photo != null) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, 100); - TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, 320); + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, AndroidUtilities.dp(thumbSide)); + TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, AndroidUtilities.dp(imageSide)); if (image == thumb) { image = null; } int size = image != null ? image.size : 0; - imageView.setImage(ImageLocation.getForPhoto(image, wallPaper.photo), "100_100", ImageLocation.getForPhoto(thumb, wallPaper.photo), "100_100_b", "jpg", size, 1, wallPaper); + imageView.setImage(ImageLocation.getForPhoto(image, wallPaper.photo), imageFilter, ImageLocation.getForPhoto(thumb, wallPaper.photo), thumbFilter, "jpg", size, 1, wallPaper); } else { - imageView.setImage(wallPaper.thumbUrl, "100_100", null); + imageView.setImage(wallPaper.thumbUrl, imageFilter, null); } } else { isSelected = false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java index 639ac6b80..5beb69228 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeBioActivity.java @@ -19,6 +19,7 @@ import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -75,7 +76,7 @@ public class ChangeBioActivity extends BaseFragment { }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); fragmentView = new LinearLayout(context); @@ -86,7 +87,15 @@ public class ChangeBioActivity extends BaseFragment { FrameLayout fieldContainer = new FrameLayout(context); linearLayout.addView(fieldContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 24, 24, 20, 0)); - firstNameField = new EditTextBoldCursor(context); + firstNameField = new EditTextBoldCursor(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + Editable s = getEditableText(); + int number = getMessagesController().getAboutLimit() - Character.codePointCount(s, 0, s.length()); + info.setText(getText() + ", " + LocaleController.formatPluralString("PeopleJoinedRemaining", number)); + } + }; firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); firstNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); firstNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -99,7 +108,7 @@ public class ChangeBioActivity extends BaseFragment { firstNameField.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_MULTI_LINE); firstNameField.setImeOptions(EditorInfo.IME_ACTION_DONE); InputFilter[] inputFilters = new InputFilter[1]; - inputFilters[0] = new CodepointsLengthInputFilter(70) { + inputFilters[0] = new CodepointsLengthInputFilter(getMessagesController().getAboutLimit()) { @Override public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { if (source != null && source.length() > 0 && TextUtils.indexOf(source, '\n') == source.length() - 1) { @@ -140,7 +149,7 @@ public class ChangeBioActivity extends BaseFragment { @Override public void afterTextChanged(Editable s) { - checkTextView.setNumber(70 - Character.codePointCount(s, 0, s.length()), true); + checkTextView.setNumber(getMessagesController().getAboutLimit() - Character.codePointCount(s, 0, s.length()), true); } }); @@ -149,10 +158,10 @@ public class ChangeBioActivity extends BaseFragment { checkTextView = new NumberTextView(context); checkTextView.setCenterAlign(true); checkTextView.setTextSize(15); - checkTextView.setNumber(70, false); + checkTextView.setNumber(getMessagesController().getAboutLimit(), false); checkTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText4)); checkTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); - fieldContainer.addView(checkTextView, LayoutHelper.createFrame(20, 20, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT, 0, 4, 4, 0)); + fieldContainer.addView(checkTextView, LayoutHelper.createFrame(26, 20, LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT, 0, 4, 4, 0)); helpTextView = new TextView(context); helpTextView.setFocusable(true); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java index fe77c7fae..4576c44c1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java @@ -43,10 +43,18 @@ public class ChangeNameActivity extends BaseFragment { private View headerLabelView; private View doneButton; + private Theme.ResourcesProvider resourcesProvider; + private final static int done_button = 1; + public ChangeNameActivity(Theme.ResourcesProvider resourcesProvider) { + this.resourcesProvider = resourcesProvider; + } + @Override public View createView(Context context) { + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_avatar_actionBarSelectorBlue, resourcesProvider), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider), false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); actionBar.setTitle(LocaleController.getString("EditName", R.string.EditName)); @@ -65,7 +73,7 @@ public class ChangeNameActivity extends BaseFragment { }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); if (user == null) { @@ -78,10 +86,15 @@ public class ChangeNameActivity extends BaseFragment { ((LinearLayout) fragmentView).setOrientation(LinearLayout.VERTICAL); fragmentView.setOnTouchListener((v, event) -> true); - firstNameField = new EditTextBoldCursor(context); + firstNameField = new EditTextBoldCursor(context) { + @Override + protected Theme.ResourcesProvider getResourcesProvider() { + return resourcesProvider; + } + }; firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - firstNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - firstNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + firstNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourcesProvider)); + firstNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); firstNameField.setBackgroundDrawable(null); firstNameField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); firstNameField.setMaxLines(1); @@ -91,7 +104,7 @@ public class ChangeNameActivity extends BaseFragment { firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT); firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName)); - firstNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + firstNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); firstNameField.setCursorSize(AndroidUtilities.dp(20)); firstNameField.setCursorWidth(1.5f); linearLayout.addView(firstNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 24, 24, 0)); @@ -104,10 +117,15 @@ public class ChangeNameActivity extends BaseFragment { return false; }); - lastNameField = new EditTextBoldCursor(context); + lastNameField = new EditTextBoldCursor(context) { + @Override + protected Theme.ResourcesProvider getResourcesProvider() { + return resourcesProvider; + } + }; lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - lastNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - lastNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + lastNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourcesProvider)); + lastNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); lastNameField.setBackgroundDrawable(null); lastNameField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); lastNameField.setMaxLines(1); @@ -117,7 +135,7 @@ public class ChangeNameActivity extends BaseFragment { lastNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); lastNameField.setImeOptions(EditorInfo.IME_ACTION_DONE); lastNameField.setHint(LocaleController.getString("LastName", R.string.LastName)); - lastNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + lastNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); lastNameField.setCursorSize(AndroidUtilities.dp(20)); lastNameField.setCursorWidth(1.5f); linearLayout.addView(lastNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 16, 24, 0)); @@ -176,6 +194,11 @@ public class ChangeNameActivity extends BaseFragment { }); } + @Override + public Theme.ResourcesProvider getResourceProvider() { + return resourcesProvider; + } + @Override public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { if (isOpen) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java index 8d16143bf..e69de29bb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java @@ -1,1668 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 5.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2018. - */ - -package org.telegram.ui; - -import android.Manifest; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.annotation.SuppressLint; -import android.app.Activity; -import android.app.Dialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.telephony.PhoneNumberUtils; -import android.telephony.TelephonyManager; -import android.text.Editable; -import android.text.InputFilter; -import android.text.InputType; -import android.text.TextUtils; -import android.text.TextWatcher; -import android.util.TypedValue; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.View; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.inputmethod.EditorInfo; -import android.widget.AdapterView; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -import org.telegram.PhoneFormat.PhoneFormat; -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.MessagesStorage; -import org.telegram.messenger.NotificationCenter; -import org.telegram.messenger.R; -import org.telegram.messenger.UserConfig; -import org.telegram.tgnet.ConnectionsManager; -import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.ActionBarMenu; -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.Components.AlertsCreator; -import org.telegram.ui.Components.EditTextBoldCursor; -import org.telegram.ui.Components.HintEditText; -import org.telegram.ui.Components.LayoutHelper; -import org.telegram.ui.Components.RLottieDrawable; -import org.telegram.ui.Components.RLottieImageView; -import org.telegram.ui.Components.SlideView; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Timer; -import java.util.TimerTask; - -public class ChangePhoneActivity extends BaseFragment { - - private int currentViewNum = 0; - private SlideView[] views = new SlideView[5]; - private AlertDialog progressDialog; - private Dialog permissionsDialog; - private ArrayList permissionsItems = new ArrayList<>(); - private boolean checkPermissions = true; - private View doneButton; - - private int scrollHeight; - - private final static int done_button = 1; - - private static class ProgressView extends View { - - private Paint paint = new Paint(); - private Paint paint2 = new Paint(); - private float progress; - - public ProgressView(Context context) { - super(context); - paint.setColor(Theme.getColor(Theme.key_login_progressInner)); - paint2.setColor(Theme.getColor(Theme.key_login_progressOuter)); - } - - public void setProgress(float value) { - progress = value; - invalidate(); - } - - @Override - protected void onDraw(Canvas canvas) { - int start = (int) (getMeasuredWidth() * progress); - canvas.drawRect(0, 0, start, getMeasuredHeight(), paint2); - canvas.drawRect(start, 0, getMeasuredWidth(), getMeasuredHeight(), paint); - } - } - - @Override - public void onFragmentDestroy() { - super.onFragmentDestroy(); - for (int a = 0; a < views.length; a++) { - if (views[a] != null) { - views[a].onDestroyActivity(); - } - } - if (progressDialog != null) { - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e(e); - } - progressDialog = null; - } - AndroidUtilities.removeAdjustResize(getParentActivity(), classGuid); - } - - @Override - public View createView(Context context) { - actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName)); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); - actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { - @Override - public void onItemClick(int id) { - if (id == done_button) { - views[currentViewNum].onNextPressed(null); - } else if (id == -1) { - finishFragment(); - } - } - }); - - ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); - - ScrollView scrollView = new ScrollView(context) { - @Override - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { - if (currentViewNum == 1 || currentViewNum == 2 || currentViewNum == 4) { - rectangle.bottom += AndroidUtilities.dp(40); - } - return super.requestChildRectangleOnScreen(child, rectangle, immediate); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - scrollHeight = MeasureSpec.getSize(heightMeasureSpec) - AndroidUtilities.dp(30); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - }; - scrollView.setFillViewport(true); - fragmentView = scrollView; - - FrameLayout frameLayout = new FrameLayout(context); - scrollView.addView(frameLayout, LayoutHelper.createScroll(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT)); - - views[0] = new PhoneView(context); - views[1] = new LoginActivitySmsView(context, 1); - views[2] = new LoginActivitySmsView(context, 2); - views[3] = new LoginActivitySmsView(context, 3); - views[4] = new LoginActivitySmsView(context, 4); - - for (int a = 0; a < views.length; a++) { - views[a].setVisibility(a == 0 ? View.VISIBLE : View.GONE); - frameLayout.addView(views[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, a == 0 ? LayoutHelper.WRAP_CONTENT : LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 26 : 18, 30, AndroidUtilities.isTablet() ? 26 : 18, 0)); - } - - actionBar.setTitle(views[0].getHeaderName()); - - return fragmentView; - } - - @Override - public void onResume() { - super.onResume(); - AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); - } - - @Override - public void onRequestPermissionsResultFragment(int requestCode, String[] permissions, int[] grantResults) { - if (requestCode == 6) { - checkPermissions = false; - if (currentViewNum == 0) { - views[currentViewNum].onNextPressed(null); - } - } - } - - @Override - protected void onDialogDismiss(Dialog dialog) { - if (Build.VERSION.SDK_INT >= 23 && dialog == permissionsDialog && !permissionsItems.isEmpty()) { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); - } - } - - @Override - public boolean onBackPressed() { - if (currentViewNum == 0) { - for (int a = 0; a < views.length; a++) { - if (views[a] != null) { - views[a].onDestroyActivity(); - } - } - return true; - } else { - if (views[currentViewNum].onBackPressed(false)) { - setPage(0, true, null, true); - } - } - return false; - } - - @Override - public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { - if (isOpen) { - views[currentViewNum].onShow(); - } - } - - public void needShowProgress() { - if (getParentActivity() == null || getParentActivity().isFinishing() || progressDialog != null) { - return; - } - progressDialog = new AlertDialog(getParentActivity(), 3); - progressDialog.setCanCancel(false); - progressDialog.show(); - } - - public void needHideProgress() { - if (progressDialog == null) { - return; - } - try { - progressDialog.dismiss(); - } catch (Exception e) { - FileLog.e(e); - } - progressDialog = null; - } - - public void setPage(int page, boolean animated, Bundle params, boolean back) { - if (page == 3) { - doneButton.setVisibility(View.GONE); - } else { - if (page == 0) { - checkPermissions = true; - } - doneButton.setVisibility(View.VISIBLE); - } - final SlideView outView = views[currentViewNum]; - final SlideView newView = views[page]; - currentViewNum = page; - - newView.setParams(params, false); - actionBar.setTitle(newView.getHeaderName()); - newView.onShow(); - newView.setX(back ? -AndroidUtilities.displaySize.x : AndroidUtilities.displaySize.x); - - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); - animatorSet.setDuration(300); - animatorSet.playTogether( - ObjectAnimator.ofFloat(outView, "translationX", back ? AndroidUtilities.displaySize.x : -AndroidUtilities.displaySize.x), - ObjectAnimator.ofFloat(newView, "translationX", 0)); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - newView.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animator animation) { - outView.setVisibility(View.GONE); - outView.setX(0); - } - }); - animatorSet.start(); - } - - private void fillNextCodeParams(Bundle params, TLRPC.TL_auth_sentCode res) { - params.putString("phoneHash", res.phone_code_hash); - if (res.next_type instanceof TLRPC.TL_auth_codeTypeCall) { - params.putInt("nextType", 4); - } else if (res.next_type instanceof TLRPC.TL_auth_codeTypeFlashCall) { - params.putInt("nextType", 3); - } else if (res.next_type instanceof TLRPC.TL_auth_codeTypeSms) { - params.putInt("nextType", 2); - } - if (res.type instanceof TLRPC.TL_auth_sentCodeTypeApp) { - params.putInt("type", 1); - params.putInt("length", res.type.length); - setPage(1, true, params, false); - } else { - if (res.timeout == 0) { - res.timeout = 60; - } - params.putInt("timeout", res.timeout * 1000); - if (res.type instanceof TLRPC.TL_auth_sentCodeTypeCall) { - params.putInt("type", 4); - params.putInt("length", res.type.length); - setPage(4, true, params, false); - } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeFlashCall) { - params.putInt("type", 3); - params.putString("pattern", res.type.pattern); - setPage(3, true, params, false); - } else if (res.type instanceof TLRPC.TL_auth_sentCodeTypeSms) { - params.putInt("type", 2); - params.putInt("length", res.type.length); - setPage(2, true, params, false); - } - } - } - - public class PhoneView extends SlideView implements AdapterView.OnItemSelectedListener { - - private EditTextBoldCursor codeField; - private HintEditText phoneField; - private TextView countryButton; - private View view; - private TextView textView; - private TextView textView2; - - private int countryState = 0; - - private ArrayList countriesArray = new ArrayList<>(); - private HashMap countriesMap = new HashMap<>(); - private HashMap codesMap = new HashMap<>(); - private HashMap phoneFormatMap = new HashMap<>(); - - private boolean ignoreSelection = false; - private boolean ignoreOnTextChange = false; - private boolean ignoreOnPhoneChange = false; - private boolean nextPressed = false; - - public PhoneView(Context context) { - super(context); - - setOrientation(VERTICAL); - - countryButton = new TextView(context); - countryButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - countryButton.setPadding(AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4), AndroidUtilities.dp(4)); - countryButton.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - countryButton.setMaxLines(1); - countryButton.setSingleLine(true); - countryButton.setEllipsize(TextUtils.TruncateAt.END); - countryButton.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_HORIZONTAL); - countryButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), 7)); - addView(countryButton, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 0, 0, 0, 14)); - countryButton.setOnClickListener(view -> { - CountrySelectActivity fragment = new CountrySelectActivity(true); - fragment.setCountrySelectActivityDelegate((country) -> { - selectCountry(country.name); - AndroidUtilities.runOnUIThread(() -> AndroidUtilities.showKeyboard(phoneField), 300); - phoneField.requestFocus(); - phoneField.setSelection(phoneField.length()); - }); - presentFragment(fragment); - }); - - view = new View(context); - view.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayLine)); - addView(view, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 1, 4, -17.5f, 4, 0)); - - LinearLayout linearLayout = new LinearLayout(context); - linearLayout.setOrientation(HORIZONTAL); - addView(linearLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 20, 0, 0)); - - textView = new TextView(context); - textView.setText("+"); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - - codeField = new EditTextBoldCursor(context); - codeField.setInputType(InputType.TYPE_CLASS_PHONE); - codeField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - codeField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - codeField.setCursorSize(AndroidUtilities.dp(20)); - codeField.setCursorWidth(1.5f); - codeField.setBackgroundDrawable(null); - codeField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); - codeField.setPadding(AndroidUtilities.dp(10), 0, 0, 0); - codeField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - codeField.setMaxLines(1); - codeField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - codeField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - InputFilter[] inputFilters = new InputFilter[1]; - inputFilters[0] = new InputFilter.LengthFilter(5); - codeField.setFilters(inputFilters); - linearLayout.addView(codeField, LayoutHelper.createLinear(55, 36, -9, 0, 16, 0)); - codeField.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) { - - } - - @Override - public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) { - - } - - @Override - public void afterTextChanged(Editable editable) { - if (ignoreOnTextChange) { - return; - } - ignoreOnTextChange = true; - String text = PhoneFormat.stripExceptNumbers(codeField.getText().toString()); - codeField.setText(text); - if (text.length() == 0) { - countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); - phoneField.setHintText(null); - countryState = 1; - } else { - String country; - boolean ok = false; - String textToSet = null; - if (text.length() > 4) { - ignoreOnTextChange = true; - for (int a = 4; a >= 1; a--) { - String sub = text.substring(0, a); - country = codesMap.get(sub); - if (country != null) { - ok = true; - textToSet = text.substring(a) + phoneField.getText().toString(); - codeField.setText(text = sub); - break; - } - } - if (!ok) { - ignoreOnTextChange = true; - textToSet = text.substring(1) + phoneField.getText().toString(); - codeField.setText(text = text.substring(0, 1)); - } - } - country = codesMap.get(text); - if (country != null) { - int index = countriesArray.indexOf(country); - if (index != -1) { - ignoreSelection = true; - countryButton.setText(countriesArray.get(index)); - String hint = phoneFormatMap.get(text); - phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); - countryState = 0; - } else { - countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); - phoneField.setHintText(null); - countryState = 2; - } - } else { - countryButton.setText(LocaleController.getString("WrongCountry", R.string.WrongCountry)); - phoneField.setHintText(null); - countryState = 2; - } - if (!ok) { - codeField.setSelection(codeField.getText().length()); - } - if (textToSet != null) { - phoneField.requestFocus(); - phoneField.setText(textToSet); - phoneField.setSelection(phoneField.length()); - } - } - ignoreOnTextChange = false; - } - }); - codeField.setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_NEXT) { - phoneField.requestFocus(); - phoneField.setSelection(phoneField.length()); - return true; - } - return false; - }); - - phoneField = new HintEditText(context); - phoneField.setInputType(InputType.TYPE_CLASS_PHONE); - phoneField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - phoneField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - phoneField.setBackgroundDrawable(null); - phoneField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); - phoneField.setPadding(0, 0, 0, 0); - phoneField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - phoneField.setCursorSize(AndroidUtilities.dp(20)); - phoneField.setCursorWidth(1.5f); - phoneField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - phoneField.setMaxLines(1); - phoneField.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL); - phoneField.setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - linearLayout.addView(phoneField, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36)); - phoneField.addTextChangedListener(new TextWatcher() { - - private int characterAction = -1; - private int actionPosition; - - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - if (count == 0 && after == 1) { - characterAction = 1; - } else if (count == 1 && after == 0) { - if (s.charAt(start) == ' ' && start > 0) { - characterAction = 3; - actionPosition = start - 1; - } else { - characterAction = 2; - } - } else { - characterAction = -1; - } - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - if (ignoreOnPhoneChange) { - return; - } - int start = phoneField.getSelectionStart(); - String phoneChars = "0123456789"; - String str = phoneField.getText().toString(); - if (characterAction == 3) { - str = str.substring(0, actionPosition) + str.substring(actionPosition + 1); - start--; - } - StringBuilder builder = new StringBuilder(str.length()); - for (int a = 0; a < str.length(); a++) { - String ch = str.substring(a, a + 1); - if (phoneChars.contains(ch)) { - builder.append(ch); - } - } - ignoreOnPhoneChange = true; - String hint = phoneField.getHintText(); - if (hint != null) { - for (int a = 0; a < builder.length(); a++) { - if (a < hint.length()) { - if (hint.charAt(a) == ' ') { - builder.insert(a, ' '); - a++; - if (start == a && characterAction != 2 && characterAction != 3) { - start++; - } - } - } else { - builder.insert(a, ' '); - if (start == a + 1 && characterAction != 2 && characterAction != 3) { - start++; - } - break; - } - } - } - phoneField.setText(builder); - if (start >= 0) { - phoneField.setSelection(Math.min(start, phoneField.length())); - } - phoneField.onTextChange(); - ignoreOnPhoneChange = false; - } - }); - phoneField.setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_NEXT) { - onNextPressed(null); - return true; - } - return false; - }); - phoneField.setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KeyEvent.KEYCODE_DEL && phoneField.length() == 0) { - codeField.requestFocus(); - codeField.setSelection(codeField.length()); - codeField.dispatchKeyEvent(event); - return true; - } - return false; - }); - - textView2 = new TextView(context); - textView2.setText(LocaleController.getString("ChangePhoneHelp", R.string.ChangePhoneHelp)); - textView2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); - textView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView2.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - textView2.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - addView(textView2, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 28, 0, 10)); - - HashMap languageMap = new HashMap<>(); - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(getResources().getAssets().open("countries.txt"))); - String line; - while ((line = reader.readLine()) != null) { - String[] args = line.split(";"); - countriesArray.add(0, args[2]); - countriesMap.put(args[2], args[0]); - codesMap.put(args[0], args[2]); - if (args.length > 3) { - phoneFormatMap.put(args[0], args[3]); - } - languageMap.put(args[1], args[2]); - } - reader.close(); - } catch (Exception e) { - FileLog.e(e); - } - - Collections.sort(countriesArray, String::compareTo); - - String country = null; - - try { - TelephonyManager telephonyManager = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); - if (telephonyManager != null) { - country = telephonyManager.getSimCountryIso().toUpperCase(); - } - } catch (Exception e) { - FileLog.e(e); - } - - if (country != null) { - String countryName = languageMap.get(country); - if (countryName != null) { - int index = countriesArray.indexOf(countryName); - if (index != -1) { - codeField.setText(countriesMap.get(countryName)); - countryState = 0; - } - } - } - if (codeField.length() == 0) { - countryButton.setText(LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); - phoneField.setHintText(null); - countryState = 1; - } - - if (codeField.length() != 0) { - AndroidUtilities.showKeyboard(phoneField); - phoneField.requestFocus(); - phoneField.setSelection(phoneField.length()); - } else { - AndroidUtilities.showKeyboard(codeField); - codeField.requestFocus(); - } - } - - public void selectCountry(String name) { - int index = countriesArray.indexOf(name); - if (index != -1) { - ignoreOnTextChange = true; - String code = countriesMap.get(name); - codeField.setText(code); - countryButton.setText(name); - String hint = phoneFormatMap.get(code); - phoneField.setHintText(hint != null ? hint.replace('X', '–') : null); - countryState = 0; - ignoreOnTextChange = false; - } - } - - @Override - public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - if (ignoreSelection) { - ignoreSelection = false; - return; - } - ignoreOnTextChange = true; - String str = countriesArray.get(i); - codeField.setText(countriesMap.get(str)); - ignoreOnTextChange = false; - } - - @Override - public void onCancelPressed() { - nextPressed = false; - } - - @Override - public void onNothingSelected(AdapterView adapterView) { - - } - - @Override - public void onNextPressed(String code) { - if (getParentActivity() == null || nextPressed) { - return; - } - TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); - boolean simcardAvailable = tm.getSimState() != TelephonyManager.SIM_STATE_ABSENT && tm.getPhoneType() != TelephonyManager.PHONE_TYPE_NONE; - boolean allowCall = true; - if (Build.VERSION.SDK_INT >= 23 && simcardAvailable) { - allowCall = getParentActivity().checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED; - if (checkPermissions) { - permissionsItems.clear(); - if (!allowCall) { - permissionsItems.add(Manifest.permission.READ_PHONE_STATE); - } - if (!permissionsItems.isEmpty()) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - if (preferences.getBoolean("firstlogin", true) || getParentActivity().shouldShowRequestPermissionRationale(Manifest.permission.READ_PHONE_STATE)) { - preferences.edit().putBoolean("firstlogin", false).commit(); - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - builder.setMessage(LocaleController.getString("AllowReadCall", R.string.AllowReadCall)); - permissionsDialog = showDialog(builder.create()); - } else { - getParentActivity().requestPermissions(permissionsItems.toArray(new String[0]), 6); - } - return; - } - } - } - - if (countryState == 1) { - AlertsCreator.showSimpleAlert(ChangePhoneActivity.this, LocaleController.getString("ChooseCountry", R.string.ChooseCountry)); - return; - } - if (codeField.length() == 0) { - AlertsCreator.showSimpleAlert(ChangePhoneActivity.this, LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); - return; - } - final TLRPC.TL_account_sendChangePhoneCode req = new TLRPC.TL_account_sendChangePhoneCode(); - String phone = PhoneFormat.stripExceptNumbers("" + codeField.getText() + phoneField.getText()); - req.phone_number = phone; - req.settings = new TLRPC.TL_codeSettings(); - req.settings.allow_flashcall = simcardAvailable && allowCall; - req.settings.allow_app_hash = ApplicationLoader.hasPlayServices; - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); - if (req.settings.allow_flashcall) { - try { - @SuppressLint("HardwareIds") String number = tm.getLine1Number(); - if (!TextUtils.isEmpty(number)) { - req.settings.current_number = PhoneNumberUtils.compare(phone, number); - if (!req.settings.current_number) { - req.settings.allow_flashcall = false; - } - } else { - req.settings.current_number = false; - } - } catch (Exception e) { - req.settings.allow_flashcall = false; - FileLog.e(e); - } - } - - final Bundle params = new Bundle(); - params.putString("phone", "+" + codeField.getText() + " " + phoneField.getText()); - try { - params.putString("ephone", "+" + PhoneFormat.stripExceptNumbers(codeField.getText().toString()) + " " + PhoneFormat.stripExceptNumbers(phoneField.getText().toString())); - } catch (Exception e) { - FileLog.e(e); - params.putString("ephone", "+" + phone); - } - params.putString("phoneFormated", phone); - nextPressed = true; - needShowProgress(); - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - nextPressed = false; - if (error == null) { - fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); - } else { - AlertsCreator.processError(currentAccount, error, ChangePhoneActivity.this, req, params.getString("phone")); - } - needHideProgress(); - }), ConnectionsManager.RequestFlagFailOnServerErrors); - } - - @Override - public void onShow() { - super.onShow(); - if (phoneField != null) { - if (codeField.length() != 0) { - AndroidUtilities.showKeyboard(phoneField); - phoneField.requestFocus(); - phoneField.setSelection(phoneField.length()); - } else { - AndroidUtilities.showKeyboard(codeField); - codeField.requestFocus(); - } - } - } - - @Override - public String getHeaderName() { - return LocaleController.getString("ChangePhoneNewNumber", R.string.ChangePhoneNewNumber); - } - } - - public class LoginActivitySmsView extends SlideView implements NotificationCenter.NotificationCenterDelegate { - - private String phone; - private String phoneHash; - private String requestPhone; - private String emailPhone; - private LinearLayout codeFieldContainer; - private EditTextBoldCursor[] codeField; - private TextView confirmTextView; - private TextView titleTextView; - private ImageView blackImageView; - private RLottieImageView blueImageView; - private TextView timeText; - private TextView problemText; - private Bundle currentParams; - private ProgressView progressView; - - RLottieDrawable hintDrawable; - - private Timer timeTimer; - private Timer codeTimer; - private final Object timerSync = new Object(); - private int time = 60000; - private int codeTime = 15000; - private double lastCurrentTime; - private double lastCodeTime; - private boolean ignoreOnTextChange; - private boolean waitingForEvent; - private boolean nextPressed; - private String lastError = ""; - private int currentType; - private int nextType; - private String pattern = "*"; - private int length; - private int timeout; - - public LoginActivitySmsView(Context context, final int type) { - super(context); - - currentType = type; - setOrientation(VERTICAL); - - confirmTextView = new TextView(context); - confirmTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); - confirmTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - confirmTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - - titleTextView = new TextView(context); - titleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - - if (currentType == 3) { - confirmTextView.setGravity(Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - FrameLayout frameLayout = new FrameLayout(context); - addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - - ImageView imageView = new ImageView(context); - imageView.setImageResource(R.drawable.phone_activate); - if (LocaleController.isRTL) { - frameLayout.addView(imageView, LayoutHelper.createFrame(64, 76, Gravity.LEFT | Gravity.CENTER_VERTICAL, 2, 2, 0, 0)); - frameLayout.addView(confirmTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 64 + 18, 0, 0, 0)); - } else { - frameLayout.addView(confirmTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 0, 64 + 18, 0)); - frameLayout.addView(imageView, LayoutHelper.createFrame(64, 76, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 2, 0, 2)); - } - } else { - confirmTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - - FrameLayout frameLayout = new FrameLayout(context); - addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); - - if (currentType == 1) { - blackImageView = new ImageView(context); - blackImageView.setImageResource(R.drawable.sms_devices); - blackImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); - frameLayout.addView(blackImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); - - blueImageView = new RLottieImageView(context); - blueImageView.setImageResource(R.drawable.sms_bubble); - blueImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chats_actionBackground), PorterDuff.Mode.SRC_IN)); - frameLayout.addView(blueImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); - - titleTextView.setText(LocaleController.getString("SentAppCodeTitle", R.string.SentAppCodeTitle)); - } else { - blueImageView = new RLottieImageView(context); - hintDrawable = new RLottieDrawable(R.raw.sms_incoming_info, "" + R.raw.sms_incoming_info, AndroidUtilities.dp(64), AndroidUtilities.dp(64), true, null); - hintDrawable.setLayerColor("Bubble.**", Theme.getColor(Theme.key_chats_actionBackground)); - hintDrawable.setLayerColor("Phone.**", Theme.getColor(Theme.key_chats_actionBackground)); - blueImageView.setAnimation(hintDrawable); - - frameLayout.addView(blueImageView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); - - titleTextView.setText(LocaleController.getString("SentSmsCodeTitle", R.string.SentSmsCodeTitle)); - } - addView(titleTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 18, 0, 0)); - addView(confirmTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 17, 0, 0)); - } - - codeFieldContainer = new LinearLayout(context); - codeFieldContainer.setOrientation(HORIZONTAL); - addView(codeFieldContainer, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36, Gravity.CENTER_HORIZONTAL)); - if (currentType == 3) { - codeFieldContainer.setVisibility(GONE); - } - - timeText = new TextView(context) { - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.AT_MOST)); - } - }; - timeText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText6)); - timeText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - if (currentType == 3) { - timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - addView(timeText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); - - progressView = new ProgressView(context); - timeText.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); - addView(progressView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3, 0, 12, 0, 0)); - } else { - timeText.setPadding(0, AndroidUtilities.dp(2), 0, AndroidUtilities.dp(10)); - timeText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - timeText.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - addView(timeText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); - } - - problemText = new TextView(context) { - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.AT_MOST)); - } - }; - problemText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)); - problemText.setLineSpacing(AndroidUtilities.dp(2), 1.0f); - problemText.setPadding(0, AndroidUtilities.dp(2), 0, AndroidUtilities.dp(10)); - problemText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - problemText.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); - if (currentType == 1) { - problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); - } else { - problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); - } - addView(problemText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); - problemText.setOnClickListener(v -> { - if (nextPressed) { - return; - } - boolean email = nextType == 4 && currentType == 2 || nextType == 0; - if (!email) { - resendCode(); - } else { - try { - PackageInfo pInfo = ApplicationLoader.applicationContext.getPackageManager().getPackageInfo(ApplicationLoader.applicationContext.getPackageName(), 0); - String version = String.format(Locale.US, "%s (%d)", pInfo.versionName, pInfo.versionCode); - - Intent mailer = new Intent(Intent.ACTION_SENDTO); - mailer.setData(Uri.parse("mailto:")); - mailer.putExtra(Intent.EXTRA_EMAIL, new String[]{"sms@telegram.org"}); - mailer.putExtra(Intent.EXTRA_SUBJECT, "Android registration/login issue " + version + " " + emailPhone); - mailer.putExtra(Intent.EXTRA_TEXT, "Phone: " + requestPhone + "\nApp version: " + version + "\nOS version: SDK " + Build.VERSION.SDK_INT + "\nDevice Name: " + Build.MANUFACTURER + Build.MODEL + "\nLocale: " + Locale.getDefault() + "\nError: " + lastError); - getContext().startActivity(Intent.createChooser(mailer, "Send email...")); - } catch (Exception e) { - AlertsCreator.showSimpleAlert(ChangePhoneActivity.this, LocaleController.getString("NoMailInstalled", R.string.NoMailInstalled)); - } - } - }); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - if (currentType != 3 && blueImageView != null) { - int innerHeight = blueImageView.getMeasuredHeight() + titleTextView.getMeasuredHeight() + confirmTextView.getMeasuredHeight() + AndroidUtilities.dp(18 + 17); - int requiredHeight = AndroidUtilities.dp(80); - int maxHeight = AndroidUtilities.dp(291); - if (scrollHeight - innerHeight < requiredHeight) { - setMeasuredDimension(getMeasuredWidth(), innerHeight + requiredHeight); - } else { - setMeasuredDimension(getMeasuredWidth(), Math.min(scrollHeight, maxHeight)); - } - } - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - super.onLayout(changed, l, t, r, b); - if (currentType != 3 && blueImageView != null) { - int bottom = confirmTextView.getBottom(); - int height = getMeasuredHeight() - bottom; - - int h; - if (problemText.getVisibility() == VISIBLE) { - h = problemText.getMeasuredHeight(); - t = bottom + height - h; - problemText.layout(problemText.getLeft(), t, problemText.getRight(), t + h); - } else if (timeText.getVisibility() == VISIBLE) { - h = timeText.getMeasuredHeight(); - t = bottom + height - h; - timeText.layout(timeText.getLeft(), t, timeText.getRight(), t + h); - } else { - t = bottom + height; - } - - height = t - bottom; - h = codeFieldContainer.getMeasuredHeight(); - t = (height - h) / 2 + bottom; - codeFieldContainer.layout(codeFieldContainer.getLeft(), t, codeFieldContainer.getRight(), t + h); - } - } - - private void resendCode() { - final Bundle params = new Bundle(); - params.putString("phone", phone); - params.putString("ephone", emailPhone); - params.putString("phoneFormated", requestPhone); - - nextPressed = true; - needShowProgress(); - - final TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); - req.phone_number = requestPhone; - req.phone_code_hash = phoneHash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - nextPressed = false; - if (error == null) { - fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); - } else { - AlertDialog dialog = (AlertDialog) AlertsCreator.processError(currentAccount, error, ChangePhoneActivity.this, req); - if (dialog != null && error.text.contains("PHONE_CODE_EXPIRED")) { - dialog.setPositiveButtonListener((dialog1, which) -> { - onBackPressed(true); - finishFragment(); - }); - } - } - needHideProgress(); - }), ConnectionsManager.RequestFlagFailOnServerErrors); - } - - @Override - public String getHeaderName() { - if (currentType == 1) { - return phone; - } else { - return LocaleController.getString("YourCode", R.string.YourCode); - } - } - - @Override - public boolean needBackButton() { - return true; - } - - @Override - public void onCancelPressed() { - nextPressed = false; - } - - @Override - public void setParams(Bundle params, boolean restore) { - if (params == null) { - return; - } - waitingForEvent = true; - if (currentType == 2) { - AndroidUtilities.setWaitingForSms(true); - NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == 3) { - AndroidUtilities.setWaitingForCall(true); - NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReceiveCall); - } - - currentParams = params; - phone = params.getString("phone"); - emailPhone = params.getString("ephone"); - requestPhone = params.getString("phoneFormated"); - phoneHash = params.getString("phoneHash"); - timeout = time = params.getInt("timeout"); - nextType = params.getInt("nextType"); - pattern = params.getString("pattern"); - length = params.getInt("length"); - if (length == 0) { - length = 5; - } - - if (codeField == null || codeField.length != length) { - codeField = new EditTextBoldCursor[length]; - for (int a = 0; a < length; a++) { - final int num = a; - codeField[a] = new EditTextBoldCursor(getContext()); - codeField[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - codeField[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - codeField[a].setCursorSize(AndroidUtilities.dp(20)); - codeField[a].setCursorWidth(1.5f); - - Drawable pressedDrawable = getResources().getDrawable(R.drawable.search_dark_activated).mutate(); - pressedDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), PorterDuff.Mode.SRC_IN)); - - codeField[a].setBackgroundDrawable(pressedDrawable); - codeField[a].setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); - codeField[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); - codeField[a].setMaxLines(1); - codeField[a].setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - codeField[a].setPadding(0, 0, 0, 0); - codeField[a].setGravity(Gravity.CENTER_HORIZONTAL | Gravity.TOP); - if (currentType == 3) { - codeField[a].setEnabled(false); - codeField[a].setInputType(InputType.TYPE_NULL); - codeField[a].setVisibility(GONE); - } else { - codeField[a].setInputType(InputType.TYPE_CLASS_PHONE); - } - codeFieldContainer.addView(codeField[a], LayoutHelper.createLinear(34, 36, Gravity.CENTER_HORIZONTAL, 0, 0, a != length - 1 ? 7 : 0, 0)); - codeField[a].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 (ignoreOnTextChange) { - return; - } - int len = s.length(); - if (len >= 1) { - if (len > 1) { - String text = s.toString(); - ignoreOnTextChange = true; - for (int a = 0; a < Math.min(length - num, len); a++) { - if (a == 0) { - s.replace(0, len, text.substring(a, a + 1)); - } else { - codeField[num + a].setText(text.substring(a, a + 1)); - } - } - ignoreOnTextChange = false; - } - - if (num != length - 1) { - codeField[num + 1].setSelection(codeField[num + 1].length()); - codeField[num + 1].requestFocus(); - } - if ((num == length - 1 || num == length - 2 && len >= 2) && getCode().length() == length) { - onNextPressed(null); - } - } - } - }); - codeField[a].setOnKeyListener((v, keyCode, event) -> { - if (keyCode == KeyEvent.KEYCODE_DEL && codeField[num].length() == 0 && num > 0) { - codeField[num - 1].setSelection(codeField[num - 1].length()); - codeField[num - 1].requestFocus(); - codeField[num - 1].dispatchKeyEvent(event); - return true; - } - return false; - }); - codeField[a].setOnEditorActionListener((textView, i, keyEvent) -> { - if (i == EditorInfo.IME_ACTION_NEXT) { - onNextPressed(null); - return true; - } - return false; - }); - } - } else { - for (int a = 0; a < codeField.length; a++) { - codeField[a].setText(""); - } - } - - if (progressView != null) { - progressView.setVisibility(nextType != 0 ? VISIBLE : GONE); - } - - if (phone == null) { - return; - } - - String number = PhoneFormat.getInstance().format(phone); - CharSequence str = ""; - if (currentType == 1) { - str = AndroidUtilities.replaceTags(LocaleController.getString("SentAppCode", R.string.SentAppCode)); - } else if (currentType == 2) { - str = AndroidUtilities.replaceTags(LocaleController.formatString("SentSmsCode", R.string.SentSmsCode, LocaleController.addNbsp(number))); - } else if (currentType == 3) { - str = AndroidUtilities.replaceTags(LocaleController.formatString("SentCallCode", R.string.SentCallCode, LocaleController.addNbsp(number))); - } else if (currentType == 4) { - str = AndroidUtilities.replaceTags(LocaleController.formatString("SentCallOnly", R.string.SentCallOnly, LocaleController.addNbsp(number))); - } - confirmTextView.setText(str); - - if (currentType != 3) { - AndroidUtilities.showKeyboard(codeField[0]); - codeField[0].requestFocus(); - } else { - AndroidUtilities.hideKeyboard(codeField[0]); - } - - destroyTimer(); - destroyCodeTimer(); - - lastCurrentTime = System.currentTimeMillis(); - if (currentType == 1) { - problemText.setVisibility(VISIBLE); - timeText.setVisibility(GONE); - } else if (currentType == 3 && (nextType == 4 || nextType == 2)) { - problemText.setVisibility(GONE); - timeText.setVisibility(VISIBLE); - if (nextType == 4) { - timeText.setText(LocaleController.formatString("CallText", R.string.CallText, 1, 0)); - } else if (nextType == 2) { - timeText.setText(LocaleController.formatString("SmsText", R.string.SmsText, 1, 0)); - } - createTimer(); - } else if (currentType == 2 && (nextType == 4 || nextType == 3)) { - timeText.setText(LocaleController.formatString("CallText", R.string.CallText, 2, 0)); - problemText.setVisibility(time < 1000 ? VISIBLE : GONE); - timeText.setVisibility(time < 1000 ? GONE : VISIBLE); - createTimer(); - } else if (currentType == 4 && nextType == 2) { - timeText.setText(LocaleController.formatString("SmsText", R.string.SmsText, 2, 0)); - problemText.setVisibility(time < 1000 ? VISIBLE : GONE); - timeText.setVisibility(time < 1000 ? GONE : VISIBLE); - createTimer(); - } else { - timeText.setVisibility(GONE); - problemText.setVisibility(GONE); - createCodeTimer(); - } - } - - private void createCodeTimer() { - if (codeTimer != null) { - return; - } - codeTime = 15000; - codeTimer = new Timer(); - lastCodeTime = System.currentTimeMillis(); - codeTimer.schedule(new TimerTask() { - @Override - public void run() { - AndroidUtilities.runOnUIThread(() -> { - double currentTime = System.currentTimeMillis(); - double diff = currentTime - lastCodeTime; - lastCodeTime = currentTime; - codeTime -= diff; - if (codeTime <= 1000) { - problemText.setVisibility(VISIBLE); - timeText.setVisibility(GONE); - destroyCodeTimer(); - } - }); - } - }, 0, 1000); - } - - private void destroyCodeTimer() { - try { - synchronized (timerSync) { - if (codeTimer != null) { - codeTimer.cancel(); - codeTimer = null; - } - } - } catch (Exception e) { - FileLog.e(e); - } - } - - private void createTimer() { - if (timeTimer != null) { - return; - } - timeTimer = new Timer(); - timeTimer.schedule(new TimerTask() { - @Override - public void run() { - if (timeTimer == null) { - return; - } - AndroidUtilities.runOnUIThread(() -> { - final double currentTime = System.currentTimeMillis(); - double diff = currentTime - lastCurrentTime; - time -= diff; - lastCurrentTime = currentTime; - if (time >= 1000) { - int minutes = time / 1000 / 60; - int seconds = time / 1000 - minutes * 60; - if (nextType == 4 || nextType == 3) { - timeText.setText(LocaleController.formatString("CallText", R.string.CallText, minutes, seconds)); - } else if (nextType == 2) { - timeText.setText(LocaleController.formatString("SmsText", R.string.SmsText, minutes, seconds)); - } - if (progressView != null) { - progressView.setProgress(1.0f - (float) time / (float) timeout); - } - } else { - if (progressView != null) { - progressView.setProgress(1.0f); - } - destroyTimer(); - if (currentType == 3) { - AndroidUtilities.setWaitingForCall(false); - NotificationCenter.getGlobalInstance().removeObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); - waitingForEvent = false; - destroyCodeTimer(); - resendCode(); - } else if (currentType == 2 || currentType == 4) { - if (nextType == 4 || nextType == 2) { - if (nextType == 4) { - timeText.setText(LocaleController.getString("Calling", R.string.Calling)); - } else { - timeText.setText(LocaleController.getString("SendingSms", R.string.SendingSms)); - } - createCodeTimer(); - TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); - req.phone_number = requestPhone; - req.phone_code_hash = phoneHash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (error != null && error.text != null) { - AndroidUtilities.runOnUIThread(() -> lastError = error.text); - } - }, ConnectionsManager.RequestFlagFailOnServerErrors); - } else if (nextType == 3) { - AndroidUtilities.setWaitingForSms(false); - NotificationCenter.getGlobalInstance().removeObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); - waitingForEvent = false; - destroyCodeTimer(); - resendCode(); - } - } - } - }); - } - }, 0, 1000); - } - - private void destroyTimer() { - try { - synchronized (timerSync) { - if (timeTimer != null) { - timeTimer.cancel(); - timeTimer = null; - } - } - } catch (Exception e) { - FileLog.e(e); - } - } - - private String getCode() { - if (codeField == null) { - return ""; - } - StringBuilder codeBuilder = new StringBuilder(); - for (int a = 0; a < codeField.length; a++) { - codeBuilder.append(PhoneFormat.stripExceptNumbers(codeField[a].getText().toString())); - } - return codeBuilder.toString(); - } - - @Override - public void onNextPressed(String code) { - if (nextPressed) { - return; - } - code = getCode(); - if (TextUtils.isEmpty(code)) { - AndroidUtilities.shakeView(codeFieldContainer, 2, 0); - return; - } - nextPressed = true; - if (currentType == 2) { - AndroidUtilities.setWaitingForSms(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == 3) { - AndroidUtilities.setWaitingForCall(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveCall); - } - waitingForEvent = false; - final TLRPC.TL_account_changePhone req = new TLRPC.TL_account_changePhone(); - req.phone_number = requestPhone; - req.phone_code = code; - req.phone_code_hash = phoneHash; - destroyTimer(); - needShowProgress(); - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - needHideProgress(); - nextPressed = false; - if (error == null) { - TLRPC.User user = (TLRPC.User) response; - destroyTimer(); - destroyCodeTimer(); - UserConfig.getInstance(currentAccount).setCurrentUser(user); - UserConfig.getInstance(currentAccount).saveConfig(true); - ArrayList users = new ArrayList<>(); - users.add(user); - MessagesStorage.getInstance(currentAccount).putUsersAndChats(users, null, true, true); - MessagesController.getInstance(currentAccount).putUser(user, false); - finishFragment(); - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.mainUserInfoChanged); - getMessagesController().removeSuggestion(0, "VALIDATE_PHONE_NUMBER"); - } else { - lastError = error.text; - if (currentType == 3 && (nextType == 4 || nextType == 2) || currentType == 2 && (nextType == 4 || nextType == 3) || currentType == 4 && nextType == 2) { - createTimer(); - } - if (currentType == 2) { - AndroidUtilities.setWaitingForSms(true); - NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == 3) { - AndroidUtilities.setWaitingForCall(true); - NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); - } - waitingForEvent = true; - if (currentType != 3) { - AlertsCreator.processError(currentAccount, error, ChangePhoneActivity.this, req); - } - if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - for (int a = 0; a < codeField.length; a++) { - codeField[a].setText(""); - } - codeField[0].requestFocus(); - } else if (error.text.contains("PHONE_CODE_EXPIRED")) { - onBackPressed(true); - setPage(0, true, null, true); - } - } - }), ConnectionsManager.RequestFlagFailOnServerErrors); - } - - @Override - public boolean onBackPressed(boolean force) { - if (!force) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("StopVerification", R.string.StopVerification)); - builder.setPositiveButton(LocaleController.getString("Continue", R.string.Continue), null); - builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { - onBackPressed(true); - setPage(0, true, null, true); - }); - showDialog(builder.create()); - return false; - } - TLRPC.TL_auth_cancelCode req = new TLRPC.TL_auth_cancelCode(); - req.phone_number = requestPhone; - req.phone_code_hash = phoneHash; - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - - }, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); - - destroyTimer(); - destroyCodeTimer(); - currentParams = null; - if (currentType == 2) { - AndroidUtilities.setWaitingForSms(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == 3) { - AndroidUtilities.setWaitingForCall(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveCall); - } - waitingForEvent = false; - return true; - } - - @Override - public void onDestroyActivity() { - super.onDestroyActivity(); - if (currentType == 2) { - AndroidUtilities.setWaitingForSms(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == 3) { - AndroidUtilities.setWaitingForCall(false); - NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveCall); - } - waitingForEvent = false; - destroyTimer(); - destroyCodeTimer(); - } - - @Override - public void onShow() { - super.onShow(); - if (currentType == 3) { - return; - } - if (hintDrawable != null) { - hintDrawable.setCurrentFrame(0); - } - AndroidUtilities.runOnUIThread(() -> { - if (codeField != null) { - for (int a = codeField.length - 1; a >= 0; a--) { - if (a == 0 || codeField[a].length() != 0) { - codeField[a].requestFocus(); - codeField[a].setSelection(codeField[a].length()); - AndroidUtilities.showKeyboard(codeField[a]); - break; - } - } - } - if (hintDrawable != null) { - hintDrawable.start(); - } - }, 100); - } - - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (!waitingForEvent || codeField == null) { - return; - } - if (id == NotificationCenter.didReceiveSmsCode) { - codeField[0].setText("" + args[0]); - onNextPressed(null); - } else if (id == NotificationCenter.didReceiveCall) { - String num = "" + args[0]; - if (!AndroidUtilities.checkPhonePattern(pattern, num)) { - return; - } - ignoreOnTextChange = true; - codeField[0].setText(num); - ignoreOnTextChange = false; - onNextPressed(null); - } - } - } - - @Override - public ArrayList getThemeDescriptions() { - PhoneView phoneView = (PhoneView) views[0]; - LoginActivitySmsView smsView1 = (LoginActivitySmsView) views[1]; - LoginActivitySmsView smsView2 = (LoginActivitySmsView) views[2]; - LoginActivitySmsView smsView3 = (LoginActivitySmsView) views[3]; - LoginActivitySmsView smsView4 = (LoginActivitySmsView) views[4]; - - ArrayList arrayList = new ArrayList<>(); - - ThemeDescription.ThemeDescriptionDelegate descriptionDelegate = () -> { - for (int i = 0; i < views.length; i++) { - if (views[i] instanceof LoginActivity.LoginActivitySmsView) { - LoginActivity.LoginActivitySmsView smsView = (LoginActivity.LoginActivitySmsView) views[i]; - if (smsView.hintDrawable != null) { - smsView.hintDrawable.setLayerColor("Bubble.**", Theme.getColor(Theme.key_chats_actionBackground)); - smsView.hintDrawable.setLayerColor("Phone.**", Theme.getColor(Theme.key_chats_actionBackground)); - } - } - } - }; - - arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); - - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_actionBarDefault)); - arrayList.add(new ThemeDescription(fragmentView, ThemeDescription.FLAG_LISTGLOWCOLOR, null, null, null, null, Theme.key_actionBarDefault)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_ITEMSCOLOR, null, null, null, null, Theme.key_actionBarDefaultIcon)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_TITLECOLOR, null, null, null, null, Theme.key_actionBarDefaultTitle)); - arrayList.add(new ThemeDescription(actionBar, ThemeDescription.FLAG_AB_SELECTORCOLOR, null, null, null, null, Theme.key_actionBarDefaultSelector)); - - arrayList.add(new ThemeDescription(phoneView.countryButton, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(phoneView.countryButton, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_listSelector)); - arrayList.add(new ThemeDescription(phoneView.view, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhiteGrayLine)); - arrayList.add(new ThemeDescription(phoneView.textView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(phoneView.codeField, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(phoneView.codeField, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); - arrayList.add(new ThemeDescription(phoneView.codeField, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - arrayList.add(new ThemeDescription(phoneView.phoneField, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(phoneView.phoneField, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); - arrayList.add(new ThemeDescription(phoneView.phoneField, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputField)); - arrayList.add(new ThemeDescription(phoneView.phoneField, ThemeDescription.FLAG_BACKGROUNDFILTER | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - arrayList.add(new ThemeDescription(phoneView.textView2, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - - arrayList.add(new ThemeDescription(smsView1.confirmTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView1.titleTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - if (smsView1.codeField != null) { - for (int a = 0; a < smsView1.codeField.length; a++) { - arrayList.add(new ThemeDescription(smsView1.codeField[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView1.codeField[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - } - } - arrayList.add(new ThemeDescription(smsView1.timeText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView1.problemText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueText4)); - arrayList.add(new ThemeDescription(smsView1.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressInner)); - arrayList.add(new ThemeDescription(smsView1.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressOuter)); - arrayList.add(new ThemeDescription(smsView1.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView1.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - - arrayList.add(new ThemeDescription(smsView2.confirmTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView2.titleTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - if (smsView2.codeField != null) { - for (int a = 0; a < smsView2.codeField.length; a++) { - arrayList.add(new ThemeDescription(smsView2.codeField[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView2.codeField[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - } - } - arrayList.add(new ThemeDescription(smsView2.timeText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView2.problemText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueText4)); - arrayList.add(new ThemeDescription(smsView2.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressInner)); - arrayList.add(new ThemeDescription(smsView2.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressOuter)); - arrayList.add(new ThemeDescription(smsView2.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView2.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - - arrayList.add(new ThemeDescription(smsView3.confirmTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView3.titleTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - if (smsView3.codeField != null) { - for (int a = 0; a < smsView3.codeField.length; a++) { - arrayList.add(new ThemeDescription(smsView3.codeField[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView3.codeField[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - } - } - arrayList.add(new ThemeDescription(smsView3.timeText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView3.problemText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueText4)); - arrayList.add(new ThemeDescription(smsView3.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressInner)); - arrayList.add(new ThemeDescription(smsView3.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressOuter)); - arrayList.add(new ThemeDescription(smsView3.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView3.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - - arrayList.add(new ThemeDescription(smsView4.confirmTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView4.titleTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - if (smsView4.codeField != null) { - for (int a = 0; a < smsView4.codeField.length; a++) { - arrayList.add(new ThemeDescription(smsView4.codeField[a], ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView4.codeField[a], ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_windowBackgroundWhiteInputFieldActivated)); - } - } - arrayList.add(new ThemeDescription(smsView4.timeText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText6)); - arrayList.add(new ThemeDescription(smsView4.problemText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlueText4)); - arrayList.add(new ThemeDescription(smsView4.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressInner)); - arrayList.add(new ThemeDescription(smsView4.progressView, 0, new Class[]{ProgressView.class}, new String[]{"paint"}, null, null, null, Theme.key_login_progressOuter)); - arrayList.add(new ThemeDescription(smsView4.blackImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - arrayList.add(new ThemeDescription(smsView4.blueImageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_chats_actionBackground)); - arrayList.add(new ThemeDescription(smsView4.blueImageView, 0, null, null, null, descriptionDelegate, Theme.key_chats_actionBackground)); - - return arrayList; - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java index d2d52decb..ca590390b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java @@ -131,7 +131,7 @@ public class ChangeUsernameActivity extends BaseFragment { }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); if (user == null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java index 971b50de1..df9efc18c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelAdminLogActivity.java @@ -1016,7 +1016,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio bottomOverlayChat.addView(bottomOverlayChatText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); bottomOverlayImage = new ImageView(context); - bottomOverlayImage.setImageResource(R.drawable.log_info); + bottomOverlayImage.setImageResource(R.drawable.msg_help); bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_chat_fieldOverlayText), PorterDuff.Mode.SRC_IN)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); bottomOverlayChat.addView(bottomOverlayImage, LayoutHelper.createFrame(48, 48, Gravity.RIGHT | Gravity.TOP, 3, 0, 0, 0)); @@ -1389,7 +1389,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } if (selectedObject.type == 3 || selectedObject.type == 1) { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { @@ -1410,7 +1410,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (locFile == null) { - File f = FileLoader.getPathToMessage(selectedObject.messageOwner); + File f = getFileLoader().getPathToMessage(selectedObject.messageOwner); if (f.exists()) { locFile = f; } @@ -1465,7 +1465,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.getDocument().mime_type); @@ -1491,7 +1491,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); @@ -1523,7 +1523,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), selectedObject.isMusic() ? 3 : 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : ""); break; @@ -1593,7 +1593,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (!canSave) { - File f = FileLoader.getPathToMessage(messageObject.messageOwner); + File f = getFileLoader().getPathToMessage(messageObject.messageOwner); if (f.exists()) { canSave = true; } @@ -2259,7 +2259,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio f = new File(message.messageOwner.attachPath); } if (f == null || !f.exists()) { - f = FileLoader.getPathToMessage(message.messageOwner); + f = getFileLoader().getPathToMessage(message.messageOwner); } Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= 24) { @@ -2289,7 +2289,7 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio } } if (locFile == null) { - File f = FileLoader.getPathToMessage(message.messageOwner); + File f = getFileLoader().getPathToMessage(message.messageOwner); if (f.exists()) { locFile = f; } @@ -2913,10 +2913,6 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][0], Theme.chat_photoStatesDrawables[11][0]}, null, Theme.key_chat_inLoaderPhotoIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoIconSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[9][0]}, null, Theme.key_chat_outFileIcon)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[9][1]}, null, Theme.key_chat_outFileSelectedIcon)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][0]}, null, Theme.key_chat_inFileIcon)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][1]}, null, Theme.key_chat_inFileSelectedIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[0]}, null, Theme.key_chat_inContactBackground)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[0]}, null, Theme.key_chat_inContactIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[1]}, null, Theme.key_chat_outContactBackground)); @@ -2942,9 +2938,6 @@ public class ChannelAdminLogActivity extends BaseFragment implements Notificatio themeDescriptions.add(new ThemeDescription(progressView2, ThemeDescription.FLAG_SERVICEBACKGROUND, null, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(emptyView, ThemeDescription.FLAG_SERVICEBACKGROUND, null, null, null, null, Theme.key_chat_serviceBackground)); - themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_SERVICEBACKGROUND, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceBackground)); - themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceText)); - themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTimeItem() : null, 0, null, null, null, null, Theme.key_chat_secretTimerBackground)); themeDescriptions.add(new ThemeDescription(avatarContainer != null ? avatarContainer.getTimeItem() : null, 0, null, null, null, null, Theme.key_chat_secretTimerText)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java index 60ae346ef..6c36e5476 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChannelCreateActivity.java @@ -12,11 +12,15 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Editable; import android.text.InputFilter; @@ -33,6 +37,7 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; +import android.widget.ViewAnimator; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -58,12 +63,16 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextBlockCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AvatarDrawable; +import org.telegram.ui.Components.CircularProgressDrawable; +import org.telegram.ui.Components.CrossfadeDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextEmoji; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkActionView; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgressView; @@ -78,8 +87,8 @@ import tw.nekomimi.nekogram.utils.VibrateUtil; public class ChannelCreateActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ImageUpdater.ImageUpdaterDelegate { private View doneButton; + private CrossfadeDrawable doneButtonDrawable; private EditTextEmoji nameTextView; - private AlertDialog progressDialog; private ShadowSectionCell sectionCell; private BackupImageView avatarImage; private View avatarOverlay; @@ -133,6 +142,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC private boolean createAfterUpload; private boolean donePressed; + private Integer doneRequestId; private final static int done_button = 1; @@ -176,6 +186,10 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC @Override public void onFragmentDestroy() { super.onFragmentDestroy(); + if (doneRequestId != null) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(doneRequestId, true); + doneRequestId = null; + } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatDidCreated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatDidFailCreate); if (imageUpdater != null) { @@ -239,6 +253,45 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC return true; } + private AlertDialog cancelDialog; + private void showDoneCancelDialog() { + if (cancelDialog != null) { + return; + } + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("StopLoading", R.string.StopLoading)); + builder.setPositiveButton(LocaleController.getString("WaitMore", R.string.WaitMore), null); + builder.setNegativeButton(LocaleController.getString("Stop", R.string.Stop), (dialogInterface, i) -> { + donePressed = false; + createAfterUpload = false; + if (doneRequestId != null) { + ConnectionsManager.getInstance(currentAccount).cancelRequest(doneRequestId, true); + doneRequestId = null; + } + updateDoneProgress(false); + dialogInterface.dismiss(); + }); + cancelDialog = builder.show(); + } + + private ValueAnimator doneButtonDrawableAnimator; + private void updateDoneProgress(boolean loading) { + if (doneButtonDrawable != null) { + if (doneButtonDrawableAnimator != null) { + doneButtonDrawableAnimator.cancel(); + } + doneButtonDrawableAnimator = ValueAnimator.ofFloat(doneButtonDrawable.getProgress(), loading ? 1f : 0); + doneButtonDrawableAnimator.addUpdateListener(a -> { + doneButtonDrawable.setProgress((float) a.getAnimatedValue()); + doneButtonDrawable.invalidateSelf(); + }); + doneButtonDrawableAnimator.setDuration((long) (200 * Math.abs(doneButtonDrawable.getProgress() - (loading ? 1f : 0)))); + doneButtonDrawableAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + doneButtonDrawableAnimator.start(); + } + } + @Override public View createView(Context context) { if (nameTextView != null) { @@ -252,10 +305,18 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC @Override public void onItemClick(int id) { if (id == -1) { + if (donePressed) { + showDoneCancelDialog(); + return; + } finishFragment(); } else if (id == done_button) { if (currentStep == 0) { - if (donePressed || getParentActivity() == null) { + if (getParentActivity() == null) { + return; + } + if (donePressed) { + showDoneCancelDialog(); return; } if (nameTextView.length() == 0) { @@ -264,24 +325,12 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC return; } donePressed = true; + updateDoneProgress(true); if (imageUpdater.isUploadingImage()) { createAfterUpload = true; - progressDialog = new AlertDialog(getParentActivity(), 3); - progressDialog.setOnCancelListener(dialog -> { - createAfterUpload = false; - progressDialog = null; - donePressed = false; - }); - progressDialog.show(); return; } - final int reqId = MessagesController.getInstance(currentAccount).createChat(nameTextView.getText().toString(), new ArrayList<>(), descriptionTextView.getText().toString(), ChatObject.CHAT_TYPE_CHANNEL, false, null, null, ChannelCreateActivity.this); - progressDialog = new AlertDialog(getParentActivity(), 3); - progressDialog.setOnCancelListener(dialog -> { - ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); - donePressed = false; - }); - progressDialog.show(); + doneRequestId = MessagesController.getInstance(currentAccount).createChat(nameTextView.getText().toString(), new ArrayList<>(), descriptionTextView.getText().toString(), ChatObject.CHAT_TYPE_CHANNEL, false, null, null, ChannelCreateActivity.this); } else if (currentStep == 1) { if (!isPrivate) { if (descriptionTextView.length() == 0) { @@ -312,7 +361,10 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + Drawable checkmark = context.getResources().getDrawable(R.drawable.ic_ab_done).mutate(); + checkmark.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); + doneButtonDrawable = new CrossfadeDrawable(checkmark, new CircularProgressDrawable(Theme.getColor(Theme.key_actionBarDefaultIcon))); + doneButton = menu.addItemWithWidth(done_button, doneButtonDrawable, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); if (currentStep == 0) { actionBar.setTitle(LocaleController.getString("NewChannel", R.string.NewChannel)); @@ -482,6 +534,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC } } }; + avatarOverlay.setContentDescription(LocaleController.getString("ChatSetPhotoOrVideo", R.string.ChatSetPhotoOrVideo)); frameLayout.addView(avatarOverlay, LayoutHelper.createFrame(64, 64, Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), LocaleController.isRTL ? 0 : 16, 12, LocaleController.isRTL ? 16 : 0, 12)); avatarOverlay.setOnClickListener(view -> { imageUpdater.openMenu(avatar != null, () -> { @@ -634,6 +687,10 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC radioButtonCell1.setTextAndValueAndCheck(LocaleController.getString("ChannelPublic", R.string.ChannelPublic), LocaleController.getString("ChannelPublicInfo", R.string.ChannelPublicInfo), false, !isPrivate); linearLayout2.addView(radioButtonCell1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); radioButtonCell1.setOnClickListener(v -> { + if (!canCreatePublic) { + showPremiumIncreaseLimitDialog(); + return; + } if (!isPrivate) { return; } @@ -666,7 +723,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC publicContainer = new LinearLayout(context); publicContainer.setOrientation(LinearLayout.HORIZONTAL); - linkContainer.addView(publicContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 17, 7, 17, 0)); + linkContainer.addView(publicContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 21, 7, 21, 0)); editText = new EditTextBoldCursor(context); editText.setText(MessagesController.getInstance(currentAccount).linkPrefix + "/"); @@ -850,14 +907,15 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC inputVideoPath = videoPath; videoTimestamp = videoStartTimestamp; if (createAfterUpload) { - try { - if (progressDialog != null && progressDialog.isShowing()) { - progressDialog.dismiss(); - progressDialog = null; + if (cancelDialog != null) { + try { + cancelDialog.dismiss(); + cancelDialog = null; + } catch (Exception e) { + FileLog.e(e); } - } catch (Exception e) { - FileLog.e(e); } + updateDoneProgress(false); donePressed = false; doneButton.performClick(); } @@ -987,18 +1045,21 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.chatDidFailCreate) { - if (progressDialog != null) { + if (cancelDialog != null) { try { - progressDialog.dismiss(); + cancelDialog.dismiss(); + cancelDialog = null; } catch (Exception e) { FileLog.e(e); } } + updateDoneProgress(false); donePressed = false; } else if (id == NotificationCenter.chatDidCreated) { - if (progressDialog != null) { + if (cancelDialog != null) { try { - progressDialog.dismiss(); + cancelDialog.dismiss(); + cancelDialog = null; } catch (Exception e) { FileLog.e(e); } @@ -1063,7 +1124,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC }); builder.addCancelItem(); showDialog(builder.create()); - }); + }, false, 0); adminedChannelCell.setChannel(res.chats.get(a), a == res.chats.size() - 1); adminedChannelCells.add(adminedChannelCell); adminnedChannelsLayout.addView(adminedChannelCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 72)); @@ -1143,7 +1204,7 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC } else { if (error != null && error.text.equals("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) { canCreatePublic = false; - loadAdminedChannels(); + showPremiumIncreaseLimitDialog(); } else { checkTextView.setText(LocaleController.getString("LinkInUse", R.string.LinkInUse)); } @@ -1179,6 +1240,19 @@ public class ChannelCreateActivity extends BaseFragment implements NotificationC showDialog(builder.create()); } + private void showPremiumIncreaseLimitDialog() { + if (getParentActivity() == null) { + return; + } + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_PUBLIC_LINKS, currentAccount); + limitReachedBottomSheet.parentIsChannel = true; + limitReachedBottomSheet.onSuccessRunnable = () -> { + canCreatePublic = true; + updatePrivatePublic(); + }; + showDialog(limitReachedBottomSheet); + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Charts/view_data/ChartHeaderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Charts/view_data/ChartHeaderView.java index a264c6a6b..f2223e2c6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Charts/view_data/ChartHeaderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Charts/view_data/ChartHeaderView.java @@ -5,7 +5,6 @@ import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.TextPaint; -import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -18,8 +17,8 @@ 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.LayoutHelper; import org.telegram.ui.Charts.BaseChartView; +import org.telegram.ui.Components.LayoutHelper; import java.text.SimpleDateFormat; import java.util.Date; @@ -73,7 +72,7 @@ public class ChartHeaderView extends FrameLayout { back.setVisibility(View.GONE); back.setText(LocaleController.getString("ZoomOut", R.string.ZoomOut)); - zoomIcon = ContextCompat.getDrawable(getContext(), R.drawable.stats_zoom); + zoomIcon = ContextCompat.getDrawable(getContext(), R.drawable.msg_zoomout_stats); back.setCompoundDrawablesWithIntrinsicBounds(zoomIcon, null, null, null); back.setCompoundDrawablePadding(AndroidUtilities.dp(4)); back.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(4), AndroidUtilities.dp(8), AndroidUtilities.dp(4)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index dcad9e82e..3f7129f62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -64,6 +64,7 @@ import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.ForegroundColorSpan; import android.text.style.URLSpan; +import android.util.Log; import android.util.Property; import android.util.SparseArray; import android.util.SparseIntArray; @@ -75,6 +76,7 @@ import android.view.Menu; import android.view.MotionEvent; import android.view.TextureView; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; @@ -98,7 +100,6 @@ import androidx.core.content.FileProvider; import androidx.core.graphics.ColorUtils; import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.ChatListItemAnimator; -import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManagerFixed; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScrollerCustom; @@ -107,6 +108,7 @@ import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; +import com.google.zxing.common.detector.MathUtils; import org.openintents.openpgp.OpenPgpError; import org.openintents.openpgp.util.OpenPgpApi; @@ -166,7 +168,6 @@ import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.SimpleTextView; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; -import org.telegram.ui.Adapters.MentionsAdapter; import org.telegram.ui.Adapters.MessagesSearchAdapter; import org.telegram.ui.Adapters.StickersAdapter; import org.telegram.ui.Cells.BotHelpCell; @@ -206,9 +207,11 @@ import org.telegram.ui.Components.ChatNotificationsPopupWrapper; import org.telegram.ui.Components.ChatScrimPopupContainerLayout; import org.telegram.ui.Components.ChatThemeBottomSheet; import org.telegram.ui.Components.ChecksHintView; +import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.ClippingImageView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CounterView; +import org.telegram.ui.Components.CrossfadeDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextCaption; @@ -227,6 +230,7 @@ import org.telegram.ui.Components.InstantCameraView; import org.telegram.ui.Components.InviteMembersBottomSheet; import org.telegram.ui.Components.JoinGroupAlert; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.MentionsContainerView; import org.telegram.ui.Components.MessageBackgroundDrawable; import org.telegram.ui.Components.MotionBackgroundDrawable; import org.telegram.ui.Components.NumberTextView; @@ -234,6 +238,8 @@ import org.telegram.ui.Components.PhonebookShareAlert; import org.telegram.ui.Components.PinnedLineView; import org.telegram.ui.Components.PipRoundVideoView; import org.telegram.ui.Components.PollVotesAlert; +import org.telegram.ui.Components.PopupSwipeBackLayout; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.ReactedHeaderView; @@ -248,12 +254,12 @@ import org.telegram.ui.Components.ReportAlert; import org.telegram.ui.Components.SearchCounterView; import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SharedMediaLayout; -import org.telegram.ui.Components.Size; import org.telegram.ui.Components.SizeNotifierFrameLayout; import org.telegram.ui.Components.StickersAlert; import org.telegram.ui.Components.TextSelectionHint; import org.telegram.ui.Components.TextStyleSpan; import org.telegram.ui.Components.ThemeEditorView; +import org.telegram.ui.Components.TranscribeButton; import org.telegram.ui.Components.TrendingStickersAlert; import org.telegram.ui.Components.TypefaceSpan; import org.telegram.ui.Components.URLSpanBotCommand; @@ -307,7 +313,8 @@ import tw.nekomimi.nekogram.utils.ProxyUtil; import tw.nekomimi.nekogram.utils.TelegramUtil; @SuppressWarnings("unchecked") -public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, LocationActivity.LocationActivityDelegate, ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate { +public class +ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.DialogsActivityDelegate, LocationActivity.LocationActivityDelegate, ChatAttachAlertDocumentLayout.DocumentSelectActivityDelegate { // buttons by Neko @@ -431,11 +438,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Runnable tapForForwardingOptionsHitRunnable; private ImageView replyIconImageView; private ImageView replyCloseImageView; - private MentionsAdapter mentionsAdapter; - private FrameLayout mentionContainer; - private RecyclerListView mentionListView; - private LinearLayoutManager mentionLayoutManager; - private ExtendedGridLayoutManager mentionGridLayoutManager; + public MentionsContainerView mentionContainer; private AnimatorSet mentionListAnimation; private ChatAttachAlert chatAttachAlert; private BlurredFrameLayout topChatPanelView; @@ -516,9 +519,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private Bulletin pinBulletin; private boolean showPinBulletin; private int pinBullerinTag; - private boolean openKeyboardOnAttachMenuClose; + protected boolean openKeyboardOnAttachMenuClose; private Runnable unregisterFlagSecurePasscode; private Runnable unregisterFlagSecureNoforwards; + private boolean isFullyVisible; private MessageObject hintMessageObject; private int hintMessageType; @@ -574,13 +578,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int topViewWasVisible; - private boolean mentionListViewIgnoreLayout; - private int mentionListViewScrollOffsetY; - private int mentionListViewLastViewTop; - private int mentionListViewLastViewPosition; - private boolean mentionListViewIsScrolling; - private boolean mentionListViewIsDragging; - private ArrayList pinnedMessageIds = new ArrayList<>(); private HashMap pinnedMessageObjects = new HashMap<>(); private SparseArray loadingPinnedMessages = new SparseArray<>(); @@ -643,6 +640,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private String pendingLinkSearchString; private Runnable pendingWebPageTimeoutRunnable; private Runnable waitingForCharaterEnterRunnable; + private Runnable onChatMessagesLoaded; private TLRPC.ChatInvite chatInvite; private Runnable chatInviteRunnable; @@ -704,6 +702,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int last_message_id = 0; private long mergeDialogId; + private boolean premiumInvoiceBot; private boolean showScrollToMessageError; private int startLoadFromMessageId; private int startLoadFromDate; @@ -855,10 +854,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int scrollAnimationIndex; private int scrollCallbackAnimationIndex; + public boolean allowExpandPreviewByClick; private boolean showSearchAsIcon; private boolean showAudioCallAsIcon; public MessageEnterTransitionContainer messageEnterTransitionContainer; - private float pullingDownOffset; + private float pullingDownOffset, pullingBottomOffset; private ChatPullingDownDrawable pullingDownDrawable; private Animator pullingDownBackAnimator; private boolean fromPullingDownTransition; @@ -876,9 +876,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }; + private KeyboardHideHelper keyboardHideHelper = new KeyboardHideHelper(); + private boolean isPauseOnThemePreview; private ChatThemeBottomSheet chatThemeBottomSheet; - private ThemeDelegate themeDelegate; + public ThemeDelegate themeDelegate; private ChatActivityMemberRequestsDelegate pendingRequestsDelegate; private TLRPC.TL_channels_sendAsPeers sendAsPeersObj; @@ -911,6 +913,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private final static int OPTION_UNVOTE = 25; private final static int OPTION_STOP_POLL_OR_QUIZ = 26; private final static int OPTION_VIEW_REPLIES_OR_THREAD = 27; + private final static int OPTION_STATISTICS = 28; + private final static int OPTION_TRANSLATE = 29; + private final static int OPTION_TRANSCRIBE = 30; + private final static int OPTION_HIDE_SPONSORED_MESSAGE = 31; private final static int OPTION_SEND_NOW = 100; private final static int OPTION_EDIT_SCHEDULE_TIME = 102; @@ -920,7 +926,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not NotificationCenter.commentsRead, NotificationCenter.messagesReadEncrypted, NotificationCenter.messagesReadContent, - NotificationCenter.commentsRead, NotificationCenter.didLoadPinnedMessages, NotificationCenter.newDraftReceived, NotificationCenter.updateMentionsCount, @@ -973,6 +978,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public int blurredViewTopOffset; public int blurredViewBottomOffset; + private ValueAnimator searchExpandAnimator; + private float searchExpandProgress; + public void deleteHistory(int dateSelectedStart, int dateSelectedEnd, boolean forAll) { chatAdapter.frozenMessages.clear(); for (int i = 0; i < messages.size(); i++) { @@ -1208,7 +1216,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onDraw(Canvas canvas) { Layout layout = textLayout; - int color = getThemedColor(Theme.key_chat_fieldOverlayText); + int color = getThemedColor(isEnabled() ? Theme.key_chat_fieldOverlayText : Theme.key_windowBackgroundWhiteGrayText); if (textColor != color) { layoutPaint.setColor(textColor = color); } @@ -1295,15 +1303,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { - if (index < 0 || index >= botContextResults.size()) { + if (index < 0 || index >= botContextResults.size() || mentionContainer == null || mentionContainer.getListView() == null) { return null; } - int count = mentionListView.getChildCount(); + int count = mentionContainer.getListView().getChildCount(); Object result = botContextResults.get(index); for (int a = 0; a < count; a++) { ImageReceiver imageReceiver = null; - View view = mentionListView.getChildAt(a); + View view = mentionContainer.getListView().getChildAt(a); if (view instanceof ContextLinkCell) { ContextLinkCell cell = (ContextLinkCell) view; if (cell.getResult() == result) { @@ -1317,7 +1325,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); object.viewX = coords[0]; object.viewY = coords[1] - (Build.VERSION.SDK_INT >= 21 ? 0 : AndroidUtilities.statusBarHeight); - object.parentView = mentionListView; +// object.clipTopAddition = (int) (chatListViewPaddingTop - chatListViewPaddingVisibleOffset - AndroidUtilities.dp(4)); + object.parentView = mentionContainer.getListView(); object.imageReceiver = imageReceiver; object.thumb = imageReceiver.getBitmapSafe(); object.radius = imageReceiver.getRoundRadius(); @@ -1384,6 +1393,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not RecyclerListView.OnItemLongClickListenerExtended onItemLongClickListener = new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { + if (keyboardHideHelper.disableScrolling()) { + return false; + } if (textSelectionHelper.isTryingSelect() || textSelectionHelper.isSelectionMode() || inPreviewMode) { return false; } @@ -1567,7 +1579,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onDoubleTap(View view, int position, float x, float y) { - if (!(view instanceof ChatMessageCell) || getParentActivity() == null || isSecretChat() || isInScheduleMode()) { + if (!(view instanceof ChatMessageCell) || getParentActivity() == null || isSecretChat() || isInScheduleMode() || isInPreviewMode()) { return; } if (NekoConfig.reactions.Int() == 2) return; @@ -1638,6 +1650,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not attachMenuBotStartCommand = arguments.getString("attach_bot_start_command", null); inlineReturn = arguments.getLong("inline_return", 0); String inlineQuery = arguments.getString("inline_query"); + premiumInvoiceBot = arguments.getBoolean("premium_bot", false); startLoadFromMessageId = arguments.getInt("message_id", 0); startLoadFromDate = arguments.getInt("start_from_date", 0); startFromVideoTimestamp = arguments.getInt("video_timestamp", -1); @@ -1704,6 +1717,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not botUser = arguments.getString("botUser"); if (inlineQuery != null) { getMessagesController().sendBotStart(currentUser, inlineQuery); + } else if (premiumInvoiceBot && !TextUtils.isEmpty(botUser)) { + getMessagesController().sendBotStart(currentUser, botUser); + + botUser = null; + premiumInvoiceBot = false; } } else if (encId != 0) { currentEncryptedChat = getMessagesController().getEncryptedChat(encId); @@ -1822,6 +1840,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().addObserver(this, NotificationCenter.didCreatedNewDeleteTask); getNotificationCenter().addObserver(this, NotificationCenter.messagePlayingDidStart); getNotificationCenter().addObserver(this, NotificationCenter.updateMessageMedia); + getNotificationCenter().addObserver(this, NotificationCenter.voiceTranscriptionUpdate); getNotificationCenter().addObserver(this, NotificationCenter.replaceMessagesObjects); getNotificationCenter().addObserver(this, NotificationCenter.notificationsSettingsUpdated); getNotificationCenter().addObserver(this, NotificationCenter.replyMessagesDidLoad); @@ -2076,8 +2095,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (avatarContainer != null) { avatarContainer.onDestroy(); } - if (mentionsAdapter != null) { - mentionsAdapter.onDestroy(); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().onDestroy(); } if (chatAttachAlert != null) { chatAttachAlert.dismissInternal(); @@ -2125,6 +2144,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingDidStart); getNotificationCenter().removeObserver(this, NotificationCenter.messagePlayingGoingToStop); getNotificationCenter().removeObserver(this, NotificationCenter.updateMessageMedia); + getNotificationCenter().removeObserver(this, NotificationCenter.voiceTranscriptionUpdate); getNotificationCenter().removeObserver(this, NotificationCenter.replaceMessagesObjects); getNotificationCenter().removeObserver(this, NotificationCenter.notificationsSettingsUpdated); getNotificationCenter().removeObserver(this, NotificationCenter.replyMessagesDidLoad); @@ -2599,7 +2619,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); View backButton = actionBar.getBackButton(); backButton.setOnLongClickListener(e -> { - scrimPopupWindow = BackButtonMenu.show(this, backButton, dialog_id); + scrimPopupWindow = BackButtonMenu.show(this, backButton, dialog_id, themeDelegate); if (scrimPopupWindow != null) { scrimPopupWindow.setOnDismissListener(() -> { scrimPopupWindow = null; @@ -2645,6 +2665,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not avatarContainer.onDestroy(); } avatarContainer = new ChatAvatarContainer(context, this, currentEncryptedChat != null, themeDelegate); + avatarContainer.allowShorterStatus = true; + avatarContainer.premiumIconHiddable = true; AndroidUtilities.updateViewVisibilityAnimated(avatarContainer, true, 1f, false); if (inPreviewMode || inBubbleMode) { avatarContainer.setOccupyStatusBar(false); @@ -2746,11 +2768,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUserButton.setVisibility(View.VISIBLE); } if (searchingForUser) { - mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false, true); + mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchingForUser = false; } - mentionLayoutManager.setReverseLayout(false); - mentionsAdapter.setSearchingMentions(false); + mentionContainer.setReversed(false); + mentionContainer.getAdapter().setSearchingMentions(false); searchingUserMessages = null; searchingChatMessages = null; searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); @@ -2850,7 +2872,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public void onTextChanged(EditText editText) { showMessagesSearchListView(false); if (searchingForUser) { - mentionsAdapter.searchUsernameOrHashtag("@" + editText.getText().toString(), 0, messages, true, true); + mentionContainer.getAdapter().searchUsernameOrHashtag("@" + editText.getText().toString(), 0, messages, true, true); } else if (searchingUserMessages == null && searchingChatMessages == null && searchUserButton != null && TextUtils.equals(editText.getText(), LocaleController.getString("SearchFrom", R.string.SearchFrom))) { searchUserButton.callOnClick(); } @@ -2862,7 +2884,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUserButton.callOnClick(); } else { if (searchingForUser) { - mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false, true); + mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchingForUser = false; searchItem.setSearchFieldText("", true); } @@ -2886,10 +2908,48 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchItemVisible = false; } - if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0 && !inMenuMode) { + editTextItem = menu.addItem(0, R.drawable.ic_ab_other, themeDelegate); + editTextItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); + editTextItem.setTag(null); + editTextItem.setVisibility(View.GONE); + + // NekoX + editTextItem.addSubItem(text_transalte, LocaleController.getString("Translate", R.string.Translate)); + + editTextItem.addSubItem(text_spoiler, LocaleController.getString("Spoiler", R.string.Spoiler)); + 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); + editTextItem.addSubItem(text_bold, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); + stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_italic, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); + stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_mono, stringBuilder); + if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); + TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_strike, stringBuilder); + stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); + run = new TextStyleSpan.TextStyleRun(); + run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; + stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + editTextItem.addSubItem(text_underline, stringBuilder); + } + editTextItem.addSubItem(text_link, LocaleController.getString("CreateLink", R.string.CreateLink)); + + // NekoX + editTextItem.addSubItem(text_mention, LocaleController.getString("CreateMention", R.string.CreateMention)); + + editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); + + if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { TLRPC.UserFull userFull = null; if (currentUser != null) { // audioCallIconItem = menu.addItem(call, R.drawable.ic_call, themeDelegate); + audioCallIconItem.setContentDescription(LocaleController.getString("Call", R.string.Call)); userFull = getMessagesController().getUserFull(currentUser.id); // if (userFull != null && userFull.phone_calls_available) { // showAudioCallAsIcon = !inPreviewMode; @@ -2946,7 +3006,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } Bundle args = new Bundle(); args.putLong("dialog_id", dialog_id); - presentFragment(new ProfileNotificationsActivity(args)); + presentFragment(new ProfileNotificationsActivity(args, themeDelegate)); } } @@ -2960,6 +3020,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not muteItem.setOnClickListener(view -> { boolean muted = MessagesController.getInstance(currentAccount).isDialogMuted(dialog_id); if (muted) { + updateTitleIcons(true); AndroidUtilities.runOnUIThread(() -> { ChatActivity.this.toggleMute(true); }, 150); @@ -2989,39 +3050,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - editTextItem = menu.addItem(0, R.drawable.ic_ab_other, themeDelegate); - editTextItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); - editTextItem.setTag(null); - editTextItem.setVisibility(View.GONE); - - editTextItem.addSubItem(text_transalte, LocaleController.getString("Translate", R.string.Translate)); - - editTextItem.addSubItem(text_spoiler, LocaleController.getString("Spoiler", R.string.Spoiler)); - 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); - editTextItem.addSubItem(text_bold, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Italic", R.string.Italic)); - stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/ritalic.ttf")), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_italic, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Mono", R.string.Mono)); - stringBuilder.setSpan(new TypefaceSpan(Typeface.MONOSPACE), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_mono, stringBuilder); - if (currentEncryptedChat == null || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) >= 101) { - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Strike", R.string.Strike)); - TextStyleSpan.TextStyleRun run = new TextStyleSpan.TextStyleRun(); - run.flags |= TextStyleSpan.FLAG_STYLE_STRIKE; - stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_strike, stringBuilder); - stringBuilder = new SpannableStringBuilder(LocaleController.getString("Underline", R.string.Underline)); - run = new TextStyleSpan.TextStyleRun(); - run.flags |= TextStyleSpan.FLAG_STYLE_UNDERLINE; - stringBuilder.setSpan(new TextStyleSpan(run), 0, stringBuilder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - editTextItem.addSubItem(text_underline, stringBuilder); - } - editTextItem.addSubItem(text_link, LocaleController.getString("CreateLink", R.string.CreateLink)); - editTextItem.addSubItem(text_mention, LocaleController.getString("CreateMention", R.string.CreateMention)); - editTextItem.addSubItem(text_regular, LocaleController.getString("Regular", R.string.Regular)); - if (searchItem != null) { headerItem.addSubItem(search, R.drawable.baseline_search_24, LocaleController.getString("Search", R.string.Search), themeDelegate); } @@ -3102,6 +3130,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateBotButtons(); } } + menu.setVisibility(inMenuMode ? View.GONE : View.VISIBLE); updateTitle(); avatarContainer.updateOnlineCount(); @@ -3110,7 +3139,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatMode == 0 && !isThreadChat() && reportType < 0) { attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other, themeDelegate).setOverrideMenuClick(true).setAllowCloseAnimation(false); - attachItem.setContentDescription(LocaleController.getString("AccDescrAttachButton", R.string.AccDescrAttachButton)); + attachItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); attachItem.setVisibility(View.GONE); } @@ -3246,78 +3275,89 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return chatListView.getTranslationY(); } - AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { + { + adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { - @Override - protected void onTransitionStart(boolean keyboardVisible, int contentHeight) { - wasManualScroll = true; - if (chatActivityEnterView != null) { - chatActivityEnterView.onAdjustPanTransitionStart(keyboardVisible, contentHeight); - } - } - - @Override - protected void onTransitionEnd() { - if (chatActivityEnterView != null) { - chatActivityEnterView.onAdjustPanTransitionEnd(); - } - } - - @Override - protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { - if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { - return; - } - contentPanTranslation = y; - if (chatAttachAlert != null && chatAttachAlert.isShowing()) { - setNonNoveTranslation(y); - } else { - actionBar.setTranslationY(y); - emptyViewContainer.setTranslationY(y / 2); - progressView.setTranslationY(y / 2); - contentView.setBackgroundTranslation((int) y); - instantCameraView.onPanTranslationUpdate(y); - if (blurredView != null) { - blurredView.drawable.onPanTranslationUpdate(y); + @Override + protected void onTransitionStart(boolean keyboardVisible, int contentHeight) { + wasManualScroll = true; + if (chatActivityEnterView != null) { + chatActivityEnterView.onAdjustPanTransitionStart(keyboardVisible, contentHeight); + } + if (mentionContainer != null) { + mentionContainer.onPanTransitionStart(); } - setFragmentPanTranslationOffset((int) y); - invalidateChatListViewTopPadding(); - invalidateMessagesVisiblePart(); } - chatListView.invalidate(); - updateBulletinLayout(); - if (chatActivityEnterView != null) { - chatActivityEnterView.onAdjustPanTransitionUpdate(y, progress, keyboardVisible); - } - } - @Override - protected boolean heightAnimationEnabled() { - ActionBarLayout actionBarLayout = getParentLayout(); - if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { - return false; + @Override + protected void onTransitionEnd() { + if (chatActivityEnterView != null) { + chatActivityEnterView.onAdjustPanTransitionEnd(); + } + if (mentionContainer != null) { + mentionContainer.onPanTransitionEnd(); + } } - if (System.currentTimeMillis() - activityResumeTime < 250) { - return false; - } - if ((ChatActivity.this == actionBarLayout.getLastFragment() && actionBarLayout.isTransitionAnimationInProgress()) || actionBarLayout.isPreviewOpenAnimationInProgress() || isPaused || !openAnimationEnded || (chatAttachAlert != null && chatAttachAlert.isShowing())) { - return false; - } - if (chatActivityEnterView != null && chatActivityEnterView.getTrendingStickersAlert() != null && chatActivityEnterView.getTrendingStickersAlert().isShowing()) { - return false; - } - return true; - } - @Override - protected int startOffset() { - int keyboardSize = getKeyboardHeight(); - if (keyboardSize <= AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing()) { - return chatActivityEnterView.getEmojiPadding(); + @Override + protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { + if (getParentLayout() != null && getParentLayout().isPreviewOpenAnimationInProgress()) { + return; + } + contentPanTranslation = y; + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + setNonNoveTranslation(y); + } else { + actionBar.setTranslationY(y); + emptyViewContainer.setTranslationY(y / 2); + progressView.setTranslationY(y / 2); + contentView.setBackgroundTranslation((int) y); + instantCameraView.onPanTranslationUpdate(y); + if (blurredView != null) { + blurredView.drawable.onPanTranslationUpdate(y); + } + setFragmentPanTranslationOffset((int) y); + invalidateChatListViewTopPadding(); + invalidateMessagesVisiblePart(); + } + chatListView.invalidate(); + updateBulletinLayout(); + if (chatActivityEnterView != null) { + chatActivityEnterView.onAdjustPanTransitionUpdate(y, progress, keyboardVisible); + } + if (mentionContainer != null) { + mentionContainer.onPanTransitionUpdate(y); + } } - return 0; - } - }; + + @Override + protected boolean heightAnimationEnabled() { + ActionBarLayout actionBarLayout = getParentLayout(); + if (inPreviewMode || inBubbleMode || AndroidUtilities.isInMultiwindow || actionBarLayout == null || fixedKeyboardHeight > 0) { + return false; + } + if (System.currentTimeMillis() - activityResumeTime < 250) { + return false; + } + if ((ChatActivity.this == actionBarLayout.getLastFragment() && actionBarLayout.isTransitionAnimationInProgress()) || actionBarLayout.isPreviewOpenAnimationInProgress() || isPaused || !openAnimationEnded || (chatAttachAlert != null && chatAttachAlert.isShowing())) { + return false; + } + if (chatActivityEnterView != null && chatActivityEnterView.getTrendingStickersAlert() != null && chatActivityEnterView.getTrendingStickersAlert().isShowing()) { + return false; + } + return true; + } + + @Override + protected int startOffset() { + int keyboardSize = getKeyboardHeight(); + if (keyboardSize <= AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing()) { + return chatActivityEnterView.getEmojiPadding(); + } + return 0; + } + }; + } @Override protected void onAttachedToWindow() { @@ -3348,6 +3388,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }); } + private float x, y; + private long pressTime; + @Override public boolean dispatchTouchEvent(MotionEvent ev) { float expandY; @@ -3359,6 +3402,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (scrimView != null || chatActivityEnterView != null && chatActivityEnterView.isStickersExpanded() && ev.getY() < expandY) { return false; } + + keyboardHideHelper.onTouch(adjustPanLayoutHelper, this, chatListView, chatActivityEnterView, ChatActivity.this, ev); lastTouchY = ev.getY(); TextSelectionHelper.TextSelectionOverlay selectionOverlay = textSelectionHelper.getOverlayView(context); ev.offsetLocation(-selectionOverlay.getX(), -selectionOverlay.getY()); @@ -3391,7 +3436,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; } - return super.dispatchTouchEvent(ev); + boolean r = false; + if (isInPreviewMode() && allowExpandPreviewByClick) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + boolean pressedOnPageDownButtons = false; + int[] off = new int[2]; + getLocationInWindow(off); + int[] pos = new int[2]; + if (pagedownButton != null) { + pagedownButton.getLocationInWindow(pos); + AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + pagedownButton.getMeasuredWidth(), pos[1] - off[1] + pagedownButton.getMeasuredHeight()); + if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { + pressedOnPageDownButtons = true; + } + } + if (!pressedOnPageDownButtons && mentiondownButton != null) { + mentiondownButton.getLocationInWindow(pos); + AndroidUtilities.rectTmp2.set(pos[0] - off[0], pos[1] - off[1], pos[0] - off[0] + mentiondownButton.getMeasuredWidth(), pos[1] - off[1] + mentiondownButton.getMeasuredHeight()); + if (AndroidUtilities.rectTmp2.contains((int) ev.getX(), (int) ev.getY())) { + pressedOnPageDownButtons = true; + } + } + if (!pressedOnPageDownButtons) { + x = ev.getX(); + y = ev.getY(); + pressTime = SystemClock.elapsedRealtime(); + r = true; + } else { + pressTime = -1; + } + } else if (ev.getAction() == MotionEvent.ACTION_UP) { + if (MathUtils.distance(x, y, ev.getX(), ev.getY()) < AndroidUtilities.dp(6) && SystemClock.elapsedRealtime() - pressTime <= ViewConfiguration.getTapTimeout()) { + parentLayout.expandPreviewFragment(); + ev.setAction(MotionEvent.ACTION_CANCEL); + } + pressTime = -1; + } else if (ev.getAction() == MotionEvent.ACTION_CANCEL) { + pressTime = -1; + } + } + + return super.dispatchTouchEvent(ev) || r; } @Override @@ -3477,7 +3562,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (pullingDownAnimateProgress != 0) { transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; } - canvas.translate(0, -pullingDownOffset - transitionOffset); + canvas.translate(0, -pullingDownOffset - transitionOffset + pullingBottomOffset); super.drawChild(canvas, videoPlayerContainer, drawingTime); if (drawLaterRoundProgressCell != null) { canvas.save(); @@ -3601,7 +3686,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not canvas.translate(scrimView.getLeft(), scrimView.getTop()); if (scrimView == actionBar.getBackButton()) { int r = Math.max(scrimView.getMeasuredWidth(), scrimView.getMeasuredHeight()) / 2; - canvas.drawCircle(r, r, r * 0.8f, actionBarBackgroundPaint); + canvas.drawCircle(r, r, r * 0.7f, actionBarBackgroundPaint); } scrimView.draw(canvas); canvas.restoreToCount(c); @@ -3669,7 +3754,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } canvas.save(); - canvas.clipRect(0, listTop, getMeasuredWidth(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset); + canvas.clipRect(0, listTop + (mentionContainer != null ? mentionContainer.clipTop() : 0), getMeasuredWidth(), chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset - (mentionContainer != null ? mentionContainer.clipBottom() : 0)); canvas.translate(0, chatListView.getY()); scrimGroup.transitionParams.cell.drawBackground(canvas, (int) l, (int) t, (int) r, (int) b, scrimGroup.transitionParams.pinnedTop, scrimGroup.transitionParams.pinnedBotton, selected, contentView.getKeyboardHeight()); canvas.restore(); @@ -3685,6 +3770,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not float viewClipRight = chatListView.getRight(); float viewClipBottom = chatListView.getY() + chatListView.getMeasuredHeight() - blurredViewBottomOffset; + if (mentionContainer != null) { + viewClipTop += mentionContainer.clipTop(); + viewClipBottom -= mentionContainer.clipBottom(); + } + if (cell == null || !cell.getTransitionParams().animateBackgroundBoundsInner) { viewClipLeft = Math.max(viewClipLeft, chatListView.getLeft() + child.getX()); viewClipTop = Math.max(viewClipTop, chatListView.getTop() + child.getY()); @@ -3785,14 +3875,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (scrimView != null || messageEnterTransitionContainer.isRunning()) { - if (pagedownButton != null && pagedownButton.getTag() != null) { - super.drawChild(canvas, pagedownButton, SystemClock.uptimeMillis()); - } - if (mentiondownButton != null && mentiondownButton.getTag() != null) { - super.drawChild(canvas, mentiondownButton, SystemClock.uptimeMillis()); - } - if (reactionsMentiondownButton != null && reactionsMentiondownButton.getTag() != null) { - super.drawChild(canvas, reactionsMentiondownButton, SystemClock.uptimeMillis()); + if (mentionContainer == null || mentionContainer.getVisibility() != View.VISIBLE) { + if (pagedownButton != null && pagedownButton.getTag() != null) { + super.drawChild(canvas, pagedownButton, SystemClock.uptimeMillis()); + } + if (mentiondownButton != null && mentiondownButton.getTag() != null) { + super.drawChild(canvas, mentiondownButton, SystemClock.uptimeMillis()); + } + if (reactionsMentiondownButton != null && reactionsMentiondownButton.getTag() != null) { + super.drawChild(canvas, reactionsMentiondownButton, SystemClock.uptimeMillis()); + } } if (floatingDateView != null && floatingDateView.getTag() != null) { super.drawChild(canvas, floatingDateView, SystemClock.uptimeMillis()); @@ -3830,6 +3922,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not top = bottomOverlayChat.getTop() + AndroidUtilities.dp2(2); bottom = bottomOverlayChat.getBottom(); } + top -= (int) ((pullingDownAnimateToActivity == null ? 0 : pullingDownAnimateToActivity.pullingBottomOffset) * pullingDownAnimateProgress); pullingDownDrawable.drawBottomPanel(canvas, top, bottom, getMeasuredWidth()); } if (pullingDownAnimateToActivity != null) { @@ -3893,7 +3986,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not // if (showAudioCallAsIcon) { // headerItem.hideSubItem(call); if (userInfo != null && userInfo.phone_calls_available) { - headerItem.showSubItem(call); + headerItem.showSubItem(call, true); } } globalIgnoreLayout = false; @@ -4024,31 +4117,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (child == mentionContainer) { FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) mentionContainer.getLayoutParams(); - if (mentionsAdapter.isBannedInline()) { + if (mentionContainer.getAdapter().isBannedInline()) { child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST)); } else { int height; - mentionListViewIgnoreLayout = true; - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout()) { - int size = mentionGridLayoutManager.getRowsCount(widthSize); + mentionContainer.setIgnoreLayout(true); + LinearLayoutManager layoutManager = mentionContainer.getCurrentLayoutManager(); + if (layoutManager instanceof ExtendedGridLayoutManager) { + int size = ((ExtendedGridLayoutManager) layoutManager).getRowsCount(widthSize); int maxHeight = size * 102; - if (mentionsAdapter.isBotContext()) { - if (mentionsAdapter.getBotContextSwitch() != null) { + if (mentionContainer.getAdapter().isBotContext()) { + if (mentionContainer.getAdapter().getBotContextSwitch() != null) { maxHeight += 34; } } height = heightSize - chatActivityEnterView.getMeasuredHeight() + (maxHeight != 0 ? AndroidUtilities.dp(2) : 0); int padding = Math.max(0, height - AndroidUtilities.dp(Math.min(maxHeight, 68 * 1.8f))); - if (mentionLayoutManager.getReverseLayout()) { - mentionListView.setPadding(0, 0, 0, padding); - } else { - mentionListView.setPadding(0, padding, 0, 0); - } } else { - int size = mentionsAdapter.getItemCount(); + int size = mentionContainer.getAdapter().getLastItemCount(); int maxHeight = 0; - if (mentionsAdapter.isBotContext()) { - if (mentionsAdapter.getBotContextSwitch() != null) { + if (mentionContainer.getAdapter().isBotContext()) { + if (mentionContainer.getAdapter().getBotContextSwitch() != null) { maxHeight += 36; size -= 1; } @@ -4057,20 +4146,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not maxHeight += size * 36; } height = heightSize - chatActivityEnterView.getMeasuredHeight() + (maxHeight != 0 ? AndroidUtilities.dp(2) : 0); - int padding = Math.max(0, height - AndroidUtilities.dp(Math.min(maxHeight, 68 * 1.8f))); - if (mentionLayoutManager.getReverseLayout()) { - mentionListView.setPadding(0, 0, 0, padding); - } else { - mentionListView.setPadding(0, padding, 0, 0); - } } layoutParams.height = height; layoutParams.topMargin = 0; - mentionListViewIgnoreLayout = false; + mentionContainer.setIgnoreLayout(false); child.measure(MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY)); } + mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); } else if (child == textSelectionHelper.getOverlayView(context)) { int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); int h = heightSize + blurredViewTopOffset; @@ -4194,6 +4278,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not childTop = 0; } else if (child == mentionContainer) { childTop -= chatActivityEnterView.getMeasuredHeight() - AndroidUtilities.dp(2); + mentionContainer.setTranslationY(chatActivityEnterView.getAnimatedTop()); } else if (child == pagedownButton || child == mentiondownButton || child == reactionsMentiondownButton) { if (!inPreviewMode) { childTop -= chatActivityEnterView.getMeasuredHeight(); @@ -4381,8 +4466,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { oldMessage = null; } - if (mentionsAdapter != null) { - mentionsAdapter.onDestroy(); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().onDestroy(); } chatListView = new RecyclerListView(context, themeDelegate) { @@ -4492,6 +4577,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onInterceptTouchEvent(MotionEvent e) { textSelectionHelper.checkSelectionCancel(e); + if (keyboardHideHelper.disableScrolling()) { + return false; + } if (isFastScrollAnimationRunning()) { return false; } @@ -4663,6 +4751,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onTouchEvent(MotionEvent e) { textSelectionHelper.checkSelectionCancel(e); + if (keyboardHideHelper.disableScrolling()) { + return false; + } if (e.getAction() == MotionEvent.ACTION_DOWN) { scrollByTouch = true; } @@ -4805,11 +4896,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not drawReplyButton(c); } - if (!NekoConfig.disableSwipeToNext.Bool() && pullingDownOffset != 0) { + if (!NekoConfig.disableSwipeToNext.Bool() && pullingDownOffset != 0 && !isInPreviewMode()) { c.save(); float transitionOffset = 0; if (pullingDownAnimateProgress != 0) { - transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset) * pullingDownAnimateProgress; + transitionOffset = (chatListView.getMeasuredHeight() - pullingDownOffset + (pullingDownAnimateToActivity == null ? 0 : pullingDownAnimateToActivity.pullingBottomOffset)) * pullingDownAnimateProgress; } c.translate(0, getMeasuredHeight() - blurredViewBottomOffset - transitionOffset); if (pullingDownDrawable == null) { @@ -5627,7 +5718,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.setInstantClick(true); chatListView.setDisableHighlightState(true); chatListView.setTag(1); - chatListView.setVerticalScrollBarEnabled(true); + chatListView.setVerticalScrollBarEnabled(!SharedConfig.chatBlurEnabled()); chatListView.setAdapter(chatAdapter = new ChatActivityAdapter(context)); chatListView.setClipToPadding(false); chatListView.setAnimateEmptyView(true, 1); @@ -6316,6 +6407,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateMessagesVisiblePart(false); } }); + pinnedMessageView.setEnabled(!isInPreviewMode()); View selector = new View(context); selector.setBackground(Theme.getSelectorDrawable(false)); @@ -6777,59 +6869,63 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return true; }); - mentionContainer = new FrameLayout(context) { - - private Rect padding; - - @Override - public void onDraw(Canvas canvas) { - if (mentionListView.getChildCount() <= 0) { - return; - } - if (mentionLayoutManager.getReverseLayout()) { - float top = mentionListView.getY() + mentionListViewScrollOffsetY + AndroidUtilities.dp(2); - float bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); - Theme.chat_composeShadowDrawable.setBounds(0, (int) bottom, getMeasuredWidth(), (int) top); - Theme.chat_composeShadowDrawable.draw(canvas); - canvas.drawRect(0, 0, getMeasuredWidth(), top, getThemedPaint(Theme.key_paint_chatComposeBackground)); - } else { - int top = (int) mentionListView.getY(); - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout() && mentionsAdapter.getBotContextSwitch() == null) { - top += mentionListViewScrollOffsetY - AndroidUtilities.dp(4); - } else { - top += mentionListViewScrollOffsetY - AndroidUtilities.dp(2); - } - if (mentionsAdapter.isMediaLayout()) { - if (padding == null) { - padding = new Rect(); - Theme.chat_composeShadowRoundDrawable.getPadding(padding); - } - Theme.chat_composeShadowRoundDrawable.setBounds(-padding.left, top - padding.top - AndroidUtilities.dp(8), getMeasuredWidth() + padding.right, (int) (bottomPanelTranslationYReverse + getMeasuredHeight())); - Theme.chat_composeShadowRoundDrawable.draw(canvas); - } else { - int bottom = top + Theme.chat_composeShadowDrawable.getIntrinsicHeight(); - Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom); - Theme.chat_composeShadowDrawable.draw(canvas); - canvas.drawRect(0, bottom, getMeasuredWidth(), bottomPanelTranslationYReverse + getMeasuredHeight(), getThemedPaint(Theme.key_paint_chatComposeBackground)); - } - } - } - - @Override - public void requestLayout() { - if (mentionListViewIgnoreLayout) { - return; - } - super.requestLayout(); - } - }; - mentionContainer.setVisibility(View.GONE); updateMessageListAccessibilityVisibility(); - mentionContainer.setWillNotDraw(false); reactionsMentiondownButton = new FrameLayout(context); contentView.addView(reactionsMentiondownButton, LayoutHelper.createFrame(46, 61, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 7, 5)); + mentionContainer = new MentionsContainerView(context, dialog_id, threadMessageId, contentView, themeDelegate) { + + @Override + protected boolean canOpen() { + return bottomOverlay.getVisibility() != View.VISIBLE || searchingForUser; + } + + @Override + protected void onOpen() { + if (allowStickersPanel && (!getAdapter().isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { + if (currentEncryptedChat != null && getAdapter().isBotContext()) { + SharedPreferences preferences = MessagesController.getGlobalMainSettings(); + if (!preferences.getBoolean("secretbot", false)) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); + preferences.edit().putBoolean("secretbot", true).commit(); + } + } + } + updateMessageListAccessibilityVisibility(); + } + + @Override + protected void onClose() { + updateMessageListAccessibilityVisibility(); + } + + @Override + protected void onContextSearch(boolean searching) { + if (chatActivityEnterView != null) { + chatActivityEnterView.setCaption(getAdapter().getBotCaption()); + chatActivityEnterView.showContextProgress(searching); + } + } + + @Override + protected void onContextClick(TLRPC.BotInlineResult result) { + if (getParentActivity() == null || result.content == null) { + return; + } + if (result.type.equals("video") || result.type.equals("web_player_video")) { + int[] size = MessageObject.getInlineResultWidthAndHeight(result); + EmbedBottomSheet.show(getParentActivity(), null, botContextProvider, result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1], isKeyboardVisible()); + } else { + processExternalUrl(0, result.content.url, false); + } + } + }; + contentView.addView(mentionContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); final ContentPreviewViewer.ContentPreviewViewerDelegate contentPreviewViewerDelegate = new ContentPreviewViewer.ContentPreviewViewerDelegate() { @@ -6872,368 +6968,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return dialog_id; } }; - - mentionListView = new RecyclerListView(context, themeDelegate) { - - private int lastWidth; - private int lastHeight; - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (mentionLayoutManager.getReverseLayout()) { - if (!mentionListViewIsDragging && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { - return false; - } - } else { - if (!mentionListViewIsDragging && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { - return false; - } - } - boolean result = !mentionListViewIsScrolling && ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, mentionListView, 0, null, themeDelegate); - if (mentionsAdapter.isStickers() && event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { - mentionsAdapter.doSomeStickersAction(); - } - return super.onInterceptTouchEvent(event) || result; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mentionLayoutManager.getReverseLayout()) { - if (!mentionListViewIsDragging && mentionListViewScrollOffsetY != 0 && event.getY() > mentionListViewScrollOffsetY) { - return false; - } - } else { - if (!mentionListViewIsDragging && mentionListViewScrollOffsetY != 0 && event.getY() < mentionListViewScrollOffsetY) { - return false; - } - } - //supress warning - return super.onTouchEvent(event); - } - - @Override - public void requestLayout() { - if (mentionListViewIgnoreLayout) { - return; - } - super.requestLayout(); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int width = r - l; - int height = b - t; - - int newPosition = -1; - int newTop = 0; - if (!mentionLayoutManager.getReverseLayout() && mentionListView != null && mentionListViewLastViewPosition >= 0 && width == lastWidth && height - lastHeight != 0) { - newPosition = mentionListViewLastViewPosition; - newTop = mentionListViewLastViewTop + height - lastHeight - getPaddingTop(); - } - - super.onLayout(changed, l, t, r, b); - - if (newPosition != -1) { - mentionListViewIgnoreLayout = true; - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout()) { - mentionGridLayoutManager.scrollToPositionWithOffset(newPosition, newTop); - } else { - mentionLayoutManager.scrollToPositionWithOffset(newPosition, newTop); - } - super.onLayout(false, l, t, r, b); - mentionListViewIgnoreLayout = false; - } - - lastHeight = height; - lastWidth = width; - mentionListViewUpdateLayout(); - } - - @Override - public void setTranslationY(float translationY) { - super.setTranslationY(translationY); - mentionContainer.invalidate(); - } - }; - mentionListView.setOnTouchListener((v, event) -> ContentPreviewViewer.getInstance().onTouch(event, mentionListView, 0, mentionsOnItemClickListener, mentionsAdapter.isStickers() ? contentPreviewViewerDelegate : null, themeDelegate)); - mentionListView.setTag(2); - mentionLayoutManager = new LinearLayoutManager(context) { - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - - @Override - public void setReverseLayout(boolean reverseLayout) { - super.setReverseLayout(reverseLayout); - invalidateChatListViewTopPadding(); - } - }; - mentionLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); - mentionGridLayoutManager = new ExtendedGridLayoutManager(context, 100) { - - private Size size = new Size(); - - @Override - protected Size getSizeForItem(int i) { - if (mentionsAdapter.getBotContextSwitch() != null) { - i++; - } - size.width = 0; - size.height = 0; - Object object = mentionsAdapter.getItem(i); - if (object instanceof TLRPC.BotInlineResult) { - TLRPC.BotInlineResult inlineResult = (TLRPC.BotInlineResult) object; - if (inlineResult.document != null) { - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(inlineResult.document.thumbs, 90); - size.width = thumb != null ? thumb.w : 100; - size.height = thumb != null ? thumb.h : 100; - for (int b = 0; b < inlineResult.document.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.document.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } - } - } else if (inlineResult.content != null) { - for (int b = 0; b < inlineResult.content.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.content.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } - } - } else if (inlineResult.thumb != null) { - for (int b = 0; b < inlineResult.thumb.attributes.size(); b++) { - TLRPC.DocumentAttribute attribute = inlineResult.thumb.attributes.get(b); - if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { - size.width = attribute.w; - size.height = attribute.h; - break; - } - } - } else if (inlineResult.photo != null) { - TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.photoSize); - if (photoSize != null) { - size.width = photoSize.w; - size.height = photoSize.h; - } - } - } - return size; - } - - @Override - protected int getFlowItemCount() { - if (mentionsAdapter.getBotContextSwitch() != null) { - return getItemCount() - 1; - } - return super.getFlowItemCount(); - } - }; - mentionGridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - Object object = mentionsAdapter.getItem(position); - if (object instanceof TLRPC.TL_inlineBotSwitchPM) { - return 100; - } else if (object instanceof TLRPC.Document) { - return 20; - } else { - if (mentionsAdapter.getBotContextSwitch() != null) { - position--; - } - return mentionGridLayoutManager.getSpanSizeForItem(position); - } - } + mentionContainer.getListView().setOnTouchListener((v, event) -> { + return ContentPreviewViewer.getInstance().onTouch(event, mentionContainer.getListView(), 0, mentionsOnItemClickListener, mentionContainer.getAdapter().isStickers() ? contentPreviewViewerDelegate : null, themeDelegate); }); - mentionListView.addItemDecoration(new RecyclerView.ItemDecoration() { - @Override - public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { - outRect.left = 0; - outRect.right = 0; - outRect.top = 0; - outRect.bottom = 0; - if (parent.getLayoutManager() == mentionGridLayoutManager) { - int position = parent.getChildAdapterPosition(view); - if (mentionsAdapter.isStickers()) { - return; - } else if (mentionsAdapter.getBotContextSwitch() != null) { - if (position == 0) { - return; - } - position--; - if (!mentionGridLayoutManager.isFirstRow(position)) { - outRect.top = AndroidUtilities.dp(2); - } - } else { - outRect.top = AndroidUtilities.dp(2); - } - outRect.right = mentionGridLayoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2); - } - } - }); - mentionListView.setItemAnimator(null); - mentionListView.setLayoutAnimation(null); - mentionListView.setClipToPadding(false); - mentionListView.setLayoutManager(mentionLayoutManager); - mentionListView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); - mentionContainer.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(context, false, dialog_id, threadMessageId, new MentionsAdapter.MentionsAdapterDelegate() { - @Override - public void needChangePanelVisibility(boolean show) { - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout()) { - mentionListView.setLayoutManager(mentionGridLayoutManager); - } else { - mentionListView.setLayoutManager(mentionLayoutManager); - } - if (show && bottomOverlay.getVisibility() == View.VISIBLE && !searchingForUser) { - show = false; - } -// final int mentionContainerTranslationHidden = AndroidUtilities.dp(8) * (mentionLayoutManager.getReverseLayout() ? -1 : 1); - if (show) { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - mentionListAnimation = null; - } - - if (mentionContainer.getVisibility() == View.VISIBLE) { - mentionContainer.setAlpha(1.0f); - return; - } - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout()) { - mentionGridLayoutManager.scrollToPositionWithOffset(0, 10000); - } else if (!mentionLayoutManager.getReverseLayout()) { - mentionLayoutManager.scrollToPositionWithOffset(0, mentionLayoutManager.getReverseLayout() ? -10000 : 10000); - } - if (allowStickersPanel && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { - if (currentEncryptedChat != null && mentionsAdapter.isBotContext()) { - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - if (!preferences.getBoolean("secretbot", false)) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); - builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); - builder.setMessage(LocaleController.getString("SecretChatContextBotAlert", R.string.SecretChatContextBotAlert)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - preferences.edit().putBoolean("secretbot", true).apply(); - } - } - mentionContainer.setVisibility(View.VISIBLE); - updateMessageListAccessibilityVisibility(); - mentionContainer.setTag(null); - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) -// ObjectAnimator.ofFloat(mentionContainer, View.TRANSLATION_Y, mentionContainerTranslationHidden, 0f) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); - mentionListAnimation.start(); - } else { - mentionContainer.setAlpha(1.0f); -// mentionContainer.setTranslationY(0f); - mentionContainer.setVisibility(View.INVISIBLE); - updateMessageListAccessibilityVisibility(); - } - } else { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - mentionListAnimation = null; - } - - if (mentionContainer.getVisibility() == View.GONE) { - return; - } - if (allowStickersPanel) { - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) -// ObjectAnimator.ofFloat(mentionContainer, View.TRANSLATION_Y, 0, mentionContainerTranslationHidden) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionContainer.setVisibility(View.GONE); - mentionContainer.setTag(null); - updateMessageListAccessibilityVisibility(); - mentionListAnimation = null; - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); - mentionListAnimation.start(); - } else { - mentionContainer.setTag(null); -// mentionContainer.setTranslationY(mentionContainerTranslationHidden); - mentionContainer.setVisibility(View.GONE); - updateMessageListAccessibilityVisibility(); - } - } - } - - @Override - public void onContextSearch(boolean searching) { - if (chatActivityEnterView != null) { - chatActivityEnterView.setCaption(mentionsAdapter.getBotCaption()); - chatActivityEnterView.showContextProgress(searching); - } - } - - @Override - public void onContextClick(TLRPC.BotInlineResult result) { - if (getParentActivity() == null || result.content == null) { - return; - } - if (result.type.equals("video") || result.type.equals("web_player_video")) { - int[] size = MessageObject.getInlineResultWidthAndHeight(result); - EmbedBottomSheet.show(getParentActivity(), null, botContextProvider, result.title != null ? result.title : "", result.description, result.content.url, result.content.url, size[0], size[1], isKeyboardVisible()); - } else { - processExternalUrl(0, result.content.url, false); - } - } - }, themeDelegate)); if (!ChatObject.isChannel(currentChat) || currentChat.megagroup) { - mentionsAdapter.setBotInfo(botInfo); + mentionContainer.getAdapter().setBotInfo(botInfo); } - mentionsAdapter.setParentFragment(this); - mentionsAdapter.setChatInfo(chatInfo); - mentionsAdapter.setNeedUsernames(currentChat != null); - mentionsAdapter.setNeedBotContext(true); - mentionsAdapter.setBotsCount(currentChat != null ? botsCount : 1); - mentionListView.setOnItemClickListener(mentionsOnItemClickListener = (view, position) -> { - if (mentionsAdapter.isBannedInline()) { + mentionContainer.getAdapter().setParentFragment(this); + mentionContainer.getAdapter().setChatInfo(chatInfo); + mentionContainer.getAdapter().setNeedUsernames(currentChat != null); + mentionContainer.getAdapter().setNeedBotContext(true); + mentionContainer.getAdapter().setBotsCount(currentChat != null ? botsCount : 1); + mentionContainer.getListView().setOnItemClickListener(mentionsOnItemClickListener = (view, position) -> { + if (position == 0 || mentionContainer.getAdapter().isBannedInline()) { return; } - Object object = mentionsAdapter.getItem(position); - int start = mentionsAdapter.getResultStartPosition(); - int len = mentionsAdapter.getResultLength(); + position--; + Object object = mentionContainer.getAdapter().getItem(position); + int start = mentionContainer.getAdapter().getResultStartPosition(); + int len = mentionContainer.getAdapter().getResultLength(); if (object instanceof TLRPC.TL_document) { if (chatMode == 0 && checkSlowMode(view)) { return; @@ -7243,7 +6996,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not sendAnimationData = ((StickerCell) view).getSendAnimationData(); } TLRPC.TL_document document = (TLRPC.TL_document) object; - Object parent = mentionsAdapter.getItemParent(position); + Object parent = mentionContainer.getAdapter().getItemParent(position); if (chatMode == MODE_SCHEDULED) { String query = stickersAdapter.getQuery(); AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), parent, null, notify, scheduleDate), themeDelegate); @@ -7277,7 +7030,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } else if (object instanceof String) { - if (mentionsAdapter.isBotCommands()) { + if (mentionContainer.getAdapter().isBotCommands()) { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> { getSendMessagesHelper().sendMessage((String) object, dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, notify, scheduleDate, null); @@ -7323,9 +7076,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if ((result.type.equals("photo") && (result.photo != null || result.content != null) || result.type.equals("gif") && (result.document != null || result.content != null) || result.type.equals("video") && (result.document != null/* || result.content_url != null*/))) { - ArrayList arrayList = botContextResults = new ArrayList<>(mentionsAdapter.getSearchResultBotContext()); + ArrayList arrayList = botContextResults = new ArrayList<>(mentionContainer.getAdapter().getSearchResultBotContext()); PhotoViewer.getInstance().setParentActivity(getParentActivity(), themeDelegate); - PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionsAdapter.getItemPosition(position), 3, false, botContextProvider, ChatActivity.this); + PhotoViewer.getInstance().openPhotoForSelect(arrayList, mentionContainer.getAdapter().getItemPosition(position), 3, false, botContextProvider, ChatActivity.this); } else { if (chatMode == MODE_SCHEDULED) { AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, (notify, scheduleDate) -> sendBotInlineResult(result, notify, scheduleDate), themeDelegate); @@ -7339,18 +7092,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not String code = ((MediaDataController.KeywordResult) object).emoji; chatActivityEnterView.addEmojiToRecent(code); chatActivityEnterView.replaceWithText(start, len, code, true); + mentionContainer.updateVisibility(false); } }); - - mentionListView.setOnItemLongClickListener((view, position) -> { - if (getParentActivity() == null || !mentionsAdapter.isLongClickEnabled()) { + mentionContainer.getListView().setOnItemLongClickListener((view, position) -> { + if (getParentActivity() == null || !mentionContainer.getAdapter().isLongClickEnabled()) { return false; } - Object object = mentionsAdapter.getItem(position); - int start = mentionsAdapter.getResultStartPosition(); - int len = mentionsAdapter.getResultLength(); + Object object = mentionContainer.getAdapter().getItem(position); + int start = mentionContainer.getAdapter().getResultStartPosition(); + int len = mentionContainer.getAdapter().getResultLength(); if (object instanceof String) { - if (mentionsAdapter.isBotCommands()) { + if (mentionContainer.getAdapter().isBotCommands()) { if (URLSpanBotCommand.enabled) { chatActivityEnterView.setFieldText(""); chatActivityEnterView.setCommand(null, (String) object, true, currentChat != null && currentChat.megagroup); @@ -7361,7 +7114,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); - builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionsAdapter.clearRecentHashtags()); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> mentionContainer.getAdapter().clearRecentHashtags()); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); return true; @@ -7379,30 +7132,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; }); - mentionListView.setOnScrollListener(new RecyclerView.OnScrollListener() { - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - mentionListViewIsScrolling = newState != RecyclerView.SCROLL_STATE_IDLE; - mentionListViewIsDragging = newState == RecyclerView.SCROLL_STATE_DRAGGING; - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - int lastVisibleItem; - if ((mentionsAdapter.isStickers() || mentionsAdapter.isBotContext()) && mentionsAdapter.isMediaLayout()) { - lastVisibleItem = mentionGridLayoutManager.findLastVisibleItemPosition(); - } else { - lastVisibleItem = mentionLayoutManager.findLastVisibleItemPosition(); - } - int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; - if (visibleItemCount > 0 && lastVisibleItem > mentionsAdapter.getItemCount() - 5) { - mentionsAdapter.searchForContextBotForNextOffset(); - } - mentionListViewUpdateLayout(); - } - }); - pagedownButtonImage = new ImageView(context); pagedownButtonImage.setImageResource(R.drawable.pagedown); pagedownButtonImage.setScaleType(ImageView.ScaleType.CENTER); @@ -7545,24 +7274,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reactionsMentiondownButton.addView(reactionsMentiondownButtonCounter, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 28, Gravity.TOP | Gravity.LEFT)); reactionsMentiondownButton.setContentDescription(LocaleController.getString("AccDescrReactionMentionDown", R.string.AccDescrReactionMentionDown)); - if (!inMenuMode) { - fragmentLocationContextView = new FragmentContextView(context, this, true, themeDelegate); - fragmentContextView = new FragmentContextView(context, this, false, themeDelegate) { - @Override - protected void playbackSpeedChanged(float value) { - if (Math.abs(value - 1.0f) < 0.001f || Math.abs(value - 1.8f) < 0.001f) { - undoView.showWithAction(0, Math.abs(value - 1.0f) > 0.001f ? UndoView.ACTION_PLAYBACK_SPEED_ENABLED : UndoView.ACTION_PLAYBACK_SPEED_DISABLED, value, null, null); - } + fragmentLocationContextView = new FragmentContextView(context, this, true, themeDelegate); + fragmentContextView = new FragmentContextView(context, this, false, themeDelegate) { + @Override + protected void playbackSpeedChanged(float value) { + if (Math.abs(value - 1.0f) < 0.001f || Math.abs(value - 1.8f) < 0.001f) { + undoView.showWithAction(0, Math.abs(value - 1.0f) > 0.001f ? UndoView.ACTION_PLAYBACK_SPEED_ENABLED : UndoView.ACTION_PLAYBACK_SPEED_DISABLED, value, null, null); } + } + }; + contentView.addView(fragmentLocationContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + contentView.addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); + fragmentContextView.setAdditionalContextView(fragmentLocationContextView); + fragmentLocationContextView.setAdditionalContextView(fragmentContextView); - }; - contentView.addView(fragmentLocationContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); - contentView.addView(fragmentContextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, -36, 0, 0)); - - fragmentContextView.setAdditionalContextView(fragmentLocationContextView); - fragmentLocationContextView.setAdditionalContextView(fragmentContextView); - } + fragmentContextView.setEnabled(!inPreviewMode); + fragmentLocationContextView.setEnabled(!inPreviewMode); if (chatMode != 0) { fragmentContextView.setSupportsCalls(false); @@ -7708,21 +7436,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topLineView.setTranslationY(animatedTop); } } + if (mentionContainer != null) { + mentionContainer.setTranslationY(dy); + } - changeBoundAnimator = ValueAnimator.ofFloat(1f, 0); + changeBoundAnimator = ValueAnimator.ofFloat(dy, 0); changeBoundAnimator.addUpdateListener(a -> { - int v = (int) (dy * (float) a.getAnimatedValue()); - animatedTop = v; + float top = (float) a.getAnimatedValue(); + animatedTop = (int) top; if (topView != null && topView.getVisibility() == View.VISIBLE) { - topView.setTranslationY(animatedTop + (1f - topViewEnterProgress) * topView.getLayoutParams().height); + topView.setTranslationY(top + (1f - topViewEnterProgress) * topView.getLayoutParams().height); if (topLineView != null) { - topLineView.setTranslationY(animatedTop); + topLineView.setTranslationY(top); } } else { if (mentionContainer != null) { - mentionContainer.setTranslationY(v); + mentionContainer.setTranslationY(top); } - chatListView.setTranslationY(v); + chatListView.setTranslationY(top); invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); } @@ -7739,6 +7470,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else { chatListView.setTranslationY(0); + if (mentionContainer != null) { + mentionContainer.setTranslationY(0); + } } changeBoundAnimator = null; } @@ -7789,6 +7523,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setDelegate(new ChatActivityEnterView.ChatActivityEnterViewDelegate() { int lastSize; + boolean isEditTextItemVisibilitySuppressed; @Override public int getContentViewHeight() { @@ -7813,8 +7548,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterViewAnimateBeforeSending = true; } } - if (mentionsAdapter != null) { - mentionsAdapter.addHashtagsFromMessage(message); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().addHashtagsFromMessage(message); } if (scheduleDate != 0) { if (scheduledMessagesCount == -1) { @@ -7869,22 +7604,73 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (end - start > 0) { if (editTextItem.getTag() == null) { editTextItem.setTag(1); - editTextItem.setVisibility(View.VISIBLE); - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.GONE); + + if (editTextItem.getVisibility() != View.VISIBLE) { + if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { + editTextItem.setVisibility(View.VISIBLE); + headerItem.setVisibility(View.GONE); + attachItem.setVisibility(View.GONE); + } else { + ValueAnimator valueAnimator = ValueAnimator.ofFloat(AndroidUtilities.dp(48), 0); + valueAnimator.setDuration(220); + valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + actionBar.setMenuOffsetSuppressed(true); + editTextItem.setVisibility(View.VISIBLE); + menu.translateXItems(AndroidUtilities.dp(48)); + } + + @Override + public void onAnimationEnd(Animator animation) { + actionBar.setMenuOffsetSuppressed(false); + } + }); + valueAnimator.addUpdateListener(animation -> menu.translateXItems((float) animation.getAnimatedValue())); + valueAnimator.start(); + } + } } editTextStart = start; editTextEnd = end; } else { if (editTextItem.getTag() != null) { editTextItem.setTag(null); - editTextItem.setVisibility(View.GONE); - if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { - headerItem.setVisibility(View.GONE); - attachItem.setVisibility(View.VISIBLE); - } else { - headerItem.setVisibility(View.VISIBLE); - attachItem.setVisibility(View.GONE); + if (editTextItem.getVisibility() != View.GONE) { + if (chatMode == 0 && threadMessageId == 0 && !UserObject.isReplyUser(currentUser) && reportType < 0) { + editTextItem.setVisibility(View.GONE); + + if (chatActivityEnterView.hasText() && TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { + headerItem.setVisibility(View.GONE); + attachItem.setVisibility(View.VISIBLE); + } else { + headerItem.setVisibility(View.VISIBLE); + attachItem.setVisibility(View.GONE); + } + } else { + ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, AndroidUtilities.dp(48)); + valueAnimator.setDuration(220); + valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + actionBar.setMenuOffsetSuppressed(true); + isEditTextItemVisibilitySuppressed = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + editTextItem.setVisibility(View.GONE); + menu.translateXItems(0); + + actionBar.setMenuOffsetSuppressed(false); + isEditTextItemVisibilitySuppressed = false; + } + }); + valueAnimator.addUpdateListener(animation -> menu.translateXItems((float) animation.getAnimatedValue())); + valueAnimator.start(); + } } } } @@ -7896,8 +7682,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (stickersAdapter != null && chatActivityEnterView != null && chatActivityEnterView.getVisibility() == View.VISIBLE && (bottomOverlay == null || bottomOverlay.getVisibility() != View.VISIBLE)) { stickersAdapter.searchEmojiByKeyword(text); } - if (mentionsAdapter != null) { - mentionsAdapter.searchUsernameOrHashtag(text.toString(), chatActivityEnterView.getCursorPosition(), messages, false, false); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().searchUsernameOrHashtag(text.toString(), chatActivityEnterView.getCursorPosition(), messages, false, false); } if (waitingForCharaterEnterRunnable != null) { AndroidUtilities.cancelRunOnUIThread(waitingForCharaterEnterRunnable); @@ -7936,7 +7722,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (actionBar.isSearchFieldVisible()) { return; } - if (editTextItem != null) { + if (editTextItem != null && !isEditTextItemVisibilitySuppressed) { editTextItem.setVisibility(View.GONE); } if (TextUtils.isEmpty(chatActivityEnterView.getSlowModeTimer())) { @@ -7957,7 +7743,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (headerItem != null) { headerItem.setVisibility(View.VISIBLE); } - if (editTextItem != null) { + if (editTextItem != null && !isEditTextItemVisibilitySuppressed) { editTextItem.setVisibility(View.GONE); } if (attachItem != null) { @@ -7974,7 +7760,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!loading) { - mentionsAdapter.setNeedBotContext(true); + if (mentionContainer != null) { + mentionContainer.getAdapter().setNeedBotContext(true); + } if (editingMessageObject != null) { AndroidUtilities.runOnUIThread(() -> hideFieldPanel(true), 30); } @@ -8001,24 +7789,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (stickersPanel.getVisibility() == View.VISIBLE) { stickersPanel.setVisibility(View.INVISIBLE); } - if (mentionContainer != null && mentionContainer.getVisibility() == View.VISIBLE) { - mentionContainer.setVisibility(View.INVISIBLE); - updateMessageListAccessibilityVisibility(); - } } else { allowStickersPanel = true; if (stickersPanel.getVisibility() == View.INVISIBLE) { stickersPanel.setVisibility(View.VISIBLE); } - if (mentionContainer != null && mentionContainer.getVisibility() == View.INVISIBLE && (!mentionsAdapter.isBotContext() || (allowContextBotPanel || allowContextBotPanelSecond))) { - mentionContainer.setVisibility(View.VISIBLE); - mentionContainer.setTag(null); - updateMessageListAccessibilityVisibility(); - } } allowContextBotPanel = !chatActivityEnterView.isPopupShowing(); - checkContextBotPanel(); +// checkContextBotPanel(); int size2 = size + (chatActivityEnterView.isPopupShowing() ? 1 << 16 : 0); if (lastSize != size2) { chatActivityEnterViewAnimateFromTop = 0; @@ -8033,7 +7812,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not emojiButtonRed.setVisibility(View.GONE); } allowContextBotPanelSecond = !opened; - checkContextBotPanel(); +// checkContextBotPanel(); } @Override @@ -8130,9 +7909,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomPanelTranslationY = chatActivityEnterView.panelAnimationInProgress() ? chatActivityEnterView.getEmojiPadding() - translation : 0; bottomPanelTranslationYReverse = chatActivityEnterView.panelAnimationInProgress() ? translation : 0; chatActivityEnterView.setTranslationY(translation); + mentionContainer.setTranslationY(translation); contentView.setEmojiOffset(chatActivityEnterView.panelAnimationInProgress(), bottomPanelTranslationY); translation += chatActivityEnterView.getTopViewTranslation(); + mentionContainer.setTranslationY(translation); chatListView.setTranslationY(translation); invalidateChatListViewTopPadding(); @@ -8204,9 +7985,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (progressView != null) { progressView.setTranslationY(translationY); } - if (mentionContainer != null) { - mentionContainer.setTranslationY(translationY); - } invalidateChatListViewTopPadding(); invalidateMessagesVisiblePart(); if (fragmentView != null) { @@ -8230,9 +8008,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (progressView != null) { progressView.setTranslationY(0); } - if (mentionContainer != null) { - mentionContainer.setTranslationY(0); - } } } }; @@ -8487,8 +8262,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not searchUserButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); searchContainer.addView(searchUserButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP, 48, 0, 0, 0)); searchUserButton.setOnClickListener(view -> { - mentionLayoutManager.setReverseLayout(true); - mentionsAdapter.setSearchingMentions(true); + if (mentionContainer != null) { + mentionContainer.setReversed(true); + mentionContainer.getAdapter().setSearchingMentions(true); + } searchCalendarButton.setVisibility(View.GONE); searchUserButton.setVisibility(View.GONE); searchingForUser = true; @@ -8589,7 +8366,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } super.dispatchDraw(canvas); } - }; bottomOverlayChat.isTopView = false; bottomOverlayChat.drawBlur = false; @@ -8653,18 +8429,43 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { if (ChatObject.isNotInChat(currentChat)) { - if (chatInviteRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(chatInviteRunnable); - chatInviteRunnable = null; - } - showBottomOverlayProgress(true, true); - getMessagesController().addUserToChat(currentChat.id, getUserConfig().getCurrentUser(), 0, null, ChatActivity.this, null); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); + if (currentChat.join_request) { +// showDialog(new JoinGroupAlert(context, currentChat, null, this)); + showBottomOverlayProgress(true, true); + MessagesController.getInstance(currentAccount).addUserToChat( + currentChat.id, + UserConfig.getInstance(currentAccount).getCurrentUser(), + 0, + null, + null, + true, + () -> { + showBottomOverlayProgress(false, true); + }, + err -> { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + preferences.edit().putLong("dialog_join_requested_time_" + dialog_id, System.currentTimeMillis()).commit(); + if (err != null && "INVITE_REQUEST_SENT".equals(err.text)) { + JoinGroupAlert.showBulletin(context, this, ChatObject.isChannel(currentChat) && !currentChat.megagroup); + } + showBottomOverlayProgress(false, true); + return false; + } + ); + } else { + if (chatInviteRunnable != null) { + AndroidUtilities.cancelRunOnUIThread(chatInviteRunnable); + chatInviteRunnable = null; + } + showBottomOverlayProgress(true, true); + getMessagesController().addUserToChat(currentChat.id, getUserConfig().getCurrentUser(), 0, null, ChatActivity.this, null); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.closeSearchByActiveAction); - if (hasReportSpam() && reportSpamButton.getTag(R.id.object_tag) != null) { - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("dialog_bar_vis3" + dialog_id, 3).apply(); - getNotificationCenter().postNotificationName(NotificationCenter.peerSettingsDidLoad, dialog_id); + if (hasReportSpam() && reportSpamButton.getTag(R.id.object_tag) != null) { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + preferences.edit().putInt("dialog_bar_vis3" + dialog_id, 3).apply(); + getNotificationCenter().postNotificationName(NotificationCenter.peerSettingsDidLoad, dialog_id); + } } } else { toggleMute(true); @@ -8692,7 +8493,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayImage = new ImageView(context); int color = getThemedColor(Theme.key_chat_fieldOverlayText); - bottomOverlayImage.setImageResource(R.drawable.log_info); + bottomOverlayImage.setImageResource(R.drawable.msg_help); bottomOverlayImage.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); bottomOverlayImage.setScaleType(ImageView.ScaleType.CENTER); if (Build.VERSION.SDK_INT >= 21) { @@ -8953,7 +8754,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topBottom[1] = chatListView.getBottom() - blurredViewBottomOffset; topBottom[0] = chatListView.getTop() + chatListViewPaddingTop - AndroidUtilities.dp(4); }); - emojiAnimationsOverlay = new EmojiAnimationsOverlay(ChatActivity.this, contentView, chatListView, currentAccount, dialog_id, threadMessageId); + emojiAnimationsOverlay = new EmojiAnimationsOverlay(ChatActivity.this, contentView, chatListView, currentAccount, dialog_id, threadMessageId) { + @Override + public void onAllEffectsEnd() { + updateMessagesVisiblePart(false); + } + }; actionBar.setDrawBlurBackground(contentView); TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialog_id); @@ -9069,7 +8875,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setMaxLines(1); setEllipsize(TextUtils.TruncateAt.END); setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); - setBackground(Theme.getRoundRectSelectorWithBackgroundDrawable(AndroidUtilities.dp(16), getThemedColor(Theme.key_featuredStickers_addButton), 0x60ffffff)); + setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 16)); setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); setGravity(Gravity.CENTER); @@ -9079,7 +8885,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure( - View.MeasureSpec.makeMeasureSpec(Math.min(View.MeasureSpec.getSize(widthMeasureSpec), (int) (AndroidUtilities.displaySize.x * 0.35f)), View.MeasureSpec.AT_MOST), + View.MeasureSpec.makeMeasureSpec(Math.min(View.MeasureSpec.getSize(widthMeasureSpec), (int) (AndroidUtilities.displaySize.x * 0.45f)), View.MeasureSpec.AT_MOST), heightMeasureSpec ); } @@ -9296,7 +9102,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private void searchUserMessages(TLRPC.User user, TLRPC.Chat chat) { searchingUserMessages = user; searchingChatMessages = chat; - if (searchItem == null || searchingUserMessages == null && searchingChatMessages == null) { + if (searchItem == null || mentionContainer == null || searchingUserMessages == null && searchingChatMessages == null) { return; } String name; @@ -9319,7 +9125,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Spannable spannable = new SpannableString(from + " " + name); spannable.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_actionBarDefaultSubtitle)), from.length() + 1, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); searchItem.setSearchFieldCaption(spannable); - mentionsAdapter.searchUsernameOrHashtag(null, 0, null, false, true); + mentionContainer.getAdapter().searchUsernameOrHashtag(null, 0, null, false, true); searchItem.setSearchFieldHint(null); searchItem.clearSearchText(); getMediaDataController().searchMessagesInChat("", dialog_id, mergeDialogId, classGuid, 0, threadMessageId, searchingUserMessages, searchingChatMessages); @@ -9689,7 +9495,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateChatListViewTopPadding() { - if (!invalidateChatListViewTopPadding || chatListView == null || fixedKeyboardHeight > 0) { + if (!invalidateChatListViewTopPadding || chatListView == null || (fixedKeyboardHeight > 0 && searchExpandProgress == 0)) { return; } float topPanelViewH = Math.max(0, AndroidUtilities.dp(48) + topChatPanelViewOffset); @@ -9708,7 +9514,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListViewPaddingTop += blurredViewTopOffset; chatListViewPaddingVisibleOffset = 0; chatListViewPaddingTop += contentPanTranslation + bottomPanelTranslationY; - + float searchExpandOffset = 0; + if (searchExpandProgress != 0 && chatActivityEnterView.getVisibility() == View.VISIBLE) { + chatListViewPaddingTop -= (searchExpandOffset = searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); + } if (bottomPanelTranslationY == 0 && !chatActivityEnterView.panelAnimationInProgress() && (contentView.getLayoutParams().height < 0 || (contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && chatActivityEnterView.isPopupShowing()))) { chatListViewPaddingTop += contentView.getKeyboardHeight() <= AndroidUtilities.dp(20) && !AndroidUtilities.isInMultiwindow && !inBubbleMode ? chatActivityEnterView.getEmojiPadding() : contentView.getKeyboardHeight(); } @@ -9730,7 +9539,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (floatingDateView != null) { - floatingDateView.setTranslationY(chatListView.getTranslationY() + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); + floatingDateView.setTranslationY(chatListView.getTranslationY() - searchExpandOffset + chatListViewPaddingTop + floatingDateViewOffset - AndroidUtilities.dp(4)); } int p = chatListView.getMeasuredHeight() * 2 / 3; @@ -9836,15 +9645,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (topChatPanelView != null) { topChatPanelView.setTranslationY(contentPanTranslation + contentPaddingTop + topChatPanelViewOffset); } - if (mentionListView != null && mentionLayoutManager != null && mentionsAdapter != null && !mentionsAdapter.isBotCommands() && !mentionsAdapter.isStickers()) { - if (mentionLayoutManager.getReverseLayout()) { - mentionListView.setTranslationY(contentPanTranslation + contentPaddingTop); - } else { - mentionListView.setTranslationY(bottomPanelTranslationYReverse); - } - } else if (mentionListView != null) { - mentionListView.setTranslationY(bottomPanelTranslationYReverse); - } if (alertView != null && alertView.getVisibility() == View.VISIBLE) { alertView.setTranslationY(contentPanTranslation + contentPaddingTop - AndroidUtilities.dp(50) * (1f - alertViewEnterProgress)); } @@ -10101,7 +9901,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_X, 1.0f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.SCALE_Y, 1.0f), ObjectAnimator.ofFloat(bottomOverlayChatText, View.ALPHA, 1.0f)); - } bottomOverlayAnimation.addListener(new AnimatorListenerAdapter() { @Override @@ -10137,62 +9936,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void sendBotInlineResult(TLRPC.BotInlineResult result, boolean notify, int scheduleDate) { - long uid = mentionsAdapter.getContextBotId(); + if (mentionContainer == null) { + return; + } + long uid = mentionContainer.getAdapter().getContextBotId(); HashMap params = new HashMap<>(); params.put("id", result.id); params.put("query_id", "" + result.query_id); params.put("bot", "" + uid); - params.put("bot_name", mentionsAdapter.getContextBotName()); + params.put("bot_name", mentionContainer.getAdapter().getContextBotName()); SendMessagesHelper.prepareSendingBotContextResult(getAccountInstance(), result, params, dialog_id, replyingMessageObject, getThreadMessage(), notify, scheduleDate); chatActivityEnterView.setFieldText(""); hideFieldPanel(false); getMediaDataController().increaseInlineRaiting(uid); } - private void mentionListViewUpdateLayout() { - if (mentionListView.getChildCount() <= 0) { - mentionListViewLastViewPosition = -1; - return; - } - View child = mentionListView.getChildAt(mentionListView.getChildCount() - 1); - RecyclerListView.Holder holder = (RecyclerListView.Holder) mentionListView.findContainingViewHolder(child); - if (mentionLayoutManager.getReverseLayout()) { - if (holder != null) { - mentionListViewLastViewPosition = holder.getAdapterPosition(); - mentionListViewLastViewTop = child.getBottom(); - } else { - mentionListViewLastViewPosition = -1; - } - - child = mentionListView.getChildAt(0); - holder = (RecyclerListView.Holder) mentionListView.findContainingViewHolder(child); - int newOffset = child.getBottom() < mentionListView.getMeasuredHeight() && holder != null && holder.getAdapterPosition() == 0 ? child.getBottom() : mentionListView.getMeasuredHeight(); - if (mentionListViewScrollOffsetY != newOffset) { - mentionListView.setBottomGlowOffset(mentionListViewScrollOffsetY = newOffset); - mentionListView.setTopGlowOffset(0); - mentionListView.invalidate(); - mentionContainer.invalidate(); - } - } else { - if (holder != null) { - mentionListViewLastViewPosition = holder.getAdapterPosition(); - mentionListViewLastViewTop = child.getTop(); - } else { - mentionListViewLastViewPosition = -1; - } - - child = mentionListView.getChildAt(0); - holder = (RecyclerListView.Holder) mentionListView.findContainingViewHolder(child); - int newOffset = child.getTop() > 0 && holder != null && holder.getAdapterPosition() == 0 ? child.getTop() : 0; - if (mentionListViewScrollOffsetY != newOffset) { - mentionListView.setTopGlowOffset(mentionListViewScrollOffsetY = newOffset); - mentionListView.setBottomGlowOffset(0); - mentionListView.invalidate(); - mentionContainer.invalidate(); - } - } - } - private void checkBotCommands() { URLSpanBotCommand.enabled = false; if (currentUser != null && currentUser.bot) { @@ -10240,7 +9998,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int scrollDirection = RecyclerAnimationScrollHelper.SCROLL_DIRECTION_UNSET; int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { - if (i >= chatAdapter.messagesStartRow && i <= chatAdapter.messagesEndRow) { + if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { TLRPC.Message message = messages.get(i - chatAdapter.messagesStartRow).messageOwner; if (message != null) { boolean scrollDown = message.date < date; @@ -10273,10 +10031,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public void processInlineBotContextPM(TLRPC.TL_inlineBotSwitchPM object) { - if (object == null) { + if (object == null || mentionContainer == null) { return; } - TLRPC.User user = mentionsAdapter.getContextBotUser(); + TLRPC.User user = mentionContainer.getAdapter().getContextBotUser(); if (user == null) { return; } @@ -10311,7 +10069,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } super.dismissInternal(); - onEditTextDialogClose(false); + onEditTextDialogClose(false, true); + } + + @Override + public void onDismissAnimationStart() { + chatAttachAlert.setFocusable(false); + chatActivityEnterView.getEditField().requestFocus(); + if (chatAttachAlert != null && chatAttachAlert.isShowing()) { + AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); + } + onEditTextDialogClose(false, false); } }; chatAttachAlert.setDelegate(new ChatAttachAlert.ChatAttachViewDelegate() { @@ -10357,7 +10125,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (i == 0) { fillEditingMediaWithCaption(photos.get(0).caption, photos.get(0).entities); } - SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, i == 0 ? replyingMessageObject : null, getThreadMessage(), null, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate); + SendMessagesHelper.prepareSendingMedia(getAccountInstance(), photos, dialog_id, replyingMessageObject, getThreadMessage(), null, button == 4 || forceDocument, arg, editingMessageObject, notify, scheduleDate); } afterMessageSend(); chatActivityEnterView.setFieldText(""); @@ -10419,10 +10187,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return keyboardVisible; } - public void onEditTextDialogClose(boolean resetAdjust) { + public void onEditTextDialogClose(boolean resetAdjust, boolean reset) { if (openKeyboardOnAttachMenuClose) { AndroidUtilities.runOnUIThread(() -> chatActivityEnterView.openKeyboard(), 50); - openKeyboardOnAttachMenuClose = false; + if (reset) { + openKeyboardOnAttachMenuClose = false; + } } if (resetAdjust) { AndroidUtilities.requestAdjustResize(getParentActivity(), classGuid); @@ -11198,72 +10968,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(chatAttachAlert); } - private void checkContextBotPanel() { - if (allowStickersPanel && mentionsAdapter != null && mentionsAdapter.isBotContext()) { - if (!allowContextBotPanel && !allowContextBotPanelSecond) { - if (mentionContainer.getVisibility() == View.VISIBLE && mentionContainer.getTag() == null) { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - } - - mentionContainer.setTag(1); - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionContainer.setVisibility(View.INVISIBLE); - mentionListAnimation = null; - updateMessageListAccessibilityVisibility(); - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.start(); - } - } else { - if (mentionContainer.getVisibility() == View.INVISIBLE || mentionContainer.getTag() != null) { - if (mentionListAnimation != null) { - mentionListAnimation.cancel(); - } - mentionContainer.setTag(null); - mentionContainer.setVisibility(View.VISIBLE); - updateMessageListAccessibilityVisibility(); - mentionListAnimation = new AnimatorSet(); - mentionListAnimation.playTogether( - ObjectAnimator.ofFloat(mentionContainer, View.ALPHA, 0.0f, 1.0f) - ); - mentionListAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - - @Override - public void onAnimationCancel(Animator animation) { - if (mentionListAnimation != null && mentionListAnimation.equals(animation)) { - mentionListAnimation = null; - } - } - }); - mentionListAnimation.setDuration(200); - mentionListAnimation.start(); - } - } - } - } +// private void checkContextBotPanel() { +// if (allowStickersPanel && mentionContainer != null && mentionContainer.getAdapter() != null && mentionContainer.getAdapter().isBotContext()) { +// mentionContainer.updateVisibility(allowContextBotPanel && allowContextBotPanelSecond); +// } +// } private void checkAutoDownloadMessages(boolean scrollUp) { if (chatListView == null) { @@ -11548,7 +11257,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Intent videoPickerIntent = new Intent(); videoPickerIntent.setType("video/*"); videoPickerIntent.setAction(Intent.ACTION_GET_CONTENT); - videoPickerIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.MAX_FILE_SIZE); + videoPickerIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.DEFAULT_MAX_FILE_SIZE); Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); @@ -11582,7 +11291,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (Build.VERSION.SDK_INT >= 18) { takeVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(video)); } - takeVideoIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.MAX_FILE_SIZE); + takeVideoIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.DEFAULT_MAX_FILE_SIZE); currentPicturePath = video.getAbsolutePath(); } startActivityForResult(takeVideoIntent, 2); @@ -11856,7 +11565,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if ((scheduleDate != 0) == (chatMode == MODE_SCHEDULED)) { waitingForSendingMessageLoad = true; } - AlertsCreator.showSendMediaAlert(getSendMessagesHelper().sendMessage(arrayList, dialog_id, fromMyName, hideCaption, notify, scheduleDate), this, themeDelegate); + int result = getSendMessagesHelper().sendMessage(arrayList, dialog_id, fromMyName, hideCaption, notify, scheduleDate); + AlertsCreator.showSendMediaAlert(result, this, themeDelegate); + if (result != 0) { + AndroidUtilities.runOnUIThread(() -> { + waitingForSendingMessageLoad = false; + hideFieldPanel(true); + }); + } } // This method is used to forward messages to Saved Messages, or to multi Dialogs @@ -11973,6 +11689,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.setForceShowSendButton(false, false); final boolean canEditMedia = messageObjectToEdit.canEditMedia(); + replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelEdit", R.string.AccDescrCancelEdit)); if (!mediaEmpty && canEditMedia) { String editButtonText = null; String replaceButtonText; @@ -12001,7 +11718,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { replyIconImageView.setImageResource(R.drawable.group_edit); replyIconImageView.setContentDescription(LocaleController.getString("AccDescrEditing", R.string.AccDescrEditing)); - replyCloseImageView.setContentDescription(LocaleController.getString("AccDescrCancelEdit", R.string.AccDescrCancelEdit)); if (mediaEmpty) { replyNameTextView.setText(LocaleController.getString("EditMessage", R.string.EditMessage)); } else { @@ -12789,6 +12505,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateReactionsMentionButton(true); } getDownloadController().checkUnviewedDownloads(messageCell.getId(), dialog_id); + + if ((chatListItemAnimator == null || !chatListItemAnimator.isRunning()) && (!messageObject.isOutOwner() || messageObject.forcePlayEffect) && messageObject.messageOwner.media != null && !messageObject.messageOwner.media.nopremium && !messageObject.messageOwner.premiumEffectWasPlayed && messageObject.isPremiumSticker() && emojiAnimationsOverlay.isIdle() && emojiAnimationsOverlay.checkPosition(messageCell, chatListViewPaddingTop, chatListView.getMeasuredHeight() - blurredViewBottomOffset)) { + emojiAnimationsOverlay.onTapItem(messageCell, ChatActivity.this); + } } else if (view instanceof ChatActionCell) { ChatActionCell cell = (ChatActionCell) view; messageObject = cell.getMessageObject(); @@ -13205,7 +12925,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { int end = chatLayoutManager.findLastVisibleItemPosition(); for (int i = chatLayoutManager.findFirstVisibleItemPosition(); i <= end; i++) { - if (i >= chatAdapter.messagesStartRow && i <= chatAdapter.messagesEndRow) { + if (i >= chatAdapter.messagesStartRow && i < chatAdapter.messagesEndRow) { MessageObject messageObject = messages.get(i - chatAdapter.messagesStartRow); if (messageObject.getId() == 0) { continue; @@ -13544,19 +13264,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatRequested) { bottomOverlayText.setText(LocaleController.getString("EncryptionProcessing", R.string.EncryptionProcessing)); bottomOverlay.setVisibility(View.VISIBLE); + chatActivityEnterView.setVisibility(View.INVISIBLE); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatWaiting) { bottomOverlayText.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AwaitingEncryption", R.string.AwaitingEncryption, "" + currentUser.first_name + ""))); bottomOverlay.setVisibility(View.VISIBLE); + chatActivityEnterView.setVisibility(View.INVISIBLE); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChatDiscarded) { bottomOverlayText.setText(LocaleController.getString("EncryptionRejected", R.string.EncryptionRejected)); bottomOverlay.setVisibility(View.VISIBLE); + chatActivityEnterView.setVisibility(View.INVISIBLE); chatActivityEnterView.setFieldText(""); getMediaDataController().cleanDraft(dialog_id, threadMessageId, false); hideKeyboard = true; } else if (currentEncryptedChat instanceof TLRPC.TL_encryptedChat) { bottomOverlay.setVisibility(View.INVISIBLE); + if (!inPreviewMode) { + chatActivityEnterView.setVisibility(View.VISIBLE); + } } checkRaiseSensors(); checkActionBarMenu(false); @@ -13577,8 +13303,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } - if (mentionsAdapter != null) { - mentionsAdapter.onRequestPermissionsResultFragment(requestCode, permissions, grantResults); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().onRequestPermissionsResultFragment(requestCode, permissions, grantResults); } if (requestCode == BasePermissionsActivity.REQUEST_CODE_EXTERNAL_STORAGE && chatAttachAlert != null) { chatAttachAlert.getPhotoLayout().checkStorage(); @@ -13716,8 +13442,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!canSave) { - File f = FileLoader.getPathToMessage(messageObject.messageOwner); - if (f.exists()) { + if (messageObject.mediaExists) { canSave = true; } } @@ -13790,7 +13515,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!canSave) { - File f = FileLoader.getPathToMessage(messageObject.messageOwner); + File f = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); if (f.exists()) { canSave = true; } @@ -14297,7 +14022,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (chatMode == MODE_PINNED) { avatarContainer.setTitle(LocaleController.formatPluralString("PinnedMessagesCount", getPinnedMessagesCount())); } else if (currentChat != null) { - avatarContainer.setTitle(currentChat.title, currentChat.scam, currentChat.fake); + avatarContainer.setTitle(currentChat.title, currentChat.scam, currentChat.fake, currentChat.verified, false); } else if (currentUser != null) { if (currentUser.self) { avatarContainer.setTitle(LocaleController.getString("SavedMessages", R.string.SavedMessages)); @@ -14305,10 +14030,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!TextUtils.isEmpty(currentUser.phone)) { avatarContainer.setTitle(PhoneFormat.getInstance().format("+" + currentUser.phone)); } else { - avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake); + avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser)); } } else { - avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake); + avatarContainer.setTitle(UserObject.getUserName(currentUser), currentUser.scam, currentUser.fake, currentUser.verified, getMessagesController().isPremiumUser(currentUser)); } } setParentActivityTitle(avatarContainer.getTitleTextView().getText()); @@ -14353,13 +14078,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateTitleIcons() { + updateTitleIcons(false); + } + + private void updateTitleIcons(boolean forceToggleMuted) { if (avatarContainer == null || chatMode != 0) { return; } boolean isMuted = getMessagesController().isDialogMuted(dialog_id); - Drawable rightIcon = isMuted ? getThemedDrawable(Theme.key_drawable_muteIconDrawable) : null; - avatarContainer.setTitleIcons(currentEncryptedChat != null ? getThemedDrawable(Theme.key_drawable_lockIconDrawable) : null, !UserObject.isReplyUser(currentUser) && !isThreadChat() ? rightIcon : null); - if (muteItem != null) { + if (forceToggleMuted) { + isMuted = !isMuted; + } + Drawable rightIcon = null; + if (!UserObject.isReplyUser(currentUser) && !isThreadChat() && isMuted) { + rightIcon = getThemedDrawable(Theme.key_drawable_muteIconDrawable); + } + avatarContainer.setTitleIcons(currentEncryptedChat != null ? getThemedDrawable(Theme.key_drawable_lockIconDrawable) : null, rightIcon); + if (!forceToggleMuted && muteItem != null) { if (isMuted) { muteItem.getRightIcon().setVisibility(View.GONE); muteItem.setTextAndIcon(LocaleController.getString("Unmute", R.string.Unmute), R.drawable.msg_mute); @@ -14578,7 +14313,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (file == null) { - file = FileLoader.getPathToMessage(object.messageOwner); + file = FileLoader.getInstance(currentAccount).getPathToMessage(object.messageOwner); } if (!file.exists()) { return; @@ -14742,16 +14477,24 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } String tempPath = AndroidUtilities.getPath(uri); String originalPath = tempPath; - if (tempPath == null || !BuildVars.NO_SCOPED_STORAGE) { + boolean sendAsUri = false; + if (!BuildVars.NO_SCOPED_STORAGE) { + sendAsUri = true; + } else if (tempPath == null) { originalPath = uri.toString(); tempPath = MediaController.copyFileToCache(uri, "file"); - } - if (tempPath == null) { - showAttachmentError(); - return; + + if (tempPath == null) { + showAttachmentError(); + return; + } } fillEditingMediaWithCaption(null, null); - SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0); + if (sendAsUri) { + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), null, null, uri, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0); + } else { + SendMessagesHelper.prepareSendingDocument(getAccountInstance(), tempPath, originalPath, null, null, null, dialog_id, replyingMessageObject, getThreadMessage(), null, editingMessageObject, true, 0); + } hideFieldPanel(false); } @@ -15631,6 +15374,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } loading = false; + if (onChatMessagesLoaded != null) { + onChatMessagesLoaded.run(); + onChatMessagesLoaded = null; + } + loadSendAsPeers(false); if (chatListView != null && chatScrollHelper != null) { if (first || scrollToTopOnResume || forceScrollToTop) { @@ -15916,8 +15664,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not pinnedMessageTextView[a].invalidate(); } } - if (mentionListView != null) { - mentionListView.invalidateViews(); + if (mentionContainer != null) { + mentionContainer.getListView().invalidateViews(); } if (stickersListView != null) { stickersListView.invalidateViews(); @@ -15934,6 +15682,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not editText.setTextColor(0xffffffff); editText.setTextColor(color); } + if (pinnedMessageButton[0] != null) { + pinnedMessageButton[0].invalidate(); + } + if (pinnedMessageButton[1] != null) { + pinnedMessageButton[1].invalidate(); + } } else if (id == NotificationCenter.didUpdateConnectionState) { int state = ConnectionsManager.getInstance(account).getConnectionState(); if (state == ConnectionsManager.ConnectionStateConnected) { @@ -15952,7 +15706,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (id == NotificationCenter.updateDefaultSendAsPeer) { long chatId = (long) args[0]; if (chatId == dialog_id) { - chatActivityEnterView.updateSendAsButton(); + chatActivityEnterView.updateSendAsButton(true); } } else if (id == NotificationCenter.updateInterfaces) { int updateMask = (Integer) args[0]; @@ -16057,7 +15811,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not checkWaitingForReplies(); } } else if (id == NotificationCenter.didLoadSendAsPeers) { - loadSendAsPeers(); + loadSendAsPeers(true); } else if (id == NotificationCenter.didLoadSponsoredMessages) { addSponsoredMessages(true); } else if (id == NotificationCenter.closeChats) { @@ -16412,7 +16166,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not moveScrollToLastMessage(false); } } - getNotificationsController().playOutChatSound(); + if (obj == null || obj.messageOwner == null || !obj.messageOwner.silent) { + getNotificationsController().playOutChatSound(); + } } } else if (id == NotificationCenter.messageReceivedByAck) { Integer msgId = (Integer) args[0]; @@ -16474,9 +16230,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (ChatObject.isChannel(currentChat) && currentChat.megagroup && fragmentContextView != null) { fragmentContextView.checkCall(openAnimationStartTime == 0 || SystemClock.elapsedRealtime() < openAnimationStartTime + 150); } - loadSendAsPeers(); + loadSendAsPeers(false); if (chatActivityEnterView != null) { - chatActivityEnterView.updateSendAsButton(); + chatActivityEnterView.updateSendAsButton(false); chatActivityEnterView.updateFieldHint(false); } if (chatAdapter != null) { @@ -16503,8 +16259,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.setChatInfo(chatInfo); } - if (mentionsAdapter != null) { - mentionsAdapter.setChatInfo(chatInfo); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().setChatInfo(chatInfo); } if (!isThreadChat()) { if (avatarContainer != null) { @@ -16553,8 +16309,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatListView.invalidateViews(); } if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { - if (mentionsAdapter != null) { - mentionsAdapter.setBotInfo(botInfo); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().setBotInfo(botInfo); } if (chatActivityEnterView != null) { chatActivityEnterView.setBotInfo(botInfo); @@ -16564,8 +16320,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (chatActivityEnterView != null) { chatActivityEnterView.setBotsCount(botsCount, hasBotsCommands, true); } - if (mentionsAdapter != null) { - mentionsAdapter.setBotsCount(botsCount); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().setBotsCount(botsCount); } if (chatMode == 0 && ChatObject.isChannel(currentChat) && mergeDialogId == 0 && chatInfo.migrated_from_chat_id != 0 && !isThreadChat()) { mergeDialogId = -chatInfo.migrated_from_chat_id; @@ -16593,16 +16349,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); if (reason == 0) { - if (currentChat.has_link) { - builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate", R.string.ChannelCantOpenPrivate)); - } else { + if (currentChat instanceof TLRPC.TL_channelForbidden) { builder.setMessage(LocaleController.getString("ChannelCantOpenBannedByAdmin", R.string.ChannelCantOpenBannedByAdmin)); + } else { + builder.setTitle(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate)); + builder.setMessage(LocaleController.getString("ChannelCantOpenPrivate2", R.string.ChannelCantOpenPrivate2)); } } else if (reason == 1) { builder.setMessage(LocaleController.getString("ChannelCantOpenNa", R.string.ChannelCantOpenNa)); } else if (reason == 2) { builder.setMessage(LocaleController.getString("ChannelCantOpenBanned", R.string.ChannelCantOpenBanned)); } else if (reason == 3) { + builder.setTitle(LocaleController.getString("ChannelPrivate", R.string.ChannelPrivate)); builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); } builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); @@ -16632,8 +16390,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setAllowStickersAndGifs(true, true); chatActivityEnterView.checkRoundVideo(); } - if (mentionsAdapter != null) { - mentionsAdapter.setNeedBotContext(!chatActivityEnterView.isEditingMessage()); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().setNeedBotContext(!chatActivityEnterView.isEditingMessage()); } } } else if (id == NotificationCenter.messagesReadEncrypted) { @@ -16765,14 +16523,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - count = mentionListView.getChildCount(); - for (int a = 0; a < count; a++) { - View view = mentionListView.getChildAt(a); - if (view instanceof ContextLinkCell) { - ContextLinkCell cell = (ContextLinkCell) view; - MessageObject messageObject1 = cell.getMessageObject(); - if (messageObject1 != null && (messageObject1.isVoice() || messageObject1.isMusic())) { - cell.updateButtonState(false, true); + if (mentionContainer != null && mentionContainer.getListView() != null) { + count = mentionContainer.getListView().getChildCount(); + for (int a = 0; a < count; a++) { + View view = mentionContainer.getListView().getChildAt(a); + if (view instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) view; + MessageObject messageObject1 = cell.getMessageObject(); + if (messageObject1 != null && (messageObject1.isVoice() || messageObject1.isMusic())) { + cell.updateButtonState(false, true); + } } } } @@ -16858,14 +16618,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } - count = mentionListView.getChildCount(); - for (int a = 0; a < count; a++) { - View view = mentionListView.getChildAt(a); - if (view instanceof ContextLinkCell) { - ContextLinkCell cell = (ContextLinkCell) view; - MessageObject messageObject = cell.getMessageObject(); - if (messageObject != null && (messageObject.isVoice() || messageObject.isMusic())) { - cell.updateButtonState(false, true); + if (mentionContainer != null && mentionContainer.getListView() != null) { + count = mentionContainer.getListView().getChildCount(); + for (int a = 0; a < count; a++) { + View view = mentionContainer.getListView().getChildAt(a); + if (view instanceof ContextLinkCell) { + ContextLinkCell cell = (ContextLinkCell) view; + MessageObject messageObject = cell.getMessageObject(); + if (messageObject != null && (messageObject.isVoice() || messageObject.isMusic())) { + cell.updateButtonState(false, true); + } } } } @@ -17028,6 +16790,54 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not updateVisibleRows(); } } + } else if (id == NotificationCenter.voiceTranscriptionUpdate) { + if (chatAdapter != null) { + MessageObject messageObject = (MessageObject) args[0]; + long transcriptionId = 0; + String transcriptionText = null; + if (args[1] != null) { + transcriptionId = (Long) args[1]; + transcriptionText = (String) args[2]; + } + ArrayList messages = chatAdapter.isFrozen ? chatAdapter.frozenMessages : ChatActivity.this.messages; + if (messages != null && !messages.contains(messageObject) && args[1] != null) { + for (int a = 0; a < messages.size(); ++a) { + if (messages.get(a) != null && messages.get(a).messageOwner != null && (messages.get(a).messageOwner.voiceTranscriptionId == transcriptionId || messageObject != null && messageObject.getId() == messages.get(a).getId() && messageObject.getDialogId() == messages.get(a).getDialogId())) { + messageObject = messages.get(a); + break; + } + } + } + if (messageObject != null) { + if (transcriptionText != null && messageObject.messageOwner != null) { + messageObject.messageOwner.voiceTranscription = transcriptionText; + } + boolean wasOpen = messageObject.isVoiceTranscriptionOpen(); + if (args.length > 3 && args[3] != null) { + messageObject.messageOwner.voiceTranscriptionOpen = (Boolean) args[3]; + } + if (args.length > 4 && args[4] != null) { + messageObject.messageOwner.voiceTranscriptionFinal = (Boolean) args[4]; + } + + int index = messages.indexOf(messageObject); + if (index >= 0 && index < messages.size()) { + int position = index + chatAdapter.messagesStartRow; + chatAdapter.updateRowAtPosition(position); + for (int i = 0; i < chatListView.getChildCount(); ++i) { + View child = chatListView.getChildAt(i); + if (child instanceof ChatMessageCell && ((ChatMessageCell) child).getMessageObject() == messageObject) { + int top = child.getTop() - (int) chatListViewPaddingTop; + int halfHeight = (int) ((chatListView.getMeasuredHeight() - chatListViewPaddingTop) / 2); + if (messageObject.measureVoiceTranscriptionHeight() > halfHeight * .4f) { + chatLayoutManager.scrollToPositionWithOffset(position, (top > halfHeight * .6f && messageObject.isVoiceTranscriptionOpen() ? (int) (halfHeight * .6f) : top), false); + } + break; + } + } + } + } + } } else if (id == NotificationCenter.replaceMessagesObjects) { long did = (long) args[0]; if (did != dialog_id && did != mergeDialogId) { @@ -17259,6 +17069,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!info.commands.isEmpty() && !ChatObject.isChannel(currentChat) && !isThreadChat()) { hasBotsCommands = true; } + if (info.user_id == 0 && currentUser != null) { + info.user_id = currentUser.id; + } botInfo.put(info.user_id, info); if (chatAdapter != null) { int prevRow = chatAdapter.botInfoRow; @@ -17272,8 +17085,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (!ChatObject.isChannel(currentChat) || currentChat != null && currentChat.megagroup) { - if (mentionsAdapter != null) { - mentionsAdapter.setBotInfo(botInfo); + if (mentionContainer != null && mentionContainer.getAdapter() != null) { + mentionContainer.getAdapter().setBotInfo(botInfo); } if (chatActivityEnterView != null) { @@ -17522,15 +17335,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (audioCallIconItem != null) { if (openAnimationStartTime != 0 && audioCallIconItem.getVisibility() != View.VISIBLE) { audioCallIconItem.setAlpha(0f); - audioCallIconItem.animate().alpha(1f).setDuration(150).start(); + audioCallIconItem.animate().alpha(1f).setDuration(160).setInterpolator(CubicBezierInterpolator.EASE_IN).setStartDelay(50).start(); } audioCallIconItem.setVisibility(View.VISIBLE); } } else { - headerItem.showSubItem(call); + headerItem.showSubItem(call, true); } if (userInfo.video_calls_available) { - headerItem.showSubItem(video_call); + headerItem.showSubItem(video_call, true); } else { headerItem.hideSubItem(video_call); } @@ -17751,20 +17564,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }, true, themeDelegate); } - private void loadSendAsPeers() { + private void loadSendAsPeers(boolean animatedUpdate) { if (sendAsPeersObj != null || currentChat == null || !ChatObject.canSendAsPeers(currentChat) || chatActivityEnterView == null) { return; } sendAsPeersObj = getMessagesController().getSendAsPeers(dialog_id); if (sendAsPeersObj != null) { - chatActivityEnterView.updateSendAsButton(); + chatActivityEnterView.updateSendAsButton(animatedUpdate); } } private boolean sponsoredMessagesAdded; private void addSponsoredMessages(boolean animated) { - if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0]) { + if (sponsoredMessagesAdded || chatMode != 0 || !ChatObject.isChannel(currentChat) || !forwardEndReached[0] || getUserConfig().isPremium()) { return; } ArrayList arrayList = getMessagesController().getSponsoredMessages(dialog_id); @@ -18157,6 +17970,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + if (messageObject.wasJustSent && getUserConfig().isPremium()) { + messageObject.forcePlayEffect = true; + } } if (currentChat != null) { if (messageObject.messageOwner.action instanceof TLRPC.TL_messageActionChatDeleteUser && messageObject.messageOwner.action.user_id == currentUserId || @@ -19053,6 +18869,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (messageObject.type >= 0) { messageObject.stableId = old.stableId; + messageObject.messageOwner.premiumEffectWasPlayed = old.messageOwner.premiumEffectWasPlayed; + messageObject.forcePlayEffect = old.forcePlayEffect; messages.set(index, messageObject); if (chatAdapter != null) { chatAdapter.updateRowAtPosition(chatAdapter.messagesStartRow + index); @@ -19246,15 +19064,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void onBecomeFullyVisible() { + isFullyVisible = true; super.onBecomeFullyVisible(); if (showCloseChatDialogLater) { showDialog(closeChatDialog); } + if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { + parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); + } } @Override protected void onBecomeFullyHidden() { + isFullyVisible = false; hideUndoViews(); + if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { + parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + } } public void saveKeyboardPositionBeforeTransition() { @@ -19439,57 +19265,68 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not contentView.invalidate(); if (!TextUtils.isEmpty(attachMenuBotToOpen)) { - if (getCurrentUser() != null) { - TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); - req.username = attachMenuBotToOpen; - getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{ - if (response != null) { - TLRPC.TL_contacts_resolvedPeer resolvedPeer = (TLRPC.TL_contacts_resolvedPeer) response; - if (!resolvedPeer.users.isEmpty()) { - TLRPC.User user = resolvedPeer.users.get(0); - if (user.bot && user.bot_attach_menu) { - TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot(); - getAttachMenuBot.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); - ConnectionsManager.getInstance(currentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(()-> { - if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { - TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1; - MessagesController.getInstance(currentAccount).putUsers(attachMenuBotsBot.users, false); - TLRPC.TL_attachMenuBot attachMenuBot = attachMenuBotsBot.bot; + TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); + req.username = attachMenuBotToOpen; + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{ + if (response != null) { + TLRPC.TL_contacts_resolvedPeer resolvedPeer = (TLRPC.TL_contacts_resolvedPeer) response; + if (!resolvedPeer.users.isEmpty()) { + TLRPC.User user = resolvedPeer.users.get(0); + if (user.bot && user.bot_attach_menu) { + TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot(); + getAttachMenuBot.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); + ConnectionsManager.getInstance(currentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(()-> { + if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { + TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1; + MessagesController.getInstance(currentAccount).putUsers(attachMenuBotsBot.users, false); + TLRPC.TL_attachMenuBot attachMenuBot = attachMenuBotsBot.bot; - if (!attachMenuBot.inactive) { - openAttachBotLayout(user.id, attachMenuBotStartCommand); - } else { - AttachBotIntroTopView introTopView = new AttachBotIntroTopView(getParentActivity()); - introTopView.setColor(Theme.getColor(Theme.key_chat_attachContactIcon)); - introTopView.setBackgroundColor(Theme.getColor(Theme.key_dialogTopBackground)); - introTopView.setAttachBot(attachMenuBot); - new AlertDialog.Builder(getParentActivity()) - .setTopView(introTopView) - .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BotRequestAttachPermission", R.string.BotRequestAttachPermission, UserObject.getUserName(user)))) - .setPositiveButton(LocaleController.getString(R.string.BotAddToMenu), (dialog, which) -> { - TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); - botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); - botRequest.enabled = true; - ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { - if (error2 == null) { - MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); - - openAttachBotLayout(user.id, attachMenuBotStartCommand); - } - }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); - }) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) - .show(); + if (!MediaDataController.canShowAttachMenuBot(attachMenuBot, getCurrentUser() != null ? getCurrentUser() : getCurrentChat())) { + if (currentUser != null && currentUser.bot && user.id == attachMenuBot.bot_id) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuSameBot)).show(); + } else if (currentUser != null && currentUser.bot && user.id != attachMenuBot.bot_id) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuBot)).show(); + } else if (currentUser != null && !currentUser.bot) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuUser)).show(); + } else if (currentChat != null && !ChatObject.isChannelAndNotMegaGroup(currentChat)) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuGroup)).show(); + } else if (currentChat != null && ChatObject.isChannelAndNotMegaGroup(currentChat)) { + BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(R.string.BotCantOpenAttachMenuChannel)).show(); } + return; } - })); - } + + if (!attachMenuBot.inactive) { + openAttachBotLayout(user.id, attachMenuBotStartCommand); + } else { + AttachBotIntroTopView introTopView = new AttachBotIntroTopView(getParentActivity()); + introTopView.setColor(Theme.getColor(Theme.key_chat_attachContactIcon)); + introTopView.setBackgroundColor(Theme.getColor(Theme.key_dialogTopBackground)); + introTopView.setAttachBot(attachMenuBot); + new AlertDialog.Builder(getParentActivity()) + .setTopView(introTopView) + .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BotRequestAttachPermission", R.string.BotRequestAttachPermission, UserObject.getUserName(user)))) + .setPositiveButton(LocaleController.getString(R.string.BotAddToMenu), (dialog, which) -> { + TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); + botRequest.bot = MessagesController.getInstance(currentAccount).getInputUser(user.id); + botRequest.enabled = true; + ConnectionsManager.getInstance(currentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { + if (error2 == null) { + MediaDataController.getInstance(currentAccount).loadAttachMenuBots(false, true); + + openAttachBotLayout(user.id, attachMenuBotStartCommand); + } + }), ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); + }) + .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .show(); + } + } + })); } } - })); - } else { - BulletinFactory.of(this).createErrorBulletin(LocaleController.getString(ChatObject.isChannelAndNotMegaGroup(currentChat) ? R.string.BotCantOpenAttachMenuChannel : R.string.BotCantOpenAttachMenuGroup)).show(); - } + } + })); attachMenuBotToOpen = null; } } @@ -19605,29 +19442,47 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } showBottomOverlayProgress(false, false); } else if (currentChat != null) { - if (!isThreadChat()) { - if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { - if (ChatObject.isNotInChat(currentChat)) { - if (getMessagesController().isJoiningChannel(currentChat.id)) { - showBottomOverlayProgress(true, false); + long requestedTime = MessagesController.getNotificationsSettings(currentAccount).getLong("dialog_join_requested_time_" + dialog_id, -1); + boolean shouldApply = false; + if (ChatObject.isChannel(currentChat) && !(currentChat instanceof TLRPC.TL_channelForbidden)) { + if (ChatObject.isNotInChat(currentChat) && (!isThreadChat() || currentChat.join_to_send)) { + if (getMessagesController().isJoiningChannel(currentChat.id)) { + showBottomOverlayProgress(true, false); + } else { + if (currentChat.join_request) { + shouldApply = true; + if (requestedTime > 0 && System.currentTimeMillis() - requestedTime < 1000 * 60 * 2) { + bottomOverlayChatText.setText(LocaleController.getString("ChannelJoinRequestSent", R.string.ChannelJoinRequestSent), true); + bottomOverlayChatText.setEnabled(false); + } else { + bottomOverlayChatText.setText(LocaleController.getString("ChannelJoinRequest", R.string.ChannelJoinRequest)); + bottomOverlayChatText.setEnabled(true); + } } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelJoin", R.string.ChannelJoin)); - showBottomOverlayProgress(false, false); + bottomOverlayChatText.setEnabled(true); } - } else { - if (!getMessagesController().isDialogMuted(dialog_id)) { - bottomOverlayChatText.setText(LocaleController.getString("ChannelMute", R.string.ChannelMute), false); - } else { - bottomOverlayChatText.setText(LocaleController.getString("ChannelUnmute", R.string.ChannelUnmute), true); - } - showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); + showBottomOverlayProgress(false, false); } - } else { - bottomOverlayChatText.setText(LocaleController.getString("DeleteThisGroup", R.string.DeleteThisGroup)); + } else if (!isThreadChat()) { + if (!getMessagesController().isDialogMuted(dialog_id)) { + bottomOverlayChatText.setText(LocaleController.getString("ChannelMute", R.string.ChannelMute), false); + bottomOverlayChatText.setEnabled(true); + } else { + bottomOverlayChatText.setText(LocaleController.getString("ChannelUnmute", R.string.ChannelUnmute), true); + bottomOverlayChatText.setEnabled(true); + } + showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); } + } else if (!isThreadChat()) { + bottomOverlayChatText.setText(LocaleController.getString("DeleteThisGroup", R.string.DeleteThisGroup)); + bottomOverlayChatText.setEnabled(true); + } + if (!shouldApply && requestedTime > 0) { + MessagesController.getNotificationsSettings(currentAccount).edit().putLong("dialog_join_requested_time_" + dialog_id, -1).commit(); } } else { - showBottomOverlayProgress(false, false); + showBottomOverlayProgress(false, true); if (userBlocked) { if (currentUser.bot) { bottomOverlayChatText.setText(LocaleController.getString("BotUnblock", R.string.BotUnblock)); @@ -19650,7 +19505,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { bottomOverlayChatText.setText(LocaleController.getString("ChannelUnmute", R.string.ChannelUnmute), true); } - showBottomOverlayProgress(false, bottomOverlayProgress.getTag() != null); + showBottomOverlayProgress(false, true); } else if (botUser != null && currentUser.bot) { bottomOverlayChatText.setText(LocaleController.getString("BotStart", R.string.BotStart)); chatActivityEnterView.hidePopup(false); @@ -19682,11 +19537,34 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - chatActivityEnterView.setVisibility(View.INVISIBLE); - bottomOverlayChat.setVisibility(View.INVISIBLE); + } }).start(); + if (searchExpandAnimator != null) { + searchExpandAnimator.removeAllListeners(); + searchExpandAnimator.cancel(); + } + + searchExpandAnimator = ValueAnimator.ofFloat(searchExpandProgress, 1f); + searchExpandAnimator.addUpdateListener(animation -> { + searchExpandProgress = (float) animation.getAnimatedValue(); + chatListView.setTranslationY(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); + chatActivityEnterView.setChatSearchExpandOffset(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); + invalidateChatListViewTopPadding(); + }); + searchExpandAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + chatActivityEnterView.setVisibility(View.INVISIBLE); + bottomOverlayChat.setVisibility(View.INVISIBLE); + invalidateChatListViewTopPadding(); + } + }); + searchExpandAnimator.setDuration(250); + searchExpandAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); + searchExpandAnimator.start(); + chatActivityEnterView.setFieldFocused(false); if (chatActivityEnterView.isTopViewVisible()) { @@ -19708,6 +19586,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.setVisibility(View.VISIBLE); + + if (searchExpandAnimator != null) { + searchExpandAnimator.removeAllListeners(); + searchExpandAnimator.cancel(); + } + + searchExpandAnimator = ValueAnimator.ofFloat(searchExpandProgress, 0f); + invalidateChatListViewTopPadding(); + searchExpandAnimator.addUpdateListener(animation -> { + searchExpandProgress = (float) animation.getAnimatedValue(); + chatListView.setTranslationY(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); + chatActivityEnterView.setChatSearchExpandOffset(searchExpandProgress * (chatActivityEnterView.getMeasuredHeight() - searchContainer.getMeasuredHeight())); + invalidateChatListViewTopPadding(); + }); + searchExpandAnimator.setDuration(250); + searchExpandAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); + searchExpandAnimator.start(); if (muteItem != null) { if (currentChat != null && ChatObject.isNotInChat(currentChat)) { muteItem.setVisibility(View.GONE); @@ -19721,7 +19616,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayChat.setVisibility(View.VISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (chatMode == MODE_PINNED || - currentChat != null && !isThreadChat() && (ChatObject.isNotInChat(currentChat) || !ChatObject.canWriteToChat(currentChat)) || + currentChat != null && (ChatObject.isNotInChat(currentChat) || !ChatObject.canWriteToChat(currentChat)) && (currentChat.join_to_send || !isThreadChat()) || currentUser != null && (UserObject.isDeleted(currentUser) || userBlocked || UserObject.isReplyUser(currentUser))) { if (chatActivityEnterView.isEditingMessage()) { chatActivityEnterView.setVisibility(View.VISIBLE); @@ -19944,7 +19839,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updatePinnedListButton(boolean animated) { - if (isThreadChat() || pinnedListButton == null || inMenuMode) { + if (isThreadChat() || pinnedListButton == null) { return; } boolean show = pinnedMessageIds.size() > 1 && !pinnedMessageButtonShown; @@ -19988,7 +19883,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ObjectAnimator.ofFloat(pinnedProgress, View.SCALE_Y, !showProgress ? 0.4f : 1.0f) ); - pinnedListAnimator.setDuration(180); + pinnedListAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + pinnedListAnimator.setDuration(180 * 2); pinnedListAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -20039,7 +19935,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updatePinnedMessageView(boolean animated, int animateToNext) { - if (pinnedMessageView == null || chatMode != 0 || inMenuMode) { + if (pinnedMessageView == null || chatMode != 0) { return; } int pinned_msg_id; @@ -20136,6 +20032,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not buttonTextView.setVisibility(botButton != null ? View.VISIBLE : View.GONE); pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnClickListener(null); + pinnedMessageButton[animateToNext != 0 ? 0 : 1].setOnLongClickListener(null); if (botButton == null) { buttonTextView.setText(null); buttonTextView.setOnClickListener(null); @@ -20154,6 +20051,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } chatActivityEnterView.didPressedBotButton(botButton, buttonMessage, buttonMessage); }); + buttonTextView.setOnLongClickListener(e -> { + if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && + !(botButton instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(botButton instanceof TLRPC.TL_keyboardButtonCallback) && + !(botButton instanceof TLRPC.TL_keyboardButtonGame) && !(botButton instanceof TLRPC.TL_keyboardButtonUrl) && + !(botButton instanceof TLRPC.TL_keyboardButtonBuy) && !(botButton instanceof TLRPC.TL_keyboardButtonUrlAuth) && + !(botButton instanceof TLRPC.TL_keyboardButtonUserProfile)) { + return false; + } + if (botButton instanceof TLRPC.TL_keyboardButtonUrl) { + openClickableLink(null, botButton.url, true, null, buttonMessage); + try { + buttonTextView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + return true; + } + return false; + }); } buttonTextView.measure(View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(28), View.MeasureSpec.EXACTLY)); if (messageTextView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) { @@ -20230,7 +20144,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean showCounter = false; boolean shouldAnimateName = loadedPinnedMessagesCount == 2 || !pinnedNameTextView[animateToNext != 0 ? 0 : 1].getTrackWidth(); + pinnedNameTextView[animateToNext != 0 ? 0 : 1].setTrackWidth(false); nameTextView.setTrackWidth(true); + nameTextView.setVisibility(View.VISIBLE); if (threadMessageId != 0) { MessagesController messagesController = getMessagesController(); TLRPC.MessageFwdHeader fwd_from = threadMessageObject.messageOwner.fwd_from; @@ -20284,9 +20200,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showCounter = false; } else { if (currentPinnedMessageIndex[0] == 0 || loadedPinnedMessagesCount != 2) { - nameTextView.setText(LocaleController.getString("PinnedMessage", R.string.PinnedMessage)); + nameTextView.setText(LocaleController.getString("PinnedMessage", R.string.PinnedMessage), true); } else { - nameTextView.setText(LocaleController.getString("PreviousPinnedMessage", R.string.PreviousPinnedMessage)); + nameTextView.setText(LocaleController.getString("PreviousPinnedMessage", R.string.PreviousPinnedMessage), true); } if (currentPinnedMessageIndex[0] != 0) { int total = getPinnedMessagesCount(); @@ -20430,8 +20346,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not animators.add(ObjectAnimator.ofFloat(pinnedMessageTextView[1], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[0], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedNameTextView[1], View.TRANSLATION_X, diff, 0.0f)); - animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[0], View.TRANSLATION_X, diff, 0.0f)); - animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[1], View.TRANSLATION_X, diff, 0.0f)); +// animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[0], View.TRANSLATION_X, diff, 0.0f)); +// animators.add(ObjectAnimator.ofFloat(pinnedMessageButton[1], View.TRANSLATION_X, diff, 0.0f)); animators.add(ObjectAnimator.ofFloat(pinnedCounterTextView, View.TRANSLATION_X, pinnedCounterTextViewX + diff, pinnedCounterTextViewX)); if (diff > 0) { pinnedMessageImageView[0].setAlpha(1f); @@ -20482,8 +20398,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (animation.equals(pinnedNextAnimation[1])) { if (animateName || animateText || animateImage != null) { pinnedNextAnimation[1] = new AnimatorSet(); - pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT); - pinnedNextAnimation[1].setDuration(180); + pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + pinnedNextAnimation[1].setDuration(180 * 2); ArrayList animators1 = new ArrayList<>(); if (animateName) { animators1.add(ObjectAnimator.ofFloat(nameTextView, View.TRANSLATION_Y, 0.0f)); @@ -20524,10 +20440,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } }); - pinnedNextAnimation[1].setDuration(180); - if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { - pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT); - } + pinnedNextAnimation[1].setDuration(180 * 2); +// if (forceScrollToFirst && loadedPinnedMessagesCount > 5) { + pinnedNextAnimation[1].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); +// } pinnedNextAnimation[1].playTogether(animators2); pinnedNextAnimation[0].playTogether(animators); @@ -20590,7 +20506,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not setPinnedTextTranslationX = false; } }); - pinnedNextAnimation[0].setDuration(180); + pinnedNextAnimation[0].setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + pinnedNextAnimation[0].setDuration(180 * 2); if (!setPinnedTextTranslationX) { pinnedNextAnimation[0].start(); pinnedNextAnimation[1].start(); @@ -20685,10 +20602,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected boolean createLayout(int width) { boolean result = super.createLayout(width); - if (trackWidth && getVisibility() == View.VISIBLE && pinnedCounterTextView != null) { - int newX = getTextWidth() + AndroidUtilities.dp(4); - if (newX != pinnedCounterTextViewX) { - pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX = newX); + if (trackWidth && getVisibility() == View.VISIBLE) { + pinnedCounterTextViewX = getTextWidth() + AndroidUtilities.dp(4); + if (pinnedCounterTextView != null) { + pinnedCounterTextView.setTranslationX(pinnedCounterTextViewX); } } return result; @@ -20696,7 +20613,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } private void updateTopPanel(boolean animated) { - if (topChatPanelView == null || chatMode != 0 || inMenuMode) { + if (topChatPanelView == null || chatMode != 0) { return; } @@ -21001,6 +20918,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override protected void setInPreviewMode(boolean value) { super.setInPreviewMode(value); + if (currentUser != null && audioCallIconItem != null) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(currentUser.id); + if (userFull != null && userFull.phone_calls_available) { + showAudioCallAsIcon = !inPreviewMode; + audioCallIconItem.setVisibility(View.VISIBLE); + } else { + showAudioCallAsIcon = false; + audioCallIconItem.setVisibility(View.GONE); + } + } if (avatarContainer != null) { avatarContainer.setOccupyStatusBar(!value); avatarContainer.setLayoutParams(LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !value ? 56 : (chatMode == MODE_PINNED ? 10 : 0), 0, 40, 0)); @@ -21051,6 +20978,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } updateBottomOverlay(); updateSecretStatus(); + + if (fragmentContextView != null) { + fragmentContextView.setEnabled(!value); + } + if (fragmentLocationContextView != null) { + fragmentLocationContextView.setEnabled(!value); + } + if (pinnedMessageView != null) { + pinnedMessageView.setEnabled(!isInPreviewMode()); + } } Bulletin.Delegate bulletinDelegate; @@ -21520,11 +21457,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not AnimatedFileDrawable visibleAnimation = null; if (noSoundHintView != null && noSoundHintView.getTag() != null) { ChatMessageCell cell = noSoundHintView.getMessageCell(); - ImageReceiver imageReceiver = cell.getPhotoImage(); - visibleAnimation = imageReceiver.getAnimation(); - if (visibleAnimation != null) { - visibleMessage = cell.getMessageObject(); - scrollToVideo = cell.getTop() + imageReceiver.getImageY2() > chatListView.getMeasuredHeight(); + if (cell != null) { + ImageReceiver imageReceiver = cell.getPhotoImage(); + visibleAnimation = imageReceiver.getAnimation(); + if (visibleAnimation != null) { + visibleMessage = cell.getMessageObject(); + scrollToVideo = cell.getTop() + imageReceiver.getImageY2() > chatListView.getMeasuredHeight(); + } } } if (visibleMessage == null) { @@ -21677,6 +21616,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!TextUtils.isEmpty(restrictionReason)) { return restrictionReason; } + if (messageObject.isVoiceTranscriptionOpen() && !TranscribeButton.isTranscribing(messageObject)) { + return messageObject.getVoiceTranscription(); + } if (messageObject.caption != null) { return messageObject.caption; } @@ -21696,20 +21638,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return caption; } - private static boolean isEmoji(String message){ - return message.matches("(?:[\uD83C\uDF00-\uD83D\uDDFF]|[\uD83E\uDD00-\uD83E\uDDFF]|" + - "[\uD83D\uDE00-\uD83D\uDE4F]|[\uD83D\uDE80-\uD83D\uDEFF]|" + - "[\u2600-\u26FF]\uFE0F?|[\u2700-\u27BF]\uFE0F?|\u24C2\uFE0F?|" + - "[\uD83C\uDDE6-\uD83C\uDDFF]{1,2}|" + - "[\uD83C\uDD70\uD83C\uDD71\uD83C\uDD7E\uD83C\uDD7F\uD83C\uDD8E\uD83C\uDD91-\uD83C\uDD9A]\uFE0F?|" + - "[\u0023\u002A\u0030-\u0039]\uFE0F?\u20E3|[\u2194-\u2199\u21A9-\u21AA]\uFE0F?|[\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55]\uFE0F?|" + - "[\u2934\u2935]\uFE0F?|[\u3030\u303D]\uFE0F?|[\u3297\u3299]\uFE0F?|" + - "[\uD83C\uDE01\uD83C\uDE02\uD83C\uDE1A\uD83C\uDE2F\uD83C\uDE32-\uD83C\uDE3A\uD83C\uDE50\uD83C\uDE51]\uFE0F?|" + - "[\u203C\u2049]\uFE0F?|[\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE]\uFE0F?|" + - "[\u00A9\u00AE]\uFE0F?|[\u2122\u2139]\uFE0F?|\uD83C\uDC04\uFE0F?|\uD83C\uDCCF\uFE0F?|" + - "[\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA]\uFE0F?)+"); - } - // NekoX overload private boolean createMenu(View v, boolean single, boolean listView, float x, float y, boolean searchGroup) { return createMenu(v, single, listView, x, y, searchGroup, false); @@ -21865,7 +21793,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not final ArrayList options = new ArrayList<>(); View optionsView = null; - CharSequence messageText = null; + CharSequence messageTextToTranslate = null; if (message.messageOwner.action instanceof TLRPC.TL_messageActionSetMessagesTTL && single && (dialog_id >= 0 || (currentChat != null && ChatObject.canUserDoAdminAction(currentChat, ChatObject.ACTION_DELETE_MESSAGES)))) { AutoDeletePopupWrapper autoDeletePopupWrapper = new AutoDeletePopupWrapper(contentView.getContext(), null, new AutoDeletePopupWrapper.Callback() { @Override @@ -21888,25 +21816,29 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (type >= 0 || type == -1 && single && (message.isSending() || message.isEditing()) && currentEncryptedChat == null) { selectedObject = message; selectedObjectGroup = groupedMessages; - messageText = getMessageCaption(selectedObject, selectedObjectGroup); // used only in translations - if (messageText == null && selectedObject.isPoll()) { + messageTextToTranslate = getMessageCaption(selectedObject, selectedObjectGroup); + if (messageTextToTranslate == null && selectedObject.isPoll()) { try { TLRPC.Poll poll = ((TLRPC.TL_messageMediaPoll) selectedObject.messageOwner.media).poll; StringBuilder pollText = new StringBuilder(); pollText = new StringBuilder(poll.question).append("\n"); for (TLRPC.TL_pollAnswer answer : poll.answers) pollText.append("\n\uD83D\uDD18 ").append(answer.text); - messageText = pollText.toString(); + messageTextToTranslate = pollText.toString(); } catch (Exception e) {} } - if (messageText == null) - messageText = getMessageContent(selectedObject, 0, false); - if (messageText != null) { - if (isEmoji(messageText.toString())) { - messageText = null; // message fully consists of emojis, do not translate - } + if (messageTextToTranslate == null) { + messageTextToTranslate = getMessageContent(selectedObject, 0, false); + } + if (messageTextToTranslate != null && Emoji.fullyConsistsOfEmojis(messageTextToTranslate)) { + messageTextToTranslate = null; // message fully consists of emojis, do not translate } + if (message.isSponsored() && !getMessagesController().premiumLocked) { + items.add(LocaleController.getString("HideAd", R.string.HideAd)); + options.add(OPTION_HIDE_SPONSORED_MESSAGE); + icons.add(R.drawable.msg_block2); + } if (type == -1) { if ((selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOverride) { items.add(LocaleController.getString("Copy", R.string.Copy)); @@ -21944,9 +21876,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_PIN); icons.add(R.drawable.deproko_baseline_pin_24); } -// if (selectedObject != null && selectedObject.contentType == 0 && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { +// if (selectedObject != null && selectedObject.contentType == 0 && (messageTextToTranslate != null && messageTextToTranslate.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { // items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); -// options.add(29); +// options.add(OPTION_TRANSLATE); // icons.add(R.drawable.msg_translate); // } if (message.canEditMessage(currentChat)) { @@ -22010,12 +21942,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); - options.add(8); + options.add(OPTION_REPLY); icons.add(R.drawable.baseline_reply_24); } if ((selectedObject.type == 0 || selectedObject.isDice() || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOverride) { items.add(LocaleController.getString("Copy", R.string.Copy)); - options.add(3); + options.add(OPTION_COPY); icons.add(R.drawable.baseline_content_copy_24); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { @@ -22024,7 +21956,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { items.add(LocaleController.getString("ViewThread", R.string.ViewThread)); } - options.add(27); + options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.baseline_forum_24); } else if (isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null) { options.add(nkbtn_view_in_chat); @@ -22033,7 +21965,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && ChatObject.isChannel(currentChat) && selectedObject.getDialogId() != mergeDialogId) { items.add(LocaleController.getString("CopyLink", R.string.CopyLink)); - options.add(22); + options.add(OPTION_COPY_LINK); icons.add(R.drawable.baseline_link_24); } if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && currentUser != null && selectedObject.getDialogId() != mergeDialogId) { @@ -22046,7 +21978,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject.type == MessageObject.TYPE_POLL && !message.isPollClosed()) { if (message.canUnvote()) { items.add(LocaleController.getString("Unvote", R.string.Unvote)); - options.add(25); + options.add(OPTION_UNVOTE); icons.add(R.drawable.msg_unvote); } if (!message.isForwarded() && ( @@ -22057,7 +21989,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { items.add(LocaleController.getString("StopPoll", R.string.StopPoll)); } - options.add(26); + options.add(OPTION_STOP_POLL_OR_QUIZ); icons.add(R.drawable.msg_pollstop); } } else if (selectedObject.isMusic() && !noforwardsOverride) { @@ -22073,7 +22005,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (type == 3 && !noforwardsOverride) { if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && MessageObject.isNewGifDocument(selectedObject.messageOwner.media.webpage.document)) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); - options.add(11); + options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.deproko_baseline_gif_24); } } else if (type == 4) { @@ -22081,10 +22013,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (selectedObject.isVideo()) { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); - options.add(4); + options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } } else if (selectedObject.isMusic()) { @@ -22092,43 +22024,43 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else if (selectedObject.getDocument() != null) { if (MessageObject.isNewGifDocument(selectedObject.getDocument())) { items.add(LocaleController.getString("SaveToGIFs", R.string.SaveToGIFs)); - options.add(11); + options.add(OPTION_ADD_TO_GIFS); icons.add(R.drawable.deproko_baseline_gif_24); } items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else { if (!selectedObject.needDrawBluredPreview()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); - options.add(4); + options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.baseline_image_24); } } } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); - options.add(5); + options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.baseline_language_24); if (!noforwards) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); - options.add(5); + options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.baseline_palette_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(10); @@ -22153,23 +22085,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } } else if (type == 6 && !noforwardsOverride) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); - options.add(7); + options.add(OPTION_SAVE_TO_GALLERY2); icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else if (type == 7) { if (selectedObject.isMask()) { items.add(LocaleController.getString("AddToMasks", R.string.AddToMasks)); - options.add(9); + options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.deproko_baseline_stickers_24); } else { if (!selectedObject.isAnimatedSticker()) { @@ -22178,18 +22110,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.baseline_image_24); } items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); - options.add(9); + options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.deproko_baseline_stickers_24); TLRPC.Document document = selectedObject.getDocument(); if (!getMediaDataController().isStickerInFavorites(document)) { if (getMediaDataController().canAddStickerToFavorites()/* && MessageObject.isStickerHasSet(document)*/) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - options.add(20); + options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.baseline_star_24); } } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); - options.add(21); + options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); icons.add(R.drawable.baseline_star_24); } } @@ -22201,17 +22133,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); - options.add(15); + options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.baseline_person_add_24); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwardsOverride) { items.add(LocaleController.getString("Copy", R.string.Copy)); - options.add(16); + options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.baseline_content_copy_24); } items.add(LocaleController.getString("Call", R.string.Call)); - options.add(17); + options.add(OPTION_CALL); icons.add(R.drawable.baseline_call_24); } } else if (type == 9) { @@ -22224,12 +22156,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!getMediaDataController().isStickerInFavorites(document)) { //if (MessageObject.isStickerHasSet(document)) { items.add(LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - options.add(20); + options.add(OPTION_ADD_STICKER_TO_FAVORITES); icons.add(R.drawable.baseline_star_24); //} } else { items.add(LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites)); - options.add(21); + options.add(OPTION_DELETE_STICKER_FROM_FAVORITES); icons.add(R.drawable.baseline_star_24); } } @@ -22237,7 +22169,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean noforwardOverride = noforward && !NekoXConfig.disableFlagSecure; if (!selectedObject.isSponsored() && chatMode != MODE_SCHEDULED && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16 && !noforwards) { items.add(LocaleController.getString("Forward", R.string.Forward)); - options.add(2); + options.add(OPTION_FORWARD); icons.add(R.drawable.baseline_forward_24); } if (chatMode != MODE_SCHEDULED && !selectedObject.needDrawBluredPreview() && !selectedObject.isLiveLocation() && selectedObject.type != 16) { @@ -22353,55 +22285,55 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (allowUnpin) { items.add(LocaleController.getString("UnpinMessage", R.string.UnpinMessage)); - options.add(14); + options.add(OPTION_UNPIN); icons.add(R.drawable.deproko_baseline_pin_undo_24); } else if (allowPin) { items.add(LocaleController.getString("PinMessage", R.string.PinMessage)); - options.add(13); + options.add(OPTION_PIN); icons.add(R.drawable.deproko_baseline_pin_24); } -// if (selectedObject != null && selectedObject.contentType == 0 && (messageText != null && messageText.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { +// if (selectedObject != null && selectedObject.contentType == 0 && (messageTextToTranslate != null && messageTextToTranslate.length() > 0 && !selectedObject.isAnimatedEmoji() && !selectedObject.isDice())) { // items.add(LocaleController.getString("TranslateMessage", R.string.TranslateMessage)); -// options.add(29); +// options.add(OPTION_TRANSLATE); // icons.add(R.drawable.msg_translate); // } if (allowEdit) { items.add(LocaleController.getString("Edit", R.string.Edit)); - options.add(12); + options.add(OPTION_EDIT); icons.add(R.drawable.baseline_edit_24); } if (chatMode == MODE_SCHEDULED && selectedObject.canEditMessageScheduleTime(currentChat)) { items.add(LocaleController.getString("MessageScheduleEditTime", R.string.MessageScheduleEditTime)); - options.add(102); + options.add(OPTION_EDIT_SCHEDULE_TIME); icons.add(R.drawable.baseline_date_range_24); } if (chatMode != MODE_SCHEDULED && selectedObject.contentType == 0 && selectedObject.getId() > 0 && !selectedObject.isOut() && (currentChat != null || currentUser != null && currentUser.bot)) { if (UserObject.isReplyUser(currentUser)) { items.add(LocaleController.getString("BlockContact", R.string.BlockContact)); - options.add(23); + options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.baseline_report_24); } else if (NekoConfig.showReport.Bool()) { items.add(LocaleController.getString("ReportChat", R.string.ReportChat)); - options.add(23); + options.add(OPTION_REPORT_CHAT); icons.add(R.drawable.baseline_report_24); } } if (message.canDeleteMessage(chatMode == MODE_SCHEDULED, currentChat) && (threadMessageObjects == null || !threadMessageObjects.contains(message))) { items.add(LocaleController.getString("Delete", R.string.Delete)); - options.add(1); + options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.baseline_delete_24); } } else { if (allowChatActions) { items.add(LocaleController.getString("Reply", R.string.Reply)); - options.add(8); + options.add(OPTION_REPLY); icons.add(R.drawable.baseline_reply_24); } if ((selectedObject.type == 0 || selectedObject.isAnimatedEmoji() || getMessageCaption(selectedObject, selectedObjectGroup) != null) && !noforwardsOverride) { items.add(LocaleController.getString("Copy", R.string.Copy)); - options.add(3); + options.add(OPTION_COPY); icons.add(R.drawable.baseline_content_copy_24); } if (!isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null && (currentChat.has_link || message.hasReplies()) && currentChat.megagroup && message.canViewThread()) { @@ -22410,7 +22342,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { items.add(LocaleController.getString("ViewThread", R.string.ViewThread)); } - options.add(27); + options.add(OPTION_VIEW_REPLIES_OR_THREAD); icons.add(R.drawable.baseline_forum_24); } else if (isThreadChat() && chatMode != MODE_SCHEDULED && currentChat != null) { options.add(nkbtn_view_in_chat); @@ -22420,37 +22352,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (type == 4 && !noforwardsOverride) { if (selectedObject.isVideo()) { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); - options.add(4); + options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.baseline_image_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else if (selectedObject.isMusic()) { items.add(LocaleController.getString("SaveToMusic", R.string.SaveToMusic)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else if (!selectedObject.isVideo() && selectedObject.getDocument() != null) { items.add(LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads)); options.add(OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC); icons.add(R.drawable.baseline_file_download_24); items.add(LocaleController.getString("ShareFile", R.string.ShareFile)); - options.add(6); + options.add(OPTION_SHARE); icons.add(R.drawable.baseline_share_24); } else { items.add(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); - options.add(4); + options.add(OPTION_SAVE_TO_GALLERY); icons.add(R.drawable.baseline_image_24); } } else if (type == 5) { items.add(LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile)); - options.add(5); + options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.baseline_language_24); } else if (type == 10) { items.add(LocaleController.getString("ApplyThemeFile", R.string.ApplyThemeFile)); - options.add(5); + options.add(OPTION_APPLY_LOCALIZATION_OR_THEME); icons.add(R.drawable.baseline_palette_24); } else if (type == 21) { items.add(LocaleController.getString("ImportProxyList", R.string.ImportProxyList)); @@ -22458,7 +22390,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.proxy_on); } else if (type == 7) { items.add(LocaleController.getString("AddToStickers", R.string.AddToStickers)); - options.add(9); + options.add(OPTION_ADD_TO_STICKERS_OR_MASKS); icons.add(R.drawable.deproko_baseline_stickers_24); } else if (type == 8) { long uid = selectedObject.messageOwner.media.user_id; @@ -22468,17 +22400,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (user != null && user.id != getUserConfig().getClientUserId() && getContactsController().contactsDict.get(user.id) == null) { items.add(LocaleController.getString("AddContactTitle", R.string.AddContactTitle)); - options.add(15); + options.add(OPTION_ADD_CONTACT); icons.add(R.drawable.baseline_person_add_24); } if (!TextUtils.isEmpty(selectedObject.messageOwner.media.phone_number)) { if (!noforwardsOverride) { items.add(LocaleController.getString("Copy", R.string.Copy)); - options.add(16); + options.add(OPTION_COPY_PHONE_NUMBER); icons.add(R.drawable.baseline_content_copy_24); } items.add(LocaleController.getString("Call", R.string.Call)); - options.add(17); + options.add(OPTION_CALL); icons.add(R.drawable.baseline_call_24); } } @@ -22530,7 +22462,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not icons.add(R.drawable.baseline_remove_circle_24); } items.add(LocaleController.getString("Delete", R.string.Delete)); - options.add(1); + options.add(OPTION_DELETE); icons.add(selectedObject.messageOwner.ttl_period != 0 ? R.drawable.msg_delete_auto : R.drawable.baseline_delete_24); } if (chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants != null) { @@ -22636,19 +22568,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } boolean hasHeader = count > 10 && message.messageOwner.reactions.results.size() > 1; - LinearLayout linearLayout = new LinearLayout(contentView.getContext()) { - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int size = MeasureSpec.getSize(widthMeasureSpec); - if (size < AndroidUtilities.dp(240)) { - size = AndroidUtilities.dp(240); - } - if (size < 0) { - size = 0; - } - super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), heightMeasureSpec); - } - }; + ReactedUsersListView.ContainerLinerLayout linearLayout = new ReactedUsersListView.ContainerLinerLayout(contentView.getContext()); + linearLayout.hasHeader = hasHeader; linearLayout.setOrientation(LinearLayout.VERTICAL); linearLayout.setLayoutParams(new FrameLayout.LayoutParams(AndroidUtilities.dp(200), AndroidUtilities.dp(6 * 48 + (hasHeader ? 44 * 2 + 8 : 44)) + (!hasHeader ? 1 : 0))); ActionBarMenuSubItem backCell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); @@ -22659,7 +22580,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not linearLayout.addView(backCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); int[] foregroundIndex = new int[1]; - + ReactedUsersListView reactedUsersListView = null; if (hasHeader) { List counters = message.messageOwner.reactions.results; LinearLayout tabsView = new LinearLayout(contentView.getContext()); @@ -22707,7 +22628,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not linearLayout.addView(tabsScrollView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); View divider = new FrameLayout(contentView.getContext()); - divider.setBackgroundColor(Theme.getColor(Theme.key_graySection)); + divider.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuSeparator)); linearLayout.addView(divider, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, (int) Theme.dividerPaint.getStrokeWidth())); int head = AndroidUtilities.dp(44 * 2) + 1; @@ -22716,6 +22637,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not for (int i = 0; i < counters.size() + 1; i++) { cachedHeights.put(i, head + AndroidUtilities.dp(ReactedUsersListView.ITEM_HEIGHT_DP * ReactedUsersListView.VISIBLE_ITEMS)); } + int finalCount = count; pager.setAdapter(new PagerAdapter() { @Override public int getCount() { @@ -22753,9 +22675,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not }).setOnHeightChangedListener((view, newHeight) -> { cachedHeights.put(position, head + newHeight); if (pager.getCurrentItem() == position) - popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], head + newHeight); + popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], head + newHeight, true); }); if (index < 0) { + v.setPredictiveCount(finalCount); reactedView.setSeenCallback(v::setSeenUsers); } @@ -22785,15 +22708,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - if (fX != -1 && tX != -1) + if (fX != -1 && tX != -1) { tabsScrollView.setScrollX((int) (fX + (tX - fX) * positionOffset)); + } + int fromHeight = cachedHeights.get(position, 0); + int toHeight = cachedHeights.get(position + 1, 0); + popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], (int) (fromHeight * (1f - positionOffset) + toHeight * positionOffset), false); } } @Override public void onPageSelected(int position) { int h = cachedHeights.get(position); - popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], h); + popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], h, true); } @Override @@ -22806,10 +22733,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not linearLayout.addView(pager, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); } else { View gap = new FrameLayout(contentView.getContext()); - gap.setBackgroundColor(Theme.getColor(Theme.key_graySection)); + gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); linearLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); - ReactedUsersListView lv = new ReactedUsersListView(contentView.getContext(), themeDelegate, currentAccount, message, null, true) + reactedUsersListView = new ReactedUsersListView(contentView.getContext(), themeDelegate, currentAccount, message, null, true) .setSeenUsers(reactedView.getSeenUsers()) .setOnProfileSelectedListener((view, userId) -> { Bundle args = new Bundle(); @@ -22817,15 +22744,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ProfileActivity fragment = new ProfileActivity(args); presentFragment(fragment); closeMenu(); - }).setOnHeightChangedListener((view, newHeight) -> popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], AndroidUtilities.dp(44 + 8) + newHeight)); - reactedView.setSeenCallback(lv::setSeenUsers); - linearLayout.addView(lv, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); + }).setOnHeightChangedListener((view, newHeight) -> popupLayout.getSwipeBack().setNewForegroundHeight(foregroundIndex[0], AndroidUtilities.dp(44 + 8) + newHeight, true)); + reactedView.setSeenCallback(reactedUsersListView::setSeenUsers); + linearLayout.addView(reactedUsersListView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 0, 1f)); } foregroundIndex[0] = popupLayout.addViewToSwipeBack(linearLayout); + ReactedUsersListView finalReactedUsersListView = reactedUsersListView; reactedView.setOnClickListener(v1 -> { - popupLayout.getSwipeBack().openForeground(foregroundIndex[0]); + if (finalReactedUsersListView == null || finalReactedUsersListView.isLoaded) { + popupLayout.getSwipeBack().openForeground(foregroundIndex[0]); + } }); popupLayout.addView(reactedView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); addGap = true; @@ -22837,7 +22767,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messageSeenLayout.addView(messageSeenView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); MessageSeenView finalMessageSeenView = messageSeenView; - ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); + ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); cell.setItemHeight(44); cell.setTextAndIcon(LocaleController.getString("Back", R.string.Back), R.drawable.msg_arrow_back); cell.getTextView().setPadding(LocaleController.isRTL ? 0 : AndroidUtilities.dp(40), 0, LocaleController.isRTL ? AndroidUtilities.dp(40) : 0, 0); @@ -22891,25 +22821,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not availableHeight -= contentView.getKeyboardHeight() / 3f; } - int listViewTotalHeight = AndroidUtilities.dp(8) + AndroidUtilities.dp(44) * listView2.getAdapter().getItemCount(); - - if (listViewTotalHeight > availableHeight) { - if (availableHeight > AndroidUtilities.dp(620)) { - listView2.getLayoutParams().height = AndroidUtilities.dp(620); - } else { - listView2.getLayoutParams().height = availableHeight; - } - } else { - listView2.getLayoutParams().height = listViewTotalHeight; - } - linearLayout.getLayoutParams().height = AndroidUtilities.dp(44) + listView2.getLayoutParams().height; listView2.requestLayout(); linearLayout.requestLayout(); listView2.getAdapter().notifyDataSetChanged(); popupLayout.getSwipeBack().openForeground(foregroundIndex[0]); } }); - linearLayout.addView(listView2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 320)); + linearLayout.addView(listView2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); listView2.setOnItemClickListener((view1, position) -> { TLRPC.User user = finalMessageSeenView.users.get(position); @@ -22927,8 +22845,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not popupLayout.addView(messageSeenLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 44)); addGap = true; } + boolean showRateTranscription = selectedObject != null && selectedObject.isVoice() && selectedObject.messageOwner != null && getUserConfig().isPremium() && !TextUtils.isEmpty(selectedObject.messageOwner.voiceTranscription) && selectedObject.messageOwner != null && !selectedObject.messageOwner.voiceTranscriptionRated && selectedObject.messageOwner.voiceTranscriptionId != 0 && selectedObject.messageOwner.voiceTranscriptionOpen; - if (message.probablyRingtone() && currentEncryptedChat == null) { + if (!showRateTranscription && message.probablyRingtone() && currentEncryptedChat == null) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, false, themeDelegate); cell.setMinimumWidth(AndroidUtilities.dp(200)); cell.setTextAndIcon(LocaleController.getString("SaveForNotifications", R.string.SaveForNotifications), R.drawable.msg_tone_add); @@ -22955,7 +22874,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (addGap) { View gap = new FrameLayout(contentView.getContext()); - gap.setBackgroundColor(Theme.getColor(Theme.key_graySection)); + gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); popupLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); } @@ -22963,12 +22882,100 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not popupLayout.getSwipeBack().setOnClickListener(e -> closeMenu()); } + if (showRateTranscription) { + final LinearLayout rateTranscriptionLayout = new LinearLayout(contentView.getContext()); + rateTranscriptionLayout.setOrientation(LinearLayout.VERTICAL); + LinearLayout.LayoutParams rateTranscriptionLayoutParams = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 89); + + final FrameLayout rateTranscription = new FrameLayout(contentView.getContext()); + + final View gap = new FrameLayout(contentView.getContext()); + gap.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuSeparator)); + + TextView textView = new TextView(contentView.getContext()); + textView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + textView.setGravity(Gravity.CENTER_HORIZONTAL); + textView.setText(LocaleController.getString("RateTranscription", R.string.RateTranscription)); + rateTranscription.addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 0, 12, 0, 0)); + + + boolean[] ratePositively = new boolean[1]; + boolean[] loading = new boolean[1]; + + Drawable drawable; + ImageView rateUp = new ImageView(contentView.getContext()); + rateUp.setBackground(Theme.createCircleSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 0)); + drawable = contentView.getContext().getResources().getDrawable(R.drawable.msg_rate_up).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); + drawable = new CrossfadeDrawable(drawable, new CircularProgressDrawable(AndroidUtilities.dp(12f), AndroidUtilities.dp(1.5f), getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon))); + rateUp.setImageDrawable(drawable); + rateTranscription.addView(rateUp, LayoutHelper.createFrame(33, 33, Gravity.CENTER_HORIZONTAL | Gravity.TOP, -42, 39, 0, 0)); + + ImageView rateDown = new ImageView(contentView.getContext()); + rateDown.setBackground(Theme.createCircleSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 0, 0)); + drawable = contentView.getContext().getResources().getDrawable(R.drawable.msg_rate_down).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon), PorterDuff.Mode.SRC_IN)); + drawable = new CrossfadeDrawable(drawable, new CircularProgressDrawable(AndroidUtilities.dp(12f), AndroidUtilities.dp(1.5f), getThemedColor(Theme.key_actionBarDefaultSubmenuItemIcon))); + rateDown.setImageDrawable(drawable); + rateTranscription.addView(rateDown, LayoutHelper.createFrame(33, 33, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 42, 39, 0, 0)); + + Runnable rate = () -> { + if (loading[0]) { + return; + } + loading[0] = true; + long[] progressShown = new long[1]; + progressShown[0] = -1; + Runnable showProgress = () -> { + progressShown[0] = SystemClock.elapsedRealtime(); + CrossfadeDrawable ldrawable = ((CrossfadeDrawable) (ratePositively[0] ? rateUp : rateDown).getDrawable()); + ValueAnimator lva = ValueAnimator.ofFloat(0f, 1f); + lva.addUpdateListener(a -> { + ldrawable.setProgress((float) a.getAnimatedValue()); + }); + lva.setDuration(150); + lva.setInterpolator(CubicBezierInterpolator.DEFAULT); + lva.start(); + }; + + TLRPC.TL_messages_rateTranscribedAudio req = new TLRPC.TL_messages_rateTranscribedAudio(); + req.msg_id = selectedObject.getId(); + req.peer = getMessagesController().getInputPeer(selectedObject.messageOwner.peer_id); + req.transcription_id = selectedObject.messageOwner.voiceTranscriptionId; + req.good = ratePositively[0]; + getConnectionsManager().sendRequest(req, (res, err) -> { + AndroidUtilities.cancelRunOnUIThread(showProgress); + selectedObject.messageOwner.voiceTranscriptionRated = true; + getMessagesStorage().updateMessageVoiceTranscriptionOpen(selectedObject.getDialogId(), selectedObject.getId(), selectedObject.messageOwner); + AndroidUtilities.runOnUIThread(() -> { + closeMenu(); + BulletinFactory.of(ChatActivity.this).createSimpleBulletin(R.raw.chats_infotip, LocaleController.getString("TranscriptionReportSent", R.string.TranscriptionReportSent)).show(); + }, progressShown[0] > 0 ? Math.max(0, 300 - (SystemClock.elapsedRealtime() - progressShown[0])) : 0); + }); + AndroidUtilities.runOnUIThread(showProgress, 150); + }; + + rateUp.setOnClickListener(e -> { + ratePositively[0] = true; + rate.run(); + }); + rateDown.setOnClickListener(e -> { + ratePositively[0] = false; + rate.run(); + }); + + rateTranscriptionLayout.addView(rateTranscription, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 81)); + rateTranscriptionLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); + + popupLayout.addView(rateTranscriptionLayout, rateTranscriptionLayoutParams); + } + final boolean translateButtonEnabled = MessagesController.getGlobalMainSettings().getBoolean("translate_button", false); scrimPopupWindowItems = new ActionBarMenuSubItem[items.size() + (selectedObject.isSponsored() ? 1 : 0)]; for (int a = 0, N = items.size(); a < N; a++) { if (a == 0 && selectedObject.isSponsored()) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), true, true, themeDelegate); - cell.setTextAndIcon(LocaleController.getString("SponsoredMessageInfo", R.string.SponsoredMessageInfo), R.drawable.menu_info); + cell.setTextAndIcon(LocaleController.getString("SponsoredMessageInfo", R.string.SponsoredMessageInfo), R.drawable.msg_info); cell.setItemHeight(56); cell.setTag(R.id.width_tag, 240); cell.setMultiline(); @@ -23015,7 +23022,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } processSelectedOption(options.get(i)); }); - if (option == 29) { + if (option == OPTION_TRANSLATE) { // NekoX: Official Translation Removed } cell.setOnLongClickListener(v1 -> { @@ -23079,15 +23086,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (optionsView != null) { scrimPopupContainerLayout.addView(optionsView); } else { - reactionsLayout = new ReactionsContainerLayout(contentView.getContext(), currentAccount, getResourceProvider()); + reactionsLayout = new ReactionsContainerLayout(ChatActivity.this, contentView.getContext(), currentAccount, getResourceProvider()); if (isReactionsAvailable) { int pad = 22; int sPad = 24; reactionsLayout.setPadding(AndroidUtilities.dp(4) + (LocaleController.isRTL ? 0 : sPad), AndroidUtilities.dp(4), AndroidUtilities.dp(4) + (LocaleController.isRTL ? sPad : 0), AndroidUtilities.dp(pad)); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; - reactionsLayout.setDelegate((rView, reaction, longress) -> { - selectReaction(primaryMessage, finalReactionsLayout, 0, 0, reaction, false, longress); + reactionsLayout.setDelegate(new ReactionsContainerLayout.ReactionsContainerDelegate() { + @Override + public void onReactionClicked(View v, TLRPC.TL_availableReaction reaction, boolean longpress) { + selectReaction(primaryMessage, finalReactionsLayout, 0, 0, reaction, false, longpress); + } + + @Override + public void hideMenu() { + if (scrimPopupWindow != null) { + scrimPopupWindow.dismiss(false); + } + } }); LinearLayout.LayoutParams params = LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 52 + pad, Gravity.RIGHT, 0, 50, 0, -20); @@ -23098,11 +23115,22 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not reactionsLayout.setTransitionProgress(0); if (popupLayout.getSwipeBack() != null) { - popupLayout.getSwipeBack().addOnSwipeBackProgressListener((layout, toProgress, progress) -> { - if (toProgress == 0) { - finalReactionsLayout.startEnterAnimation(); - } else if (toProgress == 1) - finalReactionsLayout.setAlpha(1f - progress); + popupLayout.getSwipeBack().addOnSwipeBackProgressListener(new PopupSwipeBackLayout.OnSwipeBackProgressListener() { + + boolean isEnter = true; + + @Override + public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress) { + if (toProgress == 0 && !isEnter) { + finalReactionsLayout.startEnterAnimation(); + isEnter = true; + } else if (toProgress == 1 && isEnter) { + finalReactionsLayout.setAlpha(1f - progress); + if (progress == 1f) { + isEnter = false; + } + } + } }); } } @@ -23115,7 +23143,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not boolean isChannel = ChatObject.isChannel(currentChat) && !currentChat.megagroup; TextView tv = new TextView(contentView.getContext()); tv.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - tv.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + tv.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubmenuItem)); if (getMessagesController().isChatNoForwards(currentChat)) { tv.setText(isChannel ? LocaleController.getString("ForwardsRestrictedInfoChannel", R.string.ForwardsRestrictedInfoChannel) : LocaleController.getString("ForwardsRestrictedInfoGroup", R.string.ForwardsRestrictedInfoGroup)); @@ -23125,7 +23153,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not tv.setMaxWidth(popupLayout.getMeasuredWidth() - AndroidUtilities.dp(38)); Drawable shadowDrawable2 = ContextCompat.getDrawable(contentView.getContext(), R.drawable.popup_fixed_alert).mutate(); - shadowDrawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); FrameLayout fl = new FrameLayout(contentView.getContext()); fl.setBackground(shadowDrawable2); @@ -23201,15 +23229,23 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } final int finalPopupX = scrimPopupX = popupX; final int finalPopupY = scrimPopupY = popupY; + scrimPopupContainerLayout.setMaxHeight(totalHeight - popupY); ReactionsContainerLayout finalReactionsLayout = reactionsLayout; Runnable showMenu = () -> { - if (scrimPopupWindow == null || fragmentView == null) { + if (scrimPopupWindow == null || fragmentView == null || scrimPopupWindow.isShowing()) { return; } scrimPopupWindow.showAtLocation(chatListView, Gravity.LEFT | Gravity.TOP, finalPopupX, finalPopupY); if (isReactionsAvailable && finalReactionsLayout != null) { finalReactionsLayout.startEnterAnimation(); } + AndroidUtilities.runOnUIThread(() -> { + if (scrimPopupWindowItems != null && scrimPopupWindowItems.length > 0 && scrimPopupWindowItems[0] != null) { + scrimPopupWindowItems[0].requestFocus(); + scrimPopupWindowItems[0].performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + scrimPopupWindowItems[0].sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); + } + }, 420); }; if (waitForLangDetection.get()) { onLangDetectionDone.set(showMenu); @@ -23305,7 +23341,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } - private void closeMenu() { + public void closeMenu() { closeMenu(true); } @@ -23357,6 +23393,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ChatMessageCell cell = findMessageCell(finalMessageIdForCell, true); ReactionsEffectOverlay.show(ChatActivity.this, reactionsLayout, cell, x, y, reaction.reaction, currentAccount, reactionsLayout != null ? (bigEmoji ? ReactionsEffectOverlay.LONG_ANIMATION : ReactionsEffectOverlay.ONLY_MOVE_ANIMATION) : ReactionsEffectOverlay.SHORT_ANIMATION); } + if (added) { + AndroidUtilities.makeAccessibilityAnnouncement(LocaleController.formatString("AccDescrYouReactedWith", R.string.AccDescrYouReactedWith, reaction.reaction)); + } getSendMessagesHelper().sendReaction(primaryMessage, added ? reaction.reaction : null, bigEmoji, ChatActivity.this, updateReactionRunnable = new Runnable() { @Override public void run() { @@ -23420,6 +23459,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } public ChatMessageCell findMessageCell(int id, boolean visibleForUser) { + if (chatListView == null) { + return null; + } for (int i = 0, n = chatListView.getChildCount(); i < n; i++) { View child = chatListView.getChildAt(i); if (chatListView.getChildAt(i) instanceof ChatMessageCell && ((ChatMessageCell) chatListView.getChildAt(i)).getMessageObject().getId() == id) { @@ -23444,7 +23486,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setFieldFocused(); } - mentionsAdapter.setNeedBotContext(false); + mentionContainer.getAdapter().setNeedBotContext(false); chatActivityEnterView.setVisibility(View.VISIBLE); showFieldPanelForEdit(true, messageObject); updateBottomOverlay(); @@ -23605,7 +23647,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (TextUtils.isEmpty(path)) { - path = FileLoader.getPathToMessage(messageObject.messageOwner).toString(); + path = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), messageObject.isVideo() ? 1 : 0, null, null); } @@ -23635,7 +23677,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } boolean preserveDim = false; switch (option) { - case 0: { + case OPTION_RETRY: { if (selectedObjectGroup != null) { boolean success = true; for (int a = 0; a < selectedObjectGroup.messages.size(); a++) { @@ -23667,7 +23709,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not createDeleteMessagesAlert(selectedObject, selectedObjectGroup, 1,true); break; } - case 2: { + case OPTION_FORWARD: { noForwardQuote = false; //fuck forwardingMessage = selectedObject; forwardingMessageGroup = selectedObjectGroup; @@ -23682,7 +23724,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(fragment); break; } - case 3: { + case OPTION_COPY: { if (selectedObject.isDice()) { AndroidUtilities.addToClipboard(selectedObject.getDiceEmoji()); } else { @@ -23696,7 +23738,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not undoView.showWithAction(0, UndoView.ACTION_MESSAGE_COPIED, null); break; } - case 4: { + case OPTION_SAVE_TO_GALLERY: { if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; @@ -23730,7 +23772,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 5: { + case OPTION_APPLY_LOCALIZATION_OR_THEME: { File locFile = null; if (!TextUtils.isEmpty(selectedObject.messageOwner.attachPath)) { File f = new File(selectedObject.messageOwner.attachPath); @@ -23739,7 +23781,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (locFile == null) { - File f = FileLoader.getPathToMessage(selectedObject.messageOwner); + File f = getFileLoader().getPathToMessage(selectedObject.messageOwner); if (f.exists()) { locFile = f; } @@ -23819,7 +23861,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 6: { + case OPTION_SHARE: { String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); @@ -23828,7 +23870,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } Intent intent = new Intent(Intent.ACTION_SEND); intent.setType(selectedObject.getDocument().mime_type); @@ -23850,7 +23892,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 7: { + case OPTION_SAVE_TO_GALLERY2: { String path = selectedObject.messageOwner.attachPath; if (path != null && path.length() > 0) { File temp = new File(path); @@ -23859,7 +23901,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); @@ -23872,11 +23914,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not BulletinFactory.createSaveToGalleryBulletin(this, selectedObject.isVideo(), themeDelegate).show(); break; } - case 8: { + case OPTION_REPLY: { showFieldPanelForReply(selectedObject); break; } - case 9: { + case OPTION_ADD_TO_STICKERS_OR_MASKS: { StickersAlert alert = new StickersAlert(getParentActivity(), this, selectedObject.getInputStickerSet(), null, bottomOverlayChat.getVisibility() != View.VISIBLE && (currentChat == null || ChatObject.canSendStickers(currentChat)) ? chatActivityEnterView : null, themeDelegate); alert.setCalcMandatoryInsets(isKeyboardVisible()); preserveDim = true; @@ -23886,7 +23928,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } case OPTION_SAVE_TO_DOWNLOADS_OR_MUSIC: { - //TODO scopped storage if (Build.VERSION.SDK_INT >= 23 && (Build.VERSION.SDK_INT <= 28 || BuildVars.NO_SCOPED_STORAGE) && getParentActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 4); selectedObject = null; @@ -23928,7 +23969,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString(); + path = getFileLoader().getPathToMessage(selectedObject.messageOwner).toString(); } MediaController.saveFile(path, getParentActivity(), 2, fileName, selectedObject.getDocument() != null ? selectedObject.getDocument().mime_type : "", () -> { if (getParentActivity() == null || fragmentView == null) { @@ -23949,7 +23990,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 11: { + case OPTION_ADD_TO_GIFS: { TLRPC.Document document = selectedObject.getDocument(); getMessagesController().saveGif(selectedObject, document); if (!showGifHint() && getParentActivity() != null) { @@ -23958,7 +23999,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.addRecentGif(document); break; } - case 12: { + case OPTION_EDIT: { if (selectedObjectToEditCaption != null) { startEditingMessageObject(selectedObjectToEditCaption); } else { @@ -23969,7 +24010,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not selectedObjectToEditCaption = null; break; } - case 13: { + case OPTION_PIN: { final int mid; if (selectedObjectGroup != null && !selectedObjectGroup.messages.isEmpty()) { mid = selectedObjectGroup.messages.get(0).getId(); @@ -24045,7 +24086,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); break; } - case 14: { + case OPTION_UNPIN: { MessageObject messageObject; if (pinnedMessageObjects.containsKey(selectedObject.getId())) { messageObject = selectedObject; @@ -24062,7 +24103,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 15: { + case OPTION_ADD_CONTACT: { Bundle args = new Bundle(); args.putLong("user_id", selectedObject.messageOwner.media.user_id); args.putString("phone", selectedObject.messageOwner.media.phone_number); @@ -24070,11 +24111,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not presentFragment(new ContactAddActivity(args)); break; } - case 16: { + case OPTION_COPY_PHONE_NUMBER: { AndroidUtilities.addToClipboard(selectedObject.messageOwner.media.phone_number); break; } - case 17: { + case OPTION_CALL: { try { Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + selectedObject.messageOwner.media.phone_number)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); @@ -24084,25 +24125,25 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 18: { + case OPTION_CALL_AGAIN: { if (currentUser != null) { VoIPHelper.startCall(currentUser, selectedObject.isVideoCall(), userInfo != null && userInfo.video_calls_available, getParentActivity(), getMessagesController().getUserFull(currentUser.id), getAccountInstance()); } break; } - case 19: { + case OPTION_RATE_CALL: { VoIPHelper.showRateAlert(getParentActivity(), (TLRPC.TL_messageActionPhoneCall) selectedObject.messageOwner.action); break; } - case 20: { + case OPTION_ADD_STICKER_TO_FAVORITES: { getMediaDataController().addRecentSticker(MediaDataController.TYPE_FAVE, selectedObject, selectedObject.getDocument(), (int) (System.currentTimeMillis() / 1000), false); break; } - case 21: { + case OPTION_DELETE_STICKER_FROM_FAVORITES: { getMediaDataController().addRecentSticker(MediaDataController.TYPE_FAVE, selectedObject, selectedObject.getDocument(), (int) (System.currentTimeMillis() / 1000), true); break; } - case 22: { + case OPTION_COPY_LINK: { TLRPC.TL_channels_exportMessageLink req = new TLRPC.TL_channels_exportMessageLink(); if (selectedObject == replyingMessageObject && isComments) { req.id = replyOriginalMessageId; @@ -24142,7 +24183,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 24: { + case OPTION_CANCEL_SENDING: { if (selectedObject.isEditing() || selectedObject.isSending() && selectedObjectGroup == null) { getSendMessagesHelper().cancelSendingMessage(selectedObject); } else if (selectedObject.isSending() && selectedObjectGroup != null) { @@ -24152,7 +24193,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 25: { + case OPTION_UNVOTE: { final AlertDialog[] progressDialog = new AlertDialog[]{new AlertDialog(getParentActivity(), 3, themeDelegate)}; int requestId = getSendMessagesHelper().sendVote(selectedObject, null, () -> { try { @@ -24173,7 +24214,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } break; } - case 26: { + case OPTION_STOP_POLL_OR_QUIZ: { MessageObject object = selectedObject; AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); preserveDim = true; @@ -24227,11 +24268,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(builder.create()); break; } - case 27: { + case OPTION_VIEW_REPLIES_OR_THREAD: { openDiscussionMessageChat(currentChat.id, null, selectedObject.getId(), 0, -1, 0, null); break; } - case 28: { + case OPTION_STATISTICS: { presentFragment(new MessageStatisticActivity(selectedObject)); break; } @@ -24269,7 +24310,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not break; } } - case 102: { + case OPTION_EDIT_SCHEDULE_TIME: { MessageObject message = selectedObject; MessageObject.GroupedMessages group = selectedObjectGroup; AlertsCreator.createScheduleDatePickerDialog(getParentActivity(), dialog_id, message.messageOwner.date, (notify, scheduleDate) -> { @@ -24284,6 +24325,11 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not preserveDim = true; break; } + case OPTION_HIDE_SPONSORED_MESSAGE: { + MessageObject message = selectedObject; + showDialog(new PremiumFeatureBottomSheet(ChatActivity.this, PremiumPreviewFragment.PREMIUM_FEATURE_ADS, true)); + break; + } default: { nkbtn_onclick(option); break; @@ -24470,7 +24516,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean onBackPressed() { - if (forwardingPreviewView != null && forwardingPreviewView.isShowing()) { + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().closeWithMenu(); + return false; + } else if (forwardingPreviewView != null && forwardingPreviewView.isShowing()) { forwardingPreviewView.dismiss(true); return false; } else if (messagesSearchListView.getTag() != null) { @@ -24488,8 +24537,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not clearSelectionMode(); return false; } else if (chatActivityEnterView != null && chatActivityEnterView.isPopupShowing()) { - chatActivityEnterView.hidePopup(true); - return false; + return !chatActivityEnterView.hidePopup(true); } else if (chatActivityEnterView != null && chatActivityEnterView.hasBotWebView() && chatActivityEnterView.botCommandsMenuIsShowing() && chatActivityEnterView.onBotWebViewBackPressed()) { return false; } else if (chatActivityEnterView != null && chatActivityEnterView.botCommandsMenuIsShowing()) { @@ -24878,15 +24926,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private boolean savedNoHistory; private boolean savedNoDiscussion; - private void processLoadedDiscussionMessage(boolean noDiscussion, TLRPC.TL_messages_discussionMessage discussionMessage, boolean noHistory, TLRPC.messages_Messages history, int maxReadId, MessageObject fallbackMessage, Runnable progressRunnable, TLRPC.TL_messages_getDiscussionMessage req, TLRPC.Chat originalChat, int highlightMsgId, MessageObject originalMessage) { - if (!noDiscussion && discussionMessage == null || noDiscussion || !noHistory && history == null) { - commentLoadingMessageId = 0; - chatListView.invalidateViews(); - return; - } - + private void processLoadedDiscussionMessage(boolean noDiscussion, TLRPC.TL_messages_discussionMessage discussionMessage, boolean noHistory, TLRPC.messages_Messages history, int maxReadId, MessageObject fallbackMessage, TLRPC.TL_messages_getDiscussionMessage req, TLRPC.Chat originalChat, int highlightMsgId, MessageObject originalMessage) { + final int thisCommentLoadingMessageId = commentLoadingMessageId; if (history != null) { - if (maxReadId != 1 && maxReadId != 0 && maxReadId != discussionMessage.read_inbox_max_id) { + if (maxReadId != 1 && maxReadId != 0 && maxReadId != discussionMessage.read_inbox_max_id && highlightMsgId <= 0) { history = null; } else if (!history.messages.isEmpty() && discussionMessage != null && !discussionMessage.messages.isEmpty()) { TLRPC.Message message = history.messages.get(0); @@ -24900,16 +24943,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - boolean chatOpened = false; - ArrayList arrayList = new ArrayList<>(); - for (int a = 0, N = discussionMessage.messages.size(); a < N; a++) { - TLRPC.Message message = discussionMessage.messages.get(a); - if (message instanceof TLRPC.TL_messageEmpty) { - continue; + if (discussionMessage != null && discussionMessage.messages != null) { + for (int a = 0, N = discussionMessage.messages.size(); a < N; a++) { + TLRPC.Message message = discussionMessage.messages.get(a); + if (message instanceof TLRPC.TL_messageEmpty) { + continue; + } + message.isThreadMessage = true; + arrayList.add(new MessageObject(UserConfig.selectedAccount, message, true, true)); } - message.isThreadMessage = true; - arrayList.add(new MessageObject(UserConfig.selectedAccount, message, true, true)); } if (!arrayList.isEmpty()) { Bundle args = new Bundle(); @@ -24929,11 +24972,21 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (originalMessage != null && originalMessage.messageOwner.reactions != null) { chatActivity.threadMessageObject.messageOwner.reactions = originalMessage.messageOwner.reactions; } - presentFragment(chatActivity); - if (isKeyboardVisible() && !chatActivity.hideKeyboardOnShow()) { - chatActivity.chatActivityEnterView.getEditField().requestFocus(); - } - chatOpened = true; + final boolean[] chatOpened = new boolean[] { false }; + Runnable openCommentsChat = () -> { + if (chatOpened[0] || thisCommentLoadingMessageId != commentLoadingMessageId || !isFullyVisible || isFinishing()) { + return; + } + chatOpened[0] = true; + AndroidUtilities.runOnUIThread(() -> { + commentLoadingMessageId = 0; + chatListView.invalidateViews(); + }, 200); + presentFragment(chatActivity); + if (isKeyboardVisible() && !chatActivity.hideKeyboardOnShow()) { + chatActivity.chatActivityEnterView.getEditField().requestFocus(); + } + }; if (history != null) { int fnid = 0; if (!history.messages.isEmpty()) { @@ -24945,16 +24998,32 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } } + TLRPC.messages_Messages historyFinal = history; int fnidFinal = fnid; - Utilities.stageQueue.postRunnable(() -> getMessagesController().processLoadedMessages(historyFinal, historyFinal.messages.size(), dialogId, 0, 30, maxReadId, 0, false, chatActivity.getClassGuid(), fnidFinal, 0, 0, 0, 2, true, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0, true)); + final int commentsClassGuid = chatActivity.getClassGuid(); + final NotificationCenter.NotificationCenterDelegate observer = new NotificationCenter.NotificationCenterDelegate() { + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.messagesDidLoad && (Integer) args[10] == commentsClassGuid) { + openCommentsChat.run(); + AndroidUtilities.runOnUIThread(() -> { + chatActivity.didReceivedNotification(id, account, args); + }, 50); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.messagesDidLoad); + } + } + }; + NotificationCenter.getInstance(currentAccount).addObserver(observer, NotificationCenter.messagesDidLoad); + Utilities.stageQueue.postRunnable(() -> { + getMessagesController().processLoadedMessages(historyFinal, historyFinal.messages.size(), dialogId, 0, 30, (highlightMsgId > 0 ? highlightMsgId : maxReadId), 0, false, commentsClassGuid, fnidFinal, 0, 0, 0, (highlightMsgId > 0 ? 3 : 2), true, 0, arrayList.get(arrayList.size() - 1).getId(), 1, false, 0, true); + }); + } else { + openCommentsChat.run(); } - } - - AndroidUtilities.cancelRunOnUIThread(progressRunnable); - commentLoadingMessageId = 0; - chatListView.invalidateViews(); - if (!chatOpened) { + } else { + commentLoadingMessageId = 0; + chatListView.invalidateViews(); if (fallbackMessage != null) { openOriginalReplyChat(fallbackMessage); } else { @@ -24992,71 +25061,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getConnectionsManager().cancelRequest(commentRequestId, false); } - Runnable progressRunnable = () -> { - commentLoadingMessageId = fallbackMessage != null ? fallbackMessage.getId() : messageId; - if (chatListView != null) { - chatListView.invalidateViews(); - } - }; - if (maxReadId >= 0 && linkedChatId != 0) { - TLRPC.Chat linkedChat = getMessagesController().getChat(linkedChatId); - if (linkedChat != null) { - int count = 30; - if (BuildVars.LOGS_ENABLED) { - FileLog.d("load replies for " + linkedChat.id + " msg_id = " + maxReadId); - } - TLRPC.TL_messages_getReplies getReplies = new TLRPC.TL_messages_getReplies(); - getReplies.peer = MessagesController.getInputPeer(linkedChat); - getReplies.msg_id = maxReadId; - getReplies.offset_date = 0; - getReplies.add_offset = -count + 10; - getReplies.limit = count; - getReplies.offset_id = maxReadId; - int guid = ++commentMessagesLoadingGuid; - commentMessagesRequestId = getConnectionsManager().sendRequest(getReplies, (response, error) -> { - Runnable runnable = () -> { - if (guid != commentMessagesLoadingGuid) { - return; - } - commentMessagesRequestId = -1; - if (response != null) { - savedHistory = (TLRPC.messages_Messages) response; - if (savedHistory.messages.size() > count) { - savedHistory.messages.remove(0); - } - } else { - if ("CHANNEL_PRIVATE".equals(error.text)) { - if (getParentActivity() != null) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - } - AndroidUtilities.cancelRunOnUIThread(progressRunnable); - commentLoadingMessageId = 0; - chatListView.invalidateViews(); - return; - } - savedNoHistory = true; - } - processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); - }; - AndroidUtilities.runOnUIThread(() -> doOnIdle(runnable)); - }); - getConnectionsManager().bindRequestToGuid(commentMessagesRequestId, classGuid); - } else { - savedNoHistory = true; - } - } else { - savedNoHistory = true; + commentLoadingMessageId = fallbackMessage != null ? fallbackMessage.getId() : messageId; + if (chatListView != null) { + chatListView.invalidateViews(); } - int guid = ++commentLoadingGuid; + final int guid1 = ++commentLoadingGuid; commentRequestId = getConnectionsManager().sendRequest(req, (response, error) -> { Runnable runnable = () -> { - if (guid != commentLoadingGuid) { + if (guid1 != commentLoadingGuid) { return; } + int maxReadId1 = maxReadId; + long linkedChatId1 = linkedChatId; commentRequestId = -1; if (response instanceof TLRPC.TL_messages_discussionMessage) { savedDiscussionMessage = (TLRPC.TL_messages_discussionMessage) response; @@ -25065,12 +25081,66 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { savedNoDiscussion = true; } - processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId, fallbackMessage, progressRunnable, req, chat, highlightMsgId, originalMessage); + + ArrayList msgs = new ArrayList<>(); + if (savedDiscussionMessage != null && savedDiscussionMessage.messages != null) { + for (int i = 0; i < savedDiscussionMessage.messages.size(); ++i) { + TLRPC.Message message = savedDiscussionMessage.messages.get(i); + if (message instanceof TLRPC.TL_messageEmpty) { + continue; + } + msgs.add(message); + } + } + if (msgs.size() > 0) { + TLRPC.Message message = msgs.get(0); + TLRPC.TL_messages_getReplies getReplies = new TLRPC.TL_messages_getReplies(); + getReplies.peer = getMessagesController().getInputPeer(message.peer_id); + getReplies.msg_id = message.id; + getReplies.offset_date = 0; + getReplies.limit = 30; + if (highlightMsgId > 0) { + getReplies.offset_id = highlightMsgId; + getReplies.add_offset = -getReplies.limit / 2; + } else { + getReplies.offset_id = maxReadId1 == 0 ? 1 : maxReadId1; + getReplies.add_offset = -getReplies.limit + 10; + } + final int guid2 = ++commentMessagesLoadingGuid; + commentMessagesRequestId = getConnectionsManager().sendRequest(getReplies, (response2, error2) -> { + AndroidUtilities.runOnUIThread(() -> doOnIdle(() -> { + if (guid2 != commentMessagesLoadingGuid) { + return; + } + commentMessagesRequestId = -1; + if (response2 != null) { + savedHistory = (TLRPC.messages_Messages) response2; + } else { + if ("CHANNEL_PRIVATE".equals(error2.text)) { + if (getParentActivity() != null) { + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); + builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); + builder.setMessage(LocaleController.getString("JoinByPeekChannelText", R.string.JoinByPeekChannelText)); + builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); + } + commentLoadingMessageId = 0; + chatListView.invalidateViews(); + return; + } + savedNoHistory = true; + } + processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId1, fallbackMessage, req, chat, highlightMsgId, originalMessage); + })); + }); + } else { + savedNoHistory = true; + processLoadedDiscussionMessage(savedNoDiscussion, savedDiscussionMessage, savedNoHistory, savedHistory, maxReadId1, fallbackMessage, req, chat, highlightMsgId, originalMessage); + } }; AndroidUtilities.runOnUIThread(() -> doOnIdle(runnable)); }); getConnectionsManager().bindRequestToGuid(commentRequestId, classGuid); - AndroidUtilities.runOnUIThread(progressRunnable, 500); } private void openOriginalReplyChat(MessageObject messageObject) { @@ -25238,51 +25308,128 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messageCell.setChecked(true, groupedMessages == null, animated); } - private void openClickableLink(String str, boolean qr) { - if (str.startsWith("@")) { - String username = str.substring(1).toLowerCase(); - if (qr) { - ProxyUtil.showQrDialog(getParentActivity(), "https://t.me/" + username); - return; + private void openClickableLink(CharacterStyle url, String str, boolean longPress, final ChatMessageCell cell, final MessageObject messageObject) { + if (longPress) { + BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity(), false, themeDelegate); + int timestamp = -1; + if (str.startsWith("video?")) { + timestamp = Utilities.parseInt(str); } - if (currentChat != null && !TextUtils.isEmpty(currentChat.username) && username.equals(currentChat.username.toLowerCase()) || - currentUser != null && !TextUtils.isEmpty(currentUser.username) && username.equals(currentUser.username.toLowerCase())) { - Bundle args = new Bundle(); - if (currentChat != null) { - args.putLong("chat_id", currentChat.id); - } else if (currentUser != null) { - args.putLong("user_id", currentUser.id); - if (currentEncryptedChat != null) { - args.putLong("dialog_id", dialog_id); + if (timestamp >= 0) { + builder.setTitle(AndroidUtilities.formatDuration(timestamp, false)); + } else { + String formattedUrl = str; + try { + formattedUrl = URLDecoder.decode(str.replaceAll("\\+", "%2b"), "UTF-8"); + } catch (Exception ignore) {} + builder.setTitle(formattedUrl); + builder.setTitleMultipleLines(true); + } + final int finalTimestamp = timestamp; + boolean noforwards = getMessagesController().isChatNoForwards(currentChat) || (messageObject != null && messageObject.messageOwner != null && messageObject.messageOwner.noforwards); + builder.setItems(noforwards ? new CharSequence[] {LocaleController.getString("Open", R.string.Open)} : new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { + if (which == 0) { + if (str.startsWith("video?")) { + didPressMessageUrl(url, false, messageObject, cell); + } else { + openClickableLink(url, str, false, cell, messageObject); } + } else if (which == 1) { + if (str.startsWith("video?") && messageObject != null && !messageObject.scheduled) { + MessageObject messageObject1 = messageObject; + boolean isMedia = messageObject.isVideo() || messageObject.isRoundVideo() || messageObject.isVoice() || messageObject.isMusic(); + if (!isMedia && messageObject.replyMessageObject != null) { + messageObject1 = messageObject.replyMessageObject; + } + long dialogId = messageObject1.getDialogId(); + int messageId = messageObject1.getId(); + String link = null; + + if (messageObject1.messageOwner.fwd_from != null) { + if (messageObject1.messageOwner.fwd_from.saved_from_peer != null) { + dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.saved_from_peer); + messageId = messageObject1.messageOwner.fwd_from.saved_from_msg_id; + } else if (messageObject1.messageOwner.fwd_from.from_id != null) { + dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.from_id); + messageId = messageObject1.messageOwner.fwd_from.channel_post; + } + } + + if (DialogObject.isChatDialog(dialogId)) { + TLRPC.Chat currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + if (currentChat != null && currentChat.username != null) { + link = "https://t.me/" + currentChat.username + "/" + messageId + "?t=" + finalTimestamp; + } + } else { + TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); + if (user != null && user.username != null) { + link = "https://t.me/" + user.username + "/" + messageId + "?t=" + finalTimestamp; + } + } + if (link == null) { + return; + } + AndroidUtilities.addToClipboard(link); + } else { + AndroidUtilities.addToClipboard(str); + } + if (str.startsWith("@")) { + undoView.showWithAction(0, UndoView.ACTION_USERNAME_COPIED, null); + } else if (str.startsWith("#") || str.startsWith("$")) { + undoView.showWithAction(0, UndoView.ACTION_HASHTAG_COPIED, null); + } else { + undoView.showWithAction(0, UndoView.ACTION_LINK_COPIED, null); + } + } - ProfileActivity fragment = new ProfileActivity(args, avatarContainer.getSharedMediaPreloader()); - fragment.setPlayProfileAnimation(1); - fragment.setChatInfo(chatInfo); - fragment.setUserInfo(userInfo); - presentFragment(fragment); - } else { - getMessagesController().openByUserName(username, ChatActivity.this, 0); - } - } else if (str.startsWith("#") || str.startsWith("$")) { - if (ChatObject.isChannel(currentChat)) { - if (chatMode == MODE_SCHEDULED || chatMode == MODE_PINNED) { - chatActivityDelegate.openSearch(str); - finishFragment(); - } else { - openSearchWithText(str); + }); + builder.setOnPreDismissListener(di -> { + if (cell != null) { + cell.resetPressedLink(-1); } - } else { - DialogsActivity fragment = new DialogsActivity(null); - fragment.setSearchString(str); - presentFragment(fragment); - } + }); + showDialog(builder.create()); } else { - if (qr) { + if (str.startsWith("@")) { + String username = str.substring(1).toLowerCase(); + if (currentChat != null && !TextUtils.isEmpty(currentChat.username) && username.equals(currentChat.username.toLowerCase()) || + currentUser != null && !TextUtils.isEmpty(currentUser.username) && username.equals(currentUser.username.toLowerCase())) { + Bundle args = new Bundle(); + if (currentChat != null) { + args.putLong("chat_id", currentChat.id); + } else if (currentUser != null) { + args.putLong("user_id", currentUser.id); + if (currentEncryptedChat != null) { + args.putLong("dialog_id", dialog_id); + } + } + ProfileActivity fragment = new ProfileActivity(args, avatarContainer.getSharedMediaPreloader()); + fragment.setPlayProfileAnimation(1); + fragment.setChatInfo(chatInfo); + fragment.setUserInfo(userInfo); + presentFragment(fragment); + } else { + getMessagesController().openByUserName(username, ChatActivity.this, 0); + } + } else if (str.startsWith("#") || str.startsWith("$")) { + if (ChatObject.isChannel(currentChat)) { + if (chatMode == MODE_SCHEDULED || chatMode == MODE_PINNED) { + chatActivityDelegate.openSearch(str); + finishFragment(); + } else { + openSearchWithText(str); + } + } else { + DialogsActivity fragment = new DialogsActivity(null); + fragment.setSearchString(str); + presentFragment(fragment); + } + } else { + if (qr) { ProxyUtil.showQrDialog(getParentActivity(), str); return; } - processExternalUrl(0, str, false); + processExternalUrl(0, str, false);} } } @@ -25329,7 +25476,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not ((URLSpanMono) url).copyToClipboard(); getUndoView().showWithAction(0, UndoView.ACTION_TEXT_COPIED, null); } - if (longPress) { + if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (url instanceof URLSpanUserMention) { @@ -25337,7 +25484,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (user != null) { MessagesController.openChatOrProfileWith(user, null, ChatActivity.this, 0, false); } - if (longPress) { + if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (url instanceof URLSpanNoUnderline) { @@ -25349,7 +25496,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not hideFieldPanel(false); } } - if (longPress) { + if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (messageObject != null && str.startsWith("video") && !longPress) { @@ -25395,7 +25542,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not messageObject.forceSeekTo = seekTime / (float) messageObject.getDuration(); mediaController.playMessage(messageObject); } - if (longPress) { + if (longPress && cell != null) { cell.resetPressedLink(-1); } } else if (str.startsWith("card:")) { @@ -25431,10 +25578,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Toast.makeText(ApplicationLoader.applicationContext, LocaleController.getString("CardNumberCopied", R.string.CardNumberCopied), Toast.LENGTH_SHORT).show(); } }); - builder.setOnPreDismissListener(di -> finalCell.resetPressedLink(-1)); - builder.fixNavigationBar(); + builder.setOnPreDismissListener(di -> { + if (finalCell != null) { + finalCell.resetPressedLink(-1); + } + }); showDialog(builder.create()); - } else { + } else if (finalCell != null) { finalCell.resetPressedLink(-1); } }), null, null, 0, getMessagesController().webFileDatacenterId, ConnectionsManager.ConnectionTypeGeneric, true); @@ -25449,120 +25599,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(progressDialog[0]); }, 500); } else { - if (longPress) { -// BottomBuilder builder = new BottomBuilder(getParentActivity(), false, themeDelegate); - BottomBuilder builder = new BottomBuilder(getParentActivity()); - int timestamp = -1; - if (str.startsWith("video?")) { - timestamp = Utilities.parseInt(str); - } - if (timestamp >= 0) { - builder.addTitle(AndroidUtilities.formatDuration(timestamp, false)); - } else { - builder.addTitle(str); - } - final int finalTimestamp = timestamp; - ChatMessageCell finalCell = cell; - MessageObject finalMessageObject = messageObject; - builder.addItems( - // TODO: builder.setItems(noforwards ? new CharSequence[] {LocaleController.getString("Open", R.string.Open)} : new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { - new String[]{ - LocaleController.getString("Open", R.string.Open), - LocaleController.getString("Copy", R.string.Copy), - LocaleController.getString("ShareQRCode", R.string.ShareQRCode), - LocaleController.getString("ShareMessages", R.string.ShareMessages) - }, - new int[]{ - R.drawable.baseline_open_in_browser_24, - R.drawable.baseline_content_copy_24, - R.drawable.wallet_qr, - R.drawable.baseline_share_24 - }, - (which, text, __) -> { - if (which == 0) { - if (str.startsWith("video?")) { - didPressMessageUrl(url, false, finalMessageObject, finalCell); - } else { - openClickableLink(str, which == 2); - } - } else if (which == 1) { - if (str.startsWith("video?") && finalMessageObject != null && !finalMessageObject.scheduled) { - MessageObject messageObject1 = finalMessageObject; - boolean isMedia = finalMessageObject.isVideo() || finalMessageObject.isRoundVideo() || finalMessageObject.isVoice() || finalMessageObject.isMusic(); - if (!isMedia && finalMessageObject.replyMessageObject != null) { - messageObject1 = finalMessageObject.replyMessageObject; - } - long dialogId = messageObject1.getDialogId(); - int messageId = messageObject1.getId(); - String link = null; - - if (messageObject1.messageOwner.fwd_from != null) { - if (messageObject1.messageOwner.fwd_from.saved_from_peer != null) { - dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.saved_from_peer); - messageId = messageObject1.messageOwner.fwd_from.saved_from_msg_id; - } else if (messageObject1.messageOwner.fwd_from.from_id != null) { - dialogId = MessageObject.getPeerId(messageObject1.messageOwner.fwd_from.from_id); - messageId = messageObject1.messageOwner.fwd_from.channel_post; - } - } - - if (DialogObject.isChatDialog(dialogId)) { - TLRPC.Chat currentChat = MessagesController.getInstance(currentAccount).getChat(-dialogId); - if (currentChat != null && currentChat.username != null) { - link = "https://t.me/" + currentChat.username + "/" + messageId + "?t=" + finalTimestamp; - } - } else { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(dialogId); - if (user != null && user.username != null) { - link = "https://t.me/" + user.username + "/" + messageId + "?t=" + finalTimestamp; - } - } - if (link == null) { - return Unit.INSTANCE; - } - AndroidUtilities.addToClipboard(link); - } else { - AndroidUtilities.addToClipboard(str); - } - if (str.startsWith("@")) { - undoView.showWithAction(0, UndoView.ACTION_USERNAME_COPIED, null); - } else if (str.startsWith("#") || str.startsWith("$")) { - undoView.showWithAction(0, UndoView.ACTION_HASHTAG_COPIED, null); - } else { - undoView.showWithAction(0, UndoView.ACTION_LINK_COPIED, null); - } - } else if (which == 2) { - ProxyUtil.showQrDialog(getParentActivity(), str); - } else if (which == 3) { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("text/plain"); - intent.putExtra(Intent.EXTRA_TEXT, str); - try { - getParentActivity().startActivity(intent); - } catch (Exception e) { - AlertUtil.showToast(e); - } - } - return Unit.INSTANCE; - }); - builder.setOnPreDismissListener(di -> { - finalCell.resetPressedLink(-1); - }); - builder.fixNavigationBar(); - showDialog(builder.create()); - } else { - openClickableLink(str, false); - if (longPress) { - cell.resetPressedLink(-1); - } - } + openClickableLink(url, str, longPress, cell, messageObject); } } else { final String urlFinal = ((URLSpan) url).getURL(); if (longPress) { BottomBuilder builder = new BottomBuilder(getParentActivity()); builder.addTitle(urlFinal); - // TODO: builder.setItems(noforwards ? new CharSequence[] {LocaleController.getString("Open", R.string.Open)} : new CharSequence[]{LocaleController.getString("Open", R.string.Open), LocaleController.getString("Copy", R.string.Copy)}, (dialog, which) -> { builder.addItems( new String[]{ LocaleController.getString("Open", R.string.Open), @@ -25703,7 +25746,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - chatListView.setImportantForAccessibility(mentionContainer.getVisibility() == View.VISIBLE || (scrimPopupWindow != null && scrimPopupWindow.isShowing()) ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); + chatListView.setImportantForAccessibility(mentionContainer != null && mentionContainer.isOpen() || (scrimPopupWindow != null && scrimPopupWindow.isShowing()) ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); } } @@ -25779,7 +25822,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not rowCount += messages.size(); messagesEndRow = rowCount; - if (currentUser != null && currentUser.bot && chatMode == 0 && (botInfo.size() > 0 && botInfo.get(currentUser.id).description != null || UserObject.isReplyUser(currentUser)) && endReached[0]) { + if ((UserObject.isReplyUser(currentUser) || currentUser != null && currentUser.bot && !MessagesController.isSupportUser(currentUser) && chatMode == 0) && endReached[0]) { botInfoRow = rowCount++; } else { botInfoRow = -5; @@ -25808,7 +25851,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public int getItemCount() { botInfoEmptyRow = -5; if (clearingHistory) { - if (currentUser != null && currentUser.bot && chatMode == 0 && (botInfo.size() > 0 && botInfo.get(currentUser.id).description != null || UserObject.isReplyUser(currentUser))) { + if (currentUser != null && currentUser.bot && chatMode == 0 && (botInfo.size() > 0 && (botInfo.get(currentUser.id).description != null || botInfo.get(currentUser.id).description_photo != null || botInfo.get(currentUser.id).description_document != null) || UserObject.isReplyUser(currentUser))) { botInfoEmptyRow = 0; return 1; } @@ -26178,15 +26221,37 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public void didPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && - !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && - !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && - !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && - !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { + !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && + !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && + !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && + !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { return; } chatActivityEnterView.didPressedBotButton(button, cell.getMessageObject(), cell.getMessageObject()); } + @Override + public void needShowPremiumFeatures(String source) { + presentFragment(new PremiumPreviewFragment(source)); + } + + @Override + public void didLongPressBotButton(ChatMessageCell cell, TLRPC.KeyboardButton button) { + if (getParentActivity() == null || bottomOverlayChat.getVisibility() == View.VISIBLE && + !(button instanceof TLRPC.TL_keyboardButtonSwitchInline) && !(button instanceof TLRPC.TL_keyboardButtonCallback) && + !(button instanceof TLRPC.TL_keyboardButtonGame) && !(button instanceof TLRPC.TL_keyboardButtonUrl) && + !(button instanceof TLRPC.TL_keyboardButtonBuy) && !(button instanceof TLRPC.TL_keyboardButtonUrlAuth) && + !(button instanceof TLRPC.TL_keyboardButtonUserProfile)) { + return; + } + if (button instanceof TLRPC.TL_keyboardButtonUrl) { + openClickableLink(null, button.url, true, cell, cell.getMessageObject()); + try { + cell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } + } + @Override public void didPressReaction(ChatMessageCell cell, TLRPC.TL_reactionCount reaction, boolean longpress) { if (getParentActivity() == null) { @@ -26217,7 +26282,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not Rect backgroundPaddings = new Rect(); Drawable shadowDrawable2 = ContextCompat.getDrawable(getParentActivity(), R.drawable.popup_fixed_alert).mutate(); - shadowDrawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable2.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground), PorterDuff.Mode.MULTIPLY)); shadowDrawable2.getPadding(backgroundPaddings); scrimPopupContainerLayout.setBackground(shadowDrawable2); @@ -26376,7 +26441,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not @Override public boolean canPerformActions() { - return actionBar != null && !actionBar.isActionModeShowed() && reportType < 0 || inPreviewMode; + return actionBar != null && !actionBar.isActionModeShowed() && reportType < 0 && !inPreviewMode; } @Override @@ -26452,7 +26517,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } if (message.isDice()) { undoView.showWithAction(0, chatActivityEnterView.getVisibility() == View.VISIBLE && bottomOverlay.getVisibility() != View.VISIBLE ? UndoView.ACTION_DICE_INFO : UndoView.ACTION_DICE_NO_SEND_INFO, message.getDiceEmoji(), null, () -> getSendMessagesHelper().sendMessage(message.getDiceEmoji(), dialog_id, replyingMessageObject, getThreadMessage(), null, false, null, null, null, true, 0, null)); - } else if (message.isAnimatedEmoji()) { + } else if (message.isAnimatedEmoji() || message.isPremiumSticker()) { restartSticker(cell); emojiAnimationsOverlay.onTapItem(cell, ChatActivity.this); chatListView.cancelClickRunnables(false); @@ -26496,7 +26561,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not f = new File(message.messageOwner.attachPath); } if (f == null || !f.exists()) { - f = FileLoader.getPathToMessage(message.messageOwner); + f = getFileLoader().getPathToMessage(message.messageOwner); } Intent intent = new Intent(Intent.ACTION_VIEW); if (Build.VERSION.SDK_INT >= 24) { @@ -26534,7 +26599,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } if (locFile == null) { - File f = FileLoader.getPathToMessage(message.messageOwner); + File f = getFileLoader().getPathToMessage(message.messageOwner); if (f.exists()) { locFile = f; } @@ -26634,7 +26699,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else { if (messageObject.isSponsored()) { Bundle args = new Bundle();if (messageObject.sponsoredChatInvite != null) { - showDialog(new JoinGroupAlert(mContext, messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this)); + showDialog(new JoinGroupAlert(mContext, messageObject.sponsoredChatInvite, messageObject.sponsoredChatInviteHash, ChatActivity.this, themeDelegate)); } else { long peerId = MessageObject.getPeerId(messageObject.messageOwner.from_id); if (peerId < 0) { @@ -26743,6 +26808,20 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not public boolean canDrawOutboundsContent() { return false; } + + @Override + public boolean onAccessibilityAction(int action, Bundle arguments) { + if (action == AccessibilityNodeInfo.ACTION_CLICK || action == R.id.acc_action_small_button || action == R.id.acc_action_msg_options) { + if (inPreviewMode && allowExpandPreviewByClick) { + if (parentLayout != null) { + parentLayout.expandPreviewFragment(); + } + return true; + } + return !canPerformActions(); + } + return false; + } }); if (currentEncryptedChat == null) { chatMessageCell.setAllowAssistant(true); @@ -26849,7 +26928,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (UserObject.isReplyUser(currentUser)) { helpView.setText(false, LocaleController.getString("RepliesChatInfo", R.string.RepliesChatInfo)); } else { - helpView.setText(true, botInfo.size() != 0 ? botInfo.get(currentUser.id).description : null); + TLRPC.BotInfo mBotInfo = botInfo.size() != 0 ? botInfo.get(currentUser.id) : null; + helpView.setText(true, mBotInfo != null ? mBotInfo.description : null, mBotInfo != null ? mBotInfo.description_document != null ? mBotInfo.description_document : mBotInfo.description_photo : null, mBotInfo); } } else if (position == loadingDownRow || position == loadingUpRow) { ChatLoadingCell loadingCell = (ChatLoadingCell) holder.itemView; @@ -27729,6 +27809,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return false; } + @Override + protected void setInMenuMode(boolean value) { + super.setInMenuMode(value); + if (actionBar != null) { + actionBar.createMenu().setVisibility(inMenuMode ? View.GONE : View.VISIBLE); + } + } + public void setPreloadedSticker(TLRPC.Document preloadedSticker, boolean historyEmpty) { preloadedGreetingsSticker = preloadedSticker; forceHistoryEmpty = historyEmpty; @@ -27876,6 +27964,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (contentView != null) { contentView.invalidateBlurredViews(); } + if (parentLayout != null && parentLayout.getDrawerLayoutContainer() != null) { + parentLayout.getDrawerLayoutContainer().setBehindKeyboardColor(getThemedColor(Theme.key_windowBackgroundWhite)); + } }; ArrayList themeDescriptions = new ArrayList<>(); @@ -28130,8 +28221,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][0], Theme.chat_photoStatesDrawables[11][0]}, null, Theme.key_chat_inLoaderPhotoIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoSelected)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[10][1], Theme.chat_photoStatesDrawables[11][1]}, null, Theme.key_chat_inLoaderPhotoIconSelected)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[9][0]}, null, Theme.key_chat_outFileIcon)); - themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[9][1]}, null, Theme.key_chat_outFileSelectedIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][0]}, null, Theme.key_chat_inFileIcon)); themeDescriptions.add(new ThemeDescription(chatListView, 0, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_photoStatesDrawables[12][1]}, null, Theme.key_chat_inFileSelectedIcon)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ChatMessageCell.class}, null, new Drawable[]{Theme.chat_contactDrawable[0]}, null, Theme.key_chat_inContactBackground)); @@ -28157,7 +28246,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Paint[]{Theme.dialogs_namePaint[0], Theme.dialogs_namePaint[1], Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Paint[]{Theme.dialogs_nameEncryptedPaint[0], Theme.dialogs_nameEncryptedPaint[1], Theme.dialogs_searchNameEncryptedPaint}, null, null, Theme.key_chats_secretName)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon)); - themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable, Theme.dialogs_fakeDrawable}, null, Theme.key_chats_draft)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messagePaint[1], null, null, Theme.key_chats_message_threeLines)); themeDescriptions.add(new ThemeDescription(messagesSearchListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_messageNamePaint, null, null, Theme.key_chats_nameMessage_threeLines)); @@ -28345,18 +28433,18 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_SERVICEBACKGROUND, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceBackground)); themeDescriptions.add(new ThemeDescription(chatListView, ThemeDescription.FLAG_PROGRESSBAR, new Class[]{ChatLoadingCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_serviceText)); - themeDescriptions.add(new ThemeDescription(mentionListView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotSwitchCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_botSwitchToInlineText)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{BotSwitchCell.class}, new String[]{"textView"}, null, null, null, Theme.key_chat_botSwitchToInlineText)); - themeDescriptions.add(new ThemeDescription(mentionListView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(mentionListView, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"usernameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"nameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), ThemeDescription.FLAG_TEXTCOLOR, new Class[]{MentionCell.class}, new String[]{"usernameTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText3)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, new Drawable[]{Theme.chat_inlineResultFile, Theme.chat_inlineResultAudio, Theme.chat_inlineResultLocation}, null, Theme.key_chat_inlineResultIcon)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteLinkText)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioProgress)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioSelectedProgress)); - themeDescriptions.add(new ThemeDescription(mentionListView, 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_divider)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, new Drawable[]{Theme.chat_inlineResultFile, Theme.chat_inlineResultAudio, Theme.chat_inlineResultLocation}, null, Theme.key_chat_inlineResultIcon)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteLinkText)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioProgress)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_chat_inAudioSelectedProgress)); + themeDescriptions.add(new ThemeDescription(mentionContainer.getListView(), 0, new Class[]{ContextLinkCell.class}, null, null, null, Theme.key_divider)); themeDescriptions.add(new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_BACKGROUNDFILTER, null, null, null, null, Theme.key_chat_gifSaveHintBackground)); themeDescriptions.add(new ThemeDescription(gifHintTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_chat_gifSaveHintText)); @@ -28611,6 +28699,17 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not toPullingDownTransition = true; ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); + if (chatActivityEnterView != null) { + chatActivityEnterView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST)); + } + if (bottomOverlay != null) { + bottomOverlay.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST)); + } + int currentBottom = Math.max(chatActivityEnterView == null ? 0 : chatActivityEnterView.getMeasuredHeight(), bottomOverlay == null ? 0 : bottomOverlay.getMeasuredHeight()); + int prevBottom = Math.max(previousChat.chatActivityEnterView == null ? 0 : previousChat.chatActivityEnterView.getMeasuredHeight(), bottomOverlay == null ? 0 : bottomOverlay.getMeasuredHeight()); + + pullingBottomOffset = -(prevBottom - currentBottom); + boolean useAlphaForContextView = previousChat.fragmentContextView.getMeasuredHeight() != fragmentContextView.getMeasuredHeight(); valueAnimator.addUpdateListener(valueAnimator1 -> { float progress = (float) valueAnimator1.getAnimatedValue(); @@ -28627,6 +28726,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not previousChat.avatarContainer.getAvatarImageView().setScaleX(0.8f + 0.2f * (1f - progress)); previousChat.avatarContainer.getAvatarImageView().setScaleY(0.8f + 0.2f * (1f - progress)); previousChat.avatarContainer.getAvatarImageView().setAlpha(1f - progress); + if (previousChat.chatActivityEnterView != null) { + previousChat.chatActivityEnterView.setTranslationY(-pullingBottomOffset * progress); + } + if (previousChat.bottomOverlay != null) { + previousChat.bottomOverlay.setTranslationY(-pullingBottomOffset * progress); + } if (useAlphaForContextView) { previousChat.fragmentContextView.setAlpha(1f - progress); @@ -28781,6 +28886,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return themeDelegate; } + public Runnable onThemeChange; + public class ThemeDelegate implements Theme.ResourcesProvider, ChatActionCell.ThemeDelegate, ForwardingPreviewView.ResourcesDelegate { private final HashMap currentDrawables = new HashMap<>(); @@ -28820,7 +28927,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (!setup && ThemeEditorView.getInstance() == null) { Theme.refreshThemeColors(true, true); } else { - AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, false, true)); + AndroidUtilities.runOnUIThread(() -> NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didSetNewTheme, false, true, parentLayout != null && !parentLayout.isTransitionAnimationInProgress())); } } @@ -29027,6 +29134,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not animationSettings.resourcesProvider = this; animationSettings.duration = 250; parentLayout.animateThemedValues(animationSettings); + if (onThemeChange != null) { + onThemeChange.run(); + } } private void setupChatTheme(EmojiThemes chatTheme, boolean withAnimation, boolean createNewResources) { @@ -29453,6 +29563,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not return super.isLightStatusBar(); } + public MessageObject.GroupedMessages getGroup(long id) { + return groupedMessagesMap.get(id); + } + private void nkbtn_onclick_actionbar(int id) { // from ActionBar & Header ( without text_* ) diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java index c60f75b3b..08a521398 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditActivity.java @@ -110,8 +110,8 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image private TextCheckCell signCell; private FrameLayout stickersContainer; - private TextSettingsCell stickersCell; - private TextInfoPrivacyCell stickersInfoCell3; + private TextCell stickersCell; + private TextInfoPrivacyCell stickersInfoCell; private LinearLayout infoContainer; private TextCell membersCell; @@ -785,7 +785,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image ActionBarMenu menu = actionBar.createMenu(); if (ChatObject.canChangeChatInfo(currentChat) || signCell != null || historyCell != null) { - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); doneButton.setContentDescription(LocaleController.getString("Done", R.string.Done)); } @@ -863,7 +863,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if ((ChatObject.isChannel(currentChat) || currentChat.gigagroup) && ChatObject.hasAdminRights(currentChat)) { logCell = new TextCell(context); logCell.setText(LocaleController.getString("EventLog", R.string.EventLog), false); - logCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + logCell.setBackground(Theme.getSelectorDrawable(false)); logCell.setOnClickListener(v -> presentFragment(new ChannelAdminLogActivity(currentChat))); } @@ -903,19 +903,34 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image stickersContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout1.addView(stickersContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - stickersCell = new TextSettingsCell(context); - stickersCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - stickersCell.setBackgroundDrawable(Theme.getSelectorDrawable(false)); + stickersCell = new TextCell(context); + stickersCell.setBackground(Theme.getSelectorDrawable(false)); + stickersCell.setOnClickListener(v -> presentFragment(new ChannelAdminLogActivity(currentChat))); + stickersCell.setPrioritizeTitleOverValue(true); stickersContainer.addView(stickersCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); stickersCell.setOnClickListener(v -> { GroupStickersActivity groupStickersActivity = new GroupStickersActivity(currentChat.id); groupStickersActivity.setInfo(info); presentFragment(groupStickersActivity); }); + } else if (logCell != null) { + infoContainer.addView(logCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } - stickersInfoCell3 = new TextInfoPrivacyCell(context); - stickersInfoCell3.setText(LocaleController.getString("GroupStickersInfo", R.string.GroupStickersInfo)); - linearLayout1.addView(stickersInfoCell3, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + if (!ChatObject.hasAdminRights(currentChat)) { + infoContainer.setVisibility(View.GONE); + settingsTopSectionCell.setVisibility(View.GONE); + } + + if (stickersCell == null) { + infoSectionCell = new ShadowSectionCell(context); + linearLayout1.addView(infoSectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + } + + if (!isChannel && info != null && info.can_set_stickers) { + stickersInfoCell = new TextInfoPrivacyCell(context); + stickersInfoCell.setText(LocaleController.getString(R.string.GroupStickersInfo)); + linearLayout1.addView(stickersInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } if (currentChat.creator) { @@ -943,21 +958,15 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image }, null)); deleteInfoCell = new ShadowSectionCell(context); - deleteInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + deleteInfoCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); linearLayout1.addView(deleteInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - } else { - if (!isChannel) { - if (stickersInfoCell3 == null) { - infoSectionCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - } - } } - if (stickersInfoCell3 != null) { + if (stickersInfoCell != null) { if (deleteInfoCell == null) { - stickersInfoCell3.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + stickersInfoCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else { - stickersInfoCell3.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + stickersInfoCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } } @@ -1183,7 +1192,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image if (info != null) { if (ChatObject.isChannel(currentChat) && info.hidden_prehistory != historyHidden) { info.hidden_prehistory = historyHidden; - getMessagesController().toogleChannelInvitesHistory(chatId, historyHidden); + getMessagesController().toggleChannelInvitesHistory(chatId, historyHidden); } } @@ -1208,7 +1217,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (signMessages != currentChat.signatures) { currentChat.signatures = true; - getMessagesController().toogleChannelSignatures(chatId, signMessages); + getMessagesController().toggleChannelSignatures(chatId, signMessages); } finishFragment(); } @@ -1402,14 +1411,6 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image historyCell.setTextAndValue(LocaleController.getString("ChatHistory", R.string.ChatHistory), type, false); } - if (stickersCell != null) { - if (info != null && info.stickerset != null) { - stickersCell.setTextAndValue(LocaleController.getString("GroupStickers", R.string.GroupStickers), info.stickerset.title, false); - } else { - stickersCell.setText(LocaleController.getString("GroupStickers", R.string.GroupStickers), false); - } - } - if (membersCell != null) { if (info != null) { if (memberRequestsCell != null) { @@ -1490,7 +1491,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } else { membersCell.setText(LocaleController.getString("ChannelMembers", R.string.ChannelMembers), logCell != null && logCell.getVisibility() == View.VISIBLE); if (currentChat.gigagroup) { - blockCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.actions_removed, logCell != null && logCell.getVisibility() == View.VISIBLE); + blockCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_chats_remove, logCell != null && logCell.getVisibility() == View.VISIBLE); } else { blockCell.setText(LocaleController.getString("ChannelPermissions", R.string.ChannelPermissions), true); } @@ -1511,11 +1512,7 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image } if (stickersCell != null && info != null) { - if (info.stickerset != null) { - stickersCell.setTextAndValue(LocaleController.getString("GroupStickers", R.string.GroupStickers), info.stickerset.title, false); - } else { - stickersCell.setText(LocaleController.getString("GroupStickers", R.string.GroupStickers), false); - } + stickersCell.setTextAndValueAndIcon(LocaleController.getString(R.string.GroupStickers), info.stickerset != null ? info.stickerset.title : LocaleController.getString(R.string.Add), R.drawable.msg_sticker, false); } } @@ -1601,7 +1598,6 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image themeDescriptions.add(new ThemeDescription(settingsTopSectionCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); themeDescriptions.add(new ThemeDescription(settingsSectionCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); themeDescriptions.add(new ThemeDescription(deleteInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); - themeDescriptions.add(new ThemeDescription(infoSectionCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); themeDescriptions.add(new ThemeDescription(signCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(signCell, 0, new Class[]{TextCheckCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); @@ -1613,8 +1609,8 @@ public class ChatEditActivity extends BaseFragment implements ImageUpdater.Image themeDescriptions.add(new ThemeDescription(stickersCell, ThemeDescription.FLAG_SELECTOR, null, null, null, null, Theme.key_listSelector)); themeDescriptions.add(new ThemeDescription(stickersCell, ThemeDescription.FLAG_TEXTCOLOR, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(stickersInfoCell3, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); - themeDescriptions.add(new ThemeDescription(stickersInfoCell3, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); + themeDescriptions.add(new ThemeDescription(stickersInfoCell, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); + themeDescriptions.add(new ThemeDescription(stickersInfoCell, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, Theme.avatarDrawables, cellDelegate, Theme.key_avatar_text)); themeDescriptions.add(new ThemeDescription(null, 0, null, null, null, cellDelegate, Theme.key_avatar_backgroundRed)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java index 1a72bcd36..443ee8f28 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatEditTypeActivity.java @@ -17,10 +17,10 @@ import android.text.TextWatcher; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.LinearLayout; import android.widget.ScrollView; -import android.widget.Toast; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; @@ -48,8 +48,10 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.InviteLinkBottomSheet; +import org.telegram.ui.Components.JoinToSendSettingsView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LinkActionView; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import java.util.ArrayList; import java.util.HashMap; @@ -91,6 +93,8 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe private TextCheckCell saveRestrictCell; private TextInfoPrivacyCell saveRestrictInfoCell; + private JoinToSendSettingsView joinContainer; + private boolean isPrivate; private TLRPC.Chat currentChat; @@ -151,7 +155,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe req.channel = new TLRPC.TL_inputChannelEmpty(); getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { canCreatePublic = error == null || !error.text.equals("CHANNELS_ADMIN_PUBLIC_TOO_MUCH"); - if (!canCreatePublic) { + if (!canCreatePublic && getUserConfig().isPremium()) { loadAdminedChannels(); } })); @@ -214,7 +218,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); fragmentView = new ScrollView(context) { @Override @@ -281,6 +285,10 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe if (!isPrivate) { return; } + if (!canCreatePublic) { + showPremiumIncreaseLimitDialog(); + return; + } isPrivate = false; updatePrivatePublic(); }); @@ -322,7 +330,19 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe editText.setImeOptions(EditorInfo.IME_ACTION_DONE); publicContainer.addView(editText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 36)); - usernameTextView = new EditTextBoldCursor(context); + usernameTextView = new EditTextBoldCursor(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + StringBuilder sb = new StringBuilder(); + sb.append(getText()); + if (checkTextView != null && checkTextView.getTextView() != null && !TextUtils.isEmpty(checkTextView.getTextView().getText())) { + sb.append("\n"); + sb.append(checkTextView.getTextView().getText()); + } + info.setText(sb); + } + }; usernameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); usernameTextView.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); usernameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -384,6 +404,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe linearLayout.addView(checkTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); typeInfoCell = new TextInfoPrivacyCell(context); + typeInfoCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); linearLayout.addView(typeInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); loadingAdminedCell = new LoadingCell(context); @@ -400,7 +421,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe manageLinksTextView = new TextCell(context); manageLinksTextView.setBackgroundDrawable(Theme.getSelectorDrawable(true)); - manageLinksTextView.setTextAndIcon(LocaleController.getString("ManageInviteLinks", R.string.ManageInviteLinks), R.drawable.actions_link, false); + manageLinksTextView.setTextAndIcon(LocaleController.getString("ManageInviteLinks", R.string.ManageInviteLinks), R.drawable.msg_link2, false); manageLinksTextView.setOnClickListener(v -> { ManageLinksActivity fragment = new ManageLinksActivity(chatId, 0, 0); fragment.setInfo(info, invite); @@ -411,6 +432,9 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe manageLinksInfoCell = new TextInfoPrivacyCell(context); linearLayout.addView(manageLinksInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + joinContainer = new JoinToSendSettingsView(context, currentChat); + linearLayout.addView(joinContainer); + saveContainer = new LinearLayout(context); saveContainer.setOrientation(LinearLayout.VERTICAL); linearLayout.addView(saveContainer); @@ -448,6 +472,19 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe return fragmentView; } + private void showPremiumIncreaseLimitDialog() { + if (getParentActivity() == null) { + return; + } + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_PUBLIC_LINKS, currentAccount); + limitReachedBottomSheet.parentIsChannel = isChannel; + limitReachedBottomSheet.onSuccessRunnable = () -> { + canCreatePublic = true; + updatePrivatePublic(); + }; + showDialog(limitReachedBottomSheet); + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.chatInfoDidLoad) { @@ -475,11 +512,39 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe if (currentChat.noforwards != isSaveRestricted) { getMessagesController().toggleChatNoForwards(chatId, currentChat.noforwards = isSaveRestricted); } - if (trySetUsername()) { + if (trySetUsername() && tryUpdateJoinSettings()) { finishFragment(); } } + private boolean tryUpdateJoinSettings() { + if (isChannel || joinContainer == null) { + return true; + } + if (getParentActivity() == null) { + return false; + } + boolean needToMigrate = !ChatObject.isChannel(currentChat) && (joinContainer.isJoinToSend || joinContainer.isJoinRequest); + if (needToMigrate) { + getMessagesController().convertToMegaGroup(getParentActivity(), chatId, this, param -> { + if (param != 0) { + chatId = param; + currentChat = getMessagesController().getChat(param); + processDone(); + } + }); + return false; + } else { + if (currentChat.join_to_send != joinContainer.isJoinToSend) { + getMessagesController().toggleChatJoinToSend(chatId, currentChat.join_to_send = joinContainer.isJoinToSend, null, null); + } + if (currentChat.join_request != joinContainer.isJoinRequest) { + getMessagesController().toggleChatJoinRequest(chatId, currentChat.join_request = joinContainer.isJoinRequest, null, null); + } + return true; + } + } + private boolean trySetUsername() { if (getParentActivity() == null) { return false; @@ -560,7 +625,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe }, ConnectionsManager.RequestFlagInvokeAfter); }); showDialog(builder.create()); - }); + }, false, 0); adminedChannelCell.setChannel(res.chats.get(a), a == res.chats.size() - 1); adminedChannelCells.add(adminedChannelCell); adminnedChannelsLayout.addView(adminedChannelCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 72)); @@ -574,7 +639,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe if (sectionCell2 == null) { return; } - if (!isPrivate && !canCreatePublic) { + if (!isPrivate && !canCreatePublic && getUserConfig().isPremium()) { typeInfoCell.setText(LocaleController.getString("ChangePublicLimitReached", R.string.ChangePublicLimitReached)); typeInfoCell.setTag(Theme.key_windowBackgroundWhiteRedText4); typeInfoCell.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText4)); @@ -622,10 +687,10 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe permanentLinkView.setLink(invite != null ? invite.link : null); permanentLinkView.loadUsers(invite, chatId); checkTextView.setVisibility(!isPrivate && checkTextView.length() != 0 ? View.VISIBLE : View.GONE); + manageLinksInfoCell.setText(LocaleController.getString("ManageLinksInfoHelp", R.string.ManageLinksInfoHelp)); if (isPrivate) { typeInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); manageLinksInfoCell.setBackground(Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - manageLinksInfoCell.setText(LocaleController.getString("ManageLinksInfoHelp", R.string.ManageLinksInfoHelp)); } else { typeInfoCell.setBackgroundDrawable(checkTextView.getVisibility() == View.VISIBLE ? null : Theme.getThemedDrawable(typeInfoCell.getContext(), R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } @@ -633,6 +698,9 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe radioButtonCell1.setChecked(!isPrivate, true); radioButtonCell2.setChecked(isPrivate, true); usernameTextView.clearFocus(); + if (joinContainer != null) { + joinContainer.setVisibility(!isChannel && !isPrivate ? View.VISIBLE : View.GONE); + } checkDoneButton(); } @@ -718,7 +786,7 @@ public class ChatEditTypeActivity extends BaseFragment implements NotificationCe } else { if (error != null && error.text.equals("CHANNELS_ADMIN_PUBLIC_TOO_MUCH")) { canCreatePublic = false; - loadAdminedChannels(); + showPremiumIncreaseLimitDialog(); } else { checkTextView.setText(LocaleController.getString("LinkInUse", R.string.LinkInUse)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java index 63e4591db..6e650d543 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatLinkActivity.java @@ -21,6 +21,9 @@ import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ImageLocation; @@ -46,15 +49,13 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Components.AvatarDrawable; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.EmptyTextProgressView; +import org.telegram.ui.Components.JoinToSendSettingsView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LoadingStickerDrawable; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class ChatLinkActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ListAdapter listViewAdapter; @@ -74,6 +75,8 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter private boolean waitingForChatCreate; private boolean chatsLoaded; + private JoinToSendSettingsView joinToSendSettings; + private long currentChatId; private int helpRow; @@ -82,6 +85,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter private int chatEndRow; private int removeChatRow; private int detailRow; + private int joinToSendRow; private int rowCount; private boolean searchWas; @@ -179,6 +183,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter chatEndRow = -1; removeChatRow = -1; detailRow = -1; + joinToSendRow = -1; helpRow = rowCount++; if (isChannel) { @@ -198,6 +203,12 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter createChatRow = rowCount++; } detailRow = rowCount++; + if (!isChannel || chats.size() > 0 && info.linked_chat_id != 0) { + TLRPC.Chat chat = isChannel ? chats.get(0) : currentChat; + if (chat != null && (TextUtils.isEmpty(chat.username) || isChannel) && (chat.creator || chat.admin_rights != null && chat.admin_rights.ban_users)) { + joinToSendRow = rowCount++; + } + } if (listViewAdapter != null) { listViewAdapter.notifyDataSetChanged(); @@ -211,6 +222,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter public boolean onFragmentCreate() { super.onFragmentCreate(); getNotificationCenter().addObserver(this, NotificationCenter.chatInfoDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); loadChats(); return true; } @@ -219,8 +231,12 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter public void onFragmentDestroy() { super.onFragmentDestroy(); getNotificationCenter().removeObserver(this, NotificationCenter.chatInfoDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.updateInterfaces); } + private boolean joinToSendProgress = false; + private boolean joinRequestProgress = false; + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.chatInfoDidLoad) { @@ -239,6 +255,29 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter showLinkAlert(waitingForFullChat, false); waitingForFullChat = null; } + } else if (id == NotificationCenter.updateInterfaces) { + int updateMask = (Integer) args[0]; + if ((updateMask & MessagesController.UPDATE_MASK_CHAT) != 0 && currentChat != null) { + TLRPC.Chat newCurrentChat = getMessagesController().getChat(currentChat.id); + if (newCurrentChat != null) { + currentChat = newCurrentChat; + } + if (chats.size() > 0) { + TLRPC.Chat linkedChat = getMessagesController().getChat(chats.get(0).id); + if (linkedChat != null) { + chats.set(0, linkedChat); + } + } + final TLRPC.Chat chat = isChannel ? (chats.size() > 0 ? chats.get(0) : null) : currentChat; + if (chat != null && joinToSendSettings != null) { + if (!joinRequestProgress) { + joinToSendSettings.setJoinRequest(chat.join_request); + } + if (!joinToSendProgress) { + joinToSendSettings.setJoinToSend(chat.join_to_send); + } + } + } } } @@ -501,7 +540,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter imageView.setForUserOrChat(chat, avatarDrawable); builder.setPositiveButton(LocaleController.getString("DiscussionLinkGroup", R.string.DiscussionLinkGroup), (dialogInterface, i) -> { if (chatFull.hidden_prehistory) { - getMessagesController().toogleChannelInvitesHistory(chat.id, false); + getMessagesController().toggleChannelInvitesHistory(chat.id, false); } linkChat(chat, null); }); @@ -516,7 +555,7 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter if (!ChatObject.isChannel(chat)) { getMessagesController().convertToMegaGroup(getParentActivity(), chat.id, this, param -> { if (param != 0) { - getMessagesController().toogleChannelInvitesHistory(param, false); + getMessagesController().toggleChannelInvitesHistory(param, false); linkChat(getMessagesController().getChat(param), createFragment); } }); @@ -827,6 +866,83 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter view = new ManageChatTextCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case 4: + final TLRPC.Chat chat = isChannel ? chats.get(0) : currentChat; + view = joinToSendSettings = new JoinToSendSettingsView(mContext, chat) { + private void migrateIfNeeded(Runnable onError, Runnable onSuccess) { + if (!ChatObject.isChannel(currentChat)) { + getMessagesController().convertToMegaGroup(getParentActivity(), chat.id, ChatLinkActivity.this, param -> { + if (param != 0) { + if (isChannel) { + chats.set(0, getMessagesController().getChat(param)); + } else { + currentChatId = param; + currentChat = getMessagesController().getChat(param); + } + onSuccess.run(); + } + }, onError); + } else { + onSuccess.run(); + } + } + + @Override + public boolean onJoinRequestToggle(boolean newValue, Runnable cancel) { + if (joinRequestProgress) { + return false; + } + joinRequestProgress = true; + migrateIfNeeded(overrideCancel(cancel), () -> { + chat.join_request = newValue; + getMessagesController().toggleChatJoinRequest(chat.id, newValue, () -> { + joinRequestProgress = false; + }, () -> { + joinRequestProgress = false; + cancel.run(); + }); + }); + return true; + } + + private Runnable overrideCancel(Runnable cancel) { + return () -> { + joinToSendProgress = false; + joinRequestProgress = false; + cancel.run(); + }; + } + + @Override + public boolean onJoinToSendToggle(boolean newValue, Runnable cancel) { + if (joinToSendProgress) { + return false; + } + joinToSendProgress = true; + migrateIfNeeded(overrideCancel(cancel), () -> { + chat.join_to_send = newValue; + getMessagesController().toggleChatJoinToSend(chat.id, newValue, () -> { + joinToSendProgress = false; + if (!newValue && chat.join_request) { + chat.join_request = false; + joinRequestProgress = true; + getMessagesController().toggleChatJoinRequest(chat.id, false, () -> { + joinRequestProgress = false; + }, () -> { + chat.join_request = true; + isJoinRequest = true; + joinRequestCell.setChecked(true); + }); + } + }, () -> { + joinToSendProgress = false; + cancel.run(); + }); + }); + return true; + } + }; + break; case 3: default: view = new HintInnerCell(mContext); @@ -887,6 +1003,8 @@ public class ChatLinkActivity extends BaseFragment implements NotificationCenter return 2; } else if (position >= chatStartRow && position < chatEndRow) { return 0; + } else if (position == joinToSendRow) { + return 4; } return 1; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java index e0bc6df4c..a8f587ba5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatPullingDownDrawable.java @@ -5,6 +5,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; @@ -13,10 +14,13 @@ import android.graphics.RectF; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; +import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; +import androidx.core.graphics.ColorUtils; + import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DialogObject; @@ -70,7 +74,7 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC long lastHapticTime; float lastProgress; boolean emptyStub; - float progressToBottomPannel; + float progressToBottomPanel; private final View fragmentView; public long lastShowingReleaseTime; @@ -162,12 +166,12 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC } layout1Width = (int) textPaint2.measureText(str1); layout1Width = Math.min(layout1Width, lastWidth - AndroidUtilities.dp(60)); - layout1 = new StaticLayout(str1, textPaint2, layout1Width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + layout1 = new StaticLayout(str1, textPaint2, layout1Width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); layout2Width = (int) textPaint2.measureText(str2); layout2Width = Math.min(layout2Width, lastWidth - AndroidUtilities.dp(60)); - layout2 = new StaticLayout(str2, textPaint2, layout2Width, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + layout2 = new StaticLayout(str2, textPaint2, layout2Width, Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); float cx = lastWidth / 2f; @@ -573,32 +577,33 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC } public void drawBottomPanel(Canvas canvas, int top, int bottom, int width) { - if (showBottomPanel && progressToBottomPannel != 1f) { - progressToBottomPannel += 16f / 150f; - if (progressToBottomPannel > 1f) { - progressToBottomPannel = 1f; + if (showBottomPanel && progressToBottomPanel != 1f) { + progressToBottomPanel += 16f / 150f; + if (progressToBottomPanel > 1f) { + progressToBottomPanel = 1f; } else { fragmentView.invalidate(); } - } else if (!showBottomPanel && progressToBottomPannel != 0) { - progressToBottomPannel -= 16f / 150f; - if (progressToBottomPannel < 0) { - progressToBottomPannel = 0; + } else if (!showBottomPanel && progressToBottomPanel != 0) { + progressToBottomPanel -= 16f / 150f; + if (progressToBottomPanel < 0) { + progressToBottomPanel = 0; } else { fragmentView.invalidate(); } } + + textPaint2.setColor(getThemedColor(Theme.key_chat_messagePanelHint)); Paint composeBackgroundPaint = getThemedPaint(Theme.key_paint_chatComposeBackground); int oldAlpha = composeBackgroundPaint.getAlpha(); int oldAlphaText = textPaint2.getAlpha(); - composeBackgroundPaint.setAlpha((int) (oldAlpha * progressToBottomPannel)); + composeBackgroundPaint.setAlpha((int) (oldAlpha * progressToBottomPanel)); canvas.drawRect(0, top, width, bottom, composeBackgroundPaint); - if (layout1 != null && swipeToReleaseProgress < 1f) { - textPaint2.setAlpha((int) (oldAlphaText * (1f - swipeToReleaseProgress) * progressToBottomPannel)); - float y = top + AndroidUtilities.dp(18) - AndroidUtilities.dp(10) * swipeToReleaseProgress; + textPaint2.setAlpha((int) (oldAlphaText * (1f - swipeToReleaseProgress) * progressToBottomPanel)); + float y = top + (bottom - top - layout1.getHeight()) / 2f - AndroidUtilities.dp(10) * swipeToReleaseProgress; canvas.save(); canvas.translate((lastWidth - layout1Width) / 2f, y); layout1.draw(canvas); @@ -606,8 +611,8 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC } if (layout2 != null && swipeToReleaseProgress > 0) { - textPaint2.setAlpha((int) (oldAlphaText * swipeToReleaseProgress * progressToBottomPannel)); - float y = top + AndroidUtilities.dp(18) + AndroidUtilities.dp(10) * (1f - swipeToReleaseProgress); + textPaint2.setAlpha((int) (oldAlphaText * swipeToReleaseProgress * progressToBottomPanel)); + float y = top + (bottom - top - layout2.getHeight()) / 2f + AndroidUtilities.dp(10) * (1f - swipeToReleaseProgress); canvas.save(); canvas.translate((lastWidth - layout2Width) / 2f, y); layout2.draw(canvas); @@ -626,7 +631,7 @@ public class ChatPullingDownDrawable implements NotificationCenter.NotificationC } public boolean needDrawBottomPanel() { - return (showBottomPanel || progressToBottomPannel > 0) && !emptyStub; + return (showBottomPanel || progressToBottomPanel > 0) && !emptyStub; } public boolean animationIsRunning() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java index 8df917f78..b51d2fa9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatRightsEditActivity.java @@ -13,17 +13,12 @@ import android.app.DatePickerDialog; import android.app.TimePickerDialog; import android.content.Context; import android.content.DialogInterface; -import android.graphics.Canvas; -import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.text.Editable; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; import android.text.TextWatcher; import android.util.TypedValue; import android.view.Gravity; @@ -36,12 +31,16 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.FileLog; @@ -69,11 +68,12 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Cells.UserCell2; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AnimatedTextView; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CircularProgressDrawable; import org.telegram.ui.Components.CrossfadeDrawable; -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 java.util.ArrayList; @@ -89,6 +89,7 @@ public class ChatRightsEditActivity extends BaseFragment { private FrameLayout addBotButtonContainer; private FrameLayout addBotButton; + private AnimatedTextView addBotButtonText; private PollEditTextCell rankEditTextCell; private CrossfadeDrawable doneDrawable; @@ -197,6 +198,28 @@ public class ChatRightsEditActivity extends BaseFragment { myAdminRights = emptyAdminRights(currentType != TYPE_ADD_BOT || (currentChat != null && currentChat.creator)); } if (type == TYPE_ADMIN || type == TYPE_ADD_BOT) { + if (type == TYPE_ADD_BOT) { + TLRPC.UserFull userFull = getMessagesController().getUserFull(userId); + if (userFull != null) { + TLRPC.TL_chatAdminRights botDefaultRights = isChannel ? userFull.bot_broadcast_admin_rights : userFull.bot_group_admin_rights; + if (botDefaultRights != null) { + if (rightsAdmin == null) { + rightsAdmin = botDefaultRights; + } else { + rightsAdmin.ban_users = rightsAdmin.ban_users || botDefaultRights.ban_users; + rightsAdmin.add_admins = rightsAdmin.add_admins || botDefaultRights.add_admins; + rightsAdmin.post_messages = rightsAdmin.post_messages || botDefaultRights.post_messages; + rightsAdmin.pin_messages = rightsAdmin.pin_messages || botDefaultRights.pin_messages; + rightsAdmin.delete_messages = rightsAdmin.delete_messages || botDefaultRights.delete_messages; + rightsAdmin.change_info = rightsAdmin.change_info || botDefaultRights.change_info; + rightsAdmin.anonymous = rightsAdmin.anonymous || botDefaultRights.anonymous; + rightsAdmin.edit_messages = rightsAdmin.edit_messages || botDefaultRights.edit_messages; + rightsAdmin.manage_call = rightsAdmin.manage_call || botDefaultRights.manage_call; + rightsAdmin.other = rightsAdmin.other || botDefaultRights.other; + } + } + } + } if (rightsAdmin == null) { initialAsAdmin = false; if (type == TYPE_ADD_BOT) { @@ -372,7 +395,9 @@ public class ChatRightsEditActivity extends BaseFragment { if (canEdit || !isChannel && currentChat.creator && UserObject.isUserSelf(currentUser)) { ActionBarMenu menu = actionBar.createMenu(); - doneDrawable = new CrossfadeDrawable(context.getResources().getDrawable(R.drawable.ic_done), new CircularProgressDrawable(Theme.getColor(Theme.key_actionBarDefaultIcon))); + Drawable checkmark = context.getResources().getDrawable(R.drawable.ic_ab_done).mutate(); + checkmark.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); + doneDrawable = new CrossfadeDrawable(checkmark, new CircularProgressDrawable(Theme.getColor(Theme.key_actionBarDefaultIcon))); menu.addItemWithWidth(done_button, 0, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); menu.getItem(done_button).setIcon(doneDrawable); } @@ -932,7 +957,11 @@ public class ChatRightsEditActivity extends BaseFragment { } }), ConnectionsManager.RequestFlagWithoutLogin); } else if (error.text.equals("CHANNELS_TOO_MUCH")) { - presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_EDIT)); + if (getParentActivity() != null && !AccountInstance.getInstance(currentAccount).getUserConfig().isPremium()) { + showDialog(new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_TO_MANY_COMMUNITIES, currentAccount)); + } else { + presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_EDIT)); + } } else { if (passwordFragment != null) { passwordFragment.needHideProgress(); @@ -1132,8 +1161,9 @@ public class ChatRightsEditActivity extends BaseFragment { adminRights.other ? 1 : 0, adminRights, bannedRights, currentRank); finishFragment(); } - }, () -> { + }, err -> { setLoading(false); + return true; }); } else if (currentType == TYPE_BANNED) { MessagesController.getInstance(currentAccount).setParticipantBannedRole(chatId, currentUser, null, bannedRights, isChannel, getFragmentForAlert(1)); @@ -1190,9 +1220,15 @@ public class ChatRightsEditActivity extends BaseFragment { } }; if (asAdmin || initialAsAdmin) { - getMessagesController().setUserAdminRole(currentChat.id, currentUser, asAdmin ? adminRights : emptyAdminRights(false), currentRank, false, this, isAddingNew, asAdmin, botHash, onFinish, () -> setLoading(false)); + getMessagesController().setUserAdminRole(currentChat.id, currentUser, asAdmin ? adminRights : emptyAdminRights(false), currentRank, false, this, isAddingNew, asAdmin, botHash, onFinish, err -> { + setLoading(false); + return true; + }); } else { - getMessagesController().addUserToChat(currentChat.id, currentUser, 0, botHash, this, true, onFinish, () -> setLoading(false)); + getMessagesController().addUserToChat(currentChat.id, currentUser, 0, botHash, this, true, onFinish, err -> { + setLoading(false); + return true; + }); } }); showDialog(builder.create()); @@ -1415,69 +1451,15 @@ public class ChatRightsEditActivity extends BaseFragment { case VIEW_TYPE_ADD_BOT_CELL: addBotButtonContainer = new FrameLayout(mContext); addBotButtonContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - addBotButton = new FrameLayout(mContext) { - - private TextPaint textPaint; - private StaticLayout mainText; - private StaticLayout asMemberText; - private StaticLayout asAdminText; { - textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); - textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - textPaint.setTextSize(AndroidUtilities.dp(14)); - textPaint.setColor(0xffffffff); - mainText = new StaticLayout(LocaleController.getString("AddBotButton", R.string.AddBotButton) + " ", textPaint, 9999, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false); - asMemberText = new StaticLayout(LocaleController.getString("AddBotButtonAsMember", R.string.AddBotButtonAsMember), textPaint, 9999, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false); - asAdminText = new StaticLayout(LocaleController.getString("AddBotButtonAsAdmin", R.string.AddBotButtonAsAdmin), textPaint, 9999, Layout.Alignment.ALIGN_NORMAL, 1f, 0f, false); - } - - private long lastFrame; - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - float t = CubicBezierInterpolator.EASE_BOTH.getInterpolation(asAdminT); - - float mainWidth = mainText.getLineWidth(0); - float asWidth; - if (asAdminT <= 0) { - asWidth = asMemberText.getLineWidth(0); - } else if (asAdminT >= 1) { - asWidth = asAdminText.getLineWidth(0); - } else { - asWidth = AndroidUtilities.lerp(asMemberText.getLineWidth(0), asAdminText.getLineWidth(0), t); - } - float width = mainWidth + asWidth; - - canvas.save(); - canvas.translate((getWidth() - width) / 2, (getHeight() - mainText.getHeight()) / 2); - textPaint.setAlpha(255); - mainText.draw(canvas); - canvas.translate(mainWidth, 0); - if (t <= 0) { - asMemberText.draw(canvas); - } else { - canvas.save(); - canvas.translate(0, AndroidUtilities.dp(8) * t); - canvas.scale(1, 1 - 0.2f * t); - textPaint.setAlpha((int) (255 * (1f - t))); - asMemberText.draw(canvas); - canvas.restore(); - } - if (t >= 1) { - textPaint.setAlpha(255); - asAdminText.draw(canvas); - } else { - canvas.save(); - canvas.translate(0, -AndroidUtilities.dp(8) * (1f - t)); - canvas.scale(1, 1 - 0.2f * (1f - t)); - textPaint.setAlpha((int) (255 * t)); - asAdminText.draw(canvas); - canvas.restore(); - } - canvas.restore(); - } - }; - addBotButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), 0x40ffffff)); + addBotButton = new FrameLayout(mContext); + addBotButtonText = new AnimatedTextView(mContext, true, false, false); + addBotButtonText.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + addBotButtonText.setTextColor(0xffffffff); + addBotButtonText.setTextSize(AndroidUtilities.dp(14)); + addBotButtonText.setGravity(Gravity.CENTER); + addBotButtonText.setText(LocaleController.getString("AddBotButton", R.string.AddBotButton) + " " + (asAdmin ? LocaleController.getString("AddBotButtonAsAdmin", R.string.AddBotButtonAsAdmin) : LocaleController.getString("AddBotButtonAsMember", R.string.AddBotButtonAsMember))); + addBotButton.addView(addBotButtonText, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + addBotButton.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addBotButton.setOnClickListener(e -> onDonePressed()); addBotButtonContainer.addView(addBotButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 14, 28, 14, 14)); addBotButtonContainer.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -1857,6 +1839,9 @@ public class ChatRightsEditActivity extends BaseFragment { // } listViewAdapter.notifyDataSetChanged(); + if (addBotButtonText != null) { + addBotButtonText.setText(LocaleController.getString("AddBotButton", R.string.AddBotButton) + " " + (asAdmin ? LocaleController.getString("AddBotButtonAsAdmin", R.string.AddBotButtonAsAdmin) : LocaleController.getString("AddBotButtonAsMember", R.string.AddBotButtonAsMember)), animated, asAdmin); + } if (asAdminAnimator != null) { asAdminAnimator.cancel(); asAdminAnimator = null; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java index 4a0351960..db4b8af74 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatUsersActivity.java @@ -15,8 +15,6 @@ import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.os.Bundle; import android.text.SpannableStringBuilder; import android.text.Spanned; @@ -24,7 +22,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.util.SparseIntArray; -import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -33,9 +30,6 @@ import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; import androidx.collection.LongSparseArray; import androidx.recyclerview.widget.DefaultItemAnimator; @@ -579,7 +573,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente loadingUserCellRow = rowCount++; } } else if (type == TYPE_ADMIN) { - if (ChatObject.isChannel(currentChat) && currentChat.megagroup && !currentChat.gigagroup && (info == null || info.participants_count <= 200) + if (ChatObject.isChannel(currentChat) && currentChat.megagroup && !currentChat.gigagroup && (info == null || info.participants_count <= 200 || !isChannel && info.can_set_stickers) && ChatObject.hasAdminRights(currentChat)) { recentActionsRow = rowCount++; addNewSectionRow = rowCount++; @@ -741,6 +735,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente flickerLoadingView.setVisibility(View.VISIBLE); } }); + if (type == TYPE_BANNED && !firstLoaded) { + searchItem.setVisibility(View.GONE); + } if (type == TYPE_KICKED) { searchItem.setSearchFieldHint(LocaleController.getString("ChannelSearchException", R.string.ChannelSearchException)); } else { @@ -751,7 +748,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } if (type == TYPE_KICKED) { - doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); } } @@ -968,40 +965,79 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente fragment.setDelegate(new GroupCreateActivity.ContactsAddActivityDelegate() { @Override public void didSelectUsers(ArrayList users, int fwdCount) { - DiffCallback savedState = saveState(); - ArrayList array = contactsMap != null && contactsMap.size() != 0 ? contacts : participants; - LongSparseArray map = contactsMap != null && contactsMap.size() != 0 ? contactsMap : participantsMap; - int k = 0; - for (int a = 0, N = users.size(); a < N; a++) { - TLRPC.User user = users.get(a); - getMessagesController().addUserToChat(chatId, user, fwdCount, null, ChatUsersActivity.this, null); - getMessagesController().putUser(user, false); - - if (map.get(user.id) == null) { - if (ChatObject.isChannel(currentChat)) { - TLRPC.TL_channelParticipant channelParticipant1 = new TLRPC.TL_channelParticipant(); - channelParticipant1.inviter_id = getUserConfig().getClientUserId(); - channelParticipant1.peer = new TLRPC.TL_peerUser(); - channelParticipant1.peer.user_id = user.id; - channelParticipant1.date = getConnectionsManager().getCurrentTime(); - array.add(k, channelParticipant1); - k++; - map.put(user.id, channelParticipant1); + final int count = users.size(); + final int[] processed = new int[1]; + final ArrayList userRestrictedPrivacy = new ArrayList<>(); + processed[0] = 0; + final Runnable showUserRestrictedPrivacyAlert = () -> { + CharSequence title, description; + if (userRestrictedPrivacy.size() == 1) { + if (count > 1) { + title = LocaleController.getString("InviteToGroupErrorTitleAUser", R.string.InviteToGroupErrorTitleAUser); } else { - TLRPC.ChatParticipant participant = new TLRPC.TL_chatParticipant(); - participant.user_id = user.id; - participant.inviter_id = getUserConfig().getClientUserId(); - array.add(k, participant); - k++; - map.put(user.id, participant); + title = LocaleController.getString("InviteToGroupErrorTitleThisUser", R.string.InviteToGroupErrorTitleThisUser); } - + description = AndroidUtilities.replaceTags(LocaleController.formatString("InviteToGroupErrorMessageSingle", R.string.InviteToGroupErrorMessageSingle, UserObject.getFirstName(userRestrictedPrivacy.get(0)))); + } else if (userRestrictedPrivacy.size() == 2) { + title = LocaleController.getString("InviteToGroupErrorTitleSomeUsers", R.string.InviteToGroupErrorTitleSomeUsers); + description = AndroidUtilities.replaceTags(LocaleController.formatString("InviteToGroupErrorMessageDouble", R.string.InviteToGroupErrorMessageDouble, UserObject.getFirstName(userRestrictedPrivacy.get(0)), UserObject.getFirstName(userRestrictedPrivacy.get(1)))); + } else if (userRestrictedPrivacy.size() == count) { + title = LocaleController.getString("InviteToGroupErrorTitleTheseUsers", R.string.InviteToGroupErrorTitleTheseUsers); + description = LocaleController.getString("InviteToGroupErrorMessageMultipleAll", R.string.InviteToGroupErrorMessageMultipleAll); + } else { + title = LocaleController.getString("InviteToGroupErrorTitleSomeUsers", R.string.InviteToGroupErrorTitleSomeUsers); + description = LocaleController.getString("InviteToGroupErrorMessageMultipleSome", R.string.InviteToGroupErrorMessageMultipleSome); } + new AlertDialog.Builder(context) + .setTitle(title) + .setMessage(description) + .setPositiveButton(LocaleController.getString("OK", R.string.OK), null) + .show(); + }; + for (int a = 0; a < count; a++) { + final TLRPC.User user = users.get(a); + getMessagesController().addUserToChat(chatId, user, fwdCount, null, ChatUsersActivity.this, false, () -> { + processed[0]++; + if (processed[0] >= count && userRestrictedPrivacy.size() > 0) { + showUserRestrictedPrivacyAlert.run(); + } + DiffCallback savedState = saveState(); + ArrayList array = contactsMap != null && contactsMap.size() != 0 ? contacts : participants; + LongSparseArray map = contactsMap != null && contactsMap.size() != 0 ? contactsMap : participantsMap; + if (map.get(user.id) == null) { + if (ChatObject.isChannel(currentChat)) { + TLRPC.TL_channelParticipant channelParticipant1 = new TLRPC.TL_channelParticipant(); + channelParticipant1.inviter_id = getUserConfig().getClientUserId(); + channelParticipant1.peer = new TLRPC.TL_peerUser(); + channelParticipant1.peer.user_id = user.id; + channelParticipant1.date = getConnectionsManager().getCurrentTime(); + array.add(0, channelParticipant1); + map.put(user.id, channelParticipant1); + } else { + TLRPC.ChatParticipant participant = new TLRPC.TL_chatParticipant(); + participant.user_id = user.id; + participant.inviter_id = getUserConfig().getClientUserId(); + array.add(0, participant); + map.put(user.id, participant); + } + } + if (array == participants) { + sortAdmins(participants); + } + updateListAnimated(savedState); + }, err -> { + processed[0]++; + boolean privacyRestricted; + if (privacyRestricted = err != null && "USER_PRIVACY_RESTRICTED".equals(err.text)) { + userRestrictedPrivacy.add(user); + } + if (processed[0] >= count && userRestrictedPrivacy.size() > 0) { + showUserRestrictedPrivacyAlert.run(); + } + return !privacyRestricted; + }); + getMessagesController().putUser(user, false); } - if (array == participants) { - sortAdmins(participants); - } - updateListAnimated(savedState); } @Override @@ -2340,6 +2376,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente final ArrayList requests = loadChatParticipantsRequests(offset, count, reset); final ArrayList responses = new ArrayList<>(); final Runnable onRequestsEnd = () -> { + int objectsCount = 0; for (int i = 0; i < requests.size(); ++i) { TLRPC.TL_channels_getParticipants req = requests.get(i); TLRPC.TL_channels_channelParticipants res = responses.get(i); @@ -2388,6 +2425,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente map.put(MessageObject.getPeerId(participant.peer), participant); } } + objectsCount += objects.size(); if (type == TYPE_USERS) { for (int a = 0, N = participants.size(); a < N; a++) { TLObject object = participants.get(a); @@ -2429,6 +2467,9 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente showItemsAnimated(listViewAdapter != null ? listViewAdapter.getItemCount() : 0); loadingUsers = false; firstLoaded = true; + if (searchItem != null) { + searchItem.setVisibility(type != TYPE_BANNED || firstLoaded && objectsCount > 5 ? View.VISIBLE : View.GONE); + } } updateRows(); if (listViewAdapter != null) { @@ -2561,6 +2602,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente if (isOpen && !backward && needOpenSearch) { searchItem.getSearchField().requestFocus(); AndroidUtilities.showKeyboard(searchItem.getSearchField()); + searchItem.setVisibility(View.GONE); } } @@ -3097,46 +3139,14 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente view = new ShadowSectionCell(mContext); break; case 4: - view = new FrameLayout(mContext) { - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - AndroidUtilities.dp(56), MeasureSpec.EXACTLY)); - } - }; - FrameLayout frameLayout = (FrameLayout) view; - frameLayout.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - - LinearLayout linearLayout = new LinearLayout(mContext); - linearLayout.setOrientation(LinearLayout.VERTICAL); - frameLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 20, 0, 20, 0)); - - ImageView imageView = new ImageView(mContext); - imageView.setImageResource(R.drawable.group_ban_empty); - imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_emptyListPlaceholder), PorterDuff.Mode.SRC_IN)); - linearLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); - - TextView textView = new TextView(mContext); - textView.setText(LocaleController.getString("NoBlockedUsers", R.string.NoBlockedUsers)); - textView.setTextColor(Theme.getColor(Theme.key_emptyListPlaceholder)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - textView.setGravity(Gravity.CENTER_HORIZONTAL); - textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 10, 0, 0)); - - textView = new TextView(mContext); + view = new TextInfoPrivacyCell(mContext); + TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) view; if (isChannel) { - textView.setText(LocaleController.getString("NoBlockedChannel2", R.string.NoBlockedChannel2)); + privacyCell.setText(LocaleController.getString(R.string.NoBlockedChannel2)); } else { - textView.setText(LocaleController.getString("NoBlockedGroup2", R.string.NoBlockedGroup2)); + privacyCell.setText(LocaleController.getString(R.string.NoBlockedGroup2)); } - textView.setTextColor(Theme.getColor(Theme.key_emptyListPlaceholder)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); - textView.setGravity(Gravity.CENTER_HORIZONTAL); - linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 10, 0, 0)); - - view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + privacyCell.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; case 5: HeaderCell headerCell = new HeaderCell(mContext, Theme.key_windowBackgroundWhiteBlueHeader, 21, 11, false); @@ -3341,7 +3351,7 @@ public class ChatUsersActivity extends BaseFragment implements NotificationCente } else if (position == addNew2Row) { actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); boolean showDivider = !(loadingUsers && !firstLoaded) && membersHeaderRow == -1 && !participants.isEmpty(); - actionCell.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), null, R.drawable.actions_link, showDivider); + actionCell.setText(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), null, R.drawable.msg_link2, showDivider); } else if (position == gigaConvertRow) { actionCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); actionCell.setText(LocaleController.getString("BroadcastGroupConvert", R.string.BroadcastGroupConvert), null, R.drawable.msg_channel, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java index 70473d6a8..a58e10b54 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChooseSpeedLayout.java @@ -14,7 +14,7 @@ public class ChooseSpeedLayout { ActionBarPopupWindow.ActionBarPopupWindowLayout speedSwipeBackLayout; ActionBarMenuSubItem[] speedItems = new ActionBarMenuSubItem[5]; - public ChooseSpeedLayout(Context context, PopupSwipeBackLayout swipeBackLayout, Callback callback) { + public ChooseSpeedLayout(Context context, PopupSwipeBackLayout swipeBackLayout, Callback callback) { speedSwipeBackLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, 0, null); speedSwipeBackLayout.setFitItems(true); @@ -23,12 +23,14 @@ public class ChooseSpeedLayout { swipeBackLayout.closeForeground(); }); backItem.setColors(0xfffafafa, 0xfffafafa); + backItem.setSelectorColor(0x0fffffff); ActionBarMenuSubItem item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_0_2, LocaleController.getString("SpeedVerySlow", R.string.SpeedVerySlow), false, null); item.setColors(0xfffafafa, 0xfffafafa); item.setOnClickListener((view) -> { callback.onSpeedSelected(0.25f); }); + item.setSelectorColor(0x0fffffff); speedItems[0] = item; item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_0_5, LocaleController.getString("SpeedSlow", R.string.SpeedSlow), false, null); @@ -36,6 +38,7 @@ public class ChooseSpeedLayout { item.setOnClickListener((view) -> { callback.onSpeedSelected(0.5f); }); + item.setSelectorColor(0x0fffffff); speedItems[1] = item; item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_1, LocaleController.getString("SpeedNormal", R.string.SpeedNormal), false, null); @@ -43,6 +46,7 @@ public class ChooseSpeedLayout { item.setOnClickListener((view) -> { callback.onSpeedSelected(1f); }); + item.setSelectorColor(0x0fffffff); speedItems[2] = item; item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_1_5, LocaleController.getString("SpeedFast", R.string.SpeedFast), false, null); @@ -50,6 +54,7 @@ public class ChooseSpeedLayout { item.setOnClickListener((view) -> { callback.onSpeedSelected(1.5f); }); + item.setSelectorColor(0x0fffffff); speedItems[3] = item; item = ActionBarMenuItem.addItem(speedSwipeBackLayout, R.drawable.msg_speed_2, LocaleController.getString("SpeedVeryFast", R.string.SpeedVeryFast), false, null); @@ -57,6 +62,7 @@ public class ChooseSpeedLayout { item.setOnClickListener((view) -> { callback.onSpeedSelected(2f); }); + item.setSelectorColor(0x0fffffff); speedItems[4] = item; } 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 f3202fc15..e3bc2ee86 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -101,6 +101,7 @@ import org.telegram.ui.Cells.CheckBoxCell; import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.LanguageSelectActivity; import org.telegram.ui.LaunchActivity; @@ -290,10 +291,14 @@ public class AlertsCreator { request instanceof TLRPC.TL_messages_migrateChat || request instanceof TLRPC.TL_phone_inviteToGroupCall) { if (fragment != null && error.text.equals("CHANNELS_TOO_MUCH")) { - if (request instanceof TLRPC.TL_channels_joinChannel || request instanceof TLRPC.TL_channels_inviteToChannel) { - fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_JOIN)); + if (fragment.getParentActivity() != null) { + fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO_MANY_COMMUNITIES, currentAccount)); } else { - fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_EDIT)); + if (request instanceof TLRPC.TL_channels_joinChannel || request instanceof TLRPC.TL_channels_inviteToChannel) { + fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_JOIN)); + } else { + fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_EDIT)); + } } return null; } else if (fragment != null) { @@ -305,7 +310,11 @@ public class AlertsCreator { } } else if (request instanceof TLRPC.TL_messages_createChat) { if (error.text.equals("CHANNELS_TOO_MUCH")) { - fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_CREATE)); + if (fragment.getParentActivity() != null) { + fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO_MANY_COMMUNITIES, currentAccount)); + } else { + fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_CREATE)); + } return null; } else if (error.text.startsWith("FLOOD_WAIT")) { showFloodWaitAlert(error.text, fragment); @@ -314,7 +323,11 @@ public class AlertsCreator { } } else if (request instanceof TLRPC.TL_channels_createChannel) { if (error.text.equals("CHANNELS_TOO_MUCH")) { - fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_CREATE)); + if (fragment.getParentActivity() != null) { + fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO_MANY_COMMUNITIES, currentAccount)); + } else { + fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_CREATE)); + } return null; } else if (error.text.startsWith("FLOOD_WAIT")) { showFloodWaitAlert(error.text, fragment); @@ -352,7 +365,11 @@ public class AlertsCreator { } else if (error.text.equals("USERS_TOO_MUCH")) { showSimpleAlert(fragment, LocaleController.getString("JoinToGroupErrorFull", R.string.JoinToGroupErrorFull)); } else if (error.text.equals("CHANNELS_TOO_MUCH")) { - fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_JOIN)); + if (fragment.getParentActivity() != null) { + fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), LimitReachedBottomSheet.TYPE_TO_MANY_COMMUNITIES, currentAccount)); + } else { + fragment.presentFragment(new TooManyCommunitiesActivity(TooManyCommunitiesActivity.TYPE_JOIN)); + } } else if (error.text.equals("INVITE_HASH_EXPIRED")) { showSimpleAlert(fragment, LocaleController.getString("ExpiredLink", R.string.ExpiredLink), LocaleController.getString("InviteExpired", R.string.InviteExpired)); } else { @@ -403,6 +420,8 @@ public class AlertsCreator { showSimpleAlert(fragment, LocaleController.getString("CodeExpired", R.string.CodeExpired)); } 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)); } else { showSimpleAlert(fragment, error.text); } @@ -1112,7 +1131,7 @@ public class AlertsCreator { } } - public static AlertDialog createSupportAlert(BaseFragment fragment) { + public static AlertDialog createSupportAlert(BaseFragment fragment, Theme.ResourcesProvider resourcesProvider) { if (fragment == null || fragment.getParentActivity() == null) { return null; } @@ -1135,13 +1154,13 @@ public class AlertsCreator { } message.setText(spanned); message.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - message.setLinkTextColor(Theme.getColor(Theme.key_dialogTextLink)); - message.setHighlightColor(Theme.getColor(Theme.key_dialogLinkSelection)); + message.setLinkTextColor(Theme.getColor(Theme.key_dialogTextLink, resourcesProvider)); + message.setHighlightColor(Theme.getColor(Theme.key_dialogLinkSelection, resourcesProvider)); message.setPadding(AndroidUtilities.dp(23), 0, AndroidUtilities.dp(23), 0); message.setMovementMethod(new AndroidUtilities.LinkMovementMethodMy()); - message.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + message.setTextColor(Theme.getColor(Theme.key_dialogTextBlack, resourcesProvider)); - AlertDialog.Builder builder1 = new AlertDialog.Builder(fragment.getParentActivity()); + AlertDialog.Builder builder1 = new AlertDialog.Builder(fragment.getParentActivity(), resourcesProvider); builder1.setView(message); builder1.setTitle(LocaleController.getString("AskAQuestion", R.string.AskAQuestion)); builder1.setPositiveButton(LocaleController.getString("AskButton", R.string.AskButton), (dialogInterface, i) -> performAskAQuestion(fragment)); @@ -1411,7 +1430,13 @@ public class AlertsCreator { final boolean[] deleteForAll = new boolean[1]; boolean deleteChatForAll = false; - if (!second && (secret && !clear || canDeleteInbox) && !UserObject.isDeleted(user) || (deleteChatForAll = checkDeleteForAll && !clear && chat != null && chat.creator)) { + boolean lastMessageIsJoined = false; + MessageObject dialogMessage = user != null ? MessagesController.getInstance(account).dialogMessage.get(user.id) : null; + if (dialogMessage != null && dialogMessage.messageOwner != null && (dialogMessage.messageOwner.action instanceof TLRPC.TL_messageActionUserJoined || dialogMessage.messageOwner.action instanceof TLRPC.TL_messageActionContactSignUp)) { + lastMessageIsJoined = true; + } + + if (!second && (secret && !clear || canDeleteInbox) && !UserObject.isDeleted(user) && !lastMessageIsJoined || (deleteChatForAll = checkDeleteForAll && !clear && chat != null && chat.creator)) { cell[0] = new CheckBoxCell(context, 1, resourcesProvider); cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); if (deleteChatForAll) { @@ -2062,7 +2087,7 @@ public class AlertsCreator { buttonTextView.setText(LocaleController.getString("IUnderstand", R.string.IUnderstand)); buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); linearLayout.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 24, 15, 16, 24)); @@ -2579,7 +2604,7 @@ public class AlertsCreator { buttonTextView.setTextColor(datePickerColors.buttonTextColor); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), datePickerColors.buttonBackgroundColor, datePickerColors.buttonBackgroundPressedColor)); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(datePickerColors.buttonBackgroundColor, 4)); container.addView(buttonTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM, 16, 15, 16, 16)); buttonTextView.setOnClickListener(v -> { canceled[0] = false; @@ -2602,6 +2627,7 @@ public class AlertsCreator { } }); bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); return builder; } @@ -2784,16 +2810,17 @@ public class AlertsCreator { builder.setCustomView(container); BottomSheet bottomSheet = builder.show(); bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); return builder; } - public static BottomSheet.Builder createAutoDeleteDatePickerDialog(Context context, final ScheduleDatePickerDelegate datePickerDelegate) { + public static BottomSheet.Builder createAutoDeleteDatePickerDialog(Context context, Theme.ResourcesProvider resourcesProvider, final ScheduleDatePickerDelegate datePickerDelegate) { if (context == null) { return null; } - ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(); - BottomSheet.Builder builder = new BottomSheet.Builder(context, false); + ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(context, false, resourcesProvider); builder.setApplyBottomPadding(false); int[] values = new int[]{ @@ -2816,7 +2843,7 @@ public class AlertsCreator { 365 * 60 * 24 }; - final NumberPicker numberPicker = new NumberPicker(context) { + final NumberPicker numberPicker = new NumberPicker(context, resourcesProvider) { @Override protected CharSequence getContentDescription(int index) { if (values[index] == 0) { @@ -2825,7 +2852,7 @@ public class AlertsCreator { return LocaleController.formatPluralString("Days", values[index] / (60 * 24)); } else if (values[index] < 31 * 60 * 24) { return LocaleController.formatPluralString("Weeks", values[index] / (60 * 24)); - } else if (values[index] < 365 * 60 * 24) { + } else if (values[index] < 365 * 60 * 24) { return LocaleController.formatPluralString("Months", values[index] / (7 * 60 * 24)); } else { return LocaleController.formatPluralString("Years", values[index] * 5 / 31 * 60 * 24); @@ -2843,7 +2870,7 @@ public class AlertsCreator { return LocaleController.formatPluralString("Days", values[index] / (60 * 24)); } else if (values[index] < 31 * 60 * 24) { return LocaleController.formatPluralString("Weeks", values[index] / (7 * 60 * 24)); - } else if (values[index] < 365 * 60 * 24) { + } else if (values[index] < 365 * 60 * 24) { return LocaleController.formatPluralString("Months", values[index] / (31 * 60 * 24)); } else { return LocaleController.formatPluralString("Years", values[index] / (365 * 60 * 24)); @@ -2932,19 +2959,24 @@ public class AlertsCreator { builder.setCustomView(container); BottomSheet bottomSheet = builder.show(); bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); return builder; } public static BottomSheet.Builder createSoundFrequencyPickerDialog(Context context, int notifyMaxCount, int notifyDelay, final SoundFrequencyDelegate delegate) { + return createSoundFrequencyPickerDialog(context, notifyMaxCount, notifyDelay, delegate, null); + } + + public static BottomSheet.Builder createSoundFrequencyPickerDialog(Context context, int notifyMaxCount, int notifyDelay, final SoundFrequencyDelegate delegate, Theme.ResourcesProvider resourcesProvider) { if (context == null) { return null; } - ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(); - BottomSheet.Builder builder = new BottomSheet.Builder(context, false); + ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(context, false, resourcesProvider); builder.setApplyBottomPadding(false); - final NumberPicker times = new NumberPicker(context) { + final NumberPicker times = new NumberPicker(context, resourcesProvider) { @Override protected CharSequence getContentDescription(int index) { return LocaleController.formatPluralString("Times", index + 1); @@ -2957,7 +2989,7 @@ public class AlertsCreator { times.setWrapSelectorWheel(false); times.setFormatter(index -> LocaleController.formatPluralString("Times", index + 1)); - final NumberPicker minutes = new NumberPicker(context) { + final NumberPicker minutes = new NumberPicker(context, resourcesProvider) { @Override protected CharSequence getContentDescription(int index) { return LocaleController.formatPluralString("Times", index + 1); @@ -2970,7 +3002,7 @@ public class AlertsCreator { minutes.setWrapSelectorWheel(false); minutes.setFormatter(index -> LocaleController.formatPluralString("Minutes", index + 1)); - NumberPicker divider = new NumberPicker(context); + NumberPicker divider = new NumberPicker(context, resourcesProvider); divider.setMinValue(0); divider.setMaxValue(0); divider.setTextColor(datePickerColors.textColor); @@ -3068,20 +3100,20 @@ public class AlertsCreator { builder.setCustomView(container); BottomSheet bottomSheet = builder.show(); bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); return builder; } - public static BottomSheet.Builder createMuteForPickerDialog(Context context, final ScheduleDatePickerDelegate datePickerDelegate) { + public static BottomSheet.Builder createMuteForPickerDialog(Context context, Theme.ResourcesProvider resourcesProvider, final ScheduleDatePickerDelegate datePickerDelegate) { if (context == null) { return null; } - ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(); - BottomSheet.Builder builder = new BottomSheet.Builder(context, false); + ScheduleDatePickerColors datePickerColors = new ScheduleDatePickerColors(resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(context, false, resourcesProvider); builder.setApplyBottomPadding(false); int[] values = new int[]{ - 0, 30, 60, 60 * 2, @@ -3105,7 +3137,7 @@ public class AlertsCreator { 365 * 60 * 24 }; - final NumberPicker numberPicker = new NumberPicker(context) { + final NumberPicker numberPicker = new NumberPicker(context, resourcesProvider) { @Override protected CharSequence getContentDescription(int index) { if (values[index] == 0) { @@ -3118,7 +3150,7 @@ public class AlertsCreator { return LocaleController.formatPluralString("Days", values[index] / (60 * 24)); } else if (values[index] < 31 * 60 * 24) { return LocaleController.formatPluralString("Weeks", values[index] / (7 * 60 * 24)); - } else if (values[index] < 365 * 60 * 24) { + } else if (values[index] < 365 * 60 * 24) { return LocaleController.formatPluralString("Months", values[index] / (31 * 60 * 24)); } else { return LocaleController.formatPluralString("Years", values[index] / (365 * 60 * 24)); @@ -3140,7 +3172,7 @@ public class AlertsCreator { return LocaleController.formatPluralString("Days", values[index] / (60 * 24)); } else if (values[index] < 31 * 60 * 24) { return LocaleController.formatPluralString("Weeks", values[index] / (7 * 60 * 24)); - } else if (values[index] < 365 * 60 * 24) { + } else if (values[index] < 365 * 60 * 24) { return LocaleController.formatPluralString("Months", values[index] / (31 * 60 * 24)); } else { return LocaleController.formatPluralString("Years", values[index] / (365 * 60 * 24)); @@ -3226,6 +3258,7 @@ public class AlertsCreator { builder.setCustomView(container); BottomSheet bottomSheet = builder.show(); bottomSheet.setBackgroundColor(datePickerColors.backgroundColor); + bottomSheet.fixNavigationBar(datePickerColors.backgroundColor); return builder; } @@ -3607,15 +3640,15 @@ public class AlertsCreator { LocaleController.getString("ReportChatOther", R.string.ReportChatOther) }; icons = new int[]{ - R.drawable.msg_report_spam, + R.drawable.msg_clearcache, R.drawable.msg_report_violence, - R.drawable.msg_report_abuse, + R.drawable.msg_block2, R.drawable.msg_report_drugs, R.drawable.msg_report_personal, R.drawable.msg_report_xxx, R.drawable.msg_report_other }; - types = new int[] { + types = new int[]{ REPORT_TYPE_SPAM, REPORT_TYPE_VIOLENCE, REPORT_TYPE_CHILD_ABUSE, @@ -3636,16 +3669,16 @@ public class AlertsCreator { LocaleController.getString("ReportChatOther", R.string.ReportChatOther) }; icons = new int[]{ - R.drawable.msg_report_spam, + R.drawable.msg_clearcache, R.drawable.msg_report_fake, R.drawable.msg_report_violence, - R.drawable.msg_report_abuse, + R.drawable.msg_block2, R.drawable.msg_report_drugs, R.drawable.msg_report_personal, R.drawable.msg_report_xxx, R.drawable.msg_report_other }; - types = new int[] { + types = new int[]{ REPORT_TYPE_SPAM, REPORT_TYPE_FAKE_ACCOUNT, REPORT_TYPE_VIOLENCE, @@ -3914,6 +3947,10 @@ public class AlertsCreator { } public static Dialog createColorSelectDialog(Activity parentActivity, final long dialog_id, final int globalType, final Runnable onSelect) { + return createColorSelectDialog(parentActivity, dialog_id, globalType, onSelect, null); + } + + public static Dialog createColorSelectDialog(Activity parentActivity, final long dialog_id, final int globalType, final Runnable onSelect, Theme.ResourcesProvider resourcesProvider) { int currentColor; SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); if (dialog_id != 0) { @@ -3946,7 +3983,7 @@ public class AlertsCreator { LocaleController.getString("ColorWhite", R.string.ColorWhite)}; final int[] selectedColor = new int[]{currentColor}; for (int a = 0; a < 9; a++) { - RadioColorCell cell = new RadioColorCell(parentActivity); + RadioColorCell cell = new RadioColorCell(parentActivity, resourcesProvider); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); cell.setTag(a); cell.setCheckColor(TextColorCell.colors[a], TextColorCell.colors[a]); @@ -3961,7 +3998,7 @@ public class AlertsCreator { selectedColor[0] = TextColorCell.colorsToSave[(Integer) v.getTag()]; }); } - AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); builder.setTitle(LocaleController.getString("LedColor", R.string.LedColor)); builder.setView(linearLayout); builder.setPositiveButton(LocaleController.getString("Set", R.string.Set), (dialogInterface, which) -> { @@ -4017,16 +4054,24 @@ public class AlertsCreator { } public static Dialog createVibrationSelectDialog(Activity parentActivity, final long dialogId, final boolean globalGroup, final boolean globalAll, final Runnable onSelect) { + return createVibrationSelectDialog(parentActivity, dialogId, globalGroup, globalAll, onSelect, null); + } + + public static Dialog createVibrationSelectDialog(Activity parentActivity, final long dialogId, final boolean globalGroup, final boolean globalAll, final Runnable onSelect, Theme.ResourcesProvider resourcesProvider) { String prefix; if (dialogId != 0) { prefix = "vibrate_" + dialogId; } else { prefix = globalGroup ? "vibrate_group" : "vibrate_messages"; } - return createVibrationSelectDialog(parentActivity, dialogId, prefix, onSelect); + return createVibrationSelectDialog(parentActivity, dialogId, prefix, onSelect, resourcesProvider); } public static Dialog createVibrationSelectDialog(Activity parentActivity, final long dialogId, final String prefKeyPrefix, final Runnable onSelect) { + return createVibrationSelectDialog(parentActivity, dialogId, prefKeyPrefix, onSelect, null); + } + + public static Dialog createVibrationSelectDialog(Activity parentActivity, final long dialogId, final String prefKeyPrefix, final Runnable onSelect, Theme.ResourcesProvider resourcesProvider) { SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); final int[] selected = new int[1]; String[] descriptions; @@ -4063,13 +4108,13 @@ public class AlertsCreator { final LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); - AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); for (int a = 0; a < descriptions.length; a++) { - RadioColorCell cell = new RadioColorCell(parentActivity); + RadioColorCell cell = new RadioColorCell(parentActivity, resourcesProvider); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); cell.setTag(a); - cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + cell.setCheckColor(Theme.getColor(Theme.key_radioBackground, resourcesProvider), Theme.getColor(Theme.key_dialogRadioBackgroundChecked, resourcesProvider)); cell.setTextAndValue(descriptions[a], selected[0] == a); linearLayout.addView(cell); cell.setOnClickListener(v -> { @@ -4430,6 +4475,10 @@ public class AlertsCreator { } public static Dialog createPrioritySelectDialog(Activity parentActivity, final long dialog_id, final int globalType, final Runnable onSelect) { + return createPrioritySelectDialog(parentActivity, dialog_id, globalType, onSelect, null); + } + + public static Dialog createPrioritySelectDialog(Activity parentActivity, final long dialog_id, final int globalType, final Runnable onSelect, Theme.ResourcesProvider resourcesProvider) { SharedPreferences preferences = MessagesController.getNotificationsSettings(UserConfig.selectedAccount); final int[] selected = new int[1]; String[] descriptions; @@ -4480,13 +4529,13 @@ public class AlertsCreator { final LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); - AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity, resourcesProvider); for (int a = 0; a < descriptions.length; a++) { - RadioColorCell cell = new RadioColorCell(parentActivity); + RadioColorCell cell = new RadioColorCell(parentActivity, resourcesProvider); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); cell.setTag(a); - cell.setCheckColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_dialogRadioBackgroundChecked)); + cell.setCheckColor(Theme.getColor(Theme.key_radioBackground, resourcesProvider), Theme.getColor(Theme.key_dialogRadioBackgroundChecked, resourcesProvider)); cell.setTextAndValue(descriptions[a], selected[0] == a); linearLayout.addView(cell); cell.setOnClickListener(v -> { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java index 47cf91eab..80bbbfd88 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFileDrawable.java @@ -31,7 +31,7 @@ import org.telegram.messenger.DispatchQueue; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; -import org.telegram.messenger.MessageObject; +import org.telegram.messenger.ImageReceiver; import org.telegram.tgnet.TLRPC; import java.io.File; @@ -43,12 +43,19 @@ import java.util.concurrent.TimeUnit; public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private static native long createDecoder(String src, int[] params, int account, long streamFileSize, Object readCallback, boolean preview); + private static native void destroyDecoder(long ptr); + private static native void stopDecoder(long ptr); + private static native int getVideoFrame(long ptr, Bitmap bitmap, int[] params, int stride, boolean preview, float startTimeSeconds, float endTimeSeconds); + private static native void seekToMs(long ptr, long ms, boolean precise); + private static native int getFrameAtTime(long ptr, long ms, Bitmap bitmap, int[] data, int stride); + private static native void prepareToSeek(long ptr); + private static native void getVideoInfo(int sdkVersion, String src, int[] params); public final static int PARAM_NUM_SUPPORTED_VIDEO_CODEC = 0; @@ -88,6 +95,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private volatile long pendingSeekToUI = -1; private boolean pendingRemoveLoading; private int pendingRemoveLoadingFramesReset; + private boolean isRestarted; private final Object sync = new Object(); private boolean invalidateParentViewWithSecond; @@ -120,19 +128,22 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { private int renderingHeight; private int renderingWidth; private float scaleFactor = 1f; - public final boolean isWebmSticker; + public boolean isWebmSticker; private final TLRPC.Document document; private View parentView; private ArrayList secondParentViews = new ArrayList<>(); - private ArrayList parents = new ArrayList<>(); + private ArrayList parents = new ArrayList<>(); private AnimatedFileDrawableStream stream; private boolean useSharedQueue; private boolean invalidatePath = true; private boolean invalidateTaskIsRunning; + private boolean limitFps; + + public int repeatCount; private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(8, new ThreadPoolExecutor.DiscardPolicy()); @@ -160,12 +171,18 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } loadFrameTask = null; scheduleNextGetFrame(); - for (int i = 0; i < parents.size(); i++) { - parents.get(i).invalidate(); - } + invalidateInternal(); } }; + private void invalidateInternal() { + for (int i = 0; i < parents.size(); i++) { + if (parents.get(i).getParentView() != null) { + parents.get(i).getParentView().invalidate(); + } + } + } + private Runnable uiRunnable = new Runnable() { @Override public void run() { @@ -205,11 +222,20 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { nextRenderingBitmap = backgroundBitmap; nextRenderingBitmapTime = backgroundBitmapTime; nextRenderingShader = backgroundShader; + if (isRestarted) { + isRestarted = false; + repeatCount++; + checkRepeat(); + } + if (metaData[3] < lastTimeStamp) { lastTimeStamp = startTime > 0 ? (int) (startTime * 1000) : 0; } if (metaData[3] - lastTimeStamp != 0) { invalidateAfter = metaData[3] - lastTimeStamp; + if (limitFps && invalidateAfter < 32) { + invalidateAfter = 32; + } } if (pendingSeekToUI >= 0 && pendingSeekTo == -1) { pendingSeekToUI = -1; @@ -221,13 +247,30 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { secondParentViews.get(a).invalidate(); } } - for (int i = 0; i < parents.size(); i++) { - parents.get(i).invalidate(); - } + invalidateInternal(); scheduleNextGetFrame(); } }; + public void checkRepeat() { + int count = 0; + for (int j = 0; j < parents.size(); j++) { + ImageReceiver parent = parents.get(j); + if (!parent.isAttachedToWindow()) { + parents.remove(j); + j--; + } + if (parent.animatedFileDrawableRepeatMaxCount > 0 && repeatCount >= parent.animatedFileDrawableRepeatMaxCount) { + count++; + } + } + if (parents.size() == count) { + stop(); + } else { + start(); + } + } + private Runnable loadFrameRunnable = new Runnable() { @Override public void run() { @@ -257,7 +300,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { if (pendingSeekTo >= 0) { metaData[3] = (int) pendingSeekTo; long seekTo = pendingSeekTo; - synchronized(sync) { + synchronized (sync) { pendingSeekTo = -1; } seekWas = true; @@ -273,10 +316,13 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { AndroidUtilities.runOnUIThread(uiRunnableNoFrame); return; } - + if (lastTimeStamp != 0 && metaData[3] == 0) { + isRestarted = true; + } if (seekWas) { lastTimeStamp = metaData[3]; } + backgroundBitmapTime = metaData[3]; } } else { @@ -314,7 +360,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { }; public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, TLRPC.Document document, ImageLocation location, Object parentObject, long seekTo, int account, boolean preview) { - this(file, createDecoder, streamSize, document, location, parentObject, seekTo ,account, preview, 0, 0); + this(file, createDecoder, streamSize, document, location, parentObject, seekTo, account, preview, 0, 0); } public AnimatedFileDrawable(File file, boolean createDecoder, long streamSize, TLRPC.Document document, ImageLocation location, Object parentObject, long seekTo, int account, boolean preview, int w, int h) { @@ -324,10 +370,6 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { renderingHeight = h; renderingWidth = w; this.document = document; - isWebmSticker = MessageObject.isWebM(document) || MessageObject.isVideoSticker(document); - if (isWebmSticker) { - useSharedQueue = true; - } getPaint().setFlags(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); if (streamSize != 0 && (document != null || location != null)) { stream = new AnimatedFileDrawableStream(document, location, parentObject, account, preview); @@ -346,6 +388,13 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } } + public void setIsWebmSticker(boolean b) { + isWebmSticker = b; + if (isWebmSticker) { + useSharedQueue = true; + } + } + public Bitmap getFrameAtTime(long ms) { return getFrameAtTime(ms, false); } @@ -380,17 +429,20 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { parentView = view; } - public void addParent(View view) { - if (view != null && !parents.contains(view)) { - parents.add(view); + public void addParent(ImageReceiver imageReceiver) { + if (imageReceiver != null && !parents.contains(imageReceiver)) { + parents.add(imageReceiver); if (isRunning) { scheduleNextGetFrame(); } } } - public void removeParent(View view) { - parents.remove(view); + public void removeParent(ImageReceiver imageReceiver) { + parents.remove(imageReceiver); + if (parents.size() == 0) { + repeatCount = 0; + } } public void setInvalidateParentViewWithSecond(boolean value) { @@ -463,12 +515,15 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { destroyDecoder(nativePtr); nativePtr = 0; } + + ArrayList bitmapToRecycle = new ArrayList<>(); + bitmapToRecycle.add(renderingBitmap); + bitmapToRecycle.add(nextRenderingBitmap); + if (renderingBitmap != null) { - renderingBitmap.recycle(); renderingBitmap = null; } if (nextRenderingBitmap != null) { - nextRenderingBitmap.recycle(); nextRenderingBitmap = null; } if (decodeQueue != null) { @@ -476,12 +531,14 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { decodeQueue = null; } getPaint().setShader(null); + AndroidUtilities.recycleBitmaps(bitmapToRecycle); } else { destroyWhenDone = true; } if (stream != null) { stream.cancel(true); } + invalidateInternal(); } public void resetStream(boolean stop) { @@ -709,6 +766,10 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } } + public long getLastFrameTimestamp() { + return lastTimeStamp; + } + @Override public int getMinimumHeight() { int height = decoderCreated ? (metaData[2] == 90 || metaData[2] == 270 ? metaData[0] : metaData[1]) : 0; @@ -802,7 +863,7 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { } public static void getVideoInfo(String src, int[] params) { - getVideoInfo(Build.VERSION.SDK_INT, src, params); + getVideoInfo(Build.VERSION.SDK_INT, src, params); } public void setStartEndTime(long startTime, long endTime) { @@ -825,7 +886,19 @@ public class AnimatedFileDrawable extends BitmapDrawable implements Animatable { if (backgroundBitmap == null) { backgroundBitmap = Bitmap.createBitmap((int) (metaData[0] * scaleFactor), (int) (metaData[1] * scaleFactor), Bitmap.Config.ARGB_8888); } - getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), false, startTime, endTime) ; + getVideoFrame(nativePtr, backgroundBitmap, metaData, backgroundBitmap.getRowBytes(), false, startTime, endTime); return backgroundBitmap; } + + public void setLimitFps(boolean limitFps) { + this.limitFps = limitFps; + } + + public ArrayList getParents() { + return parents; + } + + public File getFilePath() { + return path; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java new file mode 100644 index 000000000..0ae45c1bb --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedFloat.java @@ -0,0 +1,110 @@ +package org.telegram.ui.Components; + + +import android.animation.TimeInterpolator; +import android.os.SystemClock; +import android.view.View; + +import androidx.core.math.MathUtils; + +import org.telegram.messenger.AndroidUtilities; + +public class AnimatedFloat { + + private View parent; + private float value; + private float targetValue; + private boolean firstSet; + + private long transitionDelay = 0; + private long transitionDuration = 200; + private TimeInterpolator transitionInterpolator = CubicBezierInterpolator.DEFAULT; + private boolean transition; + private long transitionStart; + private float startValue; + + public AnimatedFloat() { + this.parent = null; + this.firstSet = true; + } + + public AnimatedFloat(long transitionDuration, TimeInterpolator transitionInterpolator) { + this.parent = null; + this.transitionDuration = transitionDuration; + this.transitionInterpolator = transitionInterpolator; + this.firstSet = true; + } + + public AnimatedFloat(long transitionDelay, long transitionDuration, TimeInterpolator transitionInterpolator) { + this.parent = null; + this.transitionDelay = transitionDelay; + this.transitionDuration = transitionDuration; + this.transitionInterpolator = transitionInterpolator; + this.firstSet = true; + } + + public AnimatedFloat(View parentToInvalidate) { + this.parent = parentToInvalidate; + this.firstSet = true; + } + + public AnimatedFloat(View parentToInvalidate, long transitionDuration, TimeInterpolator transitionInterpolator) { + this.parent = parentToInvalidate; + this.transitionDuration = transitionDuration; + this.transitionInterpolator = transitionInterpolator; + this.firstSet = true; + } + + public AnimatedFloat(float initialValue, View parentToInvalidate) { + this.parent = parentToInvalidate; + this.value = targetValue = initialValue; + this.firstSet = false; + } + + public AnimatedFloat(float initialValue, View parentToInvalidate, long transitionDelay, long transitionDuration, TimeInterpolator transitionInterpolator) { + this.parent = parentToInvalidate; + this.value = targetValue = initialValue; + this.transitionDelay = transitionDelay; + this.transitionDuration = transitionDuration; + this.transitionInterpolator = transitionInterpolator; + this.firstSet = false; + } + + public float get() { + return value; + } + + public float set(float mustBe) { + return this.set(mustBe, false); + } + + public float set(float mustBe, boolean force) { + final long now = SystemClock.elapsedRealtime(); + if (force || firstSet) { + value = targetValue = mustBe; + transition = false; + firstSet = false; + } else if (Math.abs(targetValue - mustBe) > 0.0001f) { + transition = true; + targetValue = mustBe; + startValue = value; + transitionStart = now; + } + if (transition) { + final float t = MathUtils.clamp((now - transitionStart - transitionDelay) / (float) transitionDuration, 0, 1); + if (now - transitionStart >= transitionDelay) { + value = AndroidUtilities.lerp(startValue, targetValue, transitionInterpolator.getInterpolation(t)); + } + if (t >= 1f) { + transition = false; + } else if (parent != null) { + parent.invalidate(); + } + } + return value; + } + + public void setParent(View parent) { + this.parent = parent; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java new file mode 100644 index 000000000..12ea45e1c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedTextView.java @@ -0,0 +1,791 @@ +package org.telegram.ui.Components; + + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Build; +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.View; +import android.view.accessibility.AccessibilityNodeInfo; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.telegram.messenger.AndroidUtilities; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.stream.IntStream; + +public class AnimatedTextView extends View { + + public static class AnimatedTextDrawable extends Drawable { + + private TextPaint textPaint = new TextPaint(); + private int gravity = 0; + + private boolean isRTL = false; + + private int currentWidth, currentHeight; + private Integer[] currentLayoutOffsets; + private Integer[] currentLayoutToOldIndex; + private StaticLayout[] currentLayout; + private CharSequence currentText; + + private int oldWidth, oldHeight; + private Integer[] oldLayoutOffsets; + private Integer[] oldLayoutToCurrentIndex; + private StaticLayout[] oldLayout; + private CharSequence oldText; + + private float t = 0; + private boolean moveDown = true; + private ValueAnimator animator; + private CharSequence toSetText; + private boolean toSetTextMoveDown; + + private long animateDelay = 0; + private long animateDuration = 450; + private TimeInterpolator animateInterpolator = CubicBezierInterpolator.EASE_OUT_QUINT; + private float moveAmplitude = 1f; + + private int alpha = 255; + private Rect bounds = new Rect(); + + private boolean splitByWords; + private boolean preserveIndex; + private boolean startFromEnd; + + private Runnable onAnimationFinishListener; + + public AnimatedTextDrawable() { + this(false, false, false); + } + + public AnimatedTextDrawable(boolean splitByWords, boolean preserveIndex, boolean startFromEnd) { + this.splitByWords = splitByWords; + this.preserveIndex = preserveIndex; + this.startFromEnd = startFromEnd; + } + + public void setOnAnimationFinishListener(Runnable listener) { + onAnimationFinishListener = listener; + } + + @Override + public void draw(@NonNull Canvas canvas) { + canvas.save(); + canvas.translate(bounds.left, bounds.top); + int fullWidth = bounds.width(); + int fullHeight = bounds.height(); + if (currentLayout != null && oldLayout != null) { + int width = AndroidUtilities.lerp(oldWidth, currentWidth, t); + int height = AndroidUtilities.lerp(oldHeight, currentHeight, t); + canvas.translate(0, (fullHeight - height) / 2f); + for (int i = 0; i < currentLayout.length; ++i) { + int j = currentLayoutToOldIndex[i]; + float x = currentLayoutOffsets[i], y = 0; + if (j >= 0) { + float oldX = oldLayoutOffsets[j]; + x = AndroidUtilities.lerp(oldX, x, t); + textPaint.setAlpha(alpha); + } else { + y = -textPaint.getTextSize() * moveAmplitude * (1f - t) * (moveDown ? 1f : -1f); + textPaint.setAlpha((int) (alpha * t)); + } + canvas.save(); + int lwidth = j >= 0 ? width : currentWidth; + if (isRTL) { + x = lwidth - x - currentLayout[i].getWidth(); + x -= fullWidth - lwidth; + } + if ((gravity & Gravity.RIGHT) > 0) { + x += fullWidth - lwidth; + } else if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) { + x += (fullWidth - lwidth) / 2f; + } + canvas.translate(x, y); + currentLayout[i].draw(canvas); + canvas.restore(); + } + for (int i = 0; i < oldLayout.length; ++i) { + int j = oldLayoutToCurrentIndex[i]; + if (j >= 0) { + continue; + } + float x = oldLayoutOffsets[i]; + float y = textPaint.getTextSize() * moveAmplitude * t * (moveDown ? 1f : -1f); + textPaint.setAlpha((int) (alpha * (1f - t))); + canvas.save(); + if (isRTL) { + x = oldWidth - x - oldLayout[i].getWidth(); + x -= fullWidth - oldWidth; + } + if ((gravity & Gravity.RIGHT) > 0) { + x += fullWidth - oldWidth; + } else if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) { + x += (fullWidth - oldWidth) / 2f; + } + canvas.translate(x, y); + oldLayout[i].draw(canvas); + canvas.restore(); + } + } else { + canvas.translate(0, (fullHeight - currentHeight) / 2f); + if (currentLayout != null) { + for (int i = 0; i < currentLayout.length; ++i) { + textPaint.setAlpha(alpha); + canvas.save(); + float x = currentLayoutOffsets[i]; + if (isRTL) { + x = currentWidth - x - currentLayout[i].getWidth(); + x -= fullWidth - currentWidth; + } + if ((gravity & Gravity.RIGHT) > 0) { + x += fullWidth - currentWidth; + } else if ((gravity & Gravity.CENTER_HORIZONTAL) > 0) { + x += (fullWidth - currentWidth) / 2f; + } + canvas.translate(x, 0); + currentLayout[i].draw(canvas); + canvas.restore(); + } + } + } + canvas.restore(); + } + + public boolean isAnimating() { + return animator != null && animator.isRunning(); + } + + public void setText(CharSequence text) { + setText(text, true); + } + + public void setText(CharSequence text, boolean animated) { + setText(text, animated, true); + } + + public void setText(CharSequence text, boolean animated, boolean moveDown) { + if (this.currentText == null || text == null) { + animated = false; + } + if (text == null) { + text = ""; + } + if (animated) { + if (isAnimating()) { + toSetText = text; + toSetTextMoveDown = moveDown; + return; + } + + if (text.equals(currentText)) { + return; + } + + oldText = currentText; + currentText = text; + currentLayout = null; + oldLayout = null; + + ArrayList currentLayoutOffsets = new ArrayList<>(); + ArrayList currentLayoutToOldIndex = new ArrayList<>(); + ArrayList currentLayoutList = new ArrayList<>(); + ArrayList oldLayoutOffsets = new ArrayList<>(); + ArrayList oldLayoutToCurrentIndex = new ArrayList<>(); + ArrayList oldLayoutList = new ArrayList<>(); + + currentWidth = currentHeight = 0; + oldWidth = oldHeight = 0; + + // order execution matters + RegionCallback onEqualRegion = (part, from, to) -> { + StaticLayout layout = makeLayout(part, bounds.width() - Math.min(currentWidth, oldWidth)); + oldLayoutToCurrentIndex.add(currentLayoutList.size()); + currentLayoutToOldIndex.add(oldLayoutList.size()); + currentLayoutOffsets.add(currentWidth); + currentLayoutList.add(layout); + oldLayoutOffsets.add(oldWidth); + oldLayoutList.add(layout); + float partWidth = layout.getLineWidth(0); + currentWidth += partWidth; + oldWidth += partWidth; + currentHeight = Math.max(currentHeight, layout.getHeight()); + oldHeight = Math.max(oldHeight, layout.getHeight()); + }; + RegionCallback onNewPart = (part, from, to) -> { + StaticLayout layout = makeLayout(part, bounds.width() - currentWidth); + currentLayoutOffsets.add(currentWidth); + currentLayoutList.add(layout); + currentLayoutToOldIndex.add(-1); + currentWidth += layout.getLineWidth(0); + currentHeight = Math.max(currentHeight, layout.getHeight()); + }; + RegionCallback onOldPart = (part, from, to) -> { + StaticLayout layout = makeLayout(part, bounds.width() - oldWidth); + oldLayoutOffsets.add(oldWidth); + oldLayoutList.add(layout); + oldLayoutToCurrentIndex.add(-1); + oldWidth += layout.getLineWidth(0); + oldHeight = Math.max(oldHeight, layout.getHeight()); + }; + + CharSequence from = splitByWords ? new WordSequence(oldText) : oldText; + CharSequence to = splitByWords ? new WordSequence(currentText) : currentText; + + diff(from, to, onEqualRegion, onNewPart, onOldPart); + + if (this.currentLayout == null || this.currentLayout.length != currentLayoutList.size()) { + this.currentLayout = new StaticLayout[currentLayoutList.size()]; + } + currentLayoutList.toArray(currentLayout); + if (this.currentLayoutOffsets == null || this.currentLayoutOffsets.length != currentLayoutOffsets.size()) { + this.currentLayoutOffsets = new Integer[currentLayoutOffsets.size()]; + } + currentLayoutOffsets.toArray(this.currentLayoutOffsets); + if (this.currentLayoutToOldIndex == null || this.currentLayoutToOldIndex.length != currentLayoutToOldIndex.size()) { + this.currentLayoutToOldIndex = new Integer[currentLayoutToOldIndex.size()]; + } + currentLayoutToOldIndex.toArray(this.currentLayoutToOldIndex); + + if (this.oldLayout == null || this.oldLayout.length != oldLayoutList.size()) { + this.oldLayout = new StaticLayout[oldLayoutList.size()]; + } + oldLayoutList.toArray(oldLayout); + if (this.oldLayoutOffsets == null || this.oldLayoutOffsets.length != oldLayoutOffsets.size()) { + this.oldLayoutOffsets = new Integer[oldLayoutOffsets.size()]; + } + oldLayoutOffsets.toArray(this.oldLayoutOffsets); + if (this.oldLayoutToCurrentIndex == null || this.oldLayoutToCurrentIndex.length != oldLayoutToCurrentIndex.size()) { + this.oldLayoutToCurrentIndex = new Integer[oldLayoutToCurrentIndex.size()]; + } + oldLayoutToCurrentIndex.toArray(this.oldLayoutToCurrentIndex); + + if (this.currentLayout.length > 0) { + isRTL = this.currentLayout[0].isRtlCharAt(0); + } else if (this.oldLayout.length > 0) { + isRTL = this.oldLayout[0].isRtlCharAt(0); + } + + this.moveDown = moveDown; + animator = ValueAnimator.ofFloat(t = 0f, 1f); + animator.addUpdateListener(anm -> { + t = (float) anm.getAnimatedValue(); + invalidateSelf(); + }); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + oldLayout = null; + AnimatedTextDrawable.this.oldLayoutOffsets = null; + AnimatedTextDrawable.this.oldLayoutToCurrentIndex = null; + oldText = null; + oldWidth = 0; + t = 0; + invalidateSelf(); + animator = null; + + if (toSetText != null) { + setText(toSetText, true, toSetTextMoveDown); + toSetText = null; + toSetTextMoveDown = false; + } else if (onAnimationFinishListener != null) { + onAnimationFinishListener.run(); + } + } + }); + animator.setStartDelay(animateDelay); + animator.setDuration(animateDuration); + animator.setInterpolator(animateInterpolator); + animator.start(); + } else { + if (animator != null) { + animator.cancel(); + } + animator = null; + toSetText = null; + toSetTextMoveDown = false; + t = 0; + + currentLayout = new StaticLayout[1]; + currentLayout[0] = makeLayout(currentText = text, bounds.width()); + currentWidth = (int) currentLayout[0].getLineWidth(0); + currentHeight = currentLayout[0].getHeight(); + currentLayoutOffsets = new Integer[1]; + currentLayoutOffsets[0] = 0; + currentLayoutToOldIndex = new Integer[1]; + currentLayoutToOldIndex[0] = -1; + + if (this.currentLayout.length > 0) { + isRTL = this.currentLayout[0].isRtlCharAt(0); + } + + oldLayout = null; + oldLayoutOffsets = null; + oldLayoutToCurrentIndex = null; + oldText = null; + oldWidth = 0; + oldHeight = 0; + + invalidateSelf(); + } + } + + public CharSequence getText() { + return currentText; + } + + public int getWidth() { + return Math.max(currentWidth, oldWidth); + } + + public int getCurrentWidth() { + if (currentLayout != null && oldLayout != null) { + return AndroidUtilities.lerp(oldWidth, currentWidth, t); + } + return currentWidth; + } + + private StaticLayout makeLayout(CharSequence textPart, int width) { + if (width <= 0) { + width = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return StaticLayout.Builder.obtain(textPart, 0, textPart.length(), textPaint, width) + .setMaxLines(1) + .setLineSpacing(0, 1) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setEllipsize(TextUtils.TruncateAt.END) + .setEllipsizedWidth(width) + .build(); + } + return new StaticLayout( + textPart, + 0, textPart.length(), + textPaint, + width, + Layout.Alignment.ALIGN_NORMAL, + 1, + 0, + false, + TextUtils.TruncateAt.END, + width + ); + } + + private static class WordSequence implements CharSequence { + private static final char SPACE = ' '; + + private CharSequence words[]; + private final int length; + + public WordSequence(CharSequence text) { + if (text == null) { + words = new CharSequence[0]; + length = 0; + return; + } + length = text.length(); + int spacesCount = 0; + for (int i = 0; i < length; ++i) { + if (text.charAt(i) == SPACE) { + spacesCount++; + } + } + int j = 0; + words = new CharSequence[spacesCount + 1]; + int start = 0; + for (int i = 0; i <= length; ++i) { + if (i == length || text.charAt(i) == SPACE) { + words[j++] = text.subSequence(start, i + (i < length ? 1 : 0)); + start = i + 1; + } + } + } + + public WordSequence(CharSequence[] words) { + if (words == null) { + this.words = new CharSequence[0]; + length = 0; + return; + } + this.words = words; + int length = 0; + for (int i = 0; i < this.words.length; ++i) { + if (this.words[i] != null) { + length += this.words[i].length(); + } + } + this.length = length; + } + + public CharSequence wordAt(int i) { + if (i < 0 || i >= words.length) { + return null; + } + return words[i]; + } + + @Override + public int length() { + return words.length; + } + + @Override + public char charAt(int i) { + for (int j = 0; j < words.length; ++j) { + if (i < words[j].length()) + return words[j].charAt(i); + i -= words[j].length(); + } + return 0; + } + + @NonNull + @Override + public CharSequence subSequence(int from, int to) { + return TextUtils.concat(Arrays.copyOfRange(words, from, to)); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < words.length; ++i) { + sb.append(words[i]); + } + return sb.toString(); + } + + public CharSequence toCharSequence() { + return TextUtils.concat(words); + } + + @Override + public IntStream chars() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return toCharSequence().chars(); + } + return null; + } + + @Override + public IntStream codePoints() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + return toCharSequence().codePoints(); + } + return null; + } + } + + public static boolean partEquals(CharSequence a, CharSequence b, int aIndex, int bIndex) { + if (a instanceof WordSequence && b instanceof WordSequence) { + CharSequence wordA = ((WordSequence) a).wordAt(aIndex); + CharSequence wordB = ((WordSequence) b).wordAt(bIndex); + return wordA == null && wordB == null || wordA != null && wordA.equals(wordB); + } + return (a == null && b == null || a != null && b != null && a.charAt(aIndex) == b.charAt(bIndex)); + } + + private void diff(final CharSequence oldText, final CharSequence newText, RegionCallback onEqualPart, RegionCallback onNewPart, RegionCallback onOldPart) { + if (preserveIndex) { + boolean equal = true; + int start = 0; + int minLength = Math.min(newText.length(), oldText.length()); + if (startFromEnd) { + ArrayList indexes = new ArrayList<>(); + boolean eq = true; + for (int i = 0; i <= minLength; ++i) { + int a = newText.length() - i - 1; + int b = oldText.length() - i - 1; + boolean thisEqual = a >= 0 && b >= 0 && partEquals(newText, oldText, a, b); + if (equal != thisEqual || i == minLength) { + if (i - start > 0) { + if (indexes.size() == 0) { + eq = equal; + } + indexes.add(i - start); + } + equal = thisEqual; + start = i; + } + } + int a = newText.length() - minLength; + int b = oldText.length() - minLength; + if (a > 0) { + onNewPart.run(newText.subSequence(0, a), 0, a); + } + if (b > 0) { + onOldPart.run(oldText.subSequence(0, b), 0, b); + } + for (int i = indexes.size() - 1; i >= 0; --i) { + int count = indexes.get(i); + if (i % 2 == 0 ? eq : !eq) { + if (newText.length() > oldText.length()) { + onEqualPart.run(newText.subSequence(a, a + count), a, a + count); + } else { + onEqualPart.run(oldText.subSequence(b, b + count), b, b + count); + } + } else { + onNewPart.run(newText.subSequence(a, a + count), a, a + count); + onOldPart.run(oldText.subSequence(b, b + count), b, b + count); + } + a += count; + b += count; + } + } else { + for (int i = 0; i <= minLength; ++i) { + boolean thisEqual = i < minLength && partEquals(newText, oldText, i, i); + if (equal != thisEqual || i == minLength) { + if (i - start > 0) { + if (equal) { + onEqualPart.run(newText.subSequence(start, i), start, i); + } else { + onNewPart.run(newText.subSequence(start, i), start, i); + onOldPart.run(oldText.subSequence(start, i), start, i); + } + } + equal = thisEqual; + start = i; + } + } + if (newText.length() - minLength > 0) { + onNewPart.run(newText.subSequence(minLength, newText.length()), minLength, newText.length()); + } + if (oldText.length() - minLength > 0) { + onOldPart.run(oldText.subSequence(minLength, oldText.length()), minLength, oldText.length()); + } + } + } else { + int astart = 0, bstart = 0; + boolean equal = true; + int a = 0, b = 0; + int minLength = Math.min(newText.length(), oldText.length()); + for (; a <= minLength; ++a) { + boolean thisEqual = a < minLength && partEquals(newText, oldText, a, b); + if (equal != thisEqual || a == minLength) { + if (a == minLength) { + a = newText.length(); + b = oldText.length(); + } + int alen = a - astart, blen = b - bstart; + if (alen > 0 || blen > 0) { + if (alen == blen && equal) { + // equal part on [astart, a) + onEqualPart.run(newText.subSequence(astart, a), astart, a); + } else if (!equal) { + if (alen > 0) { + // new part on [astart, a) + onNewPart.run(newText.subSequence(astart, a), astart, a); + } + if (blen > 0) { + // old part on [bstart, b) + onOldPart.run(oldText.subSequence(bstart, b), bstart, b); + } + } + } + equal = thisEqual; + astart = a; + bstart = b; + } + if (thisEqual) { + b++; + } + } + } + } + + public void setTextSize(float textSizePx) { + textPaint.setTextSize(textSizePx); + } + + public void setTextColor(int color) { + textPaint.setColor(color); + } + + public void setTypeface(Typeface typeface) { + textPaint.setTypeface(typeface); + } + + public void setGravity(int gravity) { + this.gravity = gravity; + } + + public void setAnimationProperties(float moveAmplitude, long startDelay, long duration, TimeInterpolator interpolator) { + this.moveAmplitude = moveAmplitude; + animateDelay = startDelay; + animateDuration = duration; + animateInterpolator = interpolator; + } + + public void copyStylesFrom(TextPaint paint) { + setTextColor(paint.getColor()); + setTextSize(paint.getTextSize()); + setTypeface(paint.getTypeface()); + } + + public TextPaint getPaint() { + return textPaint; + } + + private interface RegionCallback { + public void run(CharSequence part, int start, int end); + } + + @Override + public void setAlpha(int alpha) { + this.alpha = alpha; + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + textPaint.setColorFilter(colorFilter); + } + + @Deprecated @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + + @Override + public void setBounds(@NonNull Rect bounds) { + super.setBounds(bounds); + this.bounds.set(bounds); + } + + @Override + public void setBounds(int left, int top, int right, int bottom) { + super.setBounds(left, top, right, bottom); + this.bounds.set(left, top, right, bottom); + } + } + + private AnimatedTextDrawable drawable; + private int lastMaxWidth; + + private CharSequence toSetText; + private boolean toSetMoveDown; + + public AnimatedTextView(Context context) { + super(context); + drawable = new AnimatedTextDrawable(); + drawable.setCallback(this); + } + + public AnimatedTextView(Context context, boolean splitByWords, boolean preserveIndex, boolean startFromEnd) { + super(context); + drawable = new AnimatedTextDrawable(splitByWords, preserveIndex, startFromEnd); + drawable.setCallback(this); + drawable.setOnAnimationFinishListener(() -> { + if (toSetText != null) { + // wrapped toSetText here to do requestLayout() + AnimatedTextView.this.setText(toSetText, toSetMoveDown, true); + toSetText = null; + toSetMoveDown = false; + } + }); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + if (lastMaxWidth != width) { + drawable.setBounds(getPaddingLeft(), getPaddingTop(), width - getPaddingRight(), height - getPaddingBottom()); + setText(drawable.getText(), false); + } + lastMaxWidth = width; + if (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST) { + width = getPaddingLeft() + drawable.getWidth() + getPaddingRight(); + } + setMeasuredDimension(width, height); + } + + @Override + protected void onDraw(Canvas canvas) { + drawable.setBounds(getPaddingLeft(), getPaddingTop(), getMeasuredWidth() - getPaddingRight(), getMeasuredHeight() - getPaddingBottom()); + drawable.draw(canvas); + } + + public void setText(CharSequence text) { + setText(text, true, true); + } + + public void setText(CharSequence text, boolean animated) { + setText(text, animated, true); + } + + private boolean first = true; + public void setText(CharSequence text, boolean animated, boolean moveDown) { + animated = !first && animated; + first = false; + if (animated && drawable.isAnimating()) { + toSetText = text; + toSetMoveDown = moveDown; + return; + } + int wasWidth = drawable.getWidth(); + drawable.setBounds(getPaddingLeft(), getPaddingTop(), lastMaxWidth - getPaddingRight(), getMeasuredHeight() - getPaddingBottom()); + drawable.setText(text, animated, moveDown); + if (wasWidth < drawable.getWidth()) { + requestLayout(); + } + } + + public CharSequence getText() { + return drawable.getText(); + } + + public void setTextSize(float textSizePx) { + drawable.setTextSize(textSizePx); + } + + public void setTextColor(int color) { + drawable.setTextColor(color); + } + + public void setTypeface(Typeface typeface) { + drawable.setTypeface(typeface); + } + + public void setGravity(int gravity) { + drawable.setGravity(gravity); + } + + public void setAnimationProperties(float moveAmplitude, long startDelay, long duration, TimeInterpolator interpolator) { + drawable.setAnimationProperties(moveAmplitude, startDelay, duration, interpolator); + } + + public TextPaint getPaint() { + return drawable.getPaint(); + } + + @Override + public void invalidateDrawable(@NonNull Drawable drawable) { + super.invalidateDrawable(drawable); + invalidate(); + } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.TextView"); + info.setText(getText()); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AppIconBulletinLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AppIconBulletinLayout.java new file mode 100644 index 000000000..7c03890e4 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AppIconBulletinLayout.java @@ -0,0 +1,43 @@ +package org.telegram.ui.Components; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Typeface; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; + +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.Cells.AppIconsSelectorCell; +import org.telegram.ui.LauncherIconController; + +@SuppressLint("ViewConstructor") +public class AppIconBulletinLayout extends Bulletin.ButtonLayout { + + public final AppIconsSelectorCell.AdaptiveIconImageView imageView = new AppIconsSelectorCell.AdaptiveIconImageView(getContext()); + public final TextView textView = new TextView(getContext()); + + public AppIconBulletinLayout(@NonNull Context context, LauncherIconController.LauncherIcon icon, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + addView(imageView, LayoutHelper.createFrameRelatively(30, 30, Gravity.START | Gravity.CENTER_VERTICAL, 12, 8, 12, 8)); + + textView.setGravity(Gravity.START); + textView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8)); + textView.setTextColor(getThemedColor(Theme.key_undo_infoColor)); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + textView.setTypeface(Typeface.SANS_SERIF); + addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 16, 0)); + + imageView.setImageDrawable(ContextCompat.getDrawable(context, icon.background)); + imageView.setOuterPadding(AndroidUtilities.dp(8)); + imageView.setBackgroundOuterPadding(AndroidUtilities.dp(24)); + imageView.setForeground(icon.foreground); + textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.AppIconChangedTo, LocaleController.getString(icon.title)))); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java index e73fccc1d..16b64e416 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AudioPlayerAlert.java @@ -229,6 +229,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. public AudioPlayerAlert(final Context context, Theme.ResourcesProvider resourcesProvider) { super(context, true, resourcesProvider); + fixNavigationBar(); MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject(); if (messageObject != null) { @@ -1222,6 +1223,36 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. updateEmptyView(); } + @Override + public int getContainerViewHeight() { + if (playerLayout == null) { + return 0; + } + if (playlist.size() <= 1) { + return playerLayout.getMeasuredHeight() + backgroundPaddingTop; + } else { + int offset = AndroidUtilities.dp(13); + int top = scrollOffsetY - backgroundPaddingTop - offset; + if (currentSheetAnimationType == 1) { + top += listView.getTranslationY(); + } + if (top + backgroundPaddingTop < ActionBar.getCurrentActionBarHeight()) { + float toMove = offset + AndroidUtilities.dp(11 - 7); + float moveProgress = Math.min(1.0f, (ActionBar.getCurrentActionBarHeight() - top - backgroundPaddingTop) / toMove); + float availableToMove = ActionBar.getCurrentActionBarHeight() - toMove; + + int diff = (int) (availableToMove * moveProgress); + top -= diff; + } + + if (Build.VERSION.SDK_INT >= 21) { + top += AndroidUtilities.statusBarHeight; + } + + return container.getMeasuredHeight() - top; + } + } + private void startForwardRewindingSeek() { if (rewindingState == 1) { lastRewindingTime = System.currentTimeMillis(); @@ -1408,7 +1439,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } } if (f == null) { - f = FileLoader.getPathToMessage(messageObject.messageOwner); + f = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); } if (f.exists()) { @@ -1476,7 +1507,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } } if (path == null || path.length() == 0) { - path = FileLoader.getPathToMessage(messageObject.messageOwner).toString(); + path = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner).toString(); } MediaController.saveFile(path, parentActivity, 3, fileName, messageObject.getDocument() != null ? messageObject.getDocument().mime_type : "", () -> BulletinFactory.of((FrameLayout) containerView, resourcesProvider).createDownloadBulletin(BulletinFactory.FileType.AUDIO).show()); } @@ -1841,7 +1872,7 @@ public class AudioPlayerAlert extends BottomSheet implements NotificationCenter. } } if (cacheFile == null) { - cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); + cacheFile = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); } boolean canStream = SharedConfig.streamMedia && (int) messageObject.getDialogId() != 0 && messageObject.isMusic(); if (!cacheFile.exists() && !canStream) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AutoDeletePopupWrapper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AutoDeletePopupWrapper.java index b526a38b4..2704d6bdf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AutoDeletePopupWrapper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AutoDeletePopupWrapper.java @@ -52,7 +52,7 @@ public class AutoDeletePopupWrapper { item = ActionBarMenuItem.addItem(windowLayout, R.drawable.msg_customize, LocaleController.getString("AutoDeleteCustom", R.string.AutoDeleteCustom), false, resourcesProvider); item.setOnClickListener(view -> { dismiss(); - AlertsCreator.createAutoDeleteDatePickerDialog(context, (notify, timeInMinutes) -> { + AlertsCreator.createAutoDeleteDatePickerDialog(context, resourcesProvider, (notify, timeInMinutes) -> { callback.setAutoDeleteHistory(timeInMinutes * 60, timeInMinutes == 0 ? UndoView.ACTION_AUTO_DELETE_OFF : UndoView.ACTION_AUTO_DELETE_ON); }); }); @@ -63,9 +63,8 @@ public class AutoDeletePopupWrapper { }); disableItem.setColors(Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogTextRed2)); - View gap = new FrameLayout(context); - gap.setBackgroundColor(Theme.getColor(Theme.key_graySection)); + gap.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuSeparator, resourcesProvider)); gap.setTag(R.id.fit_width_tag, 1); windowLayout.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); 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 8750fdec0..a40d20a4d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AvatarDrawable.java @@ -121,24 +121,24 @@ public class AvatarDrawable extends Drawable { return Theme.getColor(Theme.keys_avatar_background[getColorIndex(id)]); } - public static int getButtonColorForId(long id) { - return Theme.getColor(Theme.key_avatar_actionBarSelectorBlue); + public static int getButtonColorForId(long id, Theme.ResourcesProvider resourcesProvider) { + return Theme.getColor(Theme.key_avatar_actionBarSelectorBlue, resourcesProvider); } - public static int getIconColorForId(long id) { - return Theme.getColor(Theme.key_avatar_actionBarIconBlue); + public static int getIconColorForId(long id, Theme.ResourcesProvider resourcesProvider) { + return Theme.getColor(Theme.key_avatar_actionBarIconBlue, resourcesProvider); } - public static int getProfileColorForId(long id) { - return Theme.getColor(Theme.keys_avatar_background[getColorIndex(id)]); + public static int getProfileColorForId(long id, Theme.ResourcesProvider resourcesProvider) { + return Theme.getColor(Theme.keys_avatar_background[getColorIndex(id)], resourcesProvider); } - public static int getProfileTextColorForId(long id) { - return Theme.getColor(Theme.key_avatar_subtitleInProfileBlue); + public static int getProfileTextColorForId(long id, Theme.ResourcesProvider resourcesProvider) { + return Theme.getColor(Theme.key_avatar_subtitleInProfileBlue, resourcesProvider); } - public static int getProfileBackColorForId(long id) { - return Theme.getColor(Theme.key_avatar_backgroundActionBarBlue); + public static int getProfileBackColorForId(long id, Theme.ResourcesProvider resourcesProvider) { + return Theme.getColor(Theme.key_avatar_backgroundActionBarBlue, resourcesProvider); } public static String getNameColorNameForId(long id) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java index e89baa748..132777900 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackButtonMenu.java @@ -42,7 +42,7 @@ public class BackButtonMenu { int filterId; } - public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButton, long currentDialogId) { + public static ActionBarPopupWindow show(BaseFragment thisFragment, View backButton, long currentDialogId, Theme.ResourcesProvider resourcesProvider) { if (thisFragment == null) { return null; } @@ -57,11 +57,11 @@ public class BackButtonMenu { return null; } - ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context); + ActionBarPopupWindow.ActionBarPopupWindowLayout layout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(context, resourcesProvider); android.graphics.Rect backgroundPaddings = new Rect(); Drawable shadowDrawable = thisFragment.getParentActivity().getResources().getDrawable(R.drawable.popup_fixed_alert).mutate(); shadowDrawable.getPadding(backgroundPaddings); - layout.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground)); + layout.setBackgroundColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider)); AtomicReference scrimPopupWindowRef = new AtomicReference<>(); @@ -79,18 +79,25 @@ public class BackButtonMenu { TextView titleView = new TextView(context); titleView.setLines(1); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); + titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider)); titleView.setEllipsize(TextUtils.TruncateAt.END); cell.addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 59, 0, 12, 0)); AvatarDrawable avatarDrawable = new AvatarDrawable(); avatarDrawable.setSmallSize(true); + Drawable thumb = avatarDrawable; if (chat != null) { avatarDrawable.setInfo(chat); - imageView.setImage(ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, chat); + if (chat.photo != null && chat.photo.strippedBitmap != null) { + thumb = chat.photo.strippedBitmap; + } + imageView.setImage(ImageLocation.getForChat(chat, ImageLocation.TYPE_SMALL), "50_50", thumb, chat); titleView.setText(chat.title); } else if (user != null) { String name; + if (user.photo != null && user.photo.strippedBitmap != null) { + thumb = user.photo.strippedBitmap; + } if (pDialog.activity == ChatActivity.class && UserObject.isUserSelf(user)) { name = LocaleController.getString("SavedMessages", R.string.SavedMessages); avatarDrawable.setAvatarType(AvatarDrawable.AVATAR_TYPE_SAVED); @@ -106,12 +113,12 @@ public class BackButtonMenu { } else { name = UserObject.getUserName(user); avatarDrawable.setInfo(user); - imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, user); + imageView.setImage(ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL), "50_50", thumb, user); } titleView.setText(name); } - cell.setBackground(Theme.getSelectorDrawable(Theme.getColor(Theme.key_listSelector), false)); + cell.setBackground(Theme.getSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), false)); cell.setOnClickListener(e2 -> { if (scrimPopupWindowRef.get() != null) { scrimPopupWindowRef.getAndSet(null).dismiss(); @@ -175,9 +182,9 @@ public class BackButtonMenu { int popupY = (int) (backButton.getBottom() - backgroundPaddings.top - AndroidUtilities.dp(8)); scrimPopupWindow.showAtLocation(fragmentView, Gravity.LEFT | Gravity.TOP, popupX, popupY); - try { - fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } catch (Exception ignore) {} +// try { +// fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); +// } catch (Exception ignore) {} return scrimPopupWindow; } @@ -270,7 +277,9 @@ public class BackButtonMenu { } } if (pulledDialogs != null) { - for (PulledDialog pulledDialog : pulledDialogs) { + int count = pulledDialogs.size(); + for (int i = count - 1; i >= 0; --i) { + PulledDialog pulledDialog = pulledDialogs.get(i); if (pulledDialog.dialogId == ignoreDialogId) { continue; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java index 596883388..51d7e688c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BackupImageView.java @@ -106,7 +106,7 @@ public class BackupImageView extends View { imageReceiver.setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, thumb, size, ext, parentObject, 0); } - public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, String ext, int size, int cacheType, Object parentObject) { + public void setImage(ImageLocation imageLocation, String imageFilter, ImageLocation thumbLocation, String thumbFilter, String ext, long size, int cacheType, Object parentObject) { imageReceiver.setImage(imageLocation, imageFilter, thumbLocation, thumbFilter, null, size, ext, parentObject, cacheType); } 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 022aaab51..b796034eb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BlockingUpdateView.java @@ -13,8 +13,6 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.net.Uri; import android.os.Build; -import android.provider.Settings; -import androidx.core.content.FileProvider; import android.text.SpannableStringBuilder; import android.util.TypedValue; import android.view.Gravity; @@ -25,7 +23,7 @@ import android.widget.ImageView; import android.widget.ScrollView; import android.widget.TextView; -import com.google.android.exoplayer2.util.Log; +import androidx.core.content.FileProvider; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; @@ -37,10 +35,10 @@ import org.telegram.messenger.MessageObject; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; -import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.voip.CellFlickerDrawable; @@ -129,7 +127,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente } cellFlickerDrawable.setParentWidth(getMeasuredWidth()); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4)); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null); invalidate(); } @@ -144,7 +142,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente } }; acceptButton.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); - acceptButton.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + acceptButton.setBackgroundDrawable(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); 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 -> { @@ -242,7 +240,7 @@ public class BlockingUpdateView extends FrameLayout implements NotificationCente boolean exists = false; try { String fileName = FileLoader.getAttachFileName(document); - File f = FileLoader.getPathToAttach(document, true); + File f = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); if (exists = f.exists()) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java index dc6bf00df..3b979b475 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotCommandsMenuView.java @@ -81,6 +81,7 @@ public class BotCommandsMenuView extends View { backDrawable.setRoundCap(); backgroundDrawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(16), Color.TRANSPARENT, Theme.getColor(Theme.key_featuredStickers_addButtonPressed)); backgroundDrawable.setCallback(this); + setContentDescription(LocaleController.getString("AccDescrBotMenu", R.string.AccDescrBotMenu)); } public void setDrawBackgroundDrawable(boolean drawBackgroundDrawable) { @@ -219,13 +220,15 @@ public class BotCommandsMenuView extends View { } - public void setMenuText(String menuText) { + public boolean setMenuText(String menuText) { if (menuText == null) { menuText = LocaleController.getString(R.string.BotsMenuTitle); } + boolean changed = this.menuText == null || !this.menuText.equals(menuText); this.menuText = menuText; menuTextLayout = null; requestLayout(); + return changed; } public void setExpanded(boolean expanded, boolean animated) { 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 430eb4781..2a84f4436 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewContainer.java @@ -22,6 +22,7 @@ import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.InputMethodManager; import android.webkit.GeolocationPermissions; @@ -45,6 +46,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BotWebViewVibrationEffect; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; @@ -57,8 +59,10 @@ import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserObject; import org.telegram.messenger.browser.Browser; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Components.voip.CellFlickerDrawable; @@ -71,7 +75,6 @@ import java.util.List; import java.util.Objects; public class BotWebViewContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { - private final static boolean WEB_VIEW_CAN_GO_BACK = false; private final static String DURGER_KING_USERNAME = "DurgerKingBot"; private final static int REQUEST_CODE_WEB_VIEW_FILE = 3000, REQUEST_CODE_WEB_PERMISSION = 4000; @@ -99,8 +102,13 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent private String lastButtonText = ""; private String buttonData; + private int currentAccount; private boolean isPageLoaded; private boolean lastExpanded; + private boolean isRequestingPageOpen; + private long lastClickMs; + + private boolean isBackButtonVisible; private boolean hasUserPermissions; private TLRPC.User botUser; @@ -110,6 +118,8 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent private boolean isViewPortByMeasureSuppressed; + private String currentPaymentSlug; + public BotWebViewContainer(@NonNull Context context, Theme.ResourcesProvider resourcesProvider, int backgroundColor) { super(context); this.resourcesProvider = resourcesProvider; @@ -230,6 +240,15 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY)); } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + lastClickMs = System.currentTimeMillis(); + } + return super.onTouchEvent(event); + } }; webView.setBackgroundColor(getColor(Theme.key_windowBackgroundWhite)); WebSettings settings = webView.getSettings(); @@ -256,31 +275,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent override = true; if (WHITELISTED_SCHEMES.contains(uriNew.getScheme())) { - boolean[] forceBrowser = {false}; - boolean internal = Browser.isInternalUri(uriNew, forceBrowser); - - if (internal) { - if (delegate != null) { - setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS); - BotWebViewContainer.this.setFocusable(false); - webView.setFocusable(false); - webView.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS); - webView.clearFocus(); - InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); - - delegate.onCloseRequested(()-> Browser.openUrl(getContext(), uriNew, true, false)); - } else { - Browser.openUrl(getContext(), uriNew, true, false); - } - } else { - new AlertDialog.Builder(getContext(), resourcesProvider) - .setTitle(LocaleController.getString(R.string.OpenUrlTitle)) - .setMessage(LocaleController.formatString(R.string.OpenUrlAlert2, uriNew.toString())) - .setPositiveButton(LocaleController.getString(R.string.Open), (dialog, which) -> Browser.openUrl(getContext(), uriNew, true, false)) - .setNegativeButton(LocaleController.getString(R.string.Cancel), null) - .show(); - } + onOpenUri(uriNew); } } else { override = false; @@ -446,6 +441,47 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } } + private void onOpenUri(Uri uri) { + onOpenUri(uri, false); + } + + private void onOpenUri(Uri uri, boolean suppressPopup) { + if (isRequestingPageOpen || System.currentTimeMillis() - lastClickMs > 10000 && suppressPopup) { + return; + } + + lastClickMs = 0; + boolean[] forceBrowser = {false}; + boolean internal = Browser.isInternalUri(uri, forceBrowser); + + if (internal && !forceBrowser[0]) { + if (delegate != null) { + setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS); + BotWebViewContainer.this.setFocusable(false); + webView.setFocusable(false); + webView.setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS); + webView.clearFocus(); + InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + + delegate.onCloseRequested(() -> Browser.openUrl(getContext(), uri, true, false)); + } else { + Browser.openUrl(getContext(), uri, true, false); + } + } else if (suppressPopup) { + Browser.openUrl(getContext(), uri, true, false); + } else { + isRequestingPageOpen = true; + new AlertDialog.Builder(getContext(), resourcesProvider) + .setTitle(LocaleController.getString(R.string.OpenUrlTitle)) + .setMessage(LocaleController.formatString(R.string.OpenUrlAlert2, uri.toString())) + .setPositiveButton(LocaleController.getString(R.string.Open), (dialog, which) -> Browser.openUrl(getContext(), uri, true, false)) + .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .setOnDismissListener(dialog -> isRequestingPageOpen = false) + .show(); + } + } + public static int getMainButtonRippleColor(int buttonColor) { return ColorUtils.calculateLuminance(buttonColor) >= 0.3f ? 0x12000000 : 0x16FFFFFF; } @@ -462,15 +498,11 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent * @return If this press was consumed */ public boolean onBackPressed() { - if (!WEB_VIEW_CAN_GO_BACK) { - return false; - } - if (webView == null) { return false; } - if (webView.canGoBack()) { - webView.goBack(); + if (isBackButtonVisible) { + notifyEvent("back_button_pressed", null); return true; } return false; @@ -546,8 +578,33 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } } + public void onInvoiceStatusUpdate(String slug, String status) { + onInvoiceStatusUpdate(slug, status, false); + } + + public void onInvoiceStatusUpdate(String slug, String status, boolean ignoreCurrentCheck) { + try { + JSONObject data = new JSONObject(); + data.put("slug", slug); + data.put("status", status); + notifyEvent("invoice_closed", data); + + if (!ignoreCurrentCheck && Objects.equals(currentPaymentSlug, slug)) { + currentPaymentSlug = null; + } + } catch (JSONException e) { + FileLog.e(e); + } + } + + public void onSettingsButtonPressed() { + lastClickMs = System.currentTimeMillis(); + notifyEvent("settings_button_pressed", null); + } + public void onMainButtonPressed() { - evaluateJs("window.Telegram.WebView.receiveEvent('main_button_pressed', null);"); + lastClickMs = System.currentTimeMillis(); + notifyEvent("main_button_pressed", null); } public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { @@ -609,7 +666,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent data.put("height", viewPortHeight / AndroidUtilities.density); data.put("is_state_stable", isStable); data.put("is_expanded", lastExpanded); - evaluateJs("window.Telegram.WebView.receiveEvent('viewport_changed', " + data + ");"); + notifyEvent("viewport_changed", data); } catch (JSONException e) { e.printStackTrace(); } @@ -630,7 +687,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); - flickerDrawable.draw(canvas, AndroidUtilities.rectTmp, 0); + flickerDrawable.draw(canvas, AndroidUtilities.rectTmp, 0, this); invalidate(); return draw; } @@ -660,7 +717,7 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent return webView; } - public void loadFlicker(int currentAccount, long botId) { + public void loadFlickerAndSettingsItem(int currentAccount, long botId, ActionBarMenuSubItem settingsItem) { TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(botId); if (user.username != null && Objects.equals(user.username, DURGER_KING_USERNAME)) { flickerView.setVisibility(VISIBLE); @@ -691,6 +748,10 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent 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); @@ -710,6 +771,12 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent 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); } })); } @@ -733,16 +800,19 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent checkCreateWebView(); isPageLoaded = false; + lastClickMs = 0; hasUserPermissions = false; if (webView != null) { webView.reload(); } } - public void loadUrl(String url) { + public void loadUrl(int currentAccount, String url) { checkCreateWebView(); + this.currentAccount = currentAccount; isPageLoaded = false; + lastClickMs = 0; hasUserPermissions = false; mUrl = url; if (webView != null) { @@ -770,10 +840,17 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent public void destroyWebView() { if (webView != null) { + if (webView.getParent() != null) { + removeView(webView); + } webView.destroy(); } } + public boolean isBackButtonVisible() { + return isBackButtonVisible; + } + @SuppressWarnings("deprecation") public void evaluateJs(String script) { checkCreateWebView(); @@ -808,7 +885,11 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } private void notifyThemeChanged() { - evaluateJs("window.Telegram.WebView.receiveEvent('theme_changed', {theme_params: " + buildThemeParams() + "});"); + notifyEvent("theme_changed", buildThemeParams()); + } + + private void notifyEvent(String event, JSONObject eventData) { + evaluateJs("window.Telegram.WebView.receiveEvent('" + event + "', " + eventData + ");"); } public void setWebViewScrollListener(WebViewScrollListener webViewScrollListener) { @@ -828,6 +909,38 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent delegate.onCloseRequested(null); break; } + case "web_app_set_background_color": { + try { + JSONObject jsonObject = new JSONObject(eventData); + delegate.onWebAppSetBackgroundColor(Color.parseColor(jsonObject.optString("color")) | 0xFF000000); + } catch (JSONException e) { + FileLog.e(e); + } + break; + } + case "web_app_set_header_color": { + try { + JSONObject jsonObject = new JSONObject(eventData); + String key = jsonObject.getString("color_key"); + String themeKey = null; + switch (key) { + case "bg_color": { + themeKey = Theme.key_windowBackgroundWhite; + break; + } + case "secondary_bg_color": { + themeKey = Theme.key_windowBackgroundGray; + break; + } + } + if (themeKey != null) { + delegate.onWebAppSetActionBarColor(themeKey); + } + } catch (JSONException e) { + FileLog.e(e); + } + break; + } case "web_app_data_send": { try { JSONObject jsonData = new JSONObject(eventData); @@ -837,6 +950,140 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } break; } + case "web_app_trigger_haptic_feedback": { + try { + JSONObject jsonData = new JSONObject(eventData); + String type = jsonData.optString("type"); + + BotWebViewVibrationEffect vibrationEffect = null; + switch (type) { + case "impact": { + switch (jsonData.optString("impact_style")) { + case "light": { + vibrationEffect = BotWebViewVibrationEffect.IMPACT_LIGHT; + break; + } + case "medium": { + vibrationEffect = BotWebViewVibrationEffect.IMPACT_MEDIUM; + break; + } + case "heavy": { + vibrationEffect = BotWebViewVibrationEffect.IMPACT_HEAVY; + break; + } + case "rigid": { + vibrationEffect = BotWebViewVibrationEffect.IMPACT_RIGID; + break; + } + case "soft": { + vibrationEffect = BotWebViewVibrationEffect.IMPACT_SOFT; + break; + } + } + break; + } + case "notification": { + switch (jsonData.optString("notification_type")) { + case "error": { + vibrationEffect = BotWebViewVibrationEffect.NOTIFICATION_ERROR; + break; + } + case "success": { + vibrationEffect = BotWebViewVibrationEffect.NOTIFICATION_SUCCESS; + break; + } + case "warning": { + vibrationEffect = BotWebViewVibrationEffect.NOTIFICATION_WARNING; + break; + } + } + break; + } + case "selection_change": { + vibrationEffect = BotWebViewVibrationEffect.SELECTION_CHANGE; + break; + } + } + if (vibrationEffect != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + AndroidUtilities.getVibrator().vibrate(vibrationEffect.getVibrationEffectForOreo()); + } else { + AndroidUtilities.getVibrator().vibrate(vibrationEffect.fallbackTimings, -1); + } + } + } catch (Exception e) { + FileLog.e(e); + } + break; + } + case "web_app_open_link": { + try { + JSONObject jsonData = new JSONObject(eventData); + Uri uri = Uri.parse(jsonData.optString("url")); + if (WHITELISTED_SCHEMES.contains(uri.getScheme())) { + onOpenUri(uri, true); + } + } catch (Exception e) { + FileLog.e(e); + } + break; + } + case "web_app_open_tg_link": { + try { + JSONObject jsonData = new JSONObject(eventData); + String pathFull = jsonData.optString("path_full"); + if (pathFull.startsWith("/")) { + pathFull = pathFull.substring(1); + } + onOpenUri(Uri.parse("https://t.me/" + pathFull)); + } catch (JSONException e) { + FileLog.e(e); + } + break; + } + case "web_app_setup_back_button": { + try { + JSONObject jsonData = new JSONObject(eventData); + boolean newVisible = jsonData.optBoolean("is_visible"); + if (newVisible != isBackButtonVisible) { + isBackButtonVisible = newVisible; + + delegate.onSetBackButtonVisible(isBackButtonVisible); + } + } catch (JSONException e) { + FileLog.e(e); + } + break; + } + case "web_app_open_invoice": { + try { + JSONObject jsonData = new JSONObject(eventData); + String slug = jsonData.optString("slug"); + + if (currentPaymentSlug != null) { + onInvoiceStatusUpdate(slug, "cancelled", true); + break; + } + + currentPaymentSlug = slug; + + TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); + TLRPC.TL_inputInvoiceSlug invoiceSlug = new TLRPC.TL_inputInvoiceSlug(); + invoiceSlug.slug = slug; + req.invoice = invoiceSlug; + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + onInvoiceStatusUpdate(slug, "failed"); + } else { + delegate.onWebAppOpenInvoice(slug, response); + } + })); + } catch (JSONException e) { + FileLog.e(e); + } + break; + } case "web_app_expand": { delegate.onWebAppExpand(); break; @@ -878,19 +1125,20 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent } } - private String buildThemeParams() { + 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 object.toString(); + return new JSONObject().put("theme_params", object); } catch (Exception e) { FileLog.e(e); - return "{}"; + return new JSONObject(); } } @@ -946,16 +1194,43 @@ public class BotWebViewContainer extends FrameLayout implements NotificationCent */ default void onSendWebViewData(String data) {} + /** + * Called when WebView requests to set action bar color + * + * @param colorKey Color theme key + */ + void onWebAppSetActionBarColor(String colorKey); + + /** + * Called when WebView requests to set background color + * + * @param color New color + */ + void onWebAppSetBackgroundColor(int color); + /** * Called when WebView requests to expand viewport */ void onWebAppExpand(); + /** + * Called when web app attempts to open invoice + * + * @param slug Invoice slug for the form + * @param response Payment request response + */ + void onWebAppOpenInvoice(String slug, TLObject response); + /** * Setups main button */ void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible); + /** + * Sets back button enabled and visible + */ + void onSetBackButtonVisible(boolean visible); + /** * Called when WebView is ready (Called web_app_ready or page load finished) */ 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 e7d9e5243..220b4eb15 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewMenuContainer.java @@ -13,6 +13,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.widget.FrameLayout; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; @@ -29,13 +30,16 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; +import java.util.Locale; import java.util.Objects; public class BotWebViewMenuContainer extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -59,6 +63,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification private Paint dimPaint = new Paint(); private Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private Paint actionBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private Paint linePaint = new Paint(); private ChatActivityEnterView parentEnterView; @@ -79,11 +84,18 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification private ActionBarMenuItem botMenuItem; private ActionBar.ActionBarMenuOnItemClick actionBarOnItemClick; + private ActionBarMenuSubItem settingsItem; private Editable savedEditText; private MessageObject savedReplyMessageObject; private MessageObject savedEditMessageObject; + private Runnable globalOnDismissListener; + + private float overrideActionBarBackgroundProgress; + private int overrideActionBarBackground; + private boolean overrideBackgroundColor; + private Runnable pollRunnable = () -> { if (!dismissed) { TLRPC.TL_messages_prolongWebView prolongWebView = new TLRPC.TL_messages_prolongWebView(); @@ -125,6 +137,43 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification dismiss(callback); } + @Override + public void onWebAppSetActionBarColor(String colorKey) { + int from = overrideActionBarBackground; + int to = getColor(colorKey); + + if (from == 0) { + overrideActionBarBackground = to; + } + + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.addUpdateListener(animation -> { + if (from != 0) { + overrideActionBarBackground = ColorUtils.blendARGB(from, to, (float) animation.getAnimatedValue()); + } else { + overrideActionBarBackgroundProgress = (float) animation.getAnimatedValue(); + } + actionBarPaint.setColor(overrideActionBarBackground); + invalidateActionBar(); + }); + animator.start(); + } + + @Override + public void onWebAppSetBackgroundColor(int color) { + overrideBackgroundColor = true; + + int from = backgroundPaint.getColor(); + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.addUpdateListener(animation -> { + backgroundPaint.setColor(ColorUtils.blendARGB(from, color, (Float) animation.getAnimatedValue())); + BotWebViewMenuContainer.this.invalidate(); + }); + animator.start(); + } + @Override public void onWebAppExpand() { if (/* System.currentTimeMillis() - lastSwipeTime <= 1000 || */ swipeContainer.isSwipeInProgress()) { @@ -133,6 +182,11 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY()); } + @Override + public void onWebAppOpenInvoice(String slug, TLObject response) { + Toast.makeText(getContext(), LocaleController.getString("nekoXPaymentRemovedToast", R.string.nekoXPaymentRemovedToast), Toast.LENGTH_LONG).show(); + } + @Override public void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible) { ChatActivityBotWebViewButton botWebViewButton = parentEnterView.getBotWebViewButton(); @@ -142,6 +196,17 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification animateBotButton(isVisible); } } + + @Override + public void onSetBackButtonVisible(boolean visible) { + if (actionBarTransitionProgress == 1f) { + if (visible) { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), actionBar.getBackButtonDrawable()); + } else { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), R.drawable.ic_close_white); + } + } + } }); linePaint.setStyle(Paint.Style.FILL_AND_STROKE); @@ -171,9 +236,6 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification ignoreLayout = false; } - if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { - widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY); - } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec) - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.statusBarHeight + AndroidUtilities.dp(24) - AndroidUtilities.dp(5), MeasureSpec.EXACTLY)); } @@ -196,10 +258,21 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification if (springAnimation != null) { float progress = (1f - Math.min(swipeContainer.getTopActionBarOffsetY(), swipeContainer.getTranslationY() - swipeContainer.getTopActionBarOffsetY()) / swipeContainer.getTopActionBarOffsetY()); + if (BotWebViewMenuContainer.this.getVisibility() != VISIBLE) { + progress = 0; + } float newPos = (progress > 0.5f ? 1 : 0) * 100f; if (springAnimation.getSpring().getFinalPosition() != newPos) { springAnimation.getSpring().setFinalPosition(newPos); springAnimation.start(); + + if (!webViewContainer.isBackButtonVisible()) { + if (newPos == 100f) { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), R.drawable.ic_close_white); + } else { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), actionBar.getBackButtonDrawable()); + } + } } } lastSwipeTime = System.currentTimeMillis(); @@ -209,6 +282,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification swipeContainer.setDelegate(this::dismiss); swipeContainer.setTopActionBarOffsetY(ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight - AndroidUtilities.dp(24)); swipeContainer.setSwipeOffsetAnimationDisallowed(true); + swipeContainer.setIsKeyboardVisible(obj -> parentEnterView.getSizeNotifierLayout().getKeyboardHeight() >= AndroidUtilities.dp(20)); addView(swipeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 24, 0, 0)); addView(progressView = new ChatAttachAlertBotWebViewLayout.WebProgressView(context, parentEnterView.getParentFragment().getResourceProvider()), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 0, 5)); @@ -317,7 +391,9 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification @Override public void onItemClick(int id) { if (id == -1) { - dismiss(); + if (!webViewContainer.onBackPressed()) { + dismiss(); + } } else if (id == R.id.menu_reload_page) { if (webViewContainer.getWebView() != null) { webViewContainer.getWebView().animate().cancel(); @@ -330,8 +406,10 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification progressView.setVisibility(VISIBLE); webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, botId); + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); webViewContainer.reload(); + } else if (id == R.id.menu_settings) { + webViewContainer.onSettingsButtonPressed(); } } }); @@ -373,38 +451,47 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification return; } + boolean doNotScroll = false; + float openOffset = -swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY(); + if (swipeContainer.getSwipeOffsetY() != openOffset) { + swipeContainer.stickTo(openOffset); + doNotScroll = true; + } + int oldh = contentHeight + parentEnterView.getSizeNotifierLayout().measureKeyboardHeight(); setMeasuredDimension(getMeasuredWidth(), contentHeight); ignoreMeasure = true; - if (webViewScrollAnimator != null) { - webViewScrollAnimator.cancel(); - webViewScrollAnimator = null; - } + if (!doNotScroll) { + if (webViewScrollAnimator != null) { + webViewScrollAnimator.cancel(); + webViewScrollAnimator = null; + } - if (webViewContainer.getWebView() != null) { - int fromY = webViewContainer.getWebView().getScrollY(); - int toY = fromY + (oldh - contentHeight); - webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250); - webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); - webViewScrollAnimator.addUpdateListener(animation -> { - int val = (int) animation.getAnimatedValue(); - if (webViewContainer.getWebView() != null) { - webViewContainer.getWebView().setScrollY(val); - } - }); - webViewScrollAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { + if (webViewContainer.getWebView() != null) { + int fromY = webViewContainer.getWebView().getScrollY(); + int toY = fromY + (oldh - contentHeight); + webViewScrollAnimator = ValueAnimator.ofInt(fromY, toY).setDuration(250); + webViewScrollAnimator.setInterpolator(ChatListItemAnimator.DEFAULT_INTERPOLATOR); + webViewScrollAnimator.addUpdateListener(animation -> { + int val = (int) animation.getAnimatedValue(); if (webViewContainer.getWebView() != null) { - webViewContainer.getWebView().setScrollY(toY); + webViewContainer.getWebView().setScrollY(val); } - if (animation == webViewScrollAnimator) { - webViewScrollAnimator = null; + }); + webViewScrollAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (webViewContainer.getWebView() != null) { + webViewContainer.getWebView().setScrollY(toY); + } + if (animation == webViewScrollAnimator) { + webViewScrollAnimator = null; + } } - } - }); - webViewScrollAnimator.start(); + }); + webViewScrollAnimator.start(); + } } } @@ -437,13 +524,21 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification protected void onDraw(Canvas canvas) { super.onDraw(canvas); - backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); + if (!overrideBackgroundColor) { + backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); + } + if (overrideActionBarBackgroundProgress == 0) { + actionBarPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); + } AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); canvas.drawRect(AndroidUtilities.rectTmp, dimPaint); float radius = AndroidUtilities.dp(16) * (1f - actionBarTransitionProgress); - AndroidUtilities.rectTmp.set(0, AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress), getWidth(), getHeight() + radius); - canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, backgroundPaint); + AndroidUtilities.rectTmp.set(0, AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress), getWidth(), swipeContainer.getTranslationY() + AndroidUtilities.dp(24) + radius); + canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, actionBarPaint); + + AndroidUtilities.rectTmp.set(0, swipeContainer.getTranslationY() + AndroidUtilities.dp(24), getWidth(), getHeight() + radius); + canvas.drawRect(AndroidUtilities.rectTmp, backgroundPaint); } @SuppressLint("ClickableViewAccessibility") @@ -460,7 +555,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification public void draw(Canvas canvas) { super.draw(canvas); - linePaint.setColor(getColor(Theme.key_dialogGrayLine)); + linePaint.setColor(getColor(Theme.key_sheet_scrollUp)); linePaint.setAlpha((int) (linePaint.getAlpha() * (1f - Math.min(0.5f, actionBarTransitionProgress) / 0.5f))); canvas.save(); @@ -526,7 +621,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification progressView.setVisibility(VISIBLE); webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, botId); + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView(); req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); @@ -538,6 +633,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification 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)); @@ -558,7 +654,7 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response; queryId = resultUrl.query_id; - webViewContainer.loadUrl(resultUrl.url); + webViewContainer.loadUrl(currentAccount, resultUrl.url); swipeContainer.setWebView(webViewContainer.getWebView()); AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD); @@ -577,6 +673,13 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification return color != null ? color : Theme.getColor(key); } + /** + * Sets global dismiss callback to run every time menu being dismissed + */ + public void setOnDismissGlobalListener(Runnable callback) { + globalOnDismissListener = callback; + } + /** * Dismisses menu */ @@ -597,6 +700,9 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification if (callback != null) { callback.run(); } + if (globalOnDismissListener != null) { + globalOnDismissListener.run(); + } }); } @@ -606,6 +712,9 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification public void onDismiss() { setVisibility(GONE); + overrideActionBarBackground = 0; + overrideActionBarBackgroundProgress = 0; + actionBarPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); webViewContainer.destroyWebView(); swipeContainer.removeView(webViewContainer); @@ -658,6 +767,10 @@ public class BotWebViewMenuContainer extends FrameLayout implements Notification }, delayRestoreText ? 200 : 0); } + public boolean hasSavedText() { + return savedEditText != null || savedReplyMessageObject != null || savedEditMessageObject != null; + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.webViewResultSent) { 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 89036c35b..3addf67c8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotWebViewSheet.java @@ -21,7 +21,9 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; +import android.widget.Toast; +import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; @@ -39,15 +41,32 @@ import org.telegram.messenger.R; import org.telegram.messenger.UserObject; import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; import org.telegram.ui.LaunchActivity; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Locale; + public class BotWebViewSheet extends Dialog implements NotificationCenter.NotificationCenterDelegate { + public final static int TYPE_WEB_VIEW_BUTTON = 0, TYPE_SIMPLE_WEB_VIEW_BUTTON = 1, TYPE_BOT_MENU_BUTTON = 2; + + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = { + TYPE_WEB_VIEW_BUTTON, + TYPE_SIMPLE_WEB_VIEW_BUTTON, + TYPE_BOT_MENU_BUTTON + }) + public @interface WebViewType {} + private final static int POLL_PERIOD = 60000; private final static SimpleFloatPropertyCompat ACTION_BAR_TRANSITION_PROGRESS_VALUE = new SimpleFloatPropertyCompat("actionBarTransitionProgress", obj -> obj.actionBarTransitionProgress, (obj, value) -> { @@ -85,8 +104,14 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi private Paint dimPaint = new Paint(); private Paint backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + private int actionBarColor; + private Paint actionBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private boolean overrideBackgroundColor; + private ActionBar actionBar; private Drawable actionBarShadow; + private ActionBarMenuSubItem settingsItem; private boolean dismissed; @@ -182,7 +207,50 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi sendWebViewData.random_id = Utilities.random.nextLong(); sendWebViewData.button_text = buttonText; sendWebViewData.data = data; - ConnectionsManager.getInstance(currentAccount).sendRequest(sendWebViewData, (response, error) -> AndroidUtilities.runOnUIThread(()-> dismiss())); + ConnectionsManager.getInstance(currentAccount).sendRequest(sendWebViewData, (response, error) -> { + if (response instanceof TLRPC.TL_updates) { + MessagesController.getInstance(currentAccount).processUpdates((TLRPC.TL_updates) response, false); + } + AndroidUtilities.runOnUIThread(BotWebViewSheet.this::dismiss); + }); + } + + @Override + public void onWebAppSetActionBarColor(String colorKey) { + int from = actionBarColor; + int to = getColor(colorKey); + + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.addUpdateListener(animation -> { + actionBarColor = ColorUtils.blendARGB(from, to, (Float) animation.getAnimatedValue()); + frameLayout.invalidate(); + }); + animator.start(); + } + + @Override + public void onWebAppSetBackgroundColor(int color) { + overrideBackgroundColor = true; + + int from = backgroundPaint.getColor(); + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.addUpdateListener(animation -> { + backgroundPaint.setColor(ColorUtils.blendARGB(from, color, (Float) animation.getAnimatedValue())); + frameLayout.invalidate(); + }); + animator.start(); + } + + @Override + public void onSetBackButtonVisible(boolean visible) { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), visible ? R.drawable.ic_ab_back : R.drawable.ic_close_white); + } + + @Override + public void onWebAppOpenInvoice(String slug, TLObject response) { + Toast.makeText(getContext(), LocaleController.getString("nekoXPaymentRemovedToast", R.string.nekoXPaymentRemovedToast), Toast.LENGTH_LONG).show(); } @Override @@ -245,6 +313,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi linePaint.setStrokeCap(Paint.Cap.ROUND); dimPaint.setColor(0x40000000); + actionBarColor = getColor(Theme.key_windowBackgroundWhite); frameLayout = new SizeNotifierFrameLayout(context) { { setWillNotDraw(false); @@ -254,25 +323,33 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi protected void onDraw(Canvas canvas) { super.onDraw(canvas); - backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); + if (!overrideBackgroundColor) { + backgroundPaint.setColor(getColor(Theme.key_windowBackgroundWhite)); + } AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); canvas.drawRect(AndroidUtilities.rectTmp, dimPaint); - float radius = AndroidUtilities.dp(16) * (1f - actionBarTransitionProgress); - AndroidUtilities.rectTmp.set(0, AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress), getWidth(), getHeight() + radius); - canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, backgroundPaint); + actionBarPaint.setColor(ColorUtils.blendARGB(actionBarColor, getColor(Theme.key_windowBackgroundWhite), actionBarTransitionProgress)); + float radius = AndroidUtilities.dp(16) * (AndroidUtilities.isTablet() ? 1f : 1f - actionBarTransitionProgress); + AndroidUtilities.rectTmp.set(swipeContainer.getLeft(), AndroidUtilities.lerp(swipeContainer.getTranslationY(), 0, actionBarTransitionProgress), swipeContainer.getRight(), swipeContainer.getTranslationY() + AndroidUtilities.dp(24) + radius); + canvas.drawRoundRect(AndroidUtilities.rectTmp, radius, radius, actionBarPaint); + + AndroidUtilities.rectTmp.set(swipeContainer.getLeft(), swipeContainer.getTranslationY() + AndroidUtilities.dp(24), swipeContainer.getRight(), getHeight()); + canvas.drawRect(AndroidUtilities.rectTmp, backgroundPaint); } @Override public void draw(Canvas canvas) { super.draw(canvas); - linePaint.setColor(Theme.getColor(Theme.key_dialogGrayLine)); - linePaint.setAlpha((int) (linePaint.getAlpha() * (1f - Math.min(0.5f, actionBarTransitionProgress) / 0.5f))); + float transitionProgress = AndroidUtilities.isTablet() ? 0 : actionBarTransitionProgress; + linePaint.setColor(Theme.getColor(Theme.key_sheet_scrollUp)); + linePaint.setAlpha((int) (linePaint.getAlpha() * (1f - Math.min(0.5f, transitionProgress) / 0.5f))); canvas.save(); - float scale = 1f - actionBarTransitionProgress; - float y = AndroidUtilities.lerp(swipeContainer.getTranslationY(), AndroidUtilities.statusBarHeight + ActionBar.getCurrentActionBarHeight() / 2f, actionBarTransitionProgress) + AndroidUtilities.dp(12); + float scale = 1f - transitionProgress; + float y = AndroidUtilities.isTablet() ? AndroidUtilities.lerp(swipeContainer.getTranslationY() + AndroidUtilities.dp(12), AndroidUtilities.statusBarHeight / 2f, actionBarTransitionProgress) : + (AndroidUtilities.lerp(swipeContainer.getTranslationY(), AndroidUtilities.statusBarHeight + ActionBar.getCurrentActionBarHeight() / 2f, transitionProgress) + AndroidUtilities.dp(12)); canvas.scale(scale, scale, getWidth() / 2f, y); canvas.drawLine(getWidth() / 2f - AndroidUtilities.dp(16), y, getWidth() / 2f + AndroidUtilities.dp(16), y, linePaint); canvas.restore(); @@ -286,7 +363,8 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() <= AndroidUtilities.lerp(swipeContainer.getTranslationY() + AndroidUtilities.dp(24), 0, actionBarTransitionProgress)) { + if (event.getAction() == MotionEvent.ACTION_DOWN && (event.getY() <= AndroidUtilities.lerp(swipeContainer.getTranslationY() + AndroidUtilities.dp(24), 0, actionBarTransitionProgress) || + event.getX() > swipeContainer.getRight() || event.getX() < swipeContainer.getLeft())) { dismiss(); return true; } @@ -298,9 +376,17 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi swipeContainer.stickTo(-swipeContainer.getOffsetY() + swipeContainer.getTopActionBarOffsetY()); } }); - frameLayout.addView(swipeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 0, 24, 0, 0)); + frameLayout.addView(swipeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 24, 0, 0)); - mainButton = new TextView(context); + mainButton = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; mainButton.setVisibility(View.GONE); mainButton.setAlpha(0f); mainButton.setSingleLine(); @@ -310,10 +396,22 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi mainButton.setPadding(padding, 0, padding, 0); mainButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); mainButton.setOnClickListener(v -> webViewContainer.onMainButtonPressed()); - frameLayout.addView(mainButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM)); + frameLayout.addView(mainButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL)); mainButtonAutoAnimator = VerticalPositionAutoAnimator.attach(mainButton); - radialProgressView = new RadialProgressView(context); + radialProgressView = new RadialProgressView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams(); + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + params.rightMargin = (int) (AndroidUtilities.dp(10) + Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.1f); + } else { + params.rightMargin = AndroidUtilities.dp(10); + } + } + }; radialProgressView.setSize(AndroidUtilities.dp(18)); radialProgressView.setAlpha(0f); radialProgressView.setScaleX(0.1f); @@ -324,9 +422,17 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi actionBarShadow = ContextCompat.getDrawable(getContext(), R.drawable.header_shadow).mutate(); - actionBar = new ActionBar(context, resourcesProvider); + actionBar = new ActionBar(context, resourcesProvider) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; actionBar.setBackgroundColor(Color.TRANSPARENT); - actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setBackButtonImage(R.drawable.ic_close_white); updateActionBarColors(); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override @@ -337,9 +443,17 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } }); actionBar.setAlpha(0f); - frameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP)); + frameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); - frameLayout.addView(progressView = new ChatAttachAlertBotWebViewLayout.WebProgressView(context, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 0, 0)); + frameLayout.addView(progressView = new ChatAttachAlertBotWebViewLayout.WebProgressView(context, resourcesProvider) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + widthMeasureSpec = MeasureSpec.makeMeasureSpec((int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f), MeasureSpec.EXACTLY); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 0)); webViewContainer.setWebViewProgressListener(progress -> { progressView.setLoadProgressAnimated(progress); if (progress == 1f) { @@ -382,6 +496,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi swipeContainer.setScrollEndListener(()-> webViewContainer.invalidateViewPortHeight(true)); swipeContainer.setDelegate(this::dismiss); swipeContainer.setTopActionBarOffsetY(ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight - AndroidUtilities.dp(24)); + swipeContainer.setIsKeyboardVisible(obj -> frameLayout.getKeyboardHeight() >= AndroidUtilities.dp(20)); setContentView(frameLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } @@ -402,7 +517,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi private void updateLightStatusBar() { int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true); - boolean lightStatusBar = ColorUtils.calculateLuminance(color) >= 0.9 && actionBarTransitionProgress >= 0.85f; + boolean lightStatusBar = !AndroidUtilities.isTablet() && ColorUtils.calculateLuminance(color) >= 0.9 && actionBarTransitionProgress >= 0.85f; if (wasLightStatusBar != null && wasLightStatusBar == lightStatusBar) { return; @@ -487,7 +602,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } } - public void requestWebView(int currentAccount, long peerId, long botId, String buttonText, String buttonUrl, boolean simple, int replyToMsgId, boolean silent) { + public void requestWebView(int currentAccount, long peerId, long botId, String buttonText, String buttonUrl, @WebViewType int type, int replyToMsgId, boolean silent) { this.currentAccount = currentAccount; this.peerId = peerId; this.botId = botId; @@ -506,7 +621,9 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi @Override public void onItemClick(int id) { if (id == -1) { - dismiss(); + if (!webViewContainer.onBackPressed()) { + dismiss(); + } } else if (id == R.id.menu_open_bot) { Bundle bundle = new Bundle(); bundle.putLong("user_id", botId); @@ -525,8 +642,10 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi progressView.setVisibility(View.VISIBLE); webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, botId); + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); webViewContainer.reload(); + } else if (id == R.id.menu_settings) { + webViewContainer.onSettingsButtonPressed(); } } }); @@ -536,6 +655,7 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi 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)); @@ -548,56 +668,89 @@ public class BotWebViewSheet extends Dialog implements NotificationCenter.Notifi } webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, botId); - if (simple) { - TLRPC.TL_messages_requestSimpleWebView req = new TLRPC.TL_messages_requestSimpleWebView(); - req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); - if (hasThemeParams) { - req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; - req.flags |= 1; - } - req.url = buttonUrl; + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); + switch (type) { + case TYPE_BOT_MENU_BUTTON: { + TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView(); + req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(botId); - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(()->{ - if (response instanceof TLRPC.TL_simpleWebViewResultUrl) { - TLRPC.TL_simpleWebViewResultUrl resultUrl = (TLRPC.TL_simpleWebViewResultUrl) response; - queryId = 0; - webViewContainer.loadUrl(resultUrl.url); - swipeContainer.setWebView(webViewContainer.getWebView()); - } - })); - } else { - TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView(); - req.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId); - req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); - if (buttonUrl != null) { req.url = buttonUrl; req.flags |= 2; - } - if (replyToMsgId != 0) { - req.reply_to_msg_id = replyToMsgId; - req.flags |= 1; - } - - if (hasThemeParams) { - req.theme_params = new TLRPC.TL_dataJSON(); - req.theme_params.data = themeParams; - req.flags |= 4; - } - - ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - if (response instanceof TLRPC.TL_webViewResultUrl) { - TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response; - queryId = resultUrl.query_id; - webViewContainer.loadUrl(resultUrl.url); - swipeContainer.setWebView(webViewContainer.getWebView()); - - AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD); + if (hasThemeParams) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams; + req.flags |= 4; } - })); - NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent); + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_webViewResultUrl) { + TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response; + queryId = resultUrl.query_id; + webViewContainer.loadUrl(currentAccount, resultUrl.url); + swipeContainer.setWebView(webViewContainer.getWebView()); + + AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD); + } + })); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent); + + break; + } + case TYPE_SIMPLE_WEB_VIEW_BUTTON: { + TLRPC.TL_messages_requestSimpleWebView req = new TLRPC.TL_messages_requestSimpleWebView(); + req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); + if (hasThemeParams) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams; + req.flags |= 1; + } + req.url = buttonUrl; + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_simpleWebViewResultUrl) { + TLRPC.TL_simpleWebViewResultUrl resultUrl = (TLRPC.TL_simpleWebViewResultUrl) response; + queryId = 0; + webViewContainer.loadUrl(currentAccount, resultUrl.url); + swipeContainer.setWebView(webViewContainer.getWebView()); + } + })); + break; + } + case TYPE_WEB_VIEW_BUTTON: { + TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView(); + req.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId); + req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); + if (buttonUrl != null) { + req.url = buttonUrl; + req.flags |= 2; + } + + if (replyToMsgId != 0) { + req.reply_to_msg_id = replyToMsgId; + req.flags |= 1; + } + + if (hasThemeParams) { + req.theme_params = new TLRPC.TL_dataJSON(); + req.theme_params.data = themeParams; + req.flags |= 4; + } + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (response instanceof TLRPC.TL_webViewResultUrl) { + TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response; + queryId = resultUrl.query_id; + webViewContainer.loadUrl(currentAccount, resultUrl.url); + swipeContainer.setWebView(webViewContainer.getWebView()); + + AndroidUtilities.runOnUIThread(pollRunnable, POLL_PERIOD); + } + })); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.webViewResultSent); + break; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java new file mode 100644 index 000000000..e4af3851c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BottomSheetWithRecyclerListView.java @@ -0,0 +1,244 @@ +package org.telegram.ui.Components; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.view.MotionEvent; +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.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; + +public abstract class BottomSheetWithRecyclerListView extends BottomSheet { + + protected RecyclerListView recyclerListView; + protected ActionBar actionBar; + boolean wasDrawn; + private int contentHeight; + private BaseFragment baseFragment; + public final boolean hasFixedSize; + protected boolean clipToActionBar; + + public float topPadding = 0.4f; + + public BottomSheetWithRecyclerListView(BaseFragment fragment, boolean needFocus, boolean hasFixedSize) { + super(fragment.getParentActivity(), needFocus); + this.baseFragment = fragment; + this.hasFixedSize = hasFixedSize; + Context context = fragment.getParentActivity(); + Drawable headerShadowDrawable = ContextCompat.getDrawable(context, R.drawable.header_shadow).mutate(); + FrameLayout containerView = new FrameLayout(context) { + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + contentHeight = MeasureSpec.getSize(heightMeasureSpec); + onPreMeasure(widthMeasureSpec, heightMeasureSpec); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (!hasFixedSize) { + RecyclerView.ViewHolder holder = recyclerListView.findViewHolderForAdapterPosition(0); + int top = -AndroidUtilities.dp(16); + if (holder != null) { + top = holder.itemView.getBottom() - AndroidUtilities.dp(16); + } + + float progressToFullView = 1f - (top + AndroidUtilities.dp(16)) / (float) AndroidUtilities.dp(56); + if (progressToFullView < 0) { + progressToFullView = 0; + } + + AndroidUtilities.updateViewVisibilityAnimated(actionBar, progressToFullView != 0f, 1f, wasDrawn); + shadowDrawable.setBounds(0, top, getMeasuredWidth(), getMeasuredHeight()); + shadowDrawable.draw(canvas); + + onPreDraw(canvas, top, progressToFullView); + } + super.dispatchDraw(canvas); + if (actionBar != null && actionBar.getVisibility() == View.VISIBLE && actionBar.getAlpha() != 0) { + headerShadowDrawable.setBounds(0, actionBar.getBottom(), getMeasuredWidth(), actionBar.getBottom() + headerShadowDrawable.getIntrinsicHeight()); + headerShadowDrawable.setAlpha((int) (255 * actionBar.getAlpha())); + headerShadowDrawable.draw(canvas); + } + wasDrawn = true; + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (!hasFixedSize && clipToActionBar && child == recyclerListView) { + canvas.save(); + canvas.clipRect(0, actionBar.getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight()); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + + @Override + public boolean dispatchTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < shadowDrawable.getBounds().top) { + dismiss(); + } + return super.dispatchTouchEvent(event); + } + }; + recyclerListView = new RecyclerListView(context); + recyclerListView.setLayoutManager(new LinearLayoutManager(context)); + + RecyclerListView.SelectionAdapter adapter = createAdapter(); + + if (hasFixedSize) { + recyclerListView.setHasFixedSize(true); + recyclerListView.setAdapter(adapter); + 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(); + } + }); + this.containerView = containerView; + actionBar = new ActionBar(context) { + @Override + public void setAlpha(float alpha) { + if (getAlpha() != alpha) { + super.setAlpha(alpha); + containerView.invalidate(); + } + } + + @Override + public void setTag(Object tag) { + super.setTag(tag); + updateStatusBar(); + } + }; + actionBar.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + actionBar.setTitleColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarActionModeDefaultIcon), false); + + actionBar.setCastShadows(true); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setTitle(getTitle()); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick(){ + @Override + public void onItemClick(int id) { + if (id == -1) { + dismiss(); + } + } + }); + + containerView.addView(recyclerListView); + containerView.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 6, 0, 6, 0)); + + recyclerListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + containerView.invalidate(); + } + }); + } + onViewCreated(containerView); + updateStatusBar(); + } + + protected void onPreMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + } + + protected void onPreDraw(Canvas canvas, int top, float progressToFullView) { + + } + + private boolean isLightStatusBar() { + return ColorUtils.calculateLuminance(Theme.getColor(Theme.key_dialogBackground)) > 0.7f; + } + + public void onViewCreated(FrameLayout containerView) { + + } + + protected abstract CharSequence getTitle(); + + protected abstract RecyclerListView.SelectionAdapter createAdapter(); + + public void notifyDataSetChanged() { + recyclerListView.getAdapter().notifyDataSetChanged(); + } + + @Override + protected boolean canDismissWithSwipe() { + return false; + } + + private void updateStatusBar() { + if (actionBar != null && actionBar.getTag() != null) { + AndroidUtilities.setLightStatusBar(getWindow(), isLightStatusBar()); + } else if (baseFragment != null) { + AndroidUtilities.setLightStatusBar(getWindow(), baseFragment.isLightStatusBar()); + } + } + +} 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 cf0f164bd..72ec20cdc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -16,6 +16,7 @@ import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; +import android.text.method.LinkMovementMethod; import android.util.Property; import android.util.TypedValue; import android.view.GestureDetector; @@ -63,8 +64,10 @@ public class Bulletin { public static final int TYPE_BIO_CHANGED = 2; public static final int TYPE_NAME_CHANGED = 3; public static final int TYPE_ERROR_SUBTITLE = 4; + public static final int TYPE_APP_ICON = 5; public int tag; + public int hash; public static Bulletin make(@NonNull ViewGroup containerLayout, @NonNull Layout contentLayout, int duration) { return new Bulletin(containerLayout, contentLayout, duration); @@ -156,6 +159,11 @@ public class Bulletin { if (!showing && containerLayout != null) { showing = true; + CharSequence text = layout.getAccessibilityText(); + if (text != null) { + AndroidUtilities.makeAccessibilityAnnouncement(text); + } + if (layout.getParent() != parentLayout) { throw new IllegalStateException("Layout has incorrect parent"); } @@ -600,6 +608,10 @@ public class Bulletin { } } + protected CharSequence getAccessibilityText() { + return null; + } + public Bulletin getBulletin() { return bulletin; } @@ -932,6 +944,10 @@ public class Bulletin { addView(textView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 56, 0, 16, 0)); } + public CharSequence getAccessibilityText() { + return textView.getText(); + } + @Override protected void onShow() { super.onShow(); @@ -962,6 +978,10 @@ public class Bulletin { super.onShow(); AndroidUtilities.makeAccessibilityAnnouncement(textView.getText()); } + + public CharSequence getAccessibilityText() { + return textView.getText(); + } } @SuppressLint("ViewConstructor") @@ -992,6 +1012,8 @@ public class Bulletin { subtitleTextView = new TextView(context); subtitleTextView.setMaxLines(2); subtitleTextView.setTextColor(undoInfoColor); + subtitleTextView.setLinkTextColor(getThemedColor(Theme.key_undo_cancelColor)); + subtitleTextView.setMovementMethod(new LinkMovementMethod()); subtitleTextView.setTypeface(Typeface.SANS_SERIF); subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); linearLayout.addView(subtitleTextView); @@ -1002,6 +1024,9 @@ public class Bulletin { super.onShow(); AndroidUtilities.makeAccessibilityAnnouncement(titleTextView.getText() + ". " + subtitleTextView.getText()); } + public CharSequence getAccessibilityText() { + return titleTextView.getText() + ".\n" + subtitleTextView.getText(); + } } public static class TwoLineLottieLayout extends ButtonLayout { @@ -1060,6 +1085,10 @@ public class Bulletin { imageView.setLayerColor(layer + ".**", textColor); } } + + public CharSequence getAccessibilityText() { + return titleTextView.getText() + ".\n" + subtitleTextView.getText(); + } } public static class LottieLayout extends ButtonLayout { @@ -1120,6 +1149,10 @@ public class Bulletin { public void setIconPaddingBottom(int paddingBottom) { imageView.setLayoutParams(LayoutHelper.createFrameRelatively(56, 48 - paddingBottom, Gravity.START | Gravity.CENTER_VERTICAL, 0, 0, 0, paddingBottom)); } + + public CharSequence getAccessibilityText() { + return textView.getText(); + } } //endregion @@ -1172,6 +1205,7 @@ public class Bulletin { private Runnable delayedAction; private Bulletin bulletin; + private TextView undoTextView; private boolean isUndone; public UndoButton(@NonNull Context context, boolean text) { @@ -1185,7 +1219,7 @@ public class Bulletin { final int undoCancelColor = getThemedColor(Theme.key_undo_cancelColor); if (text) { - TextView undoTextView = new TextView(context); + undoTextView = new TextView(context); undoTextView.setOnClickListener(v -> undo()); final int leftInset = LocaleController.isRTL ? AndroidUtilities.dp(16) : 0; final int rightInset = LocaleController.isRTL ? 0 : AndroidUtilities.dp(16); @@ -1208,6 +1242,13 @@ public class Bulletin { } } + public UndoButton setText(CharSequence text) { + if (undoTextView != null) { + undoTextView.setText(text); + } + return this; + } + public void undo() { if (bulletin != null) { isUndone = true; 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 e2a22fae8..d256d1d52 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BulletinFactory.java @@ -1,20 +1,33 @@ package org.telegram.ui.Components; +import android.app.DownloadManager; import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.view.HapticFeedbackConstants; import android.view.ViewGroup; import android.os.Build; import android.widget.FrameLayout; import androidx.annotation.CheckResult; +import androidx.core.content.FileProvider; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.DialogObject; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import java.io.File; + public final class BulletinFactory { public static BulletinFactory of(BaseFragment fragment) { @@ -208,6 +221,11 @@ public final class BulletinFactory { @CheckResult public Bulletin createCopyBulletin(String message) { + return createCopyBulletin(message, null); + } + + @CheckResult + public Bulletin createCopyBulletin(String message, Theme.ResourcesProvider resourcesProvider) { if (!AndroidUtilities.shouldShowClipboardToast()) { return new Bulletin.EmptyBulletin(); } @@ -236,6 +254,17 @@ public final class BulletinFactory { } } + @CheckResult + public Bulletin createCopyLinkBulletin(String text, Theme.ResourcesProvider resourcesProvider) { + if (!AndroidUtilities.shouldShowClipboardToast()) { + return new Bulletin.EmptyBulletin(); + } + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(getContext(), resourcesProvider); + layout.setAnimation(R.raw.voip_invite, 36, 36, "Wibe", "Circle"); + layout.textView.setText(text); + return create(layout, Bulletin.DURATION_SHORT); + } + private Bulletin create(Bulletin.Layout layout, int duration) { if (fragment != null) { return Bulletin.make(fragment, layout, duration); @@ -355,7 +384,7 @@ public final class BulletinFactory { @CheckResult public static Bulletin createPromoteToAdminBulletin(BaseFragment fragment, String userFirstName) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), null); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); layout.setAnimation(R.raw.ic_admin, "Shield"); layout.textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("UserSetAsAdminHint", R.string.UserSetAsAdminHint, userFirstName))); return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); @@ -363,15 +392,65 @@ public final class BulletinFactory { @CheckResult public static Bulletin createAddedAsAdminBulletin(BaseFragment fragment, String userFirstName) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), null); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); layout.setAnimation(R.raw.ic_admin, "Shield"); layout.textView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("UserAddedAsAdminHint", R.string.UserAddedAsAdminHint, userFirstName))); return Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT); } + @CheckResult + public static Bulletin createForwardedBulletin(Context context, FrameLayout containerLayout, int dialogsCount, long did, int messagesCount, int backgroundColor, int textColor) { + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(context, null, backgroundColor, textColor); + CharSequence text; + int hapticDelay = -1; + if (dialogsCount <= 1) { + if (did == UserConfig.getInstance(UserConfig.selectedAccount).clientUserId) { + if (messagesCount <= 1) { + text = AndroidUtilities.replaceTags(LocaleController.getString("FwdMessageToSavedMessages", R.string.FwdMessageToSavedMessages)); + } else { + text = AndroidUtilities.replaceTags(LocaleController.getString("FwdMessagesToSavedMessages", R.string.FwdMessagesToSavedMessages)); + } + layout.setAnimation(R.raw.saved_messages, 30, 30); + } else { + if (DialogObject.isChatDialog(did)) { + TLRPC.Chat chat = MessagesController.getInstance(UserConfig.selectedAccount).getChat(-did); + if (messagesCount <= 1) { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessageToGroup", R.string.FwdMessageToGroup, chat.title)); + } else { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessagesToGroup", R.string.FwdMessagesToGroup, chat.title)); + } + } else { + TLRPC.User user = MessagesController.getInstance(UserConfig.selectedAccount).getUser(did); + if (messagesCount <= 1) { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessageToUser", R.string.FwdMessageToUser, UserObject.getFirstName(user))); + } else { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessagesToUser", R.string.FwdMessagesToUser, UserObject.getFirstName(user))); + } + } + layout.setAnimation(R.raw.forward, 30, 30); + hapticDelay = 300; + } + } else { + if (messagesCount <= 1) { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessageToChats", R.string.FwdMessageToChats, LocaleController.formatPluralString("Chats", dialogsCount))); + } else { + text = AndroidUtilities.replaceTags(LocaleController.formatString("FwdMessagesToChats", R.string.FwdMessagesToChats, LocaleController.formatPluralString("Chats", dialogsCount))); + } + layout.setAnimation(R.raw.forward, 30, 30); + hapticDelay = 300; + } + layout.textView.setText(text); + if (hapticDelay > 0) { + layout.postDelayed(() -> { + layout.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + }, hapticDelay); + } + return Bulletin.make(containerLayout, layout, Bulletin.DURATION_SHORT); + } + @CheckResult public static Bulletin createRemoveFromChatBulletin(BaseFragment fragment, TLRPC.User user, String chatName) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), null); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); layout.setAnimation(R.raw.ic_ban, "Hand"); String name; if (user.deleted) { @@ -385,7 +464,7 @@ public final class BulletinFactory { @CheckResult public static Bulletin createBanBulletin(BaseFragment fragment, boolean banned) { - final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), null); + final Bulletin.LottieLayout layout = new Bulletin.LottieLayout(fragment.getParentActivity(), fragment.getResourceProvider()); final String text; if (banned) { layout.setAnimation(R.raw.ic_ban, "Hand"); 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 7ae699863..5e2ae91a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -143,6 +143,7 @@ import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.BasePermissionsActivity; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.ContentPreviewViewer; import org.telegram.ui.DialogsActivity; import org.telegram.ui.GroupStickersActivity; import org.telegram.ui.LaunchActivity; @@ -292,6 +293,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private final static int RECORD_STATE_CANCEL_BY_TIME = 4; private final static int RECORD_STATE_CANCEL_BY_GESTURE = 5; + private final static int POPUP_CONTENT_BOT_KEYBOARD = 1; private int currentAccount = UserConfig.selectedAccount; private AccountInstance accountInstance = AccountInstance.getInstance(UserConfig.selectedAccount); @@ -332,6 +334,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private ValueAnimator searchAnimator; private float searchToOpenProgress; + private float chatSearchExpandOffset; private HashMap animationParamsX = new HashMap<>(); @@ -691,7 +694,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } if (!recordingAudioVideo) { recordingAudioVideo = true; - updateRecordIntefrace(RECORD_STATE_ENTER); + updateRecordInterface(RECORD_STATE_ENTER); recordCircle.showWaves(false, false); recordTimerView.reset(); } @@ -707,7 +710,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific startedDraggingX = -1; MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid); recordingAudioVideo = true; - updateRecordIntefrace(RECORD_STATE_ENTER); + updateRecordInterface(RECORD_STATE_ENTER); recordTimerView.start(); recordDot.enterAnimation = false; audioVideoButtonContainer.getParent().requestDisallowInterceptTouchEvent(true); @@ -1685,6 +1688,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific super(host); } + private int[] coords = new int[2]; @Override protected int getVirtualViewAt(float x, float y) { @@ -1693,6 +1697,15 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return 1; } else if (pauseRect.contains(x, y)) { return 2; + } else if (slideText != null && slideText.cancelRect != null) { + AndroidUtilities.rectTmp.set(slideText.cancelRect); + slideText.getLocationOnScreen(coords); + AndroidUtilities.rectTmp.offset(coords[0], coords[1]); + recordCircle.getLocationOnScreen(coords); + AndroidUtilities.rectTmp.offset(-coords[0], -coords[1]); + if (AndroidUtilities.rectTmp.contains(x, y)) { + return 3; + } } } return HOST_ID; @@ -1703,6 +1716,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (isSendButtonVisible()) { list.add(1); list.add(2); + list.add(3); } } @@ -1715,6 +1729,16 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific rect.set((int) pauseRect.left, (int) pauseRect.top, (int) pauseRect.right, (int) pauseRect.bottom); info.setBoundsInParent(rect); info.setText(LocaleController.getString("Stop", R.string.Stop)); + } else if (id == 3) { + if (slideText != null && slideText.cancelRect != null) { + AndroidUtilities.rectTmp2.set(slideText.cancelRect); + slideText.getLocationOnScreen(coords); + AndroidUtilities.rectTmp2.offset(coords[0], coords[1]); + recordCircle.getLocationOnScreen(coords); + AndroidUtilities.rectTmp2.offset(-coords[0], -coords[1]); + info.setBoundsInParent(AndroidUtilities.rectTmp2); + } + info.setText(LocaleController.getString("Cancel", R.string.Cancel)); } } @@ -1948,12 +1972,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return false; } if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) { - boolean rez = false; if (searchingType != 0) { setSearchingTypeInternal(0, false); emojiView.closeSearch(false); requestFocus(); - rez = true; } showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0); if (stickersExpanded) { @@ -1966,7 +1988,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } else { openKeyboardInternal(); } - return rez; + return true; } try { return super.onTouchEvent(event); @@ -2167,19 +2189,28 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageEditText.setBackgroundDrawable(null); messageEditText.setTextColor(getThemedColor(Theme.key_chat_messagePanelText)); messageEditText.setLinkTextColor(getThemedColor(Theme.key_chat_messageLinkOut)); + messageEditText.setHighlightColor(getThemedColor(Theme.key_chat_inTextSelectionHighlight)); messageEditText.setHintColor(getThemedColor(Theme.key_chat_messagePanelHint)); messageEditText.setHintTextColor(getThemedColor(Theme.key_chat_messagePanelHint)); messageEditText.setCursorColor(getThemedColor(Theme.key_chat_messagePanelCursor)); + messageEditText.setHandlesColor(getThemedColor(Theme.key_chat_TextSelectionCursor)); frameLayout.addView(messageEditText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 52, 0, isChat ? 50 : 2, 0)); messageEditText.setOnKeyListener(new OnKeyListener() { boolean ctrlPressed = false; @Override - public boolean onKey(View view, int i, KeyEvent keyEvent) { - if (i == KeyEvent.KEYCODE_BACK && !keyboardVisible && isPopupShowing()) { + public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { + if (keyCode == KeyEvent.KEYCODE_BACK && !keyboardVisible && isPopupShowing() && keyEvent.getAction() == KeyEvent.ACTION_UP) { + if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().closeWithMenu(); + return true; + } + if (currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD && botButtonsMessageObject != null) { + return false; + } if (keyEvent.getAction() == 1) { - if (currentPopupContentType == 1 && botButtonsMessageObject != null) { + if (currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD && botButtonsMessageObject != null) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).apply(); } @@ -2194,16 +2225,20 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific setStickersExpanded(false, true, false); } else { if (stickersExpansionAnim == null) { - showPopup(0, 0); + if (botButtonsMessageObject != null && currentPopupContentType != POPUP_CONTENT_BOT_KEYBOARD && TextUtils.isEmpty(messageEditText.getText())) { + showPopup(1, POPUP_CONTENT_BOT_KEYBOARD); + } else { + showPopup(0, 0); + } } } } } return true; - } else if (i == KeyEvent.KEYCODE_ENTER && (ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && editingMessageObject == null) { + } else if (keyCode == KeyEvent.KEYCODE_ENTER && (ctrlPressed || sendByEnter) && keyEvent.getAction() == KeyEvent.ACTION_DOWN && editingMessageObject == null) { sendMessage(); return true; - } else if (i == KeyEvent.KEYCODE_CTRL_LEFT || i == KeyEvent.KEYCODE_CTRL_RIGHT) { + } else if (keyCode == KeyEvent.KEYCODE_CTRL_LEFT || keyCode == KeyEvent.KEYCODE_CTRL_RIGHT) { ctrlPressed = keyEvent.getAction() == KeyEvent.ACTION_DOWN; return true; } @@ -2491,6 +2526,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific }; sizeNotifierLayout.addView(botWebViewMenuContainer, 15, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM)); botWebViewMenuContainer.setVisibility(GONE); + botWebViewMenuContainer.setOnDismissGlobalListener(()->{ + if (botButtonsMessageObject != null && TextUtils.isEmpty(messageEditText.getText()) && !botWebViewMenuContainer.hasSavedText()) { + showPopup(1, POPUP_CONTENT_BOT_KEYBOARD); + } + }); botButton = new ImageView(context); botButton.setImageDrawable(botButtonDrawable = new ReplaceableIconDrawable(context)); @@ -2501,6 +2541,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific botButton.setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector))); } botButton.setVisibility(GONE); + AndroidUtilities.updateViewVisibilityAnimated(botButton, false, 0.1f, false); attachLayout.addView(botButton, LayoutHelper.createLinear(48, 48)); botButton.setOnClickListener(v -> { if (hasBotWebView() && botCommandsMenuIsShowing()) { @@ -2513,16 +2554,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageEditText.requestFocus(); } if (botReplyMarkup != null) { - if (!isPopupShowing() || currentPopupContentType != 1) { - showPopup(1, 1); - SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); - preferences1.edit().remove("hidekeyboard_" + dialog_id).apply(); - } else { - if (botButtonsMessageObject != null) { - SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount); - preferences1.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); - } - openKeyboardInternal(); + if (!isPopupShowing() || currentPopupContentType != POPUP_CONTENT_BOT_KEYBOARD) { + showPopup(1, POPUP_CONTENT_BOT_KEYBOARD); } } else if (hasBotCommands) { setFieldText("/"); @@ -3022,6 +3055,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific recordTimeContainer = new LinearLayout(context); recordTimeContainer.setOrientation(LinearLayout.HORIZONTAL); recordTimeContainer.setPadding(AndroidUtilities.dp(13), 0, 0, 0); + recordTimeContainer.setFocusable(false); recordPanel.addView(recordTimeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_VERTICAL)); recordDot = new RecordDot(context); @@ -3047,6 +3081,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific audioVideoButtonContainer.setSoundEffectsEnabled(false); sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48)); if (NekoConfig.useChatAttachMediaMenu.Bool()) { + audioVideoButtonContainer.setFocusable(true); + audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); audioVideoButtonContainer.setOnClickListener(v -> { if (recordCircle.isSendButtonVisible()) { if (!hasRecordVideo || calledRecordRunnable) { @@ -3061,7 +3097,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific delegate.needStartRecordAudio(0); } recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_SENDING); + updateRecordInterface(RECORD_STATE_SENDING); } return; @@ -3087,7 +3123,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageTransitionIsRunning = false; AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { moveToSendStateRunnable = null; - updateRecordIntefrace(RECORD_STATE_SENDING); + updateRecordInterface(RECORD_STATE_SENDING); }, 200); } return false; @@ -3106,6 +3142,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } else { recordAudioVideoRunnable.run(); } + return true; } else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) { if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL && recordingAudioVideo) { if (recordCircle.slideToCancelProgress < 0.7f) { @@ -3117,7 +3154,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_CANCEL_BY_GESTURE); + updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); } else { recordCircle.sendButtonVisible = true; startLockTransition(); @@ -3143,7 +3180,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_CANCEL_BY_GESTURE); + updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); } else { if (recordAudioVideoRunnableStarted) { AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); @@ -3176,11 +3213,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific messageTransitionIsRunning = false; AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { moveToSendStateRunnable = null; - updateRecordIntefrace(RECORD_STATE_SENDING); + updateRecordInterface(RECORD_STATE_SENDING); }, 500); } } - } + }return true; } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) { float x = motionEvent.getX(); float y = motionEvent.getY(); @@ -3224,15 +3261,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_CANCEL_BY_GESTURE); - } + updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); + }return true; } view.onTouchEvent(motionEvent); return true; }); } - audioSendButton = new ImageView(context); audioSendButton.setScaleType(ImageView.ScaleType.CENTER_INSIDE); audioSendButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); @@ -3247,6 +3283,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } audioSendButton.setFocusable(true); + audioSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); audioSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); audioVideoButtonContainer.addView(audioSendButton, LayoutHelper.createFrame(48, 48)); @@ -3258,6 +3295,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific videoSendButton.setPadding(0, 0, AndroidUtilities.dp(4), 0); videoSendButton.setContentDescription(LocaleController.getString("AccDescrVideoMessage", R.string.AccDescrVideoMessage)); videoSendButton.setFocusable(true); + videoSendButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); videoSendButton.setAccessibilityDelegate(mediaMessageButtonsDelegate); audioVideoButtonContainer.addView(videoSendButton, LayoutHelper.createFrame(48, 48)); } @@ -3534,7 +3572,16 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private void openWebViewMenu() { Runnable onRequestWebView = () -> { AndroidUtilities.hideKeyboard(this); - botWebViewMenuContainer.show(currentAccount, dialog_id, botMenuWebViewUrl); + if (AndroidUtilities.isTablet()) { + 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(); + + botCommandsMenuButton.setOpened(false); + } else { + botWebViewMenuContainer.show(currentAccount, dialog_id, botMenuWebViewUrl); + } }; if (SharedPrefsHelper.isWebViewConfirmShown(currentAccount, dialog_id)) { @@ -3585,8 +3632,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific private void checkBotMenu() { if (botCommandsMenuButton != null) { + boolean wasExpanded = botCommandsMenuButton.expanded; botCommandsMenuButton.setExpanded(TextUtils.isEmpty(messageEditText.getText()) && !(keyboardVisible || waitingForKeyboardOpen || isPopupShowing()), true); - beginDelayedTransition(); + if (wasExpanded != botCommandsMenuButton.expanded) { + beginDelayedTransition(); + } } } @@ -3643,7 +3693,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (clip) { canvas.save(); if (child == textFieldContainer) { - int top = animatedTop + AndroidUtilities.dp(2); + int top = (int) (animatedTop + AndroidUtilities.dp(2) + chatSearchExpandOffset); if (topView != null && topView.getVisibility() == View.VISIBLE) { top += topView.getHeight(); } @@ -3674,6 +3724,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific Theme.chat_composeShadowDrawable.setAlpha((int) (composeShadowAlpha * 0xFF)); Theme.chat_composeShadowDrawable.setBounds(0, top, getMeasuredWidth(), bottom); Theme.chat_composeShadowDrawable.draw(canvas); + bottom += chatSearchExpandOffset; if (allowBlur) { backgroundPaint.setColor(getThemedColor(Theme.key_chat_messagePanelBackground)); if (SharedConfig.chatBlurEnabled() && sizeNotifierLayout != null) { @@ -3996,7 +4047,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific sendPopupWindow.dismiss(); } }); - sendPopupLayout.setShownFromBotton(false); + sendPopupLayout.setShownFromBottom(false); boolean scheduleButtonValue = parentFragment != null && parentFragment.canScheduleMessage(); boolean sendWithoutSoundButtonValue = !(self || slowModeTimer > 0 && !isInScheduleMode()); @@ -4045,7 +4096,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); sendPopupWindow.getContentView().setFocusableInTouchMode(true); - SharedConfig.removeScheduledOrNoSuoundHint(); + SharedConfig.removeScheduledOrNoSoundHint(); if (delegate != null) { delegate.onSendLongClick(); @@ -4358,7 +4409,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_CANCEL); + updateRecordInterface(RECORD_STATE_CANCEL); } public void showContextProgress(boolean show) { @@ -4496,6 +4547,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific topView.setTranslationY(animatedTop + (1f - v) * topView.getLayoutParams().height); topLineView.setAlpha(v); topLineView.setTranslationY(animatedTop); + if (parentFragment != null && parentFragment.mentionContainer != null) { + parentFragment.mentionContainer.setTranslationY((1f - v) * topView.getLayoutParams().height); + } } }; @@ -4542,6 +4596,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific currentTopViewAnimation = null; } NotificationCenter.getInstance(currentAccount).onAnimationFinish(notificationsIndex); + if (parentFragment != null && parentFragment.mentionContainer != null) { + parentFragment.mentionContainer.setTranslationY(0); + } } }); currentTopViewAnimation.setDuration(ChatListItemAnimator.DEFAULT_DURATION + 20); @@ -4666,6 +4723,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific resizeForTopView(false); currentTopViewAnimation = null; } + if (parentFragment != null && parentFragment.mentionContainer != null) { + parentFragment.mentionContainer.setTranslationY(0); + } } @Override @@ -4932,7 +4992,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific updateScheduleButton(false); checkRoundVideo(); updateFieldHint(false); - updateSendAsButton(); + updateSendAsButton(false); } public void setChatInfo(TLRPC.ChatFull chatInfo) { @@ -6327,7 +6387,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return moveToSendStateRunnable != null; } - private void updateRecordIntefrace(int recordState) { + private void updateRecordInterface(int recordState) { if (moveToSendStateRunnable != null) { AndroidUtilities.cancelRunOnUIThread(moveToSendStateRunnable); moveToSendStateRunnable = null; @@ -7240,6 +7300,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific scheduledButton.setVisibility(VISIBLE); } messageEditText.setText(draftMessage); + draftMessage = null; messageWebPageSearch = draftSearchWebpage; messageEditText.setSelection(messageEditText.length()); if (getVisibility() == VISIBLE) { @@ -7248,8 +7309,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific checkAttachButton(false, 0); updateFieldRight(1); } - updateFieldHint(false); - updateSendAsButton(); + updateFieldHint(true); + updateSendAsButton(true); } public ImageView getAttachButton() { @@ -7545,6 +7606,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } public void updateSendAsButton() { + updateSendAsButton(true); + } + + public void updateSendAsButton(boolean animated) { if (parentFragment == null || delegate == null) { return; } @@ -7581,7 +7646,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific senderSelectView.setTag(null); } - if (parentFragment.getOtherSameChatsDiff() == 0 && parentFragment.fragmentOpened) { + if (parentFragment.getOtherSameChatsDiff() == 0 && parentFragment.fragmentOpened && animated) { ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(150); senderSelectView.setTranslationX(startX); messageEditText.setTranslationX(senderSelectView.getTranslationX()); @@ -7646,10 +7711,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } else { senderSelectView.setVisibility(isVisible ? VISIBLE : GONE); senderSelectView.setTranslationX(endX); + float translationX = isVisible ? endX : 0; for (ImageView emoji : emojiButton) { - emoji.setTranslationX(endX); + emoji.setTranslationX(translationX); } - messageEditText.setTranslationX(endX); + messageEditText.setTranslationX(translationX); senderSelectView.setAlpha(endAlpha); senderSelectView.setTag(null); } @@ -7673,21 +7739,19 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } boolean hasBotWebView = hasBotWebView(); boolean canShowBotsMenu = botMenuButtonType != BotMenuButtonType.NO_BUTTON && dialog_id > 0; -// if (canShowBotsMenu && ) { -// TLRPC.Chat chat = accountInstance.getMessagesController().getChat(-dialog_id); -// canShowBotsMenu = chat == null || !chat.megagroup; -// } - + boolean wasVisible = botButton.getVisibility() == VISIBLE; if (hasBotWebView || hasBotCommands || botReplyMarkup != null) { if (botReplyMarkup != null) { - if (botButton.getVisibility() != VISIBLE) { - botButton.setVisibility(VISIBLE); - } - if (isPopupShowing() && currentPopupContentType == 1) { - botButtonDrawable.setIcon(R.drawable.baseline_keyboard_24, true); - botButton.setContentDescription(LocaleController.getString("AccDescrShowKeyboard", R.string.AccDescrShowKeyboard)); + if (isPopupShowing() && currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD) { + if (botButton.getVisibility() != GONE) { + botButton.setVisibility(GONE); + } } else { - botButtonDrawable.setIcon(R.drawable.deproko_baseline_bots_24, true); + if (botButton.getVisibility() != VISIBLE) { + botButton.setVisibility(VISIBLE); + } + + botButtonDrawable.setIcon(R.drawable.input_bot2, true); botButton.setContentDescription(LocaleController.getString("AccDescrBotKeyboard", R.string.AccDescrBotKeyboard)); } } else { @@ -7702,11 +7766,28 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } else { botButton.setVisibility(GONE); } + boolean wasWebView = botCommandsMenuButton.isWebView; botCommandsMenuButton.setWebView(botMenuButtonType == BotMenuButtonType.WEB_VIEW); - botCommandsMenuButton.setMenuText(botMenuButtonType == BotMenuButtonType.COMMANDS ? LocaleController.getString(R.string.BotsMenuTitle) : botMenuWebViewTitle); + boolean textChanged = botCommandsMenuButton.setMenuText(botMenuButtonType == BotMenuButtonType.COMMANDS ? LocaleController.getString(R.string.BotsMenuTitle) : botMenuWebViewTitle); AndroidUtilities.updateViewVisibilityAnimated(botCommandsMenuButton, canShowBotsMenu, 0.5f, animated); - if (animated) { + boolean changed = (botButton.getVisibility() == VISIBLE) != wasVisible || textChanged || wasWebView != botCommandsMenuButton.isWebView; + if (changed && animated) { beginDelayedTransition(); + + boolean show = botButton.getVisibility() == VISIBLE; + if (show != wasVisible) { + botButton.setVisibility(VISIBLE); + if (show) { + botButton.setAlpha(0f); + botButton.setScaleX(0.1f); + botButton.setScaleY(0.1f); + } else if (!show) { + botButton.setAlpha(1f); + botButton.setScaleX(1f); + botButton.setScaleY(1f); + } + AndroidUtilities.updateViewVisibilityAnimated(botButton, show, 0.1f, true); + } } updateFieldRight(2); attachLayout.setPivotX(AndroidUtilities.dp((botButton == null || botButton.getVisibility() == GONE) && (notifyButton == null || notifyButton.getVisibility() == GONE) ? 48 : 96)); @@ -7823,19 +7904,18 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (botReplyMarkup != null) { SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); - boolean keyboardHidden = preferences.getInt("hidekeyboard_" + dialog_id, 0) == messageObject.getId(); boolean showPopup = true; if (botButtonsMessageObject != replyingMessageObject && botReplyMarkup.single_use) { if (preferences.getInt("answered_" + dialog_id, 0) == messageObject.getId()) { showPopup = false; } } - if (showPopup && !keyboardHidden && messageEditText.length() == 0 && !isPopupShowing()) { + if (showPopup && messageEditText.length() == 0 && !isPopupShowing()) { showPopup(1, 1); } botKeyboardView.setButtons(botReplyMarkup); } else { - if (isPopupShowing() && currentPopupContentType == 1) { + if (isPopupShowing() && currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD) { if (openKeyboard) { clearBotButtonsOnKeyboardOpen = true; openKeyboardInternal(); @@ -7874,7 +7954,7 @@ 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, replyMessageObject != null ? replyMessageObject.messageOwner.id : 0, false); + 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(); } }; @@ -8091,7 +8171,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (gif instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) gif; SendMessagesHelper.getInstance(currentAccount).sendSticker(document, query, dialog_id, replyingMessageObject, getThreadMessage(), parent, null, notify, scheduleDate); - MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000), true); if (DialogObject.isEncryptedDialog(dialog_id)) { accountInstance.getMessagesController().saveGif(parent, document); } @@ -8099,7 +8179,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific TLRPC.BotInlineResult result = (TLRPC.BotInlineResult) gif; if (result.document != null) { - MediaDataController.getInstance(currentAccount).addRecentGif(result.document, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(result.document, (int) (System.currentTimeMillis() / 1000), false); if (DialogObject.isEncryptedDialog(dialog_id)) { accountInstance.getMessagesController().saveGif(parent, result.document); } @@ -8391,6 +8471,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } private void showPopup(int show, int contentType) { + showPopup(show, contentType, true); + } + + private void showPopup(int show, int contentType, boolean allowAnimation) { if (show == 2) { return; } @@ -8405,7 +8489,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific View currentView = null; boolean anotherPanelWasVisible = false; boolean samePannelWasVisible = false; - int previusHeight = 0; + int previousHeight = 0; if (contentType == 0) { if (emojiView.getParent() == null) { sizeNotifierLayout.addView(emojiView, sizeNotifierLayout.getChildCount() - 5); @@ -8417,12 +8501,12 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific botKeyboardView.setVisibility(GONE); botKeyboardViewVisible = false; anotherPanelWasVisible = true; - previusHeight = botKeyboardView.getMeasuredHeight(); + previousHeight = botKeyboardView.getMeasuredHeight(); } emojiView.setShowing(true); currentView = emojiView; animatingContentType = 0; - } else if (contentType == 1) { + } else if (contentType == POPUP_CONTENT_BOT_KEYBOARD) { samePannelWasVisible = botKeyboardViewVisible && botKeyboardView.getVisibility() == View.VISIBLE; botKeyboardViewVisible = true; if (emojiView != null && emojiView.getVisibility() != GONE) { @@ -8431,11 +8515,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific emojiView.setShowing(false); emojiViewVisible = false; anotherPanelWasVisible = true; - previusHeight = emojiView.getMeasuredHeight(); + previousHeight = emojiView.getMeasuredHeight(); } botKeyboardView.setVisibility(VISIBLE); currentView = botKeyboardView; - animatingContentType = 1; + animatingContentType = POPUP_CONTENT_BOT_KEYBOARD; } currentPopupContentType = contentType; @@ -8449,7 +8533,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific /*if (!samePannelWasVisible && !anotherPanelWasVisible) { currentHeight = 0; } else */ - if (contentType == 1) { + if (contentType == POPUP_CONTENT_BOT_KEYBOARD) { currentHeight = Math.min(botKeyboardView.getKeyboardHeight(), currentHeight); } if (botKeyboardView != null) { @@ -8467,10 +8551,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific setEmojiButtonImage(true, true); updateBotButton(true); onWindowSizeChanged(); - if (smoothKeyboard && !keyboardVisible && currentHeight != previusHeight) { + if (smoothKeyboard && !keyboardVisible && currentHeight != previousHeight && allowAnimation) { panelAnimation = new AnimatorSet(); - currentView.setTranslationY(currentHeight - previusHeight); - panelAnimation.playTogether(ObjectAnimator.ofFloat(currentView, View.TRANSLATION_Y, currentHeight - previusHeight, 0)); + currentView.setTranslationY(currentHeight - previousHeight); + panelAnimation.playTogether(ObjectAnimator.ofFloat(currentView, View.TRANSLATION_Y, currentHeight - previousHeight, 0)); panelAnimation.setInterpolator(AdjustPanLayoutHelper.keyboardInterpolator); panelAnimation.setDuration(AdjustPanLayoutHelper.keyboardDuration); panelAnimation.addListener(new AnimatorListenerAdapter() { @@ -8701,15 +8785,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } - public void hidePopup(boolean byBackButton) { - hidePopup(byBackButton, false); + public boolean hidePopup(boolean byBackButton) { + return hidePopup(byBackButton, false); } - public void hidePopup(boolean byBackButton, boolean forceAnimate) { + public boolean hidePopup(boolean byBackButton, boolean forceAnimate) { if (isPopupShowing()) { - if (currentPopupContentType == 1 && byBackButton && botButtonsMessageObject != null) { - SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); - preferences.edit().putInt("hidekeyboard_" + dialog_id, botButtonsMessageObject.getId()).commit(); + if (currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD && byBackButton && botButtonsMessageObject != null) { + return false; } if (byBackButton && searchingType != 0 || forceAnimate) { setSearchingTypeInternal(0, true); @@ -8729,7 +8812,9 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } showPopup(0, 0); } + return true; } + return false; } private void setSearchingTypeInternal(int searchingType, boolean animated) { @@ -8829,7 +8914,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } public void addRecentGif(TLRPC.Document searchImage) { - MediaDataController.getInstance(currentAccount).addRecentGif(searchImage, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(searchImage, (int) (System.currentTimeMillis() / 1000), true); if (emojiView != null) { emojiView.addRecentGif(searchImage); } @@ -8877,14 +8962,14 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific if (isPopupShowing()) { int newHeight = isWidthGreater ? keyboardHeightLand : keyboardHeight; - if (currentPopupContentType == 1 && !botKeyboardView.isFullSize()) { + if (currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD && !botKeyboardView.isFullSize()) { newHeight = Math.min(botKeyboardView.getKeyboardHeight(), newHeight); } View currentView = null; if (currentPopupContentType == 0) { currentView = emojiView; - } else if (currentPopupContentType == 1) { + } else if (currentPopupContentType == POPUP_CONTENT_BOT_KEYBOARD) { currentView = botKeyboardView; } if (botKeyboardView != null) { @@ -8939,6 +9024,13 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific checkBotMenu(); if (keyboardVisible && isPopupShowing() && stickersExpansionAnim == null) { showPopup(0, currentPopupContentType); + } else if (!keyboardVisible && !isPopupShowing() && botButtonsMessageObject != null && replyingMessageObject != botButtonsMessageObject && (!hasBotWebView() || !botCommandsMenuIsShowing()) && TextUtils.isEmpty(messageEditText.getText())) { + if (sizeNotifierLayout.adjustPanLayoutHelper.animationInProgress()) { + sizeNotifierLayout.adjustPanLayoutHelper.stopTransition(); + } else { + sizeNotifierLayout.adjustPanLayoutHelper.ignoreOnce(); + } + showPopup(1, POPUP_CONTENT_BOT_KEYBOARD, false); } if (emojiPadding != 0 && !keyboardVisible && keyboardVisible != oldValue && !isPopupShowing()) { emojiPadding = 0; @@ -9027,10 +9119,10 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } } if (state != RECORD_STATE_PREPARING) { - updateRecordIntefrace(state); + updateRecordInterface(state); } } else { - updateRecordIntefrace(RECORD_STATE_CANCEL); + updateRecordInterface(RECORD_STATE_CANCEL); } } if (id == NotificationCenter.recordStopped) { @@ -9049,7 +9141,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } if (!recordingAudioVideo) { recordingAudioVideo = true; - updateRecordIntefrace(RECORD_STATE_ENTER); + updateRecordInterface(RECORD_STATE_ENTER); } else { recordCircle.showWaves(true, true); } @@ -9071,7 +9163,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific videoTimelineView.setKeyframes(keyframes); videoTimelineView.setVisibility(VISIBLE); videoTimelineView.setMinProgressDiff(1000.0f / videoToSendMessageObject.estimatedDuration); - updateRecordIntefrace(RECORD_STATE_PREPARING); + updateRecordInterface(RECORD_STATE_PREPARING); checkSendButton(false); } else { audioToSend = (TLRPC.TL_document) args[1]; @@ -9123,7 +9215,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific } recordedAudioTimeTextView.setText(AndroidUtilities.formatShortDuration(duration)); checkSendButton(false); - updateRecordIntefrace(RECORD_STATE_PREPARING); + updateRecordInterface(RECORD_STATE_PREPARING); } else { if (delegate != null) { delegate.onMessageSend(null, true, 0); @@ -9180,7 +9272,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific updateSlowModeText(); } } else if (id == NotificationCenter.audioRecordTooShort) { - updateRecordIntefrace(RECORD_STATE_CANCEL_BY_TIME); + updateRecordInterface(RECORD_STATE_CANCEL_BY_TIME); } else if (id == NotificationCenter.updateBotMenuButton) { long botId = (long) args[0]; TLRPC.BotMenuButton botMenuButton = (TLRPC.BotMenuButton) args[1]; @@ -9521,7 +9613,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific StaticLayout cancelLayout; private boolean pressed; - private Rect cancelRect = new Rect(); + public Rect cancelRect = new Rect(); Drawable selectableBackground; private int lastSize; @@ -9551,21 +9643,25 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return false; } if (event.getAction() == MotionEvent.ACTION_UP && cancelRect.contains(x, y)) { - if (hasRecordVideo && videoSendButton.getTag() != null) { - CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(5, true, 0); - } else { - delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0, false, 0); - } - recordingAudioVideo = false; - updateRecordIntefrace(RECORD_STATE_CANCEL); + onCancelButtonPressed(); } return true; } return pressed; } + public void onCancelButtonPressed() { + if (hasRecordVideo && videoSendButton.getTag() != null) { + CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); + delegate.needStartRecordVideo(5, true, 0); + } else { + delegate.needStartRecordAudio(0); + MediaController.getInstance().stopRecording(0, false, 0); + } + recordingAudioVideo = false; + updateRecordInterface(RECORD_STATE_CANCEL); + } + boolean smallSize; @@ -9712,6 +9808,18 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific canvas.restore(); } + float xi; + float yi = (getMeasuredHeight() - cancelLayout.getHeight()) / 2f; + if (!enableTransition) { + yi -= (AndroidUtilities.dp(12) - offsetY); + } + if (enableTransition) { + xi = x + offset; + } else { + xi = cancelX; + } + cancelRect.set((int) xi, (int) yi, (int) (xi + cancelLayout.getWidth()), (int) (yi + cancelLayout.getHeight())); + cancelRect.inset(-AndroidUtilities.dp(16), -AndroidUtilities.dp(16)); if (cancelToProgress > 0) { selectableBackground.setBounds( getMeasuredWidth() / 2 - w, getMeasuredHeight() / 2 - w, @@ -9719,20 +9827,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific ); selectableBackground.draw(canvas); - float xi; - float yi = (getMeasuredHeight() - cancelLayout.getHeight()) / 2f; - if (!enableTransition) { - yi -= (AndroidUtilities.dp(12) - offsetY); - } - if (enableTransition) { - xi = x + offset; - } else { - xi = cancelX; - } canvas.save(); canvas.translate(xi, yi); - cancelRect.set((int) xi, (int) yi, (int) (xi + cancelLayout.getWidth()), (int) (yi + cancelLayout.getHeight())); - cancelRect.inset(-AndroidUtilities.dp(16), -AndroidUtilities.dp(16)); cancelLayout.draw(canvas); canvas.restore(); } else { @@ -10139,6 +10235,11 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return paint != null ? paint : Theme.getThemePaint(paintKey); } + public void setChatSearchExpandOffset(float chatSearchExpandOffset) { + this.chatSearchExpandOffset = chatSearchExpandOffset; + invalidate(); + } + public enum BotMenuButtonType { NO_BUTTON, COMMANDS, 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 9494a969d..002e3934a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -27,6 +27,7 @@ import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; import android.graphics.RectF; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -55,6 +56,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.Keep; import androidx.annotation.NonNull; @@ -70,6 +72,7 @@ import org.jetbrains.annotations.NotNull; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; +import org.telegram.messenger.DocumentObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; @@ -84,6 +87,7 @@ import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenuItem; @@ -103,6 +107,8 @@ import org.telegram.ui.PhotoPickerSearchActivity; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; +import java.util.Locale; import java.util.Locale; import java.util.concurrent.atomic.AtomicBoolean; @@ -119,7 +125,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public ChatActivity.ThemeDelegate parentThemeDelegate; private final NumberTextView captionLimitView; - private final int currentLimit; + private int currentLimit; private int codepointCount; public boolean canOpenPreview = false; @@ -131,7 +137,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } public float getClipLayoutBottom() { - float alphaOffset = (frameLayout2.getMeasuredHeight()- AndroidUtilities.dp(84)) * (1f -frameLayout2.getAlpha()); + float alphaOffset = (frameLayout2.getMeasuredHeight() - AndroidUtilities.dp(84)) * (1f - frameLayout2.getAlpha()); return frameLayout2.getMeasuredHeight() - alphaOffset; } @@ -141,7 +147,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N public void showBotLayout(long id, String startCommand) { if (botAttachLayouts.get(id) == null || !Objects.equals(startCommand, botAttachLayouts.get(id).getStartCommand()) || botAttachLayouts.get(id).needReload()) { - if (baseFragment instanceof ChatActivity && ((ChatActivity) baseFragment).getCurrentUser() != null) { + if (baseFragment instanceof ChatActivity) { ChatAttachAlertBotWebViewLayout webViewLayout = new ChatAttachAlertBotWebViewLayout(this, getContext(), resourcesProvider); botAttachLayouts.put(id, webViewLayout); botAttachLayouts.get(id).setDelegate(new BotWebViewContainer.Delegate() { @@ -163,6 +169,27 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }, 150); } + @Override + public void onWebAppSetActionBarColor(String colorKey) { + int from = ((ColorDrawable) actionBar.getBackground()).getColor(); + int to = getThemedColor(colorKey); + + ValueAnimator animator = ValueAnimator.ofFloat(0, 1).setDuration(200); + animator.setInterpolator(CubicBezierInterpolator.DEFAULT); + animator.addUpdateListener(animation -> actionBar.setBackgroundColor(ColorUtils.blendARGB(from, to, (float) animation.getAnimatedValue()))); + animator.start(); + } + + @Override + public void onWebAppSetBackgroundColor(int color) { + webViewLayout.setCustomBackground(color); + } + + @Override + public void onWebAppOpenInvoice(String slug, TLObject response) { + Toast.makeText(getContext(), LocaleController.getString("nekoXPaymentRemovedToast", R.string.nekoXPaymentRemovedToast), Toast.LENGTH_LONG).show(); + } + @Override public void onWebAppExpand() { if (currentAttachLayout != webViewLayout) { @@ -257,9 +284,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N }).start(); } } + + @Override + public void onSetBackButtonVisible(boolean visible) { + AndroidUtilities.updateImageViewImageAnimated(actionBar.getBackButton(), visible ? R.drawable.ic_ab_back : R.drawable.ic_close_white); + } }); MessageObject replyingObject = ((ChatActivity) baseFragment).getChatActivityEnterView().getReplyingMessageObject(); - botAttachLayouts.get(id).requestWebView(currentAccount, ((ChatActivity) baseFragment).getCurrentUser().id, id, false, replyingObject != null ? replyingObject.messageOwner.id : 0, startCommand); + botAttachLayouts.get(id).requestWebView(currentAccount, ((ChatActivity) baseFragment).getDialogId(), id, false, replyingObject != null ? replyingObject.messageOwner.id : 0, startCommand); } } if (botAttachLayouts.get(id) != null) { @@ -377,6 +409,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } + boolean hasCustomBackground() { + return false; + } + + int getCustomBackground() { + return 0; + } + void onButtonsTranslationYUpdated() { } @@ -629,7 +669,6 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N super(context); setWillNotDraw(false); setFocusable(true); - setFocusableInTouchMode(true); imageView = new RLottieImageView(context) { @Override @@ -652,6 +691,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, 62, 0, 0)); } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setText(textView.getText()); + info.setEnabled(true); + info.setSelected(checked); + } + void updateCheckedState(boolean animate) { if (checked == (currentId == selectedId)) { return; @@ -794,6 +841,16 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 6, 60, 6, 0)); } + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + if (selector != null && checked) { + info.setCheckable(true); + info.setChecked(true); + } + } + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(MeasureSpec.makeMeasureSpec(attachItemSize, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(100), MeasureSpec.EXACTLY)); @@ -939,7 +996,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N TLRPC.Document iconDoc = icon.icon; imageView.getImageReceiver().setAllowStartLottieAnimation(false); - imageView.setImage(ImageLocation.getForDocument(iconDoc), String.valueOf(bot.bot_id), animated ? "tgs" : "svg", null, bot); + imageView.setImage(ImageLocation.getForDocument(iconDoc), String.valueOf(bot.bot_id), animated ? "tgs" : "svg", DocumentObject.getSvgThumb(iconDoc, Theme.key_windowBackgroundGray, 1f), bot); } imageView.setSize(AndroidUtilities.dp(28), AndroidUtilities.dp(28)); @@ -974,6 +1031,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N setDelegate(this); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.reloadInlineHints); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.attachMenuBotsDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); exclusionRects.add(exclustionRect); sizeNotifierFrameLayout = new SizeNotifierFrameLayout(context) { @@ -1297,7 +1355,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N height -= AndroidUtilities.statusBarHeight; } - int backgroundColor = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); + int backgroundColor = currentAttachLayout.hasCustomBackground() ? currentAttachLayout.getCustomBackground() : getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); shadowDrawable.setAlpha(viewAlpha); shadowDrawable.setBounds(0, top, getMeasuredWidth(), height); shadowDrawable.draw(canvas); @@ -1391,7 +1449,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N height -= AndroidUtilities.statusBarHeight; } - int backgroundColor = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); + int backgroundColor = currentAttachLayout.hasCustomBackground() ? currentAttachLayout.getCustomBackground() : getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); boolean drawBackground = !(currentAttachLayout == photoPreviewLayout || nextAttachLayout == photoPreviewLayout || (currentAttachLayout == photoLayout && nextAttachLayout == null)); if (drawBackground) { shadowDrawable.setAlpha(viewAlpha); @@ -1467,7 +1525,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (inBubbleMode) { return; } - int color1 = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); + int color1 = currentAttachLayout.hasCustomBackground() ? currentAttachLayout.getCustomBackground() : getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); int finalColor = Color.argb((int) (255 * actionBar.getAlpha()), Color.red(color1), Color.green(color1), Color.blue(color1)); Theme.dialogs_onlineCirclePaint.setColor(finalColor); canvas.drawRect(backgroundPaddingLeft, currentPanTranslationY, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight + currentPanTranslationY, Theme.dialogs_onlineCirclePaint); @@ -1543,6 +1601,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N containerView = sizeNotifierFrameLayout; containerView.setWillNotDraw(false); containerView.setClipChildren(false); + containerView.setClipToPadding(false); containerView.setPadding(backgroundPaddingLeft, 0, backgroundPaddingLeft, 0); actionBar = new ActionBar(context, resourcesProvider) { @@ -1738,18 +1797,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N selectedArrowImageView.setImageDrawable(arrowRight); selectedArrowImageView.setVisibility(View.GONE); selectedView.addView(selectedArrowImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 4, 1, 0, 0)); - + selectedView.setAlpha(1); headerView.addView(selectedView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT)); - mediaPreviewView = new LinearLayout(context) { - @Override - public void setAlpha(float alpha) { - selectedView.setAlpha(1f - alpha); - selectedView.setTranslationX(alpha * -AndroidUtilities.dp(16)); - mediaPreviewView.setTranslationX((1f - alpha) * AndroidUtilities.dp(16)); - super.setAlpha(alpha); - } - }; + mediaPreviewView = new LinearLayout(context); mediaPreviewView.setOrientation(LinearLayout.HORIZONTAL); mediaPreviewView.setGravity(Gravity.CENTER_VERTICAL); @@ -1810,6 +1861,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N buttonsRecyclerView.setLayoutAnimation(null); buttonsRecyclerView.setGlowColor(getThemedColor(Theme.key_dialogScrollGlow)); buttonsRecyclerView.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + buttonsRecyclerView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); containerView.addView(buttonsRecyclerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 84, Gravity.BOTTOM | Gravity.LEFT)); buttonsRecyclerView.setOnItemClickListener((view, position) -> { if (baseFragment.getParentActivity() == null) { @@ -1951,7 +2003,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N float alphaOffset = (frameLayout2.getMeasuredHeight() - AndroidUtilities.dp(84)) * (1f - getAlpha()); shadow.setTranslationY(-(frameLayout2.getMeasuredHeight() - AndroidUtilities.dp(84)) + captionEditTextTopOffset + currentPanTranslationY + bottomPannelTranslation + alphaOffset + botMainButtonOffsetY); - int newColor = getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); + int newColor = currentAttachLayout.hasCustomBackground() ? currentAttachLayout.getCustomBackground() : getThemedColor(forceDarkTheme ? Theme.key_voipgroup_listViewBackground : Theme.key_dialogBackground); if (color != newColor) { color = newColor; p.setColor(color); @@ -1982,7 +2034,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N captionLimitView.setCenterAlign(true); frameLayout2.addView(captionLimitView, LayoutHelper.createFrame(56, 20, Gravity.BOTTOM | Gravity.RIGHT, 3, 0, 14, 78)); - currentLimit = MessagesController.getInstance(UserConfig.selectedAccount).maxCaptionLength; + currentLimit = MessagesController.getInstance(UserConfig.selectedAccount).getCaptionMaxLengthLimit(); commentTextView = new EditTextEmoji(context, sizeNotifierFrameLayout, null, EditTextEmoji.STYLE_DIALOG, resourcesProvider) { @@ -2244,7 +2296,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N sendPopupWindow.dismiss(); } }); - sendPopupLayout.setShownFromBotton(false); + sendPopupLayout.setShownFromBottom(false); itemCells = new ActionBarMenuSubItem[3]; int i = 0; @@ -2476,13 +2528,10 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } openTransitionFinished = false; if (Build.VERSION.SDK_INT >= 30) { - int color = getThemedColor(Theme.key_windowBackgroundGray); - AndroidUtilities.setNavigationBarColor(getWindow(), color, false, tcolor -> { - navBarColorKey = null; - navBarColor = tcolor; - containerView.invalidate(); - }); - AndroidUtilities.setLightNavigationBar(getWindow(), AndroidUtilities.computePerceivedBrightness(color) > 0.721); + navBarColorKey = null; + navBarColor = ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundGray), 0); + AndroidUtilities.setNavigationBarColor(getWindow(), navBarColor, false); + AndroidUtilities.setLightNavigationBar(getWindow(), AndroidUtilities.computePerceivedBrightness(navBarColor) > 0.721); } } @@ -2683,29 +2732,39 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N nextAttachLayout.setAlpha(1); currentAttachLayout.setAlpha(1); ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, 0.0f); + AndroidUtilities.runOnUIThread(() -> { + float fromActionBarAlpha = actionBar.getAlpha(); + boolean showActionBar = nextAttachLayout.getCurrentItemTop() <= layout.getButtonsHideOffset(); + float toActionBarAlpha = showActionBar ? 1f : 0f; + SpringAnimation springAnimation = new SpringAnimation(new FloatValueHolder(0)); + springAnimation.addUpdateListener((animation, value, velocity) -> { + float f = value / 500f; + ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, f); + actionBar.setAlpha(AndroidUtilities.lerp(fromActionBarAlpha, toActionBarAlpha, f)); + updateLayout(currentAttachLayout, false, 0); + updateLayout(nextAttachLayout, false, 0); + float mediaPreviewAlpha = nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview && !showActionBar ? f : 1f - f; + mediaPreviewView.setAlpha(mediaPreviewAlpha); + selectedView.setAlpha(1f - mediaPreviewAlpha); + selectedView.setTranslationX(mediaPreviewAlpha * -AndroidUtilities.dp(16)); + mediaPreviewView.setTranslationX((1f - mediaPreviewAlpha) * AndroidUtilities.dp(16)); + }); + springAnimation.addEndListener((animation, canceled, value, velocity) -> { + currentAttachLayout.onHideShowProgress(1f); + nextAttachLayout.onHideShowProgress(1f); + currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); + nextAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); + containerView.invalidate(); + actionBar.setTag(showActionBar ? 1 : null); + onEnd.run(); + }); + springAnimation.setSpring(new SpringForce(500f)); + springAnimation.getSpring().setDampingRatio(1f); + springAnimation.getSpring().setStiffness(1000.0f); + springAnimation.start(); - float fromActionBarAlpha = actionBar.getAlpha(); - SpringAnimation springAnimation = new SpringAnimation(new FloatValueHolder(0)); - springAnimation.addUpdateListener((animation, value, velocity) -> { - float f = value / 500f; - ATTACH_ALERT_LAYOUT_TRANSLATION.set(currentAttachLayout, f); - actionBar.setAlpha(AndroidUtilities.lerp(fromActionBarAlpha, 0, f)); - mediaPreviewView.setAlpha(nextAttachLayout instanceof ChatAttachAlertPhotoLayoutPreview ? f : 1f - f); + viewChangeAnimator = springAnimation; }); - springAnimation.addEndListener((animation, canceled, value, velocity) -> { - currentAttachLayout.onHideShowProgress(1f); - nextAttachLayout.onHideShowProgress(1f); - currentAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); - nextAttachLayout.onContainerTranslationUpdated(currentPanTranslationY); - containerView.invalidate(); - onEnd.run(); - }); - springAnimation.setSpring(new SpringForce(500f)); - springAnimation.getSpring().setDampingRatio(1f); - springAnimation.getSpring().setStiffness(1000.0f); - springAnimation.start(); - - viewChangeAnimator = springAnimation; } } @@ -2987,6 +3046,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N protected boolean onCustomOpenAnimation() { photoLayout.setTranslationX(0); mediaPreviewView.setAlpha(0); + selectedView.setAlpha(1); int fromTranslationY = super.containerView.getMeasuredHeight(); super.containerView.setTranslationY(fromTranslationY); @@ -2998,6 +3058,17 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N ATTACH_ALERT_PROGRESS.set(this, 0.0f); buttonsAnimation.start(); + if (navigationBarAnimation != null) { + navigationBarAnimation.cancel(); + } + navigationBarAnimation = ValueAnimator.ofFloat(navigationBarAlpha, 1f); + navigationBarAnimation.addUpdateListener(a -> { + navigationBarAlpha = (float) a.getAnimatedValue(); + if (container != null) { + container.invalidate(); + } + }); + if (appearSpringAnimation != null) { appearSpringAnimation.cancel(); } @@ -3062,9 +3133,32 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 512); currentSheetAnimation.start(); +// AndroidUtilities.runOnUIThread(() -> { +// if (currentSheetAnimation != null) { +// // closes keyboard so navigation bar buttons can be accessible +// ChatAttachAlert.this.delegate.needEnterComment(); +// } +// }, 75); + ValueAnimator navigationBarAnimator = ValueAnimator.ofFloat(0, 1); + setNavBarAlpha(0); + navigationBarAnimator.addUpdateListener(a -> { + setNavBarAlpha((float) a.getAnimatedValue()); + }); + navigationBarAnimator.setStartDelay(25); + navigationBarAnimator.setDuration(200); + navigationBarAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + navigationBarAnimator.start(); + return true; } + private void setNavBarAlpha(float alpha) { + navBarColor = ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundGray), Math.min(255, Math.max(0, (int) (255 * alpha)))); + AndroidUtilities.setNavigationBarColor(getWindow(), navBarColor, false); + AndroidUtilities.setLightNavigationBar(getWindow(), AndroidUtilities.computePerceivedBrightness(navBarColor) > 0.721); + getContainer().invalidate(); + } + @Override protected boolean onContainerTouchEvent(MotionEvent event) { return currentAttachLayout.onContainerViewTouchEvent(event); @@ -3225,6 +3319,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (buttonsAdapter != null) { buttonsAdapter.notifyDataSetChanged(); } + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + currentLimit = MessagesController.getInstance(UserConfig.selectedAccount).getCaptionMaxLengthLimit(); } } @@ -3383,7 +3479,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N return; } boolean show = layout == currentAttachLayout && newOffset <= layout.getButtonsHideOffset(); - if (currentAttachLayout != photoPreviewLayout && keyboardVisible && animated) { + if (currentAttachLayout != photoPreviewLayout && keyboardVisible && animated && !(currentAttachLayout instanceof ChatAttachAlertBotWebViewLayout)) { animated = false; } if (layout == currentAttachLayout) { @@ -3518,6 +3614,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N for (int i = 0; i < botAttachLayouts.size(); i++) { botAttachLayouts.valueAt(i).setMeasureOffsetY(0); } + shadow.setAlpha(1f); + shadow.setTranslationY(0); if (baseFragment instanceof ChatActivity && avatarPicker != 2) { TLRPC.Chat chat = ((ChatActivity) baseFragment).getCurrentChat(); @@ -3597,6 +3695,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.reloadInlineHints); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.attachMenuBotsDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); baseFragment = null; if (commentTextView != null) { commentTextView.onDestroy(); @@ -3685,6 +3784,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N private int attachBotsStartRow; private int attachBotsEndRow; + private List attachMenuBots = new ArrayList<>(); private int documentButton; private int musicButton; @@ -3710,6 +3810,8 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N view = new AttachBotButton(mContext); break; } + view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); + view.setFocusable(true); return new RecyclerListView.Holder(view); } @@ -3743,7 +3845,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (position >= attachBotsStartRow && position < attachBotsEndRow) { position -= attachBotsStartRow; child.setTag(position); - TLRPC.TL_attachMenuBot bot = MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots.get(position); + TLRPC.TL_attachMenuBot bot = attachMenuBots.get(position); child.setAttachBot(MessagesController.getInstance(currentAccount).getUser(bot.bot_id), bot); break; } @@ -3804,9 +3906,18 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N if (mediaEnabled) { galleryButton = buttonsCount++; - if (baseFragment instanceof ChatActivity && ((ChatActivity) baseFragment).getCurrentUser() != null && !((ChatActivity) baseFragment).isInScheduleMode() && !((ChatActivity) baseFragment).isSecretChat()) { + if (baseFragment instanceof ChatActivity && !((ChatActivity) baseFragment).isInScheduleMode() && !((ChatActivity) baseFragment).isSecretChat()) { + ChatActivity chatActivity = (ChatActivity) baseFragment; + attachBotsStartRow = buttonsCount; - buttonsCount += MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots.size(); + attachMenuBots.clear(); + for (TLRPC.TL_attachMenuBot bot : MediaDataController.getInstance(currentAccount).getAttachMenuBots().bots) { + if (MediaDataController.canShowAttachMenuBot(bot, chatActivity.getCurrentChat() != null ? chatActivity.getCurrentChat() : chatActivity.getCurrentUser())) { + attachMenuBots.add(bot); + } + } + + buttonsCount += attachMenuBots.size(); attachBotsEndRow = buttonsCount; } @@ -3917,7 +4028,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N @Override public void dismiss() { - if (currentAttachLayout.onDismiss()) { + if (currentAttachLayout.onDismiss() || isDismissed()) { return; } if (commentTextView != null) { @@ -3963,11 +4074,14 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N layouts[a].onDismiss(); } } - AndroidUtilities.setNavigationBarColor(getWindow(), ColorUtils.setAlphaComponent(navBarColor, 0), true, tcolor -> { + AndroidUtilities.setNavigationBarColor(getWindow(), ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundGray), 0), true, tcolor -> { navBarColorKey = null; navBarColor = tcolor; containerView.invalidate(); }); + if (baseFragment != null) { + AndroidUtilities.setLightStatusBar(getWindow(), baseFragment.isLightStatusBar()); + } super.dismiss(); allowPassConfirmationAlert = false; } 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 dfe6a65d8..ff995d21b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertBotWebViewLayout.java @@ -21,6 +21,7 @@ import android.widget.FrameLayout; import androidx.annotation.NonNull; import androidx.core.math.MathUtils; import androidx.core.view.GestureDetectorCompat; +import androidx.dynamicanimation.animation.FloatValueHolder; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; import androidx.recyclerview.widget.ChatListItemAnimator; @@ -28,6 +29,7 @@ import androidx.recyclerview.widget.ChatListItemAnimator; import org.json.JSONObject; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.FileLog; +import org.telegram.messenger.GenericProvider; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; @@ -39,6 +41,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ChatActivity; @@ -63,6 +66,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private WebProgressView progressView; private WebViewSwipeContainer swipeContainer; private ActionBarMenuItem otherItem; + private ActionBarMenuSubItem settingsItem; private int measureOffsetY; @@ -71,6 +75,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private boolean ignoreMeasure; private boolean isBotButtonAvailable; + private boolean hasCustomBackground; + private int customBackground; + private boolean destroyed; private Runnable pollRunnable = () -> { if (!destroyed) { @@ -83,6 +90,18 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert prolongWebView.reply_to_msg_id = replyToMsgId; prolongWebView.flags |= 1; } + + if (peerId < 0) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-peerId); + if (chatFull != null) { + TLRPC.Peer peer = chatFull.default_send_as; + if (peer != null) { + prolongWebView.send_as = MessagesController.getInstance(currentAccount).getInputPeer(peer); + prolongWebView.flags |= 8192; + } + } + } + ConnectionsManager.getInstance(currentAccount).sendRequest(prolongWebView, (response, error) -> AndroidUtilities.runOnUIThread(() -> { if (destroyed) { return; @@ -102,13 +121,16 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert ActionBarMenu menu = parentAlert.actionBar.createMenu(); 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)); 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) { - parentAlert.dismiss(); + if (!onBackPressed()) { + parentAlert.dismiss(); + } } else if (id == R.id.menu_open_bot) { Bundle bundle = new Bundle(); bundle.putLong("user_id", botId); @@ -125,7 +147,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert progressView.setVisibility(VISIBLE); webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, 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) { @@ -134,6 +156,8 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert break; } } + } else if (id == R.id.menu_settings) { + webViewContainer.onSettingsButtonPressed(); } } }); @@ -164,6 +188,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert }); swipeContainer.setScrollEndListener(()-> webViewContainer.invalidateViewPortHeight(true)); swipeContainer.setDelegate(() -> parentAlert.dismiss()); + swipeContainer.setIsKeyboardVisible(obj -> parentAlert.sizeNotifierFrameLayout.getKeyboardHeight() >= AndroidUtilities.dp(20)); addView(swipeContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(progressView = new WebProgressView(context, resourcesProvider), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM, 0, 0, 0, 84)); @@ -189,6 +214,21 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didSetNewTheme); } + public void setCustomBackground(int customBackground) { + this.customBackground = customBackground; + hasCustomBackground = true; + } + + @Override + boolean hasCustomBackground() { + return hasCustomBackground; + } + + @Override + public int getCustomBackground() { + return customBackground; + } + public boolean canExpandByRequest() { return /* System.currentTimeMillis() - lastSwipeTime > 1000 && */ !swipeContainer.isSwipeInProgress(); } @@ -283,6 +323,10 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert webViewContainer.setParentActivity(parentAlert.getBaseFragment().getParentActivity()); } otherItem.setVisibility(VISIBLE); + + if (!webViewContainer.isBackButtonVisible()) { + AndroidUtilities.updateImageViewImageAnimated(parentAlert.actionBar.getBackButton(), R.drawable.ic_close_white); + } } @Override @@ -344,12 +388,23 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert this.startCommand = startCommand; webViewContainer.setBotUser(MessagesController.getInstance(currentAccount).getUser(botId)); - webViewContainer.loadFlicker(currentAccount, botId); + webViewContainer.loadFlickerAndSettingsItem(currentAccount, botId, settingsItem); TLRPC.TL_messages_requestWebView req = new TLRPC.TL_messages_requestWebView(); req.peer = MessagesController.getInstance(currentAccount).getInputPeer(peerId); req.bot = MessagesController.getInstance(currentAccount).getInputUser(botId); req.silent = silent; + + if (peerId < 0) { + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(-peerId); + if (chatFull != null) { + TLRPC.Peer peer = chatFull.default_send_as; + if (peer != null) { + req.send_as = MessagesController.getInstance(currentAccount).getInputPeer(peer); + req.flags |= 8192; + } + } + } if (startCommand != null) { req.start_param = startCommand; req.flags |= 8; @@ -363,6 +418,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert 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)); @@ -380,7 +436,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert if (response instanceof TLRPC.TL_webViewResultUrl) { TLRPC.TL_webViewResultUrl resultUrl = (TLRPC.TL_webViewResultUrl) response; queryId = resultUrl.query_id; - webViewContainer.loadUrl(resultUrl.url); + webViewContainer.loadUrl(currentAccount, resultUrl.url); swipeContainer.setWebView(webViewContainer.getWebView()); AndroidUtilities.runOnUIThread(pollRunnable); @@ -410,6 +466,10 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert super.onHide(); otherItem.setVisibility(GONE); isBotButtonAvailable = false; + if (!webViewContainer.isBackButtonVisible()) { + AndroidUtilities.updateImageViewImageAnimated(parentAlert.actionBar.getBackButton(), R.drawable.ic_ab_back); + } + parentAlert.actionBar.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); if (webViewContainer.hasUserPermissions()) { webViewContainer.destroyWebView(); @@ -523,12 +583,13 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private boolean isSwipeDisallowed; private float topActionBarOffsetY = ActionBar.getCurrentActionBarHeight(); - private float offsetY = -1; + private float offsetY = 0; private float pendingOffsetY = -1; + private float pendingSwipeOffsetY = Integer.MIN_VALUE; private float swipeOffsetY; private boolean isSwipeOffsetAnimationDisallowed; - private ValueAnimator offsetYAnimator; + private SpringAnimation offsetYAnimator; private boolean flingInProgress; @@ -542,6 +603,8 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert private int swipeStickyRange; + private GenericProvider isKeyboardVisible = obj -> false; + public WebViewSwipeContainer(@NonNull Context context) { super(context); @@ -574,7 +637,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (!isScrolling && !isSwipeDisallowed) { - if (Math.abs(distanceY) >= touchSlop && Math.abs(distanceY) * 1.5f >= Math.abs(distanceX) && (swipeOffsetY != -offsetY + topActionBarOffsetY || webView == null || distanceY < 0 && webView.getScrollY() == 0)) { + if (isKeyboardVisible.provide(null) && swipeOffsetY == -offsetY + topActionBarOffsetY) { + isSwipeDisallowed = true; + } else if (Math.abs(distanceY) >= touchSlop && Math.abs(distanceY) * 1.5f >= Math.abs(distanceX) && (swipeOffsetY != -offsetY + topActionBarOffsetY || webView == null || distanceY < 0 && webView.getScrollY() == 0)) { isScrolling = true; MotionEvent ev = MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0); @@ -622,6 +687,10 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert updateStickyRange(); } + public void setIsKeyboardVisible(GenericProvider isKeyboardVisible) { + this.isKeyboardVisible = isKeyboardVisible; + } + @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -669,50 +738,55 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert } public void setOffsetY(float offsetY) { - float wasOffsetY = this.offsetY; - boolean wasOnTop = swipeOffsetY == -wasOffsetY + topActionBarOffsetY; - if (wasOffsetY != -1 && !isSwipeOffsetAnimationDisallowed) { - offsetYAnimator = ValueAnimator.ofFloat(wasOffsetY, offsetY).setDuration(200); - offsetYAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); - offsetYAnimator.addUpdateListener(animation -> { - this.offsetY = (float) animation.getAnimatedValue(); - if (wasOnTop) { - swipeOffsetY = -this.offsetY + topActionBarOffsetY; - } else { - swipeOffsetY = MathUtils.clamp(swipeOffsetY, -this.offsetY + topActionBarOffsetY, getHeight() - this.offsetY + topActionBarOffsetY); - } - if (scrollAnimator != null && scrollAnimator.getSpring().getFinalPosition() == -wasOffsetY + topActionBarOffsetY) { - scrollAnimator.getSpring().setFinalPosition(-offsetY + topActionBarOffsetY); - } - invalidateTranslation(); - }); - offsetYAnimator.addListener(new AnimatorListenerAdapter() { - private boolean isCanceled; + if (pendingSwipeOffsetY != Integer.MIN_VALUE) { + pendingOffsetY = offsetY; + return; + } - @Override - public void onAnimationEnd(Animator animation) { - if (offsetYAnimator == animation) { + if (offsetYAnimator != null) { + offsetYAnimator.cancel(); + } + + float wasOffsetY = this.offsetY; + float deltaOffsetY = offsetY - wasOffsetY; + boolean wasOnTop = Math.abs(swipeOffsetY + wasOffsetY - topActionBarOffsetY) <= AndroidUtilities.dp(1); + if (!isSwipeOffsetAnimationDisallowed) { + if (offsetYAnimator != null) { + offsetYAnimator.cancel(); + } + offsetYAnimator = new SpringAnimation(new FloatValueHolder(wasOffsetY)) + .setSpring(new SpringForce(offsetY) + .setStiffness(1400) + .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY)) + .addUpdateListener((animation, value, velocity) -> { + this.offsetY = value; + + float progress = (value - wasOffsetY) / deltaOffsetY; + + if (wasOnTop) { + swipeOffsetY = MathUtils.clamp(swipeOffsetY - progress * Math.max(0, deltaOffsetY), -this.offsetY + topActionBarOffsetY, getHeight() - this.offsetY + topActionBarOffsetY); + } + if (scrollAnimator != null && scrollAnimator.getSpring().getFinalPosition() == -wasOffsetY + topActionBarOffsetY) { + scrollAnimator.getSpring().setFinalPosition(-offsetY + topActionBarOffsetY); + } + invalidateTranslation(); + }) + .addEndListener((animation, canceled, value, velocity) -> { offsetYAnimator = null; - if (!isCanceled) { + if (!canceled) { WebViewSwipeContainer.this.offsetY = offsetY; invalidateTranslation(); } else { pendingOffsetY = offsetY; } - } - } - - @Override - public void onAnimationCancel(Animator animation) { - isCanceled = true; - } - }); + }); offsetYAnimator.start(); } else { this.offsetY = offsetY; + if (wasOnTop) { - this.swipeOffsetY = -this.offsetY + topActionBarOffsetY; + swipeOffsetY = MathUtils.clamp(swipeOffsetY - Math.max(0, deltaOffsetY), -this.offsetY + topActionBarOffsetY, getHeight() - this.offsetY + topActionBarOffsetY); } invalidateTranslation(); } @@ -766,13 +840,9 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert flingInProgress = false; } else { if (swipeOffsetY <= -swipeStickyRange) { - if (swipeOffsetY != -offsetY + topActionBarOffsetY) { - stickTo(-offsetY + topActionBarOffsetY); - } + stickTo(-offsetY + topActionBarOffsetY); } else if (swipeOffsetY > -swipeStickyRange && swipeOffsetY <= swipeStickyRange) { - if (swipeOffsetY != 0) { - stickTo(0); - } + stickTo(0); } else { if (delegate != null) { delegate.onDismiss(); @@ -802,6 +872,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert } return; } + pendingSwipeOffsetY = offset; if (offsetYAnimator != null) { offsetYAnimator.cancel(); @@ -832,6 +903,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert pendingOffsetY = -1; isSwipeOffsetAnimationDisallowed = wasDisallowed; } + pendingSwipeOffsetY = Integer.MIN_VALUE; } }); scrollAnimator.start(); @@ -849,7 +921,7 @@ public class ChatAttachAlertBotWebViewLayout extends ChatAttachAlert.AttachAlert } } - public final static class WebProgressView extends View { + public static class WebProgressView extends View { private final SimpleFloatPropertyCompat LOAD_PROGRESS_PROPERTY = new SimpleFloatPropertyCompat<>("loadProgress", obj -> obj.loadProgress, WebProgressView::setLoadProgress).setMultiplier(100f); private Paint bluePaint = new Paint(Paint.ANTI_ALIAS_FLAG); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java index f763975e5..83ba88994 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertContactsLayout.java @@ -161,9 +161,11 @@ public class ChatAttachAlertContactsLayout extends ChatAttachAlert.AttachAlertLa } else { statusTextView.setText(""); Utilities.globalQueue.postRunnable(() -> { - formattedPhoneNumber = PhoneFormat.getInstance().format("+" + currentUser.phone); - formattedPhoneNumberUser = currentUser; - AndroidUtilities.runOnUIThread(() -> statusTextView.setText(formattedPhoneNumber)); + if (currentUser != null) { + formattedPhoneNumber = PhoneFormat.getInstance().format("+" + currentUser.phone); + formattedPhoneNumberUser = currentUser; + AndroidUtilities.runOnUIThread(() -> statusTextView.setText(formattedPhoneNumber)); + } }); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java index 8769c1753..5237ebadb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertDocumentLayout.java @@ -12,12 +12,15 @@ 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.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.Cursor; +import android.graphics.Canvas; +import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.media.MediaMetadataRetriever; @@ -29,6 +32,7 @@ import android.provider.MediaStore; import android.text.TextUtils; import android.util.SparseArray; import android.view.Gravity; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -70,6 +74,7 @@ import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.SharedDocumentCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.FilteredSearchView; import org.telegram.ui.PhotoPickerActivity; @@ -112,8 +117,16 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private int type; + private final static int ANIMATION_NONE = 0; + private final static int ANIMATION_FORWARD = 1; + private final static int ANIMATION_BACKWARD = 2; + private int currentAnimationType; + private RecyclerListView listView; + private RecyclerListView backgroundListView; private ListAdapter listAdapter; + private ListAdapter backgroundListAdapter; + private LinearLayoutManager backgroundLayoutManager; private SearchAdapter searchAdapter; private LinearLayoutManager layoutManager; private ActionBarMenuItem searchItem; @@ -133,15 +146,12 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private boolean hasFiles; private File currentDir; - private ArrayList items = new ArrayList<>(); private boolean receiverRegistered = false; - private ArrayList history = new ArrayList<>(); private DocumentSelectActivityDelegate delegate; private HashMap selectedFiles = new HashMap<>(); private ArrayList selectedFilesOrder = new ArrayList<>(); private HashMap selectedMessages = new HashMap<>(); private boolean scrolling; - private ArrayList recentItems = new ArrayList<>(); private int maxSelectedFiles = -1; private boolean canSelectOnlyImageFiles; private boolean allowMusic; @@ -200,6 +210,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa public ChatAttachAlertDocumentLayout(ChatAttachAlert alert, Context context, int type, Theme.ResourcesProvider resourcesProvider) { super(alert, context, resourcesProvider); + listAdapter = new ListAdapter(context); allowMusic = type == TYPE_MUSIC; isSoundPicker = type == TYPE_RINGTONE; sortByName = SharedConfig.sortFilesByName; @@ -262,7 +273,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa editText.setCursorColor(getThemedColor(Theme.key_dialogTextBlack)); editText.setHintTextColor(getThemedColor(Theme.key_chat_messagePanelHint)); - sortItem = menu.addItem(sort_button, sortByName ? R.drawable.contacts_sort_time : R.drawable.contacts_sort_name); + sortItem = menu.addItem(sort_button, sortByName ? R.drawable.msg_contacts_time : R.drawable.msg_contacts_name); sortItem.setContentDescription(LocaleController.getString("AccDescrContactSorting", R.string.AccDescrContactSorting)); addView(loadingView = new FlickerLoadingView(context, resourcesProvider)); @@ -282,7 +293,59 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa emptyView.setVisibility(View.GONE); emptyView.setOnTouchListener((v, event) -> true); - listView = new RecyclerListView(context, resourcesProvider); + backgroundListView = new RecyclerListView(context, resourcesProvider) { + Paint paint = new Paint(); + @Override + protected void dispatchDraw(Canvas canvas) { + if (currentAnimationType == ANIMATION_BACKWARD && getChildCount() > 0) { + float top = Integer.MAX_VALUE; + for (int i = 0; i < getChildCount(); i++) { + if (getChildAt(i).getY() < top) { + top = getChildAt(i).getY(); + } + } + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + // canvas.drawRect(0, top, getMeasuredWidth(), getMeasuredHeight(), paint); + } + super.dispatchDraw(canvas); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + if (currentAnimationType != ANIMATION_NONE) { + return false; + } + return super.onTouchEvent(e); + } + }; + backgroundListView.setSectionsType(RecyclerListView.SECTIONS_TYPE_DATE); + backgroundListView.setVerticalScrollBarEnabled(false); + backgroundListView.setLayoutManager(backgroundLayoutManager = new FillLastLinearLayoutManager(context, LinearLayoutManager.VERTICAL, false, AndroidUtilities.dp(56), backgroundListView)); + backgroundListView.setClipToPadding(false); + backgroundListView.setAdapter(backgroundListAdapter = new ListAdapter(context)); + backgroundListView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); + addView(backgroundListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + backgroundListView.setVisibility(View.GONE); + + listView = new RecyclerListView(context, resourcesProvider) { + + Paint paint = new Paint(); + @Override + protected void dispatchDraw(Canvas canvas) { + if (currentAnimationType == ANIMATION_FORWARD && getChildCount() > 0) { + float top = Integer.MAX_VALUE; + for (int i = 0; i < getChildCount(); i++) { + if (getChildAt(i).getY() < top) { + top = getChildAt(i).getY(); + } + } + paint.setColor(Theme.getColor(Theme.key_dialogBackground)); + // canvas.drawRect(0, top, getMeasuredWidth(), getMeasuredHeight(), paint); + } + super.dispatchDraw(canvas); + + } + }; listView.setSectionsType(RecyclerListView.SECTIONS_TYPE_DATE); listView.setVerticalScrollBarEnabled(false); listView.setLayoutManager(layoutManager = new FillLastLinearLayoutManager(context, LinearLayoutManager.VERTICAL, false, AndroidUtilities.dp(56), listView) { @@ -306,11 +369,12 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } }); listView.setClipToPadding(false); - listView.setAdapter(listAdapter = new ListAdapter(context)); + listView.setAdapter(listAdapter); listView.setPadding(0, 0, 0, AndroidUtilities.dp(48)); addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); searchAdapter = new SearchAdapter(context); + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { @@ -409,7 +473,8 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } } else { int top = getTopForScroll(); - HistoryEntry he = history.remove(history.size() - 1); + prepareAnimation(); + HistoryEntry he = listAdapter.history.remove(listAdapter.history.size() - 1); parentAlert.actionBar.setTitle(he.title); if (he.dir != null) { listFiles(he.dir); @@ -418,6 +483,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } updateSearchButton(); layoutManager.scrollToPositionWithOffset(0, top); + runAnimation(ANIMATION_BACKWARD); } } else if (file.isDirectory()) { HistoryEntry he = new HistoryEntry(); @@ -428,10 +494,14 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa he.scrollOffset = child.getTop(); he.dir = currentDir; he.title = parentAlert.actionBar.getTitle(); - history.add(he); + + prepareAnimation(); + listAdapter.history.add(he); if (!listFiles(file)) { - history.remove(he); + listAdapter.history.remove(he); return; + } else { + runAnimation(ANIMATION_FORWARD); } parentAlert.actionBar.setTitle(item.title); } @@ -468,6 +538,112 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa updateEmptyView(); } + ValueAnimator listAnimation; + private void runAnimation(int animationType) { + if (listAnimation != null) { + listAnimation.cancel(); + } + currentAnimationType = animationType; + int listViewChildIndex = 0; + for (int i = 0; i < getChildCount(); i++) { + if (getChildAt(i) == listView) { + listViewChildIndex = i; + break; + } + } + float xTranslate; + if (animationType == ANIMATION_FORWARD) { + xTranslate = AndroidUtilities.dp(150); + backgroundListView.setAlpha(1f); + backgroundListView.setScaleX(1f); + backgroundListView.setScaleY(1f); + backgroundListView.setTranslationX(0); + removeView(backgroundListView); + addView(backgroundListView, listViewChildIndex); + backgroundListView.setVisibility(View.VISIBLE); + listView.setTranslationX(xTranslate); + listView.setAlpha(0f); + listAnimation = ValueAnimator.ofFloat(1f, 0); + } else { + xTranslate = AndroidUtilities.dp(150); + listView.setAlpha(0f); + listView.setScaleX(0.95f); + listView.setScaleY(0.95f); + backgroundListView.setScaleX(1f); + backgroundListView.setScaleY(1f); + backgroundListView.setTranslationX(0f); + backgroundListView.setAlpha(1f); + removeView(backgroundListView); + addView(backgroundListView, listViewChildIndex + 1); + backgroundListView.setVisibility(View.VISIBLE); + listAnimation = ValueAnimator.ofFloat(0f, 1f); + } + + listAnimation.addUpdateListener(animation -> { + float value = (float) animation.getAnimatedValue(); + if (animationType == ANIMATION_FORWARD) { + listView.setTranslationX(xTranslate * value); + listView.setAlpha(1f - value); + listView.invalidate(); + + backgroundListView.setAlpha(value); + float s = 0.95f + value * 0.05f; + backgroundListView.setScaleX(s); + backgroundListView.setScaleY(s); + } else { + backgroundListView.setTranslationX(xTranslate * value); + backgroundListView.setAlpha(Math.max(0, 1f - value)); + backgroundListView.invalidate(); + + listView.setAlpha(value); + float s = 0.95f + value * 0.05f; + listView.setScaleX(s); + listView.setScaleY(s); + backgroundListView.invalidate(); + } + }); + listAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + backgroundListView.setVisibility(View.GONE); + currentAnimationType = ANIMATION_NONE; + listView.setAlpha(1f); + listView.setScaleX(1f); + listView.setScaleY(1f); + listView.setTranslationX(0f); + listView.invalidate(); + } + }); + if (animationType == ANIMATION_FORWARD) { + listAnimation.setDuration(220); + } else { + listAnimation.setDuration(200); + } + listAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + listAnimation.start(); + } + + private void prepareAnimation() { + backgroundListAdapter.history.clear(); + backgroundListAdapter.history.addAll(listAdapter.history); + backgroundListAdapter.items.clear(); + backgroundListAdapter.items.addAll(listAdapter.items); + backgroundListAdapter.recentItems.clear(); + backgroundListAdapter.recentItems.addAll(listAdapter.recentItems); + backgroundListAdapter.notifyDataSetChanged(); + backgroundListView.setVisibility(View.VISIBLE); + + backgroundListView.setPadding(listView.getPaddingLeft(), listView.getPaddingTop(), listView.getPaddingRight(), listView.getPaddingBottom()); + int p = layoutManager.findFirstVisibleItemPosition(); + if (p >= 0) { + View childView = layoutManager.findViewByPosition(p); + if (childView != null) { + backgroundLayoutManager.scrollToPositionWithOffset(p, childView.getTop() - backgroundListView.getPaddingTop()); + } + } + } + @Override void onDestroy() { try { @@ -491,7 +667,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa sortRecentItems(); sortFileItems(); listAdapter.notifyDataSetChanged(); - sortItem.setIcon(sortByName ? R.drawable.contacts_sort_time : R.drawable.contacts_sort_name); + sortItem.setIcon(sortByName ? R.drawable.msg_contacts_time : R.drawable.msg_contacts_name); } } @@ -620,8 +796,10 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa showErrorBox(LocaleController.formatString("PassportUploadNotImage", R.string.PassportUploadNotImage)); return false; } - if (item.file.length() > FileLoader.MAX_FILE_SIZE) { - showErrorBox(LocaleController.formatString("FileUploadLimit", R.string.FileUploadLimit, AndroidUtilities.formatFileSize(FileLoader.MAX_FILE_SIZE))); + if ((item.file.length() > FileLoader.DEFAULT_MAX_FILE_SIZE && !UserConfig.getInstance(UserConfig.selectedAccount).isPremium()) || item.file.length() > FileLoader.DEFAULT_MAX_FILE_SIZE_PREMIUM) { + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(parentAlert.baseFragment, parentAlert.getContainer().getContext(), LimitReachedBottomSheet.TYPE_LARGE_FILE, UserConfig.selectedAccount); + limitReachedBottomSheet.setVeryLargeFile(true); + limitReachedBottomSheet.show(); return false; } if (maxSelectedFiles >= 0 && selectedFiles.size() >= maxSelectedFiles) { @@ -764,7 +942,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa if (fname.endsWith(".jpg") || fname.endsWith(".png") || fname.endsWith(".gif") || fname.endsWith(".jpeg")) { item.thumb = file.getAbsolutePath(); } - recentItems.add(item); + listAdapter.recentItems.add(item); } } catch (Exception e) { FileLog.e(e); @@ -798,13 +976,13 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa if (fname.endsWith(".jpg") || fname.endsWith(".png") || fname.endsWith(".gif") || fname.endsWith(".jpeg")) { item.thumb = file.getAbsolutePath(); } - recentItems.add(item); + listAdapter.recentItems.add(item); } } } private void sortRecentItems() { - Collections.sort(recentItems, (o1, o2) -> { + Collections.sort(listAdapter.recentItems, (o1, o2) -> { if (sortByName) { String lm = o1.file.getName(); String rm = o2.file.getName(); @@ -827,7 +1005,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa if (currentDir == null) { return; } - Collections.sort(items, (lhs, rhs) -> { + Collections.sort(listAdapter.items, (lhs, rhs) -> { if (lhs.file == null) { return -1; } else if (rhs.file == null) { @@ -870,7 +1048,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa selectedMessages.clear(); searchAdapter.currentSearchFilters.clear(); selectedFilesOrder.clear(); - history.clear(); + listAdapter.history.clear(); listRoots(); updateSearchButton(); updateEmptyView(); @@ -914,7 +1092,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa return; } if (!searchItem.isSearchFieldVisible()) { - searchItem.setVisibility(hasFiles || history.isEmpty() ? View.VISIBLE : View.GONE); + searchItem.setVisibility(hasFiles || listAdapter.history.isEmpty() ? View.VISIBLE : View.GONE); } } @@ -929,8 +1107,9 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } private boolean canClosePicker() { - if (history.size() > 0) { - HistoryEntry he = history.remove(history.size() - 1); + if (listAdapter.history.size() > 0) { + prepareAnimation(); + HistoryEntry he = listAdapter.history.remove(listAdapter.history.size() - 1); parentAlert.actionBar.setTitle(he.title); int top = getTopForScroll(); if (he.dir != null) { @@ -940,6 +1119,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } updateSearchButton(); layoutManager.scrollToPositionWithOffset(0, top); + runAnimation(ANIMATION_BACKWARD); return false; } return true; @@ -972,7 +1152,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && !Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED_READ_ONLY)) { currentDir = dir; - items.clear(); + listAdapter.items.clear(); String state = Environment.getExternalStorageState(); AndroidUtilities.clearDrawableAnimation(listView); scrolling = true; @@ -995,7 +1175,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa return false; } currentDir = dir; - items.clear(); + listAdapter.items.clear(); for (int a = 0; a < files.length; a++) { File file = files[a]; if (file.getName().indexOf('.') == 0) { @@ -1018,12 +1198,12 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa item.thumb = file.getAbsolutePath(); } } - items.add(item); + listAdapter.items.add(item); } ListItem item = new ListItem(); item.title = ".."; - if (history.size() > 0) { - HistoryEntry entry = history.get(history.size() - 1); + if (listAdapter.history.size() > 0) { + HistoryEntry entry = listAdapter.history.get(listAdapter.history.size() - 1); if (entry.dir == null) { item.subtitle = LocaleController.getString("Folder", R.string.Folder); } else { @@ -1034,7 +1214,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa } item.icon = R.drawable.files_folder; item.file = null; - items.add(0, item); + listAdapter.items.add(0, item); sortFileItems(); updateSearchButton(); AndroidUtilities.clearDrawableAnimation(listView); @@ -1053,13 +1233,14 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private void listRoots() { currentDir = null; hasFiles = false; - items.clear(); + listAdapter.items.clear(); HashSet paths = new HashSet<>(); boolean isExternalStorageManager = false; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { isExternalStorageManager = Environment.isExternalStorageManager(); } + // TODO add permission for read all files and uncomment for direct version // if (!BuildVars.NO_SCOPED_STORAGE && !isExternalStorageManager) { // ListItem ext = new ListItem(); // ext.title = LocaleController.getString("InternalStorage", R.string.InternalStorage); @@ -1081,7 +1262,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa ext.subtitle = LocaleController.getString("InternalFolderInfo", R.string.InternalFolderInfo); } ext.file = Environment.getExternalStorageDirectory(); - items.add(ext); + listAdapter.items.add(ext); paths.add(defaultPath); } @@ -1122,7 +1303,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa item.subtitle = LocaleController.getString("ExternalFolderInfo", R.string.ExternalFolderInfo); item.icon = R.drawable.files_internal; item.file = new File(path); - items.add(item); + listAdapter.items.add(item); } catch (Exception e) { FileLog.e(e); } @@ -1152,7 +1333,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa fs.subtitle = LocaleController.getString("AppFolderInfo", R.string.AppFolderInfo); fs.icon = R.drawable.files_folder; fs.file = telegramPath; - items.add(fs); + listAdapter.items.add(fs); } } catch (Exception e) { FileLog.e(e); @@ -1165,8 +1346,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa fs.subtitle = LocaleController.getString("GalleryInfo", R.string.GalleryInfo); fs.icon = R.drawable.files_gallery; fs.file = null; - items.add(fs); - + listAdapter.items.add(fs); } if (allowMusic) { @@ -1175,9 +1355,9 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa fs.subtitle = LocaleController.getString("MusicInfo", R.string.MusicInfo); fs.icon = R.drawable.files_music; fs.file = null; - items.add(fs); + listAdapter.items.add(fs); } - if (!recentItems.isEmpty()) { + if (!listAdapter.recentItems.isEmpty()) { hasFiles = true; } @@ -1203,6 +1383,11 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa private class ListAdapter extends RecyclerListView.SelectionAdapter { + private ArrayList items = new ArrayList<>(); + private ArrayList history = new ArrayList<>(); + private ArrayList recentItems = new ArrayList<>(); + + private Context mContext; public ListAdapter(Context context) { @@ -1381,9 +1566,9 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa notifyDataSetChanged(); } else { AndroidUtilities.runOnUIThread(localSearchRunnable = () -> { - final ArrayList copy = new ArrayList<>(items); - if (history.isEmpty()) { - copy.addAll(0, recentItems); + final ArrayList copy = new ArrayList<>(listAdapter.items); + if (listAdapter.history.isEmpty()) { + copy.addAll(0, listAdapter.recentItems); } boolean hasFilters = !currentSearchFilters.isEmpty(); Utilities.searchQueue.postRunnable(() -> { @@ -1430,7 +1615,7 @@ public class ChatAttachAlertDocumentLayout extends ChatAttachAlert.AttachAlertLa }, 300); } - if (!canSelectOnlyImageFiles && history.isEmpty()) { + if (!canSelectOnlyImageFiles && listAdapter.history.isEmpty()) { long dialogId = 0; long minDate = 0; long maxDate = 0; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java index eaf1228b7..5bb965ca8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertLocationLayout.java @@ -31,7 +31,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.location.Location; import android.location.LocationManager; -import android.net.Uri; import android.os.Build; import android.text.Html; import android.text.TextUtils; @@ -48,7 +47,6 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; @@ -594,7 +592,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa }); } mapTypeButton.setBackgroundDrawable(drawable); - mapTypeButton.setIcon(R.drawable.location_type); + mapTypeButton.setIcon(R.drawable.msg_map_type); mapViewClip.addView(mapTypeButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.TOP, 0, 12, 12, 0)); mapTypeButton.setOnClickListener(v -> mapTypeButton.toggleSubMenu()); mapTypeButton.setDelegate(id -> { @@ -651,7 +649,7 @@ public class ChatAttachAlertLocationLayout extends ChatAttachAlert.AttachAlertLa }); } locationButton.setBackgroundDrawable(drawable); - locationButton.setImageResource(R.drawable.location_current); + locationButton.setImageResource(R.drawable.msg_current_location); locationButton.setScaleType(ImageView.ScaleType.CENTER); locationButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.SRC_IN)); locationButton.setTag(Theme.key_location_actionActiveIcon); 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 1163f1bce..cff66d0b5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayout.java @@ -18,11 +18,10 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Outline; import android.graphics.Paint; -import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; @@ -34,7 +33,6 @@ import android.os.Build; import android.provider.MediaStore; import android.provider.Settings; import android.text.TextUtils; -import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.KeyEvent; @@ -60,14 +58,12 @@ import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; import androidx.annotation.Keep; -import androidx.core.graphics.ColorUtils; import androidx.exifinterface.media.ExifInterface; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearSmoothScroller; import androidx.recyclerview.widget.RecyclerView; -import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildVars; @@ -93,8 +89,6 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; -import org.telegram.ui.ActionBar.AlertDialog; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.BasePermissionsActivity; import org.telegram.ui.Cells.PhotoAttachCameraCell; @@ -121,7 +115,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou private PhotoAttachAdapter cameraAttachAdapter; private ActionBarMenuItem dropDownContainer; - private TextView dropDown; + public TextView dropDown; private Drawable dropDownDrawable; public RecyclerListView gridView; @@ -307,6 +301,16 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } private PhotoViewer.PhotoViewerProvider photoViewerProvider = new BasePhotoProvider() { + @Override + public void onOpen() { + pauseCameraPreview(); + } + + @Override + public void onClose() { + resumeCameraPreview(); + } + @Override public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { PhotoAttachPhotoCell cell = getCellForIndex(index); @@ -691,7 +695,6 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } if (selectedPhotos.size() > 0 && selectedPhotosOrder.size() > 0) { Object o = selectedPhotos.get(selectedPhotosOrder.get(0)); - CharSequence firstPhotoCaption = null; if (o instanceof MediaController.PhotoEntry) { MediaController.PhotoEntry photoEntry1 = (MediaController.PhotoEntry) o; photoEntry1.caption = parentAlert.getCommentTextView().getText(); @@ -930,7 +933,15 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou return; } mediaFromExternalCamera = false; - MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, outputFile.getAbsolutePath(), 0, true, 0, 0, 0); + int width = 0, height = 0; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(new File(thumbPath).getAbsolutePath(), options); + width = options.outWidth; + height = options.outHeight; + } catch (Exception ignore) {} + MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, outputFile.getAbsolutePath(), 0, true, width, height, 0); photoEntry.duration = (int) duration; photoEntry.thumbPath = thumbPath; if (parentAlert.avatarPicker != 0 && cameraView.isFrontface()) { @@ -994,7 +1005,15 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou FileLog.e(e); } mediaFromExternalCamera = false; - MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, cameraFile.getAbsolutePath(), orientation, false, 0, 0, 0); + int width = 0, height = 0; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(new File(cameraFile.getAbsolutePath()).getAbsolutePath(), options); + width = options.outWidth; + height = options.outHeight; + } catch (Exception ignore) {} + MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, cameraFile.getAbsolutePath(), orientation, false, width, height, 0); photoEntry.canDeleteAfter = true; openPhotoViewer(photoEntry, sameTakePictureOrientation, false); }); @@ -1406,6 +1425,16 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } PhotoViewer.getInstance().openPhotoForSelect(arrayList, index, type, false, new BasePhotoProvider() { + @Override + public void onOpen() { + pauseCameraPreview(); + } + + @Override + public void onClose() { + resumeCameraPreview(); + } + @Override public ImageReceiver.BitmapHolder getThumbForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index) { return null; @@ -2006,7 +2035,15 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } catch (Exception e) { FileLog.e(e); } - MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, currentPicturePath, orientation, false, 0, 0, 0); + int width = 0, height = 0; + try { + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + BitmapFactory.decodeFile(new File(currentPicturePath).getAbsolutePath(), options); + width = options.outWidth; + height = options.outHeight; + } catch (Exception ignore) {} + MediaController.PhotoEntry photoEntry = new MediaController.PhotoEntry(0, lastImageId--, 0, currentPicturePath, orientation, false, width, height, 0); photoEntry.canDeleteAfter = true; openPhotoViewer(photoEntry, false, true); } else if (requestCode == 2) { @@ -2078,7 +2115,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } SharedConfig.saveConfig(); - MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, lastImageId--, 0, videoPath, 0, true, 0, 0, 0); + MediaController.PhotoEntry entry = new MediaController.PhotoEntry(0, lastImageId--, 0, videoPath, 0, true, bitmap.getWidth(), bitmap.getHeight(), 0); entry.duration = (int) duration; entry.thumbPath = cacheFile.getAbsolutePath(); openPhotoViewer(entry, false, true); @@ -2265,7 +2302,6 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou cameraIcon.setAlpha(0.0f); } - Log.i("caapl", "cameraViewH=" + cameraViewH + " (endHeight=" + endHeight + ") value=" + value); if (layoutParams.width != cameraViewW || layoutParams.height != cameraViewH) { layoutParams.width = cameraViewW; layoutParams.height = cameraViewH; @@ -2538,7 +2574,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou Intent videoPickerIntent = new Intent(); videoPickerIntent.setType("video/*"); videoPickerIntent.setAction(Intent.ACTION_GET_CONTENT); - videoPickerIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.MAX_FILE_SIZE); + videoPickerIntent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, FileLoader.DEFAULT_MAX_FILE_SIZE); Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); photoPickerIntent.setType("image/*"); @@ -2624,7 +2660,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } } - private boolean captionForAllMedia() { + public boolean captionForAllMedia() { int captionCount = 0; for (int a = 0; a < selectedPhotosOrder.size(); a++) { Object o = selectedPhotos.get(selectedPhotosOrder.get(a)); @@ -2881,16 +2917,7 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou checkCameraViewPosition(); - try { - if (cameraView != null) { - CameraSession cameraSession = cameraView.getCameraSession(); - if (cameraSession != null) { - CameraController.getInstance().startPreview(cameraSession); - } - } - } catch (Exception e) { - FileLog.e(e); - } + resumeCameraPreview(); } @Override @@ -2958,6 +2985,10 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou headerAnimator = dropDown.animate().alpha(0f).setDuration(150).setInterpolator(CubicBezierInterpolator.EASE_BOTH).withEndAction(() -> dropDownContainer.setVisibility(GONE)); headerAnimator.start(); + pauseCameraPreview(); + } + + private void pauseCameraPreview() { try { if (cameraView != null) { CameraSession cameraSession = cameraView.getCameraSession(); @@ -2970,6 +3001,19 @@ public class ChatAttachAlertPhotoLayout extends ChatAttachAlert.AttachAlertLayou } } + private void resumeCameraPreview() { + try { + if (cameraView != null) { + CameraSession cameraSession = cameraView.getCameraSession(); + if (cameraSession != null) { + CameraController.getInstance().startPreview(cameraSession); + } + } + } catch (Exception e) { + FileLog.e(e); + } + } + @Override void onHidden() { if (cameraView != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayoutPreview.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayoutPreview.java index e44307268..21e32b8f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayoutPreview.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlertPhotoLayoutPreview.java @@ -45,12 +45,15 @@ import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.VideoEditedInfo; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ChatActionCell; import org.telegram.ui.ChatActivity; +import org.telegram.ui.PhotoViewer; import java.util.ArrayList; import java.util.Arrays; @@ -71,10 +74,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle public RecyclerListView listView; private LinearLayoutManager layoutManager; - public PaddingBox paddingView; private PreviewGroupsView groupsView; private UndoView undoView; - private TextView header; + public TextView header; private float draggingCellTouchX = 0, draggingCellTouchY = 0; private float draggingCellTop = 0, draggingCellLeft = 0; @@ -177,37 +179,13 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle groupsView.deletedPhotos.clear(); groupsView.fromPhotoLayout(photoLayout); - undoView = new UndoView(context); + undoView = new UndoView(context, null, false, parentAlert.parentThemeDelegate); undoView.setEnterOffsetMargin(AndroidUtilities.dp(8 + 24)); addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 52)); videoPlayImage = context.getResources().getDrawable(R.drawable.play_mini_video); } - public class PaddingBox extends View { - private PaddingBox(Context context) { - super(context); - } - - private int thisHeight = 0; - public boolean setPadding(int height) { - if (thisHeight != height && getMeasuredHeight() != height) { - thisHeight = height; - requestLayout(); - return true; - } - return false; - } - public int getPadding() { - return thisHeight; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.max(0, thisHeight), MeasureSpec.EXACTLY)); - } - } - private ViewPropertyAnimator headerAnimator; private ChatAttachAlertPhotoLayout photoLayout; private boolean shown = false; @@ -243,7 +221,8 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle if (headerAnimator != null) { headerAnimator.cancel(); } - headerAnimator = header.animate().alpha(1f).setDuration(150).setInterpolator(CubicBezierInterpolator.EASE_BOTH); + + headerAnimator = header.animate().alpha(1f).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT); headerAnimator.start(); } @@ -949,13 +928,16 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle } public void fromPhotoLayout(ChatAttachAlertPhotoLayout photoLayout) { - ArrayList photosOrder = photoLayout.getSelectedPhotosOrder(); - HashMap photosMap = photoLayout.getSelectedPhotos(); + photosOrder = photoLayout.getSelectedPhotosOrder(); + photosMap = photoLayout.getSelectedPhotos(); + fromPhotoArrays(); + } + public void fromPhotoArrays() { groupCells.clear(); ArrayList photos = new ArrayList<>(); final int photosOrderSize = photosOrder.size(), - photosOrderLast = photosOrderSize - 1; + photosOrderLast = photosOrderSize - 1; for (int i = 0; i < photosOrderSize; ++i) { int imageId = (Integer) photosOrder.get(i); photos.add((MediaController.PhotoEntry) photosMap.get(imageId)); @@ -967,13 +949,17 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle } } } - public void toPhotoLayout(ChatAttachAlertPhotoLayout photoLayout, boolean updateLayout) { - int previousCount = photoLayout.getSelectedPhotosOrder().size(); - HashMap photosMap = photoLayout.getSelectedPhotos(); - List> photosMapKeys = new ArrayList<>(photosMap.entrySet()); - HashMap selectedPhotos = new HashMap<>(); - ArrayList photosOrder = new ArrayList<>(); + HashMap photosMap; + List> photosMapKeys; + HashMap selectedPhotos; + ArrayList photosOrder; + + public void calcPhotoArrays() { + photosMap = photoLayout.getSelectedPhotos(); + photosMapKeys = new ArrayList<>(photosMap.entrySet()); + selectedPhotos = new HashMap<>(); + photosOrder = new ArrayList<>(); final int groupCellsCount = groupCells.size(); for (int i = 0; i < groupCellsCount; ++i) { @@ -1007,11 +993,11 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle Map.Entry entry = photosMapKeys.get(k); Object value = entry.getValue(); if ( - value instanceof MediaController.PhotoEntry && - ((MediaController.PhotoEntry) value).path != null && - photoEntry != null && - ((MediaController.PhotoEntry) value).path.equals(photoEntry.path) - ) { + value instanceof MediaController.PhotoEntry && + ((MediaController.PhotoEntry) value).path != null && + photoEntry != null && + ((MediaController.PhotoEntry) value).path.equals(photoEntry.path) + ) { Object key = entry.getKey(); selectedPhotos.put(key, value); photosOrder.add(key); @@ -1022,6 +1008,11 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle } } } + } + + public void toPhotoLayout(ChatAttachAlertPhotoLayout photoLayout, boolean updateLayout) { + int previousCount = photoLayout.getSelectedPhotosOrder().size(); + calcPhotoArrays(); photoLayout.updateSelected(selectedPhotos, photosOrder, updateLayout); if (previousCount != photosOrder.size()) { @@ -1325,6 +1316,228 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle postDelayed(this, 15); } }; + /* + * + * + if (getSelectedItemsCount() > 1) { + // short tap -> remove photo + final MediaController.PhotoEntry photo = tapMediaCell.photoEntry; + final int index = tapGroupCell.group.photos.indexOf(photo); + if (index >= 0) { + saveDeletedImageId(photo); + final PreviewGroupCell groupCell = tapGroupCell; + groupCell.group.photos.remove(index); + groupCell.setGroup(groupCell.group, true); + updateGroups(); + toPhotoLayout(photoLayout, false); + + final int currentUndoViewId = ++undoViewId; + undoView.showWithAction(0, ACTION_PREVIEW_MEDIA_DESELECTED, photo, null, () -> { + if (draggingAnimator != null) { + draggingAnimator.cancel(); + } + draggingCell = null; + draggingT = 0; + pushToGroup(groupCell, photo, index); + updateGroups(); + toPhotoLayout(photoLayout, false); + }); + + postDelayed(() -> { + if (currentUndoViewId == undoViewId && undoView.isShown()) { + undoView.hide(true, 1); + } + }, 1000 * 4); + } + + if (draggingAnimator != null) { + draggingAnimator.cancel(); + } + } + * */ + + GroupingPhotoViewerProvider photoViewerProvider = new GroupingPhotoViewerProvider(); + + class GroupingPhotoViewerProvider extends PhotoViewer.EmptyPhotoViewerProvider { + private ArrayList photos = new ArrayList<>(); + public void init(ArrayList photos) { + this.photos = photos; + } + + @Override + public void onClose() { + fromPhotoArrays(); + toPhotoLayout(photoLayout, false); + } + + @Override + public boolean isPhotoChecked(int index) { + if (index < 0 || index >= photos.size()) { + return false; + } + return photosOrder.contains((Integer) photos.get(index).imageId); + } + + @Override + public int setPhotoChecked(int index, VideoEditedInfo videoEditedInfo) { + if (index < 0 || index >= photos.size()) { + return -1; + } + Object imageId = photos.get(index).imageId; + int orderIndex = photosOrder.indexOf((Integer) imageId); + if (orderIndex >= 0) { + if (photosOrder.size() <= 1) { + return -1; + } + photosOrder.remove(orderIndex); + fromPhotoArrays(); + return orderIndex; + } else { + photosOrder.add(imageId); + fromPhotoArrays(); + return photosOrder.size() - 1; + } + } + + @Override + public int setPhotoUnchecked(Object entry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) entry; + Object imageId = photoEntry.imageId; + if (photosOrder.size() <= 1) { + return -1; + } + int index = photosOrder.indexOf((Integer) imageId); + if (index >= 0) { + photosOrder.remove(index); + fromPhotoArrays(); + return index; + } + return -1; + } + + @Override + public int getSelectedCount() { + return photosOrder.size(); + } + + @Override + public ArrayList getSelectedPhotosOrder() { + return photosOrder; + } + + @Override + public HashMap getSelectedPhotos() { + return photosMap; + } + + @Override + public int getPhotoIndex(int index) { + if (index < 0 || index >= photos.size()) { + return -1; + } + MediaController.PhotoEntry photoEntry = photos.get(index); + if (photoEntry == null) { + return -1; + } + return photosOrder.indexOf(photoEntry.imageId); + } + + @Override + public PhotoViewer.PlaceProviderObject getPlaceForPhoto(MessageObject messageObject, TLRPC.FileLocation fileLocation, int index, boolean needPreview) { + if (index < 0 || index >= photos.size() || !isPhotoChecked(index)) { + return null; + } + MediaController.PhotoEntry photoEntry = photos.get(index); + if (photoEntry != null) { + PreviewGroupCell group = null; + PreviewGroupCell.MediaCell mediaCell = null; + final int groupCellsCount = groupCells.size(); + for (int i = 0; i < groupCellsCount; ++i) { + group = groupCells.get(i); + if (group != null && group.media != null) { + final int count = group.media.size(); + for (int j = 0; j < count; ++j) { + PreviewGroupCell.MediaCell cell = group.media.get(j); + if (cell != null && cell.photoEntry == photoEntry && cell.scale > .5) { + mediaCell = group.media.get(j); + break; + } + } + if (mediaCell != null) { + break; + } + } + } + + if (group != null && mediaCell != null) { + PhotoViewer.PlaceProviderObject object = new PhotoViewer.PlaceProviderObject(); + int[] coords = new int[2]; + getLocationInWindow(coords); + if (Build.VERSION.SDK_INT < 26) { + coords[0] -= parentAlert.getLeftInset(); + } + object.viewX = coords[0]; + object.viewY = coords[1] + (int) group.y; + object.scale = 1; + object.parentView = PreviewGroupsView.this; + object.imageReceiver = mediaCell.image; + object.thumb = object.imageReceiver.getBitmapSafe(); + object.radius = new int[4]; + object.radius[0] = (int) mediaCell.roundRadiuses.left; + object.radius[1] = (int) mediaCell.roundRadiuses.top; + object.radius[2] = (int) mediaCell.roundRadiuses.right; + object.radius[3] = (int) mediaCell.roundRadiuses.bottom; + object.clipTopAddition = (int) (-PreviewGroupsView.this.getY()); + object.clipBottomAddition = PreviewGroupsView.this.getHeight() - (int) (-PreviewGroupsView.this.getY() + listView.getHeight() - parentAlert.getClipLayoutBottom()); + return object; + } + } + return null; + } + + @Override + public boolean cancelButtonPressed() { + return false; + } + + @Override + public void updatePhotoAtIndex(int index) { + if (index < 0 || index >= photos.size()) { + return; + } + MediaController.PhotoEntry photoEntry = photos.get(index); + if (photoEntry == null) { + return; + } + int imageId = photoEntry.imageId; + invalidate(); + for (int i = 0; i < groupCells.size(); ++i) { + PreviewGroupCell groupCell = groupCells.get(i); + if (groupCell != null && groupCell.media != null) { + for (int j = 0; j < groupCell.media.size(); ++j) { + PreviewGroupCell.MediaCell mediaCell = groupCell.media.get(j); + if (mediaCell != null && mediaCell.photoEntry.imageId == imageId) { + mediaCell.setImage(photoEntry); + } + } + boolean hadUpdates = false; + if (groupCell.group != null && groupCell.group.photos != null) { + for (int j = 0; j < groupCell.group.photos.size(); ++j) { + if (groupCell.group.photos.get(j).imageId == imageId) { + groupCell.group.photos.set(j, photoEntry); + hadUpdates = true; + } + } + } + if (hadUpdates) { + groupCell.setGroup(groupCell.group, true); + } + } + } + remeasure(); + invalidate(); + } + }; private int undoViewId = 0; @@ -1475,11 +1688,9 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle int tapIndex = replaceGroupCell.group.photos.indexOf(replaceMediaCell.photoEntry); if (draggingIndex >= 0) { draggingCell.groupCell.group.photos.remove(draggingIndex); -// draggingCell.groupCell.group.photos.add(draggingIndex, replaceMediaCell.photoEntry); draggingCell.groupCell.setGroup(draggingCell.groupCell.group, true); } if (tapIndex >= 0) { -// replaceMediaCell.group.photos.remove(tapIndex); if (groupCells.indexOf(replaceGroupCell) > groupCells.indexOf(draggingCell.groupCell)) { tapIndex++; } @@ -1517,39 +1728,75 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle stopDragging(); result = true; } else if (action == MotionEvent.ACTION_UP && draggingCell == null && tapMediaCell != null && tapGroupCell != null) { - if (getSelectedItemsCount() > 1) { - // short tap -> remove photo - final MediaController.PhotoEntry photo = tapMediaCell.photoEntry; - final int index = tapGroupCell.group.photos.indexOf(photo); - if (index >= 0) { - saveDeletedImageId(photo); - final PreviewGroupCell groupCell = tapGroupCell; - groupCell.group.photos.remove(index); - groupCell.setGroup(groupCell.group, true); - updateGroups(); - toPhotoLayout(photoLayout, false); - final int currentUndoViewId = ++undoViewId; - undoView.showWithAction(0, ACTION_PREVIEW_MEDIA_DESELECTED, photo, null, () -> { - if (draggingAnimator != null) { - draggingAnimator.cancel(); - } - draggingCell = null; - draggingT = 0; - pushToGroup(groupCell, photo, index); + RectF cellRect = tapMediaCell.drawingRect(); + AndroidUtilities.rectTmp.set(cellRect.right - AndroidUtilities.dp(36.4f), tapGroupCell.top + cellRect.top, cellRect.right, tapGroupCell.top + cellRect.top + AndroidUtilities.dp(36.4f)); + boolean tappedAtIndex = AndroidUtilities.rectTmp.contains(touchX, touchY - tapMediaCell.groupCell.y); + + if (tappedAtIndex) { + if (getSelectedItemsCount() > 1) { + // short tap -> remove photo + final MediaController.PhotoEntry photo = tapMediaCell.photoEntry; + final int index = tapGroupCell.group.photos.indexOf(photo); + if (index >= 0) { + saveDeletedImageId(photo); + final PreviewGroupCell groupCell = tapGroupCell; + groupCell.group.photos.remove(index); + groupCell.setGroup(groupCell.group, true); updateGroups(); toPhotoLayout(photoLayout, false); - }); - postDelayed(() -> { - if (currentUndoViewId == undoViewId && undoView.isShown()) { - undoView.hide(true, 1); - } - }, 1000 * 4); + final int currentUndoViewId = ++undoViewId; + undoView.showWithAction(0, ACTION_PREVIEW_MEDIA_DESELECTED, photo, null, () -> { + if (draggingAnimator != null) { + draggingAnimator.cancel(); + } + draggingCell = null; + draggingT = 0; + pushToGroup(groupCell, photo, index); + updateGroups(); + toPhotoLayout(photoLayout, false); + }); + + postDelayed(() -> { + if (currentUndoViewId == undoViewId && undoView.isShown()) { + undoView.hide(true, 1); + } + }, 1000 * 4); + } + + if (draggingAnimator != null) { + draggingAnimator.cancel(); + } } - - if (draggingAnimator != null) { - draggingAnimator.cancel(); + } else { + calcPhotoArrays(); + ArrayList arrayList = getPhotos(); + int position = arrayList.indexOf(tapMediaCell.photoEntry); + ChatActivity chatActivity; + int type; + if (parentAlert.avatarPicker != 0) { + chatActivity = null; + type = PhotoViewer.SELECT_TYPE_AVATAR; + } else if (parentAlert.baseFragment instanceof ChatActivity) { + chatActivity = (ChatActivity) parentAlert.baseFragment; + type = 0; + } else { + chatActivity = null; + type = 4; + } + if (!parentAlert.delegate.needEnterComment()) { + AndroidUtilities.hideKeyboard(parentAlert.baseFragment.getFragmentView().findFocus()); + AndroidUtilities.hideKeyboard(parentAlert.getContainer().findFocus()); + } + PhotoViewer.getInstance().setParentActivity(parentAlert.baseFragment.getParentActivity(), resourcesProvider); + PhotoViewer.getInstance().setParentAlert(parentAlert); + PhotoViewer.getInstance().setMaxSelectedPhotos(parentAlert.maxSelectedPhotos, parentAlert.allowOrder); + photoViewerProvider.init(arrayList); + ArrayList objectArrayList = new ArrayList<>(arrayList); + PhotoViewer.getInstance().openPhotoForSelect(objectArrayList, position, type, false, photoViewerProvider, chatActivity); + if (photoLayout.captionForAllMedia()) { + PhotoViewer.getInstance().setCaption(parentAlert.getCommentTextView().getText()); } } tapMediaCell = null; @@ -1651,27 +1898,24 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle } else { videoDurationText = null; } -// if (images.containsKey(photoEntry)) { -// image = images.get(photoEntry); -// } else { + if (image == null) { image = new ImageReceiver(PreviewGroupsView.this); - if (photoEntry != null) { - if (photoEntry.thumbPath != null) { - image.setImage(ImageLocation.getForPath(photoEntry.thumbPath), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); - } else if (photoEntry.path != null) { - if (photoEntry.isVideo) { - image.setImage(ImageLocation.getForPath("vthumb://" + photoEntry.imageId + ":" + photoEntry.path), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); - image.setAllowStartAnimation(true); - } else { - image.setOrientation(photoEntry.orientation, true); - image.setImage(ImageLocation.getForPath("thumb://" + photoEntry.imageId + ":" + photoEntry.path), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); - } + } + if (photoEntry != null) { + if (photoEntry.thumbPath != null) { + image.setImage(ImageLocation.getForPath(photoEntry.thumbPath), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); + } else if (photoEntry.path != null) { + if (photoEntry.isVideo) { + image.setImage(ImageLocation.getForPath("vthumb://" + photoEntry.imageId + ":" + photoEntry.path), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); + image.setAllowStartAnimation(true); } else { - image.setImageBitmap(Theme.chat_attachEmptyDrawable); + image.setOrientation(photoEntry.orientation, true); + image.setImage(ImageLocation.getForPath("thumb://" + photoEntry.imageId + ":" + photoEntry.path), null, null, null, Theme.chat_attachEmptyDrawable, 0, null, null, 0); } + } else { + image.setImageBitmap(Theme.chat_attachEmptyDrawable); } -// images.put(photoEntry, image); -// } + } } private void layoutFrom(MediaCell fromCell) { @@ -1841,7 +2085,7 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle private Rect indexIn = new Rect(), indexOut = new Rect(); private Rect durationIn = new Rect(), durationOut = new Rect(); - private void drawPhotoIndex(Canvas canvas, float top, float right, String indexText, float scale) { + private void drawPhotoIndex(Canvas canvas, float top, float right, String indexText, float scale, float alpha) { final int radius = AndroidUtilities.dp(12), strokeWidth = AndroidUtilities.dp(1.2f), sz = (radius + strokeWidth) * 2, @@ -1889,12 +2133,12 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle if (indexBitmap != null) { indexOut.set((int) (right - sz * scale + pad), (int) (top - pad), (int) (right + pad), (int) (top - pad + sz * scale)); - bitmapPaint.setAlpha((int) (255 * scale)); + bitmapPaint.setAlpha((int) (255 * alpha)); canvas.drawBitmap(indexBitmap, indexIn, indexOut, bitmapPaint); } } - private void drawDuration(Canvas canvas, float left, float bottom, String durationText, float scale) { + private void drawDuration(Canvas canvas, float left, float bottom, String durationText, float scale, float alpha) { if (durationText != null) { if (videoDurationBitmap == null || videoDurationBitmapText == null || !videoDurationBitmapText.equals(durationText)) { if (videoDurationTextPaint == null) { @@ -1932,11 +2176,14 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle int w = videoDurationBitmap.getWidth(), h = videoDurationBitmap.getHeight(); durationOut.set((int) left, (int) (bottom - h * scale), (int) (left + w * scale), (int) bottom); - bitmapPaint.setAlpha((int) (255 * scale)); + bitmapPaint.setAlpha((int) (255 * alpha)); canvas.drawBitmap(videoDurationBitmap, durationIn, durationOut, bitmapPaint); } } + private float visibleT = 1; + private long lastVisibleTUpdate = 0; + public boolean draw(Canvas canvas) { return draw(canvas, false); } @@ -1976,14 +2223,26 @@ public class ChatAttachAlertPhotoLayoutPreview extends ChatAttachAlert.AttachAle int index = indexStart + group.photos.indexOf(photoEntry); String indexText = index >= 0 ? (index + 1) + "" : null; - drawPhotoIndex(canvas, drawingRect.top + AndroidUtilities.dp(10), drawingRect.right - AndroidUtilities.dp(10), indexText, scale); - drawDuration(canvas, drawingRect.left + AndroidUtilities.dp(4), drawingRect.bottom - AndroidUtilities.dp(4), videoDurationText, scale); + float shouldVisibleT = image.getVisible() ? 1 : 0; + boolean needVisibleTUpdate; + if (needVisibleTUpdate = Math.abs(visibleT - shouldVisibleT) > 0.01f) { + long tx = Math.min(17, SystemClock.elapsedRealtime() - lastVisibleTUpdate); + lastVisibleTUpdate = SystemClock.elapsedRealtime(); + float upd = tx / 100f; + if (shouldVisibleT < visibleT) { + visibleT = Math.max(0, visibleT - upd); + } else { + visibleT = Math.min(1, visibleT + upd); + } + } + drawPhotoIndex(canvas, drawingRect.top + AndroidUtilities.dp(10), drawingRect.right - AndroidUtilities.dp(10), indexText, scale, scale * visibleT); + drawDuration(canvas, drawingRect.left + AndroidUtilities.dp(4), drawingRect.bottom - AndroidUtilities.dp(4), videoDurationText, scale, scale * visibleT); if (ignoreBounds) { canvas.restore(); } - return t < 1f; + return t < 1f || needVisibleTUpdate; } } 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 242b59fe7..6f44e6b82 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -13,6 +13,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; @@ -24,7 +26,10 @@ import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; +import androidx.core.content.ContextCompat; + import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; @@ -50,7 +55,9 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent private BackupImageView avatarImageView; private SimpleTextView titleTextView; + private SimpleTextView titleTextLargerCopyView; private SimpleTextView subtitleTextView; + private SimpleTextView subtitleTextLargerCopyView; private ImageView timeItem; private TimerDrawable timerDrawable; private ChatActivity parentFragment; @@ -61,9 +68,14 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent private int leftPadding = AndroidUtilities.dp(8); StatusDrawable currentTypingDrawable; + private int lastWidth = -1; + private int largerWidth = -1; + + private AnimatorSet titleAnimation; private boolean[] isOnline = new boolean[1]; + public boolean[] statusMadeShorter = new boolean[1]; private boolean secretChatTimer; @@ -76,6 +88,9 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent private SharedMediaLayout.SharedMediaPreloader sharedMediaPreloader; private Theme.ResourcesProvider resourcesProvider; + public boolean allowShorterStatus = false; + public boolean premiumIconHiddable = false; + public ChatAvatarContainer(Context context, ChatActivity chatActivity, boolean needTime) { this(context, chatActivity, needTime, null); } @@ -113,7 +128,23 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent avatarImageView.setOnClickListener(v -> openProfile(true)); } - titleTextView = new SimpleTextView(context); + titleTextView = new SimpleTextView(context) { + @Override + public boolean setText(CharSequence value) { + if (titleTextLargerCopyView != null) { + titleTextLargerCopyView.setText(value); + } + return super.setText(value); + } + + @Override + public void setTranslationY(float translationY) { + if (titleTextLargerCopyView != null) { + titleTextLargerCopyView.setTranslationY(translationY); + } + super.setTranslationY(translationY); + } + }; titleTextView.setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle)); titleTextView.setTextSize(18); titleTextView.setGravity(Gravity.LEFT); @@ -121,7 +152,23 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent titleTextView.setLeftDrawableTopPadding(-AndroidUtilities.dp(1.3f)); addView(titleTextView); - subtitleTextView = new SimpleTextView(context); + subtitleTextView = new SimpleTextView(context) { + @Override + public boolean setText(CharSequence value) { + if (subtitleTextLargerCopyView != null) { + subtitleTextLargerCopyView.setText(value); + } + return super.setText(value); + } + + @Override + public void setTranslationY(float translationY) { + if (subtitleTextLargerCopyView != null) { + subtitleTextLargerCopyView.setTranslationY(translationY); + } + super.setTranslationY(translationY); + } + }; subtitleTextView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubtitle)); subtitleTextView.setTag(Theme.key_actionBarDefaultSubtitle); subtitleTextView.setTextSize(14); @@ -255,7 +302,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent ImageLoader imageLoader = ImageLoader.getInstance(); if (key != null && !imageLoader.isInMemCache(key, false)) { Drawable drawable = imageReceiver.getDrawable(); - if (drawable instanceof BitmapDrawable) { + if (drawable instanceof BitmapDrawable && !(drawable instanceof AnimatedFileDrawable)) { imageLoader.putImageToCache((BitmapDrawable) drawable, key, false); } } @@ -316,6 +363,54 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent timeItem.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(34), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(34), MeasureSpec.EXACTLY)); } setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec)); + if (lastWidth != -1 && lastWidth != width && lastWidth > width) { + fadeOutToLessWidth(lastWidth); + } + if (titleTextLargerCopyView != null) { + int largerAvailableWidth = largerWidth - AndroidUtilities.dp((avatarImageView.getVisibility() == VISIBLE ? 54 : 0) + 16); + titleTextLargerCopyView.measure(MeasureSpec.makeMeasureSpec(largerAvailableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(24), MeasureSpec.AT_MOST)); + } + lastWidth = width; + } + + private void fadeOutToLessWidth(int largerWidth) { + this.largerWidth = largerWidth; + if (titleTextLargerCopyView != null) { + removeView(titleTextLargerCopyView); + } + titleTextLargerCopyView = new SimpleTextView(getContext()); + titleTextLargerCopyView.setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle)); + titleTextLargerCopyView.setTextSize(18); + titleTextLargerCopyView.setGravity(Gravity.LEFT); + titleTextLargerCopyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleTextLargerCopyView.setLeftDrawableTopPadding(-AndroidUtilities.dp(1.3f)); + titleTextLargerCopyView.setRightDrawable(titleTextView.getRightDrawable()); + titleTextLargerCopyView.setLeftDrawable(titleTextView.getLeftDrawable()); + titleTextLargerCopyView.setText(titleTextView.getText()); + titleTextLargerCopyView.animate().alpha(0).setDuration(350).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).withEndAction(() -> { + if (titleTextLargerCopyView != null) { + removeView(titleTextLargerCopyView); + titleTextLargerCopyView = null; + } + }).start(); + addView(titleTextLargerCopyView); + + subtitleTextLargerCopyView = new SimpleTextView(getContext()); + subtitleTextLargerCopyView.setTextColor(getThemedColor(Theme.key_actionBarDefaultSubtitle)); + subtitleTextLargerCopyView.setTag(Theme.key_actionBarDefaultSubtitle); + subtitleTextLargerCopyView.setTextSize(14); + subtitleTextLargerCopyView.setGravity(Gravity.LEFT); + subtitleTextLargerCopyView.setText(subtitleTextView.getText()); + subtitleTextLargerCopyView.animate().alpha(0).setDuration(350).setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT).withEndAction(() -> { + if (subtitleTextLargerCopyView != null) { + removeView(subtitleTextLargerCopyView); + subtitleTextLargerCopyView = null; + setClipChildren(true); + } + }).start(); + addView(subtitleTextLargerCopyView); + + setClipChildren(false); } @Override @@ -326,13 +421,22 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent int l = leftPadding + (avatarImageView.getVisibility() == VISIBLE ? AndroidUtilities.dp(54) : 0); if (subtitleTextView.getVisibility() != GONE) { titleTextView.layout(l, viewTop + AndroidUtilities.dp(1.3f), l + titleTextView.getMeasuredWidth(), viewTop + titleTextView.getTextHeight() + AndroidUtilities.dp(1.3f)); + if (titleTextLargerCopyView != null) { + titleTextLargerCopyView.layout(l, viewTop + AndroidUtilities.dp(1.3f), l + titleTextLargerCopyView.getMeasuredWidth(), viewTop + titleTextLargerCopyView.getTextHeight() + AndroidUtilities.dp(1.3f)); + } } else { titleTextView.layout(l, viewTop + AndroidUtilities.dp(11), l + titleTextView.getMeasuredWidth(), viewTop + titleTextView.getTextHeight() + AndroidUtilities.dp(11)); + if (titleTextLargerCopyView != null) { + titleTextLargerCopyView.layout(l, viewTop + AndroidUtilities.dp(11), l + titleTextLargerCopyView.getMeasuredWidth(), viewTop + titleTextLargerCopyView.getTextHeight() + AndroidUtilities.dp(11)); + } } if (timeItem != null) { timeItem.layout(leftPadding + AndroidUtilities.dp(16), viewTop + AndroidUtilities.dp(15), leftPadding + AndroidUtilities.dp(16 + 34), viewTop + AndroidUtilities.dp(15 + 34)); } subtitleTextView.layout(l, viewTop + AndroidUtilities.dp(24), l + subtitleTextView.getMeasuredWidth(), viewTop + subtitleTextView.getTextHeight() + AndroidUtilities.dp(24)); + if (subtitleTextLargerCopyView != null) { + subtitleTextLargerCopyView.layout(l, viewTop + AndroidUtilities.dp(24), l + subtitleTextLargerCopyView.getMeasuredWidth(), viewTop + subtitleTextLargerCopyView.getTextHeight() + AndroidUtilities.dp(24)); + } } public void setLeftPadding(int value) { @@ -394,27 +498,61 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } } - public void setTitleIcons(Drawable leftIcon, Drawable rightIcon) { + private boolean rightDrawableIsScamOrVerified = false; + private String rightDrawableContentDescription = null; + + public void setTitleIcons(Drawable leftIcon, Drawable mutedIcon) { titleTextView.setLeftDrawable(leftIcon); - if (!(titleTextView.getRightDrawable() instanceof ScamDrawable)) { - titleTextView.setRightDrawable(rightIcon); + if (!rightDrawableIsScamOrVerified) { + titleTextView.setRightDrawable(mutedIcon); + if (mutedIcon != null) { + rightDrawableContentDescription = LocaleController.getString("NotificationsMuted", R.string.NotificationsMuted); + } else { + rightDrawableContentDescription = null; + } } } public void setTitle(CharSequence value) { - setTitle(value, false, false); + setTitle(value, false, false, false, false); } - public void setTitle(CharSequence value, boolean scam, boolean fake) { + public void setTitle(CharSequence value, boolean scam, boolean fake, boolean verified, boolean premium) { + if (value != null) { + value = Emoji.replaceEmoji(value, titleTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(24), false); + } titleTextView.setText(value); + titleTextView.setCanHideRightDrawable(false); if (scam || fake) { if (!(titleTextView.getRightDrawable() instanceof ScamDrawable)) { ScamDrawable drawable = new ScamDrawable(11, scam ? 0 : 1); drawable.setColor(getThemedColor(Theme.key_actionBarDefaultSubtitle)); titleTextView.setRightDrawable(drawable); + rightDrawableContentDescription = LocaleController.getString("ScamMessage", R.string.ScamMessage); + rightDrawableIsScamOrVerified = true; } + } else if (verified) { + Drawable verifiedBackground = getResources().getDrawable(R.drawable.verified_area).mutate(); + verifiedBackground.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_profile_verifiedBackground), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedCheck = getResources().getDrawable(R.drawable.verified_check).mutate(); + verifiedCheck.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_profile_verifiedCheck), PorterDuff.Mode.MULTIPLY)); + Drawable verifiedDrawable = new CombinedDrawable(verifiedBackground, verifiedCheck); + titleTextView.setRightDrawable(verifiedDrawable); + rightDrawableIsScamOrVerified = true; + rightDrawableContentDescription = LocaleController.getString("AccDescrVerified", R.string.AccDescrVerified); + } else if (premium) { + if (premiumIconHiddable) { + titleTextView.setCanHideRightDrawable(true); + } + Drawable drawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_premium_liststar).mutate(); + drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_profile_verifiedBackground), PorterDuff.Mode.MULTIPLY)); + titleTextView.setRightDrawable(drawable); + rightDrawableIsScamOrVerified = true; + rightDrawableContentDescription = LocaleController.getString("AccDescrPremium", R.string.AccDescrPremium); } else if (titleTextView.getRightDrawable() instanceof ScamDrawable) { titleTextView.setRightDrawable(null); + rightDrawableIsScamOrVerified = false; + rightDrawableContentDescription = null; } } @@ -614,7 +752,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent newStatus = LocaleController.getString("Bot", R.string.Bot); } else { isOnline[0] = false; - newStatus = LocaleController.formatUserStatus(currentAccount, user, isOnline); + newStatus = LocaleController.formatUserStatus(currentAccount, user, isOnline, allowShorterStatus ? statusMadeShorter : null); useOnlineColor = isOnline[0]; } newSubtitle = newStatus; @@ -730,7 +868,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent } else { avatarDrawable.setSmallSize(false); if (avatarImageView != null) { - avatarImageView.setForUserOrChat(user, avatarDrawable); + avatarImageView.imageReceiver.setForUserOrChat(user, avatarDrawable, null, true); } } } else if (chat != null) { @@ -769,6 +907,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent super.onAttachedToWindow(); if (parentFragment != null) { NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.didUpdateConnectionState); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); currentConnectionState = ConnectionsManager.getInstance(currentAccount).getConnectionState(); updateCurrentConnectionState(); } @@ -779,6 +918,7 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent super.onDetachedFromWindow(); if (parentFragment != null) { NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.didUpdateConnectionState); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); } } @@ -790,6 +930,14 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent currentConnectionState = state; updateCurrentConnectionState(); } + } else if (id == NotificationCenter.emojiLoaded) { + if (titleTextView != null) { + titleTextView.invalidate(); + } + if (subtitleTextView != null) { + subtitleTextView.invalidate(); + } + invalidate(); } } @@ -832,6 +980,15 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); + StringBuilder sb = new StringBuilder(); + sb.append(titleTextView.getText()); + if (rightDrawableContentDescription != null) { + sb.append(", "); + sb.append(rightDrawableContentDescription); + } + sb.append("\n"); + sb.append(subtitleTextView.getText()); + info.setContentDescription(sb); if (info.isClickable() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, LocaleController.getString("OpenProfile", R.string.OpenProfile))); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatBigEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatBigEmptyView.java index fd0fc19f5..5b12c392d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatBigEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatBigEmptyView.java @@ -62,8 +62,10 @@ public class ChatBigEmptyView extends LinearLayout { textViews.add(statusTextView); addView(statusTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP)); } else { - ImageView imageView = new ImageView(context); - imageView.setImageResource(R.drawable.cloud_big); + RLottieImageView imageView = new RLottieImageView(context); + imageView.setAutoRepeat(true); + imageView.setAnimation(R.raw.utyan_saved_messages, 120, 120); + imageView.playAnimation(); addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 2, 0, 0)); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java index 8396fcc6c..4af068953 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatGreetingsView.java @@ -1,6 +1,7 @@ package org.telegram.ui.Components; import android.content.Context; +import android.graphics.Canvas; import android.util.TypedValue; import android.view.Gravity; import android.view.View; @@ -34,6 +35,7 @@ public class ChatGreetingsView extends LinearLayout { public BackupImageView stickerToSendView; private final Theme.ResourcesProvider resourcesProvider; + boolean wasDraw; public ChatGreetingsView(Context context, TLRPC.User user, int distance, int currentAccount, TLRPC.Document sticker, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -66,12 +68,12 @@ public class ChatGreetingsView extends LinearLayout { titleView.setText(LocaleController.formatString("NearbyPeopleGreetingsMessage", R.string.NearbyPeopleGreetingsMessage, user.first_name, LocaleController.formatDistance(distance, 1))); descriptionView.setText(LocaleController.getString("NearbyPeopleGreetingsDescription", R.string.NearbyPeopleGreetingsDescription)); } + stickerToSendView.setContentDescription(descriptionView.getText()); preloadedGreetingsSticker = sticker; if (preloadedGreetingsSticker == null) { preloadedGreetingsSticker = MediaDataController.getInstance(currentAccount).getGreetingsSticker(); } - setSticker(preloadedGreetingsSticker); } private void setSticker(TLRPC.Document sticker) { @@ -164,6 +166,15 @@ public class ChatGreetingsView extends LinearLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + @Override + protected void dispatchDraw(Canvas canvas) { + if (!wasDraw) { + wasDraw = true; + setSticker(preloadedGreetingsSticker); + } + super.dispatchDraw(canvas); + } + @Override public void requestLayout() { if (ignoreLayot) { @@ -186,7 +197,9 @@ public class ChatGreetingsView extends LinearLayout { private void fetchSticker() { if (preloadedGreetingsSticker == null) { preloadedGreetingsSticker = MediaDataController.getInstance(currentAccount).getGreetingsSticker(); - setSticker(preloadedGreetingsSticker); + if (wasDraw) { + setSticker(preloadedGreetingsSticker); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java index db1047ee6..7c4b72bd8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java @@ -69,7 +69,7 @@ public class ChatNotificationsPopupWrapper { ActionBarMenuSubItem item = ActionBarMenuItem.addItem(windowLayout, R.drawable.msg_mute_period, LocaleController.getString("MuteForPopup", R.string.MuteForPopup), false, resourcesProvider); item.setOnClickListener(view -> { dismiss(); - AlertsCreator.createMuteForPickerDialog(context, (notify, inSecond) -> { + AlertsCreator.createMuteForPickerDialog(context, resourcesProvider, (notify, inSecond) -> { AndroidUtilities.runOnUIThread(() -> { if (inSecond != 0) { SharedPreferences sharedPreferences = MessagesController.getNotificationsSettings(currentAccount); @@ -220,7 +220,7 @@ public class ChatNotificationsPopupWrapper { } public interface Callback { - void dismiss(); + default void dismiss() {} void toggleSound(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java index 1f1f5e552..09db6306e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatScrimPopupContainerLayout.java @@ -13,6 +13,7 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { private ReactionsContainerLayout reactionsLayout; private ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout; private View bottomView; + private int maxHeight; public ChatScrimPopupContainerLayout(Context context) { super(context); @@ -21,11 +22,17 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (maxHeight != 0) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); + } if (reactionsLayout != null && popupWindowLayout != null) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int reactionsLayoutTotalWidth = reactionsLayout.getTotalWidth(); View menuContainer = popupWindowLayout.getSwipeBack() != null ? popupWindowLayout.getSwipeBack().getChildAt(0) : popupWindowLayout.getChildAt(0); int maxReactionsLayoutWidth = menuContainer.getMeasuredWidth() + AndroidUtilities.dp(16) + AndroidUtilities.dp(16) + AndroidUtilities.dp(36); + if (maxReactionsLayoutWidth > getMeasuredWidth()) { + maxReactionsLayoutWidth = getMeasuredWidth(); + } if (reactionsLayoutTotalWidth > maxReactionsLayoutWidth) { int maxFullCount = ((maxReactionsLayoutWidth - AndroidUtilities.dp(16)) / AndroidUtilities.dp(36)) + 1; int newWidth = maxFullCount * AndroidUtilities.dp(36) + AndroidUtilities.dp(16) - AndroidUtilities.dp(8); @@ -40,9 +47,12 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { if (popupWindowLayout.getSwipeBack() != null) { widthDiff = popupWindowLayout.getSwipeBack().getMeasuredWidth() - popupWindowLayout.getSwipeBack().getChildAt(0).getMeasuredWidth(); } - if (reactionsLayout.getLayoutParams().width != LayoutHelper.WRAP_CONTENT && reactionsLayout.getLayoutParams().width + widthDiff > getMeasuredWidth()) { + if (reactionsLayout.getLayoutParams().width != LayoutHelper.WRAP_CONTENT && reactionsLayout.getLayoutParams().width + widthDiff > getMeasuredWidth() && popupWindowLayout.getSwipeBack() != null && popupWindowLayout.getSwipeBack().getMeasuredWidth() > getMeasuredWidth()) { widthDiff = getMeasuredWidth() - reactionsLayout.getLayoutParams().width + AndroidUtilities.dp(8); } + if (widthDiff < 0) { + widthDiff = 0; + } ((LayoutParams) reactionsLayout.getLayoutParams()).rightMargin = widthDiff; if (bottomView != null) { if (popupWindowLayout.getSwipeBack() != null) { @@ -67,23 +77,21 @@ public class ChatScrimPopupContainerLayout extends LinearLayout { public void setPopupWindowLayout(ActionBarPopupWindow.ActionBarPopupWindowLayout popupWindowLayout) { this.popupWindowLayout = popupWindowLayout; - popupWindowLayout.setOnSizeChangedListener(new ActionBarPopupWindow.onSizeChangedListener() { - @Override - public void onSizeChanged() { - if (bottomView != null) { - bottomView.setTranslationY(popupWindowLayout.getVisibleHeight() - popupWindowLayout.getMeasuredHeight()); - } + popupWindowLayout.setOnSizeChangedListener(() -> { + if (bottomView != null) { + bottomView.setTranslationY(popupWindowLayout.getVisibleHeight() - popupWindowLayout.getMeasuredHeight()); } }); if (popupWindowLayout.getSwipeBack() != null) { - popupWindowLayout.getSwipeBack().addOnSwipeBackProgressListener(new PopupSwipeBackLayout.OnSwipeBackProgressListener() { - @Override - public void onSwipeBackProgress(PopupSwipeBackLayout layout, float toProgress, float progress) { - if (bottomView != null) { - bottomView.setAlpha(1f - progress); - } + popupWindowLayout.getSwipeBack().addOnSwipeBackProgressListener((layout, toProgress, progress) -> { + if (bottomView != null) { + bottomView.setAlpha(1f - progress); } }); } } + + public void setMaxHeight(int maxHeight) { + this.maxHeight = maxHeight; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java index a6c78aa53..5a260a11b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatThemeBottomSheet.java @@ -22,6 +22,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -126,7 +127,17 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen darkThemeDrawable.setPlayInDirectionOfCustomEndFrame(true); darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.MULTIPLY)); - darkThemeView = new RLottieImageView(getContext()); + darkThemeView = new RLottieImageView(getContext()){ + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (forceDark) { + info.setText(LocaleController.getString("AccDescrSwitchToDayTheme", R.string.AccDescrSwitchToDayTheme)); + } else { + info.setText(LocaleController.getString("AccDescrSwitchToNightTheme", R.string.AccDescrSwitchToNightTheme)); + } + } + }; darkThemeView.setAnimation(darkThemeDrawable); darkThemeView.setScaleType(ImageView.ScaleType.CENTER); darkThemeView.setOnClickListener(view -> { @@ -696,6 +707,10 @@ public class ChatThemeBottomSheet extends BottomSheet implements NotificationCen animated = false; } + view.setFocusable(true); + view.setEnabled(true); + + view.setBackgroundColor(Theme.getColor(Theme.key_dialogBackgroundGray)); view.setItem(newItem, animated); view.setSelected(position == selectedItemPosition, animated); if (position == selectedItemPosition) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularProgressDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularProgressDrawable.java index dce400dc1..4ec8de90c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularProgressDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CircularProgressDrawable.java @@ -17,32 +17,36 @@ import org.telegram.messenger.AndroidUtilities; public class CircularProgressDrawable extends Drawable { + private float size = AndroidUtilities.dp(18); + private float thickness = AndroidUtilities.dp(2.25f); + public CircularProgressDrawable() { this(0xffffffff); } public CircularProgressDrawable(int color) { setColor(color); } + public CircularProgressDrawable(float size, float thickness, int color) { + this.size = size; + this.thickness = thickness; + setColor(color); + } private long start = -1; private final FastOutSlowInInterpolator interpolator = new FastOutSlowInInterpolator(); private float segmentFrom, segmentTo; private void updateSegment() { - final float t = (SystemClock.elapsedRealtime() - start) % 5400f / 667f; - segmentFrom = - t * 187.748148f + 250 * ( - interpolator.getInterpolation(t - 1f) + - interpolator.getInterpolation(t - 3.024f) + - interpolator.getInterpolation(t - 5.048f) + - interpolator.getInterpolation(t - 7.072f) - ) - 20; - segmentTo = - t * 187.748148f + 250 * ( - interpolator.getInterpolation(t) + - interpolator.getInterpolation(t - 2.024f) + - interpolator.getInterpolation(t - 4.048f) + - interpolator.getInterpolation(t - 6.072f) - ); + final long now = SystemClock.elapsedRealtime(); + final long t = (now - start) % 5400; + segmentFrom = 1520 * t / 5400f - 20; + segmentTo = 1520 * t / 5400f; + float fraction; + for (int i = 0; i < 4; ++i) { + fraction = (t - i * 1350) / 667f; + segmentTo += interpolator.getInterpolation(fraction) * 250; + fraction = (t - (667 + i * 1350)) / 667f; + segmentFrom += interpolator.getInterpolation(fraction) * 250; + } } private final Paint paint = new Paint(); { @@ -68,14 +72,12 @@ public class CircularProgressDrawable extends Drawable { @Override public void setBounds(int left, int top, int right, int bottom) { - final float radius = AndroidUtilities.dp(9); - final float thickness = AndroidUtilities.dp(2.25f); int width = right - left, height = bottom - top; bounds.set( - left + (width - thickness / 2f) / 2f - radius, - top + (height - thickness / 2f) / 2f - radius, - left + (width + thickness / 2f) / 2f + radius, - top + (height + thickness / 2f) / 2f + radius + left + (width - thickness / 2f - size) / 2f, + top + (height - thickness / 2f - size) / 2f, + left + (width + thickness / 2f + size) / 2f, + top + (height + thickness / 2f + size) / 2f ); super.setBounds(left, top, right, bottom); paint.setStrokeWidth(thickness); @@ -86,9 +88,13 @@ public class CircularProgressDrawable extends Drawable { } @Override - public void setAlpha(int i) {} + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + } + @Override public void setColorFilter(@Nullable ColorFilter colorFilter) {} + @Override public int getOpacity() { return PixelFormat.TRANSPARENT; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClearHistoryAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClearHistoryAlert.java index b19a451a3..a1b1381f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClearHistoryAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClearHistoryAlert.java @@ -367,7 +367,6 @@ public class ClearHistoryAlert extends BottomSheet { linearLayout.addView(buttonContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); TextInfoPrivacyCell infoCell = new TextInfoPrivacyCell(context, resourcesProvider); - infoCell.setText(LocaleController.getString("AutoDeleteInfo", R.string.AutoDeleteInfo)); buttonContainer.addView(infoCell); 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 9965945ee..5042e210d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ClippingImageView.java @@ -249,6 +249,16 @@ public class ClippingImageView extends View { orientation = angle; } + public float getCenterX() { + float scaleY = getScaleY(); + return getTranslationX() + (clipLeft / scaleY + (getWidth() - clipRight / scaleY)) / 2 * getScaleX(); + } + + public float getCenterY() { + float scaleY = getScaleY(); + return getTranslationY() + (clipTop / scaleY + (getHeight() - clipBottom / scaleY)) / 2 * getScaleY(); + } + public void setImageBitmap(ImageReceiver.BitmapHolder bitmap) { if (bmp != null) { bmp.release(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java index 44ba17dc4..d8e79e5e5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColorPicker.java @@ -35,6 +35,8 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.Keep; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; @@ -45,8 +47,6 @@ import org.telegram.ui.ActionBar.ThemeDescription; import java.util.ArrayList; import java.util.List; -import androidx.annotation.Keep; - public class ColorPicker extends FrameLayout { private final ColorPickerDelegate delegate; @@ -391,7 +391,7 @@ public class ColorPicker extends FrameLayout { addButton = new ImageView(getContext()); addButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 1)); - addButton.setImageResource(R.drawable.themes_addcolor); + addButton.setImageResource(R.drawable.msg_add); addButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.MULTIPLY)); addButton.setScaleType(ImageView.ScaleType.CENTER); addButton.setOnClickListener(v -> { @@ -485,7 +485,7 @@ public class ColorPicker extends FrameLayout { } }; clearButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 1)); - clearButton.setImageResource(R.drawable.themes_deletecolor); + clearButton.setImageResource(R.drawable.msg_close); clearButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText), PorterDuff.Mode.SRC_IN)); clearButton.setAlpha(0.0f); clearButton.setScaleX(0.0f); 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 3fc886d06..ee449192d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ColoredImageSpan.java @@ -9,48 +9,80 @@ import android.text.style.ReplacementSpan; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.ui.ActionBar.Theme; public class ColoredImageSpan extends ReplacementSpan { int drawableColor; - boolean override; +// boolean override; Drawable drawable; - public ColoredImageSpan(@NonNull Drawable drawable) { + boolean usePaintColor = true; + String colorKey; + private int topOffset = 0; + + private int size; + + public ColoredImageSpan(int imageRes) { + this(ContextCompat.getDrawable(ApplicationLoader.applicationContext, imageRes)); + } + + public ColoredImageSpan(Drawable drawable) { this.drawable = drawable; drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); } - public ColoredImageSpan(@NonNull Drawable drawable, int drawableColor) { - this.drawable = drawable; - this.drawableColor = drawableColor; - this.override = true; - drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); - drawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.SRC_IN)); +// public ColoredImageSpan(@NonNull Drawable drawable, int drawableColor) { +// this.drawable = drawable; +// this.drawableColor = drawableColor; +// this.override = true; +// drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); +// drawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.SRC_IN)); +// } + + public void setSize(int size) { + this.size = size; + drawable.setBounds(0, 0, size, size); } @Override public int getSize(@NonNull Paint paint, CharSequence charSequence, int i, int i1, @Nullable Paint.FontMetricsInt fontMetricsInt) { - return drawable.getIntrinsicWidth(); + return size != 0 ? size : drawable.getIntrinsicWidth(); } @Override public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) { - if (drawableColor != paint.getColor()) { - if (override) { - paint.setColor(drawableColor); - } else { - drawableColor = paint.getColor(); - drawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.SRC_IN)); - } + int color; + if (usePaintColor) { + // override + color = paint.getColor(); + } else { + color = Theme.getColor(colorKey); + } + if (drawableColor != color) { + drawableColor = color; + drawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.MULTIPLY)); } int lineHeight = bottom - top; - int drawableHeight = drawable.getIntrinsicHeight(); + int drawableHeight = size != 0 ? size : drawable.getIntrinsicHeight(); int padding = (lineHeight - drawableHeight) / 2; canvas.save(); - canvas.translate(x, top + padding); + canvas.translate(x, top + padding + AndroidUtilities.dp(topOffset)); drawable.draw(canvas); canvas.restore(); } + + public void setColorKey(String colorKey) { + this.colorKey = colorKey; + usePaintColor = false; + } + + public void setTopOffset(int topOffset) { + this.topOffset = topOffset; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java index 5deadc000..7b64c6e30 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropAreaView.java @@ -4,11 +4,13 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; @@ -16,16 +18,20 @@ import android.os.Build; import androidx.annotation.Keep; import android.os.SystemClock; +import android.text.TextPaint; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Interpolator; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.BubbleActivity; -public class CropAreaView extends View { +public class CropAreaView extends ViewGroup { private enum Control { NONE, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, TOP, LEFT, BOTTOM, RIGHT @@ -137,8 +143,13 @@ public class CropAreaView extends View { bitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); bitmapPaint.setColor(0xffffffff); + + setWillNotDraw(false); } + @Override + protected void onLayout(boolean b, int i, int i1, int i2, int i3) {} + public void setIsVideo(boolean value) { minWidth = AndroidUtilities.dp(value ? 64 : 32); } @@ -207,19 +218,45 @@ public class CropAreaView extends View { invalidate(); } + public float rotate = 0; + public float scale = 1; + public float tx = 0, ty = 0; + public void setRotationScaleTranslation(float rotate, float scale, float tx, float ty) { + this.rotate = rotate; + this.scale = scale; + this.tx = tx; + this.ty = ty; + invalidate(); + } + @Override protected void onDraw(Canvas canvas) { if (freeform) { - int lineThickness = AndroidUtilities.dp(2); - int handleSize = AndroidUtilities.dp(16); - int handleThickness = AndroidUtilities.dp(3); + int lineThickness = AndroidUtilities.dp(2 / scale); + int handleSize = AndroidUtilities.dp(16 / scale); + int handleThickness = AndroidUtilities.dp(3 / scale); int originX = (int) actualRect.left - lineThickness; int originY = (int) actualRect.top - lineThickness; int width = (int) (actualRect.right - actualRect.left) + lineThickness * 2; int height = (int) (actualRect.bottom - actualRect.top) + lineThickness * 2; + canvas.save(); + canvas.translate(tx, ty); + canvas.scale(scale, scale, originX + width / 2, originY + height / 2); + canvas.rotate(rotate, originX + width / 2, originY + height / 2); + if (dimVisibile) { + int left = -getWidth() * 4, top = -getHeight() * 4, + right = getWidth() * 4, bottom = getHeight() * 4; + + dimPaint.setAlpha((int) (0xff - 0x7f * frameAlpha)); + + canvas.drawRect(left, top, right, 0, dimPaint); + canvas.drawRect(left, 0, 0, getHeight(), dimPaint); + canvas.drawRect(getWidth(), 0, right, getHeight(), dimPaint); + canvas.drawRect(left, getHeight(), right, bottom, dimPaint); + canvas.drawRect(0, 0, getWidth(), originY + lineThickness, dimPaint); canvas.drawRect(0, originY + lineThickness, originX + lineThickness, originY + height - lineThickness, dimPaint); canvas.drawRect(originX + width - lineThickness, originY + lineThickness, getWidth(), originY + height - lineThickness, dimPaint); @@ -244,6 +281,11 @@ public class CropAreaView extends View { framePaint.setAlpha((int) (178 * frameAlpha)); handlePaint.setAlpha((int) (255 * frameAlpha)); + canvas.drawRect(originX + inset, originY + inset, originX + width - inset, originY + inset + lineThickness, framePaint); + canvas.drawRect(originX + inset, originY + inset, originX + inset + lineThickness, originY + height - inset, framePaint); + canvas.drawRect(originX + inset, originY + height - inset - lineThickness, originX + width - inset, originY + height - inset, framePaint); + canvas.drawRect(originX + width - inset - lineThickness, originY + inset, originX + width - inset, originY + height - inset, framePaint); + for (int i = 0; i < 3; i++) { if (type == GridType.MINOR) { for (int j = 1; j < 4; j++) { @@ -272,11 +314,6 @@ public class CropAreaView extends View { } } - canvas.drawRect(originX + inset, originY + inset, originX + width - inset, originY + inset + lineThickness, framePaint); - canvas.drawRect(originX + inset, originY + inset, originX + inset + lineThickness, originY + height - inset, framePaint); - canvas.drawRect(originX + inset, originY + height - inset - lineThickness, originX + width - inset, originY + height - inset, framePaint); - canvas.drawRect(originX + width - inset - lineThickness, originY + inset, originX + width - inset, originY + height - inset, framePaint); - canvas.drawRect(originX, originY, originX + handleSize, originY + handleThickness, handlePaint); canvas.drawRect(originX, originY, originX + handleThickness, originY + handleSize, handlePaint); @@ -288,6 +325,8 @@ public class CropAreaView extends View { canvas.drawRect(originX + width - handleSize, originY + height - handleThickness, originX + width, originY + height, handlePaint); canvas.drawRect(originX + width - handleThickness, originY + height - handleSize, originX + width, originY + height, handlePaint); + + canvas.restore(); } else { float width = getMeasuredWidth() - 2 * sidePadding; float height = getMeasuredHeight() - bottomPadding - (Build.VERSION.SDK_INT >= 21 && !inBubbleMode ? AndroidUtilities.statusBarHeight : 0) - 2 * sidePadding; @@ -556,6 +595,28 @@ public class CropAreaView extends View { rect.set(left, top, right, bottom); } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (isDragging) { + return false; + } + return super.onInterceptTouchEvent(ev); + } + + public void updateStatusShow(boolean show) { + try { + Window window = ((Activity) getContext()).getWindow(); + View decorView = window.getDecorView(); + int flags = decorView.getSystemUiVisibility(); + if (show) { + flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; + } else { + flags &= ~View.SYSTEM_UI_FLAG_FULLSCREEN; + } + decorView.setSystemUiVisibility(flags); + } catch (Exception ignore) {} + } + @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) (event.getX() - ((ViewGroup) getParent()).getX()); @@ -596,6 +657,7 @@ public class CropAreaView extends View { setGridType(GridType.MAJOR, false); isDragging = true; + updateStatusShow(true); if (listener != null) { listener.onAreaChangeBegan(); @@ -604,6 +666,7 @@ public class CropAreaView extends View { return true; } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { isDragging = false; + updateStatusShow(false); if (activeControl == Control.NONE) { return false; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java index a145e5367..30a558412 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropRotationWheel.java @@ -7,11 +7,13 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.os.Build; +import android.text.TextPaint; import android.view.Gravity; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.ImageView; -import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; @@ -40,7 +42,9 @@ public class CropRotationWheel extends FrameLayout { private ImageView aspectRatioButton; private ImageView rotation90Button; private ImageView mirrorButton; - private TextView degreesLabel; +// private TextView degreesLabel; + private String degreesText; + private TextPaint degreesTextPaint; protected float rotation; private RectF tempRect; @@ -66,7 +70,7 @@ public class CropRotationWheel extends FrameLayout { bluePaint.setAntiAlias(true); mirrorButton = new ImageView(context); - mirrorButton.setImageResource(R.drawable.photo_flip); + mirrorButton.setImageResource(R.drawable.msg_photo_flip); mirrorButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); mirrorButton.setScaleType(ImageView.ScaleType.CENTER); mirrorButton.setOnClickListener(v -> { @@ -82,7 +86,7 @@ public class CropRotationWheel extends FrameLayout { addView(mirrorButton, LayoutHelper.createFrame(70, 64, Gravity.LEFT | Gravity.CENTER_VERTICAL)); aspectRatioButton = new ImageView(context); - aspectRatioButton.setImageResource(R.drawable.tool_cropfix); + aspectRatioButton.setImageResource(R.drawable.msg_photo_cropfix); aspectRatioButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); aspectRatioButton.setScaleType(ImageView.ScaleType.CENTER); aspectRatioButton.setOnClickListener(v -> { @@ -95,7 +99,7 @@ public class CropRotationWheel extends FrameLayout { addView(aspectRatioButton, LayoutHelper.createFrame(70, 64, Gravity.LEFT | Gravity.CENTER_VERTICAL)); rotation90Button = new ImageView(context); - rotation90Button.setImageResource(R.drawable.tool_rotate); + rotation90Button.setImageResource(R.drawable.msg_photo_rotate); rotation90Button.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); rotation90Button.setScaleType(ImageView.ScaleType.CENTER); rotation90Button.setOnClickListener(v -> { @@ -106,9 +110,9 @@ public class CropRotationWheel extends FrameLayout { rotation90Button.setContentDescription(LocaleController.getString("AccDescrRotate", R.string.AccDescrRotate)); addView(rotation90Button, LayoutHelper.createFrame(70, 64, Gravity.RIGHT | Gravity.CENTER_VERTICAL)); - degreesLabel = new TextView(context); - degreesLabel.setTextColor(Color.WHITE); - addView(degreesLabel, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL)); + degreesTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + degreesTextPaint.setColor(Color.WHITE); + degreesTextPaint.setTextSize(AndroidUtilities.dp(14)); setWillNotDraw(false); @@ -147,14 +151,18 @@ public class CropRotationWheel extends FrameLayout { public void setRotation(float rotation, boolean animated) { this.rotation = rotation; - float value = this.rotation; + float value = rotation; if (Math.abs(value) < 0.1 - 0.001) value = Math.abs(value); - degreesLabel.setText(String.format("%.1fº", value)); + degreesText = String.format("%.1fº", value); invalidate(); } + public float getRotation() { + return this.rotation; + } + public void setAspectLock(boolean enabled) { aspectRatioButton.setColorFilter(enabled ? new PorterDuffColorFilter(0xff51bdf3, PorterDuff.Mode.SRC_IN) : null); } @@ -167,8 +175,9 @@ public class CropRotationWheel extends FrameLayout { if (action == MotionEvent.ACTION_DOWN) { prevX = x; - if (rotationListener != null) + if (rotationListener != null) { rotationListener.onStart(); + } } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { if (rotationListener != null) rotationListener.onEnd(this.rotation); @@ -179,14 +188,26 @@ public class CropRotationWheel extends FrameLayout { float newAngle = this.rotation + (float)(delta / AndroidUtilities.density / Math.PI / 1.65f); newAngle = Math.max(-MAX_ANGLE, Math.min(MAX_ANGLE, newAngle)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + try { + if (Math.abs(newAngle - MAX_ANGLE) < 0.001f && Math.abs(this.rotation - MAX_ANGLE) >= 0.001f || + Math.abs(newAngle - -MAX_ANGLE) < 0.001f && Math.abs(this.rotation - -MAX_ANGLE) >= 0.001f) { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } else if (Math.floor(this.rotation / 2.5f) != Math.floor(newAngle / 2.5f)) { + performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } + } catch (Exception ignore) {} + } + if (Math.abs(newAngle - this.rotation) > 0.001) { if (Math.abs(newAngle) < 0.05) newAngle = 0; setRotation(newAngle, false); - if (rotationListener != null) + if (rotationListener != null) { rotationListener.onChange(this.rotation); + } prevX = x; } @@ -228,6 +249,10 @@ public class CropRotationWheel extends FrameLayout { tempRect.right = (width + AndroidUtilities.dp(2.5f)) / 2; tempRect.bottom = (height + AndroidUtilities.dp(22)) / 2; canvas.drawRoundRect(tempRect, AndroidUtilities.dp(2), AndroidUtilities.dp(2), bluePaint); + + float tx = (width - degreesTextPaint.measureText(degreesText)) / 2; + float ty = AndroidUtilities.dp(14); + canvas.drawText(degreesText, tx, ty, degreesTextPaint); } protected void drawLine(Canvas canvas, int i, float delta, int width, int height, boolean center, Paint paint) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropTransform.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropTransform.java index 2f5235fff..4921f3574 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropTransform.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropTransform.java @@ -100,7 +100,7 @@ public class CropTransform { return cropPh; } - public boolean isMirrored () { + public boolean isMirrored() { return isMirrored; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java index 7d9a227cc..3a2515f6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Crop/CropView.java @@ -44,7 +44,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen private static final int RESULT_SIDE = 1280; private static final float MAX_SCALE = 30.0f; - private CropAreaView areaView; + public CropAreaView areaView; private ImageView imageView; private Matrix overlayMatrix; private PaintingOverlay paintingOverlay; @@ -75,19 +75,19 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen private int bitmapRotation; - private class CropState { - private float width; - private float height; + public class CropState { + public float width; + public float height; - private float x; - private float y; - private float scale; - private float minimumScale; - private float baseRotation; - private float orientation; - private float rotation; - private boolean mirrored; - private Matrix matrix; + public float x; + public float y; + public float scale; + public float minimumScale; + public float baseRotation; + public float orientation; + public float rotation; + public boolean mirrored; + public Matrix matrix; private CropState(int w, int h, int bRotation) { width = w; @@ -202,9 +202,18 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen y = 0.0f; rotation = 0.0f; orientation = orient; + updateMinimumScale(); scale = minimumScale; + matrix.postScale(scale, scale); + } + private void rotateToOrientation(float orientation) { + matrix.postScale(1f / scale, 1f / scale); + this.orientation = orientation; + float wasMinimumScale = minimumScale; + updateMinimumScale(); + scale = scale / wasMinimumScale * minimumScale; matrix.postScale(scale, scale); } @@ -231,7 +240,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen } } - private CropState state; + public CropState state; public interface CropViewListener { void onChange(boolean reset); @@ -242,6 +251,18 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen private CropViewListener listener; + public float getStateOrientation() { + return state.orientation; + } + + public float getStateFullOrientation() { + return state.baseRotation + state.orientation; + } + + public boolean getStateMirror() { + return state.mirrored; + } + public CropView(Context context) { super(context); @@ -401,13 +422,17 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen } public void reset() { + reset(false); + } + + public void reset(boolean force) { areaView.resetAnimator(); areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), state.getBaseRotation() % 180 != 0, freeform); areaView.setLockedAspectRatio(freeform ? 0.0f : 1.0f); state.reset(areaView, 0, freeform); state.mirrored = false; areaView.getCropRect(initialAreaRect); - updateMatrix(); + updateMatrix(force); resetRotationStartScale(); @@ -418,6 +443,10 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen } public void updateMatrix() { + updateMatrix(false); + } + + public void updateMatrix(boolean force) { overlayMatrix.reset(); if (state.getBaseRotation() == 90 || state.getBaseRotation() == 270) { overlayMatrix.postTranslate(-state.getHeight() / 2, -state.getWidth() / 2); @@ -427,7 +456,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen overlayMatrix.postRotate(state.getOrientationOnly()); state.getConcatMatrix(overlayMatrix); overlayMatrix.postTranslate(areaView.getCropCenterX(), areaView.getCropCenterY()); - if ((!freeform || isVisible)) { + if (!freeform || isVisible || force) { updateCropTransform(); listener.onUpdate(); } @@ -685,6 +714,13 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen return bitmapRotation == 90 || bitmapRotation == 270 ? bitmap.getWidth() : bitmap.getHeight(); } + public boolean isMirrored() { + if (state == null) { + return false; + } + return state.mirrored; + } + public boolean mirror() { if (state == null) { return false; @@ -698,7 +734,58 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen return state.mirrored; } - public boolean rotate90Degrees() { + public void maximize(boolean animated) { + final float toScale = state.minimumScale; + areaView.resetAnimator(); + float aspectRatio; + if (state.getOrientation() % 180 != 0) { + aspectRatio = getCurrentHeight() / (float) getCurrentWidth(); + } else { + aspectRatio = getCurrentWidth() / (float) getCurrentHeight(); + } + if (!freeform) { + aspectRatio = 1.0f; + } + areaView.calculateRect(initialAreaRect, aspectRatio); + areaView.setLockedAspectRatio(freeform ? 0.0f : 1.0f); + resetRotationStartScale(); + + if (animated) { + ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f); + RectF fromActualRect = new RectF(), animatedRect = new RectF(); + areaView.getCropRect(fromActualRect); + final float fromX = state.x; + final float fromY = state.y; + final float fromScale = state.scale; + final float fromRot = state.rotation; + animator.addUpdateListener(animation -> { + float t = (float) animation.getAnimatedValue(); + AndroidUtilities.lerp(fromActualRect, initialAreaRect, t, animatedRect); + areaView.setActualRect(animatedRect); + float dx = state.x - fromX * (1f - t), + dy = state.y - fromY * (1f - t), + dr = state.rotation - fromRot * (1f - t), + ds = AndroidUtilities.lerp(fromScale, toScale, t) / state.scale; + state.translate(-dx, -dy); + state.scale(ds, 0, 0); + state.rotate(-dr, 0, 0); + fitContentInBounds(true, false, false); + }); + animator.setInterpolator(areaView.getInterpolator()); + animator.setDuration(250); + animator.start(); + } else { + areaView.setActualRect(initialAreaRect); + state.translate(-state.x, -state.y); + state.scale(state.minimumScale / state.scale, 0, 0); + state.rotate(-state.rotation, 0, 0); + updateMatrix(); + + resetRotationStartScale(); + } + } + + public boolean rotate(float angle) { if (state == null) { return false; } @@ -706,7 +793,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen resetRotationStartScale(); - float orientation = (state.getOrientation() - state.getBaseRotation() - 90.0f) % 360; + float orientation = (state.getOrientation() - state.getBaseRotation() + angle) % 360; boolean fform = freeform; if (freeform && areaView.getLockAspectRatio() > 0) { @@ -714,7 +801,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen areaView.setActualRect(areaView.getLockAspectRatio()); fform = false; } else { - areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), (orientation + state.getBaseRotation()) % 180 != 0, freeform); + areaView.setBitmap(getCurrentWidth(), getCurrentHeight(), (orientation + state.getBaseRotation()) % 180 != 0, freeform); } state.reset(areaView, orientation, fform); @@ -1102,6 +1189,7 @@ public class CropView extends FrameLayout implements CropAreaView.AreaViewListen editState.cropState.lockedAspectRatio = areaView.getLockAspectRatio(); editState.cropState.initied = true; + return; } private void setLockedAspectRatio(float aspectRatio) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CrossfadeDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CrossfadeDrawable.java index a2a076971..9b173c9a7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CrossfadeDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CrossfadeDrawable.java @@ -5,6 +5,7 @@ import android.graphics.ColorFilter; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.util.Log; import androidx.annotation.NonNull; @@ -14,6 +15,7 @@ public class CrossfadeDrawable extends Drawable { private final Drawable bottomDrawable; private float progress; + float globalAlpha = 255f; public CrossfadeDrawable(Drawable topDrawable, Drawable bottomDrawable) { this.topDrawable = topDrawable; @@ -28,9 +30,17 @@ public class CrossfadeDrawable extends Drawable { } } @Override - public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long l) {} + public void scheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable, long l) { + if (progress < 1.0f) { + CrossfadeDrawable.this.scheduleSelf(runnable, l); + } + } @Override - public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) {} + public void unscheduleDrawable(@NonNull Drawable drawable, @NonNull Runnable runnable) { + if (progress < 1.0f) { + CrossfadeDrawable.this.unscheduleSelf(runnable); + } + } }); } if (bottomDrawable != null) { @@ -57,19 +67,20 @@ public class CrossfadeDrawable extends Drawable { @Override public void draw(Canvas canvas) { - if (progress < 1.0f) { - topDrawable.setAlpha((int) (255f * (1.0f - progress))); + int topAlpha, bottomAlpha; + topDrawable.setAlpha(topAlpha = (int) (globalAlpha * (1.0f - progress))); + bottomDrawable.setAlpha(bottomAlpha = (int) (globalAlpha * progress)); + if (topAlpha > 0) { topDrawable.draw(canvas); } - if (progress > 0.0f) { - bottomDrawable.setAlpha((int) (255.0f * progress)); + if (bottomAlpha > 0) { bottomDrawable.draw(canvas); } } @Override public void setAlpha(int alpha) { - + globalAlpha = alpha; } @Override @@ -98,5 +109,6 @@ public class CrossfadeDrawable extends Drawable { public void setProgress(float value) { progress = value; + invalidateSelf(); } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CustomPhoneKeyboardView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CustomPhoneKeyboardView.java index 7069af3ac..f59d0ddf3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CustomPhoneKeyboardView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CustomPhoneKeyboardView.java @@ -141,7 +141,7 @@ public class CustomPhoneKeyboardView extends ViewGroup { return backDetector.onTouchEvent(event); } }; - backButton.setImageResource(R.drawable.menu_clear); + backButton.setImageResource(R.drawable.msg_clear_input); backButton.setColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); backButton.setBackground(getButtonDrawable()); int pad = AndroidUtilities.dp(11); 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 bcf12e194..0a62881f8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextBoldCursor.java @@ -16,6 +16,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.Rect; @@ -49,6 +50,7 @@ import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.R; +import org.telegram.messenger.XiaomiUtilities; import org.telegram.ui.ActionBar.FloatingActionMode; import org.telegram.ui.ActionBar.FloatingToolbar; import org.telegram.ui.ActionBar.Theme; @@ -845,7 +847,8 @@ public class EditTextBoldCursor extends EditTextEffects { } } - int bottom = (int) lineY; + int scrollHeight = (getLayout() == null ? 0 : getLayout().getHeight()) - getMeasuredHeight() + getPaddingBottom() + getPaddingTop(); + int bottom = (int) lineY + getScrollY() + Math.min(Math.max(0, scrollHeight - getScrollY()), AndroidUtilities.dp(2)); int centerX = lastTouchX < 0 ? getMeasuredWidth() / 2 : lastTouchX, maxWidth = Math.max(centerX, getMeasuredWidth() - centerX) * 2; if (lineActiveness < 1f) { @@ -1029,11 +1032,34 @@ public class EditTextBoldCursor extends EditTextEffects { super.onInitializeAccessibilityNodeInfo(info); info.setClassName("android.widget.EditText"); if (hintLayout != null) { - AccessibilityNodeInfoCompat.wrap(info).setHintText(hintLayout.getText()); + if (getText().length() <= 0) { + info.setText(hintLayout.getText()); + } else { + AccessibilityNodeInfoCompat.wrap(info).setHintText(hintLayout.getText()); + } } } protected Theme.ResourcesProvider getResourcesProvider() { return null; } + + public void setHandlesColor(int color) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || XiaomiUtilities.isMIUI()) { + return; + } + try { + Drawable left = getTextSelectHandleLeft(); + left.setColorFilter(color, PorterDuff.Mode.SRC_IN); + setTextSelectHandleLeft(left); + + Drawable middle = getTextSelectHandle(); + middle.setColorFilter(color, PorterDuff.Mode.SRC_IN); + setTextSelectHandle(middle); + + Drawable right = getTextSelectHandleRight(); + right.setColorFilter(color, PorterDuff.Mode.SRC_IN); + setTextSelectHandleRight(right); + } catch (Exception ignore) {} + } } 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 ac3909ba8..ceceac5a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EditTextEmoji.java @@ -237,6 +237,10 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not emojiPadding = 0; } + public EmojiView getEmojiView() { + return emojiView; + } + public void setDelegate(EditTextEmojiDelegate editTextEmojiDelegate) { delegate = editTextEmojiDelegate; } @@ -379,7 +383,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } } - private void showPopup(int show) { + protected void showPopup(int show) { if (show == 1) { boolean emojiWasVisible = emojiView != null && emojiView.getVisibility() == View.VISIBLE; if (emojiView == null) { @@ -473,7 +477,7 @@ public class EditTextEmoji extends FrameLayout implements NotificationCenter.Not } } - private void createEmojiView() { + protected void createEmojiView() { if (emojiView != null) { return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java index 1078fbb32..b8927bf6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmbedBottomSheet.java @@ -729,7 +729,7 @@ public class EmbedBottomSheet extends BottomSheet { pipButton = new ImageView(context); pipButton.setScaleType(ImageView.ScaleType.CENTER); - pipButton.setImageResource(R.drawable.video_pip); + pipButton.setImageResource(R.drawable.ic_goinline); pipButton.setContentDescription(LocaleController.getString("AccDescrPipMode", R.string.AccDescrPipMode)); pipButton.setEnabled(false); pipButton.setAlpha(0.5f); @@ -812,7 +812,7 @@ public class EmbedBottomSheet extends BottomSheet { ImageView copyButton = new ImageView(context); copyButton.setScaleType(ImageView.ScaleType.CENTER); - copyButton.setImageResource(R.drawable.video_copy); + copyButton.setImageResource(R.drawable.msg_copy); copyButton.setContentDescription(LocaleController.getString("CopyLink", R.string.CopyLink)); copyButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogTextBlue4), PorterDuff.Mode.SRC_IN)); copyButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 0)); 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 64117004a..25a6fd031 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java @@ -15,7 +15,9 @@ import android.animation.ObjectAnimator; import android.animation.StateListAnimator; import android.annotation.SuppressLint; import android.annotation.TargetApi; +import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.graphics.Canvas; import android.graphics.Color; @@ -48,6 +50,7 @@ import android.view.ViewGroup; import android.view.ViewOutlineProvider; import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; import android.widget.ImageView; @@ -68,6 +71,7 @@ import androidx.recyclerview.widget.SimpleItemAnimator; import androidx.viewpager.widget.PagerAdapter; import androidx.viewpager.widget.ViewPager; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; @@ -76,7 +80,6 @@ import org.telegram.messenger.Emoji; import org.telegram.messenger.EmojiData; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.LocaleController; @@ -102,16 +105,19 @@ import org.telegram.ui.Cells.FeaturedStickerSetInfoCell; import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.Cells.StickerSetGroupInfoCell; import org.telegram.ui.Cells.StickerSetNameCell; +import org.telegram.ui.Components.Premium.PremiumGradient; import org.telegram.ui.ContentPreviewViewer; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import tw.nekomimi.nekogram.NekoConfig; import tw.nekomimi.nekogram.ui.PinnedStickerHelper; @@ -218,6 +224,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private ArrayList recentGifs = new ArrayList<>(); private ArrayList recentStickers = new ArrayList<>(); private ArrayList favouriteStickers = new ArrayList<>(); + private ArrayList premiumStickers = new ArrayList<>(); private ArrayList featuredStickerSets = new ArrayList<>(); private Paint dotPaint; @@ -239,9 +246,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific private int emojiSize; private int location[] = new int[2]; private int stickersTabOffset; - private int recentTabBum = -2; - private int favTabBum = -2; + private int recentTabNum = -2; + private int favTabNum = -2; private int trendingTabNum = -2; + private int premiumTabNum = -2; private TLRPC.ChatFull info; @@ -879,6 +887,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(widthMeasureSpec)); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.view.View"); + } } private class EmojiPopupWindow extends PopupWindow { @@ -1120,15 +1134,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific };*/ emojiIcons = new Drawable[]{ - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.baseline_access_time_24, R.drawable.baseline_access_time_filled_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.baseline_emoticon_outline_24, R.drawable.baseline_emoticon_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.deproko_baseline_animals_outline_24, R.drawable.deproko_baseline_animals_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_restaurant_menu_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.outline_sports_baseball_24, R.drawable.baseline_sports_baseball_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_directions_car_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.deproko_baseline_lamp_24, R.drawable.deproko_baseline_lamp_filled_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_emoji_symbols_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)), - Theme.createEmojiIconSelectorDrawableWithPressedResources(context, R.drawable.deproko_baseline_flag_outline_24, R.drawable.deproko_baseline_flag_filled_24, getThemedColor(Theme.key_chat_messagePanelIcons), getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)) + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_access_time_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_emoticon_outline_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.deproko_baseline_animals_outline_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_restaurant_menu_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.outline_sports_baseball_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_directions_car_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.deproko_baseline_lamp_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.baseline_emoji_symbols_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), + Theme.createEmojiIconSelectorDrawable(context, R.drawable.deproko_baseline_flag_outline_24, getThemedColor(Theme.key_chat_emojiPanelIcon), getThemedColor(Theme.key_chat_emojiPanelIconSelected)), }; stickerIcons = new Drawable[]{ @@ -1296,7 +1310,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific emojiGridView.setInstantClick(true); emojiGridView.setLayoutManager(emojiLayoutManager = new GridLayoutManager(context, 8)); emojiGridView.setTopGlowOffset(AndroidUtilities.dp(38)); - emojiGridView.setBottomGlowOffset(AndroidUtilities.dp(48)); + emojiGridView.setBottomGlowOffset(AndroidUtilities.dp(36)); emojiGridView.setPadding(0, AndroidUtilities.dp(38), 0, AndroidUtilities.dp(44)); emojiGridView.setGlowColor(getThemedColor(Theme.key_chat_emojiPanelBackground)); emojiGridView.setSelectorDrawableColor(0); @@ -1347,6 +1361,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (view instanceof ImageViewEmoji) { ImageViewEmoji viewEmoji = (ImageViewEmoji) view; viewEmoji.sendEmoji(null); + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } } }); @@ -1570,7 +1585,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } }); - gifGridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, AndroidUtilities.dp(44)); + gifGridView.setPadding(0, AndroidUtilities.dp(36 + 4), 0, AndroidUtilities.dp(44)); gifGridView.setOverScrollMode(RecyclerListView.OVER_SCROLL_NEVER); ((SimpleItemAnimator) gifGridView.getItemAnimator()).setSupportsChangeAnimations(false); gifGridView.setAdapter(gifAdapter = new GifAdapter(context, true)); @@ -1620,7 +1635,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific gifTabs.setIndicatorColor(getThemedColor(Theme.key_chat_emojiPanelStickerPackSelectorLine)); gifTabs.setUnderlineColor(getThemedColor(Theme.key_chat_emojiPanelShadowLine)); gifTabs.setBackgroundColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); - gifContainer.addView(gifTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + gifContainer.addView(gifTabs, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, StickerTabView.SMALL_HEIGHT, Gravity.LEFT | Gravity.TOP)); updateGifTabs(); gifTabs.setDelegate(page -> { @@ -1770,7 +1785,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } }); - stickersGridView.setPadding(0, AndroidUtilities.dp(4 + 48), 0, AndroidUtilities.dp(44)); + stickersGridView.setPadding(0, AndroidUtilities.dp(4 + 36), 0, AndroidUtilities.dp(44)); stickersGridView.setClipToPadding(false); views.add(stickersContainer); stickersSearchGridAdapter = new StickersSearchGridAdapter(context); @@ -1789,8 +1804,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (!(view instanceof StickerEmojiCell)) { return; } - ContentPreviewViewer.getInstance().reset(); StickerEmojiCell cell = (StickerEmojiCell) view; + if (cell.getSticker() != null && MessageObject.isPremiumSticker(cell.getSticker()) && !AccountInstance.getInstance(currentAccount).getUserConfig().isPremium()) { + ContentPreviewViewer.getInstance().showMenuFor(cell); + return; + } + ContentPreviewViewer.getInstance().reset(); + if (cell.isDisabled()) { return; } @@ -1890,7 +1910,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific canvas.clipRect(0, searchProgressOffset, getMeasuredWidth(), getMeasuredHeight()); } paint.setColor(getThemedColor(Theme.key_actionBarDefaultSubmenuBackground)); - canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(48) + stickersTab.getExpandedOffset(), paint); + canvas.drawRect(0, 0, getMeasuredWidth(), AndroidUtilities.dp(36) + stickersTab.getExpandedOffset(), paint); super.dispatchDraw(canvas); stickersTab.drawOverlays(canvas); canvas.restore(); @@ -1902,10 +1922,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific updateStickerTabsPosition(); } }; - stickersTabContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + stickersTabContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP)); parentView.addView(stickersTabContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } else { - stickersContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); + stickersContainer.addView(stickersTab, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 36, Gravity.LEFT | Gravity.TOP)); } updateStickerTabs(); stickersTab.setDelegate(page -> { @@ -1915,17 +1935,23 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (page == trendingTabNum) { openTrendingStickers(null); return; - } else if (page == recentTabBum) { + } else if (page == recentTabNum) { stickersGridView.stopScroll(); scrollStickersToPosition(stickersGridAdapter.getPositionForPack("recent"), 0); resetTabsY(Type.STICKERS); - stickersTab.onPageScrolled(recentTabBum, recentTabBum > 0 ? recentTabBum : stickersTabOffset); + stickersTab.onPageScrolled(recentTabNum, recentTabNum > 0 ? recentTabNum : stickersTabOffset); return; - } else if (page == favTabBum) { + } else if (page == favTabNum) { stickersGridView.stopScroll(); scrollStickersToPosition(stickersGridAdapter.getPositionForPack("fav"), 0); resetTabsY(Type.STICKERS); - stickersTab.onPageScrolled(favTabBum, favTabBum > 0 ? favTabBum : stickersTabOffset); + stickersTab.onPageScrolled(favTabNum, favTabNum > 0 ? favTabNum : stickersTabOffset); + return; + } else if (page == premiumTabNum) { + stickersGridView.stopScroll(); + scrollStickersToPosition(stickersGridAdapter.getPositionForPack("premium"), 0); + resetTabsY(Type.STICKERS); + stickersTab.onPageScrolled(premiumTabNum, premiumTabNum > 0 ? premiumTabNum : stickersTabOffset); return; } @@ -1942,10 +1968,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific resetTabsY(Type.STICKERS); checkScroll(Type.STICKERS); int firstTab; - if (favTabBum > 0) { - firstTab = favTabBum; - } else if (recentTabBum > 0) { - firstTab = recentTabBum; + if (favTabNum > 0) { + firstTab = favTabNum; + } else if (recentTabNum > 0) { + firstTab = recentTabNum; } else { firstTab = stickersTabOffset; } @@ -1963,7 +1989,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (getParent() != null) { getParent().requestDisallowInterceptTouchEvent(canScrollHorizontally(-1)); } - return super.onInterceptTouchEvent(ev); + try { + return super.onInterceptTouchEvent(ev); + } catch (IllegalArgumentException ignore) { + } + return false; } @Override @@ -2007,6 +2037,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return true; } }; + backspaceButton.setHapticFeedbackEnabled(true); backspaceButton.setImageResource(R.drawable.smiles_tab_clear); backspaceButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_messagePanelIcons), PorterDuff.Mode.SRC_IN)); backspaceButton.setScaleType(ImageView.ScaleType.CENTER); @@ -2524,12 +2555,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific searchAnimation = new AnimatorSet(); if (tabStrip != null && a != 2) { searchAnimation.playTogether( - ObjectAnimator.ofFloat(tabStrip, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), - ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(tabStrip, View.TRANSLATION_Y, -AndroidUtilities.dp(36)), + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(36)), ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(0))); } else { searchAnimation.playTogether( - ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(48)), + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, -AndroidUtilities.dp(36)), ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(0))); } searchAnimation.setDuration(220); @@ -2559,7 +2590,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } else { currentField.setTranslationY(AndroidUtilities.dp(0)); if (tabStrip != null && a != 2) { - tabStrip.setTranslationY(-AndroidUtilities.dp(48)); + tabStrip.setTranslationY(-AndroidUtilities.dp(36)); } if (gridView == stickersGridView) { gridView.setPadding(0, AndroidUtilities.dp(4), 0, 0); @@ -2633,7 +2664,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (set != null) { int pos = stickersGridAdapter.getPositionForPack(set); if (pos >= 0 && pos < stickersGridAdapter.getItemCount()) { - scrollStickersToPosition(pos, AndroidUtilities.dp(48 + 12)); + scrollStickersToPosition(pos, AndroidUtilities.dp(36 + 12)); } } } @@ -2676,11 +2707,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (tabStrip != null && a != 2) { searchAnimation.playTogether( ObjectAnimator.ofFloat(tabStrip, View.TRANSLATION_Y, 0), - ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, AndroidUtilities.dp(48) - searchFieldHeight), - ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(48) - searchFieldHeight)); + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, AndroidUtilities.dp(36) - searchFieldHeight), + ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, AndroidUtilities.dp(36) - searchFieldHeight)); } else { searchAnimation.playTogether( - ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, AndroidUtilities.dp(48) - searchFieldHeight), + ObjectAnimator.ofFloat(gridView, View.TRANSLATION_Y, AndroidUtilities.dp(36) - searchFieldHeight), ObjectAnimator.ofFloat(currentField, View.TRANSLATION_Y, -searchFieldHeight)); } searchAnimation.setDuration(200); @@ -2697,9 +2728,9 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } gridView.setTranslationY(0); if (gridView == stickersGridView) { - gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, AndroidUtilities.dp(44)); + gridView.setPadding(0, AndroidUtilities.dp(36 + 4), 0, AndroidUtilities.dp(44)); } else if (gridView == gifGridView) { - gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, AndroidUtilities.dp(44)); + gridView.setPadding(0, AndroidUtilities.dp(36 + 4), 0, AndroidUtilities.dp(44)); } else if (gridView == emojiGridView) { gridView.setPadding(0, AndroidUtilities.dp(38), 0, AndroidUtilities.dp(44)); } @@ -2719,14 +2750,14 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }); searchAnimation.start(); } else { - currentField.setTranslationY(AndroidUtilities.dp(48) - searchFieldHeight); + currentField.setTranslationY(AndroidUtilities.dp(36) - searchFieldHeight); if (tabStrip != null && a != 2) { tabStrip.setTranslationY(0); } if (gridView == stickersGridView) { - gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, AndroidUtilities.dp(44)); + gridView.setPadding(0, AndroidUtilities.dp(36 + 4), 0, AndroidUtilities.dp(44)); } else if (gridView == gifGridView) { - gridView.setPadding(0, AndroidUtilities.dp(48 + 4), 0, AndroidUtilities.dp(44)); + gridView.setPadding(0, AndroidUtilities.dp(36 + 4), 0, AndroidUtilities.dp(44)); } else if (gridView == emojiGridView) { gridView.setPadding(0, AndroidUtilities.dp(38), 0, AndroidUtilities.dp(44)); } @@ -3087,8 +3118,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific tabsMinusDy[Type.EMOJIS] -= dy; if (tabsMinusDy[Type.EMOJIS] > 0) { tabsMinusDy[Type.EMOJIS] = 0; - } else if (tabsMinusDy[Type.EMOJIS] < -AndroidUtilities.dp(48 * 6)) { - tabsMinusDy[Type.EMOJIS] = -AndroidUtilities.dp(48 * 6); + } else if (tabsMinusDy[Type.EMOJIS] < -AndroidUtilities.dp(36 * 6)) { + tabsMinusDy[Type.EMOJIS] = -AndroidUtilities.dp(36 * 6); } emojiTabs.setTranslationY(Math.max(-AndroidUtilities.dp(38), tabsMinusDy[Type.EMOJIS])); } @@ -3142,10 +3173,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific return; } int firstTab; - if (favTabBum > 0) { - firstTab = favTabBum; - } else if (recentTabBum > 0) { - firstTab = recentTabBum; + if (favTabNum > 0) { + firstTab = favTabNum; + } else if (recentTabNum > 0) { + firstTab = recentTabNum; } else { firstTab = stickersTabOffset; } @@ -3248,9 +3279,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (stickersTab == null || stickersTab.isDragging()) { return; } - recentTabBum = -2; - favTabBum = -2; + recentTabNum = -2; + favTabNum = -2; trendingTabNum = -2; + premiumTabNum = -2; hasChatStickers = false; stickersTabOffset = 0; @@ -3282,7 +3314,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } if (!favouriteStickers.isEmpty()) { - favTabBum = stickersTabOffset; + favTabNum = stickersTabOffset; stickersTabOffset++; StickerTabView stickerTabView = stickersTab.addStickerIconTab(1, stickerIcons[1]); stickerTabView.textView.setText(LocaleController.getString("FavoriteStickersShort", R.string.FavoriteStickersShort)); @@ -3290,13 +3322,14 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } if (!recentStickers.isEmpty()) { - recentTabBum = stickersTabOffset; + recentTabNum = stickersTabOffset; stickersTabOffset++; StickerTabView stickerTabView = stickersTab.addStickerIconTab(0, stickerIcons[0]); stickerTabView.textView.setText(LocaleController.getString("RecentStickersShort", R.string.RecentStickersShort)); stickerTabView.setContentDescription(LocaleController.getString("RecentStickers", R.string.RecentStickers)); } + stickerSets.clear(); groupStickerSet = null; groupStickerPackPosition = -1; @@ -3322,13 +3355,33 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } } + premiumStickers.clear(); + packs = MessagesController.getInstance(currentAccount).filterPremiumStickers(packs); for (int a = 0; a < packs.size(); a++) { TLRPC.TL_messages_stickerSet pack = packs.get(a); if (pack.set.archived || pack.documents == null || pack.documents.isEmpty()) { continue; } stickerSets.add(pack); + if (!MessagesController.getInstance(currentAccount).premiumLocked) { + if (UserConfig.getInstance(currentAccount).isPremium()) { + for (int i = 0; i < pack.documents.size(); i++) { + if (MessageObject.isPremiumSticker(pack.documents.get(i))) { + premiumStickers.add(pack.documents.get(i)); + } + } + } + } } + + if (!premiumStickers.isEmpty()) { + premiumTabNum = stickersTabOffset; + stickersTabOffset++; + StickerTabView stickerTabView = stickersTab.addStickerIconTab(4, PremiumGradient.getInstance().premiumStarMenuDrawable2); + stickerTabView.textView.setText(LocaleController.getString("PremiumStickersShort", R.string.PremiumStickersShort)); + stickerTabView.setContentDescription(LocaleController.getString("PremiumStickers", R.string.PremiumStickers)); + } + if (info != null && (!NekoConfig.hideGroupSticker.Bool())) { long hiddenStickerSetId = MessagesController.getEmojiSettings(currentAccount).getLong("group_hide_stickers_" + info.id, -1); TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(info.id); @@ -3399,10 +3452,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific int position = stickersLayoutManager.findFirstVisibleItemPosition(); if (position != RecyclerView.NO_POSITION) { int firstTab; - if (favTabBum > 0) { - firstTab = favTabBum; - } else if (recentTabBum > 0) { - firstTab = recentTabBum; + if (favTabNum > 0) { + firstTab = favTabNum; + } else if (recentTabNum > 0) { + firstTab = recentTabNum; } else { firstTab = stickersTabOffset; } @@ -3733,10 +3786,10 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } if (stickersTab != null) { firstTabUpdate = true; - if (favTabBum >= 0) { - stickersTab.selectTab(favTabBum); - } else if (recentTabBum >= 0) { - stickersTab.selectTab(recentTabBum); + if (favTabNum >= 0) { + stickersTab.selectTab(favTabNum); + } else if (recentTabNum >= 0) { + stickersTab.selectTab(recentTabNum); } else { stickersTab.selectTab(stickersTabOffset); } @@ -3765,6 +3818,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.recentDocumentsDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.featuredStickersDidLoad); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); AndroidUtilities.runOnUIThread(() -> { updateStickerTabs(); reloadStickersAdapter(); @@ -3810,6 +3864,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.recentDocumentsDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.featuredStickersDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupStickersDidLoad); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); } } @@ -3827,8 +3882,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } else { int previousCount = recentStickers.size(); int previousCount2 = favouriteStickers.size(); + recentStickers = MediaDataController.getInstance(currentAccount).getRecentStickers(MediaDataController.TYPE_IMAGE); favouriteStickers = MediaDataController.getInstance(currentAccount).getRecentStickers(MediaDataController.TYPE_FAVE); - recentStickers = MediaDataController.getInstance(currentAccount).getRecentStickers(MediaDataController.TYPE_IMAGE, favouriteStickers.size()); for (int a = 0; a < favouriteStickers.size(); a++) { TLRPC.Document favSticker = favouriteStickers.get(a); for (int b = 0; b < recentStickers.size(); b++) { @@ -3840,6 +3895,20 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } recentStickers = new ArrayList<>(recentStickers.subList(0, Math.min(recentStickers.size(), NekoConfig.maxRecentStickerCount.Int()))); + if (MessagesController.getInstance(currentAccount).premiumLocked) { + for (int a = 0; a < favouriteStickers.size(); a++) { + if (MessageObject.isPremiumSticker(favouriteStickers.get(a))) { + favouriteStickers.remove(a); + a--; + } + } + for (int a = 0; a < recentStickers.size(); a++) { + if (MessageObject.isPremiumSticker(recentStickers.get(a))) { + recentStickers.remove(a); + a--; + } + } + } if (previousCount != recentStickers.size() || previousCount2 != favouriteStickers.size()) { updateStickerTabs(); } @@ -4050,6 +4119,8 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (emojiGridView != null && needEmojiSearch && (emojiSearchField.progressDrawable.isAnimating() || emojiGridView.getAdapter() == emojiSearchAdapter) && !TextUtils.isEmpty(emojiSearchAdapter.lastSearchEmojiString)) { emojiSearchAdapter.search(emojiSearchAdapter.lastSearchEmojiString); } + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + updateStickerTabs(); } } @@ -4206,11 +4277,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific public int getTabForPosition(int position) { Object cacheObject = cache.get(position); if ("search".equals(cacheObject) || "trend1".equals(cacheObject) || "trend2".equals(cacheObject)) { - if (favTabBum >= 0) { - return favTabBum; + if (favTabNum >= 0) { + return favTabNum; } - if (recentTabBum >= 0) { - return recentTabBum; + if (recentTabNum >= 0) { + return recentTabNum; } return 0; } @@ -4230,10 +4301,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } Object pack = rowStartPack.get(row); if (pack instanceof String) { - if ("recent".equals(pack)) { - return recentTabBum; + if ("premium".equals(pack)) { + return premiumTabNum; + } else if ("recent".equals(pack)) { + return recentTabNum; } else { - return favTabBum; + return favTabNum; } } else { TLRPC.TL_messages_stickerSet set = (TLRPC.TL_messages_stickerSet) pack; @@ -4242,6 +4315,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } + @SuppressLint("NotifyDataSetChanged") @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = null; @@ -4257,17 +4331,41 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific view = new EmptyCell(context); break; case 2: - view = new StickerSetNameCell(context, false, resourcesProvider); - ((StickerSetNameCell) view).setOnIconClickListener(v -> { - if (groupStickerSet != null) { - if (delegate != null) { - delegate.onStickersGroupClick(info.id); - } - } else { - MessagesController.getEmojiSettings(currentAccount).edit().putLong("group_hide_stickers_" + info.id, info.stickerset != null ? info.stickerset.id : 0).apply(); - updateStickerTabs(); - if (stickersGridAdapter != null) { - stickersGridAdapter.notifyDataSetChanged(); + StickerSetNameCell nameCell = new StickerSetNameCell(context, false, resourcesProvider); + view = nameCell; + nameCell.setOnIconClickListener(v -> { + if (stickersGridView.indexOfChild(nameCell) == -1) { + return; + } + RecyclerView.ViewHolder holder = stickersGridView.getChildViewHolder(nameCell); + if (holder != null) { + if (holder.getAdapterPosition() == groupStickerPackPosition) { + if (groupStickerSet != null) { + if (delegate != null) { + delegate.onStickersGroupClick(info.id); + } + } else { + MessagesController.getEmojiSettings(currentAccount).edit().putLong("group_hide_stickers_" + info.id, info.stickerset != null ? info.stickerset.id : 0).apply(); + updateStickerTabs(); + if (stickersGridAdapter != null) { + stickersGridAdapter.notifyDataSetChanged(); + } + } + } else { + Object object = cache.get(holder.getAdapterPosition()); + if (object == recentStickers) { + AlertDialog alertDialog = new AlertDialog.Builder(context) + .setTitle(LocaleController.getString(R.string.ClearRecentStickersAlertTitle)) + .setMessage(LocaleController.getString(R.string.ClearRecentStickersAlertMessage)) + .setPositiveButton(LocaleController.getString(R.string.ClearButton), (dialog, which) -> MediaDataController.getInstance(currentAccount).clearRecentStickers()) + .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .create(); + alertDialog.show(); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + } } } }); @@ -4388,7 +4486,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (groupStickersHidden && groupStickerSet == null) { icon = 0; } else { - icon = groupStickerSet != null ? R.drawable.stickersclose : R.drawable.stickerset_close; + icon = groupStickerSet != null ? R.drawable.msg_mini_customize : R.drawable.msg_close; } TLRPC.Chat chat = info != null ? MessagesController.getInstance(currentAccount).getChat(info.id) : null; cell.setText(LocaleController.formatString("CurrentGroupStickers", R.string.CurrentGroupStickers, chat != null ? chat.title : "Group Stickers"), icon); @@ -4404,9 +4502,11 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific cell.setText(title, 0); } } else if (object == recentStickers) { - cell.setText(LocaleController.getString("RecentStickers", R.string.RecentStickers), 0); + cell.setText(LocaleController.getString("RecentStickers", R.string.RecentStickers), R.drawable.msg_close, LocaleController.getString(R.string.ClearRecentStickersAlertTitle)); } else if (object == favouriteStickers) { cell.setText(LocaleController.getString("FavoriteStickers", R.string.FavoriteStickers), 0); + } else if (object == premiumStickers) { + cell.setText(LocaleController.getString("PremiumStickers", R.string.PremiumStickers), 0); } } break; @@ -4418,7 +4518,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } case 5: { StickerSetNameCell cell = (StickerSetNameCell) holder.itemView; - cell.setText(LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), R.drawable.stickerset_close); + cell.setText(MediaDataController.getInstance(currentAccount).loadFeaturedPremium ? LocaleController.getString("FeaturedStickersPremium", R.string.FeaturedStickersPremium) : LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), R.drawable.msg_close); break; } } @@ -4439,15 +4539,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific totalItems = 0; ArrayList packs = stickerSets; int startRow = 0; - for (int a = -4; a < packs.size(); a++) { + for (int a = -5; a < packs.size(); a++) { ArrayList documents; TLRPC.TL_messages_stickerSet pack = null; String key; - if (a == -4) { + if (a == -5) { cache.put(totalItems++, "search"); startRow++; continue; - } else if (a == -3) { + } else if (a == -4) { MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); SharedPreferences preferences = MessagesController.getEmojiSettings(currentAccount); ArrayList featured = mediaDataController.getFeaturedStickerSets(); @@ -4457,12 +4557,15 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific startRow += 2; } continue; - } else if (a == -2) { + } else if (a == -3) { documents = favouriteStickers; packStartPosition.put(key = "fav", totalItems); - } else if (a == -1) { + } else if (a == -2) { documents = recentStickers; packStartPosition.put(key = "recent", totalItems); + } else if (a == -1) { + documents = premiumStickers; + packStartPosition.put(key = "premium", totalItems); } else { key = null; pack = packs.get(a); @@ -4505,7 +4608,13 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (pack != null) { rowStartPack.put(startRow + b, pack); } else { - rowStartPack.put(startRow + b, a == -1 ? "recent" : "fav"); + if (a == -1) { + rowStartPack.put(startRow + b, "premium"); + } else if (a == -2) { + rowStartPack.put(startRow + b, "recent"); + } else { + rowStartPack.put(startRow + b, "fav"); + } } } totalItems += count * stickersPerRow + 1; @@ -4696,7 +4805,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific ImageView imageView = new ImageView(getContext()); imageView.setScaleType(ImageView.ScaleType.CENTER); - imageView.setImageResource(R.drawable.smiles_panel_question); + imageView.setImageResource(R.drawable.msg_emoji_question); imageView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_chat_emojiPanelEmptyText), PorterDuff.Mode.SRC_IN)); frameLayout.addView(imageView, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT)); imageView.setOnClickListener(new OnClickListener() { @@ -5513,7 +5622,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific if (!loadingState) { height = (int) ((height - searchFieldHeight - AndroidUtilities.dp(8)) / 3 * 1.7f); } else { - height -= AndroidUtilities.dp(48 + 44); + height -= AndroidUtilities.dp(36 + 44); } super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); @@ -5642,6 +5751,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific }); } ArrayList local = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); + MessagesController.getInstance(currentAccount).filterPremiumStickers(local); int index; for (int a = 0, size = local.size(); a < size; a++) { TLRPC.TL_messages_stickerSet set = local.get(a); @@ -5660,6 +5770,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific } } local = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_FEATURED); + MessagesController.getInstance(currentAccount).filterPremiumStickers(local); for (int a = 0, size = local.size(); a < size; a++) { TLRPC.TL_messages_stickerSet set = local.get(a); if ((index = AndroidUtilities.indexOfIgnoreCase(set.set.title, searchQuery)) >= 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java index 939f73a3e..9bfe0196d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ExtendedGridLayoutManager.java @@ -18,6 +18,7 @@ import androidx.recyclerview.widget.RecyclerView; public class ExtendedGridLayoutManager extends GridLayoutManager { + private final boolean firstRowFullWidth; private final boolean lastRowFullWidth; private SparseIntArray itemSpans = new SparseIntArray(); @@ -31,8 +32,13 @@ public class ExtendedGridLayoutManager extends GridLayoutManager { } public ExtendedGridLayoutManager(Context context, int spanCount, boolean lastRowFullWidth) { + this(context, spanCount, lastRowFullWidth, false); + } + + public ExtendedGridLayoutManager(Context context, int spanCount, boolean lastRowFullWidth, boolean firstRowFullWidth) { super(context, spanCount); this.lastRowFullWidth = lastRowFullWidth; + this.firstRowFullWidth = firstRowFullWidth; } @Override @@ -61,6 +67,15 @@ public class ExtendedGridLayoutManager extends GridLayoutManager { int currentItemsInRow = 0; int currentItemsSpanAmount = 0; for (int a = 0, N = itemsCount + (lastRowFullWidth ? 1 : 0); a < N; a++) { + if (a == 0 && firstRowFullWidth) { + itemSpans.put(a, itemSpans.get(a) + spanCount); + itemsToRow.put(0, rowsCount); + rowsCount++; + currentItemsSpanAmount = 0; + currentItemsInRow = 0; + spanLeft = spanCount; + continue; + } Size size = a < itemsCount ? sizeForItem(a) : null; int requiredSpan; boolean moveToNewRow; @@ -69,7 +84,7 @@ public class ExtendedGridLayoutManager extends GridLayoutManager { requiredSpan = spanCount; } else { requiredSpan = Math.min(spanCount, (int) Math.floor(spanCount * (size.width / size.height * preferredRowSize / viewPortAvailableSize))); - moveToNewRow = spanLeft 33 && spanLeft < requiredSpan - 15; + moveToNewRow = spanLeft < requiredSpan || requiredSpan > 33 && spanLeft < requiredSpan - 15; } if (moveToNewRow) { if (spanLeft != 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastLinearLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastLinearLayoutManager.java index 7a535e37b..34a1e8659 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastLinearLayoutManager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FillLastLinearLayoutManager.java @@ -18,9 +18,12 @@ public class FillLastLinearLayoutManager extends LinearLayoutManager { private boolean skipFirstItem; private boolean bind = true; private boolean canScrollVertically = true; + boolean fixedLastItemHeight; + private int minimumHeight; public FillLastLinearLayoutManager(Context context, int h, RecyclerView recyclerView) { super(context); + listView = recyclerView; additionalHeight = h; } @@ -63,6 +66,7 @@ public class FillLastLinearLayoutManager extends LinearLayoutManager { } int count = adapter.getItemCount() - 1; int allHeight = 0; + int firstItemHeight = 0; for (int a = skipFirstItem ? 1 : 0; a < count; a++) { int type = adapter.getItemViewType(a); RecyclerView.ViewHolder holder = heights.get(type, null); @@ -82,11 +86,24 @@ public class FillLastLinearLayoutManager extends LinearLayoutManager { final int heightSpec = getChildMeasureSpec(listHeight, getHeightMode(), getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, lp.height, canScrollVertically()); holder.itemView.measure(widthSpec, heightSpec); allHeight += holder.itemView.getMeasuredHeight(); - if (allHeight >= listHeight) { - break; + if (a == 0) { + firstItemHeight = holder.itemView.getMeasuredHeight(); + } + if (fixedLastItemHeight) { + if (allHeight >= listHeight + firstItemHeight) { + break; + } + } else { + if (allHeight >= listHeight) { + break; + } } } - lastItemHeight = Math.max(0, listHeight - allHeight - additionalHeight - listView.getPaddingBottom()); + if (fixedLastItemHeight) { + lastItemHeight = Math.max(minimumHeight, firstItemHeight + (listHeight - allHeight - additionalHeight - listView.getPaddingBottom())); + } else { + lastItemHeight = Math.max(minimumHeight, listHeight - allHeight - additionalHeight - listView.getPaddingBottom()); + } } @Override @@ -154,4 +171,12 @@ public class FillLastLinearLayoutManager extends LinearLayoutManager { } super.measureChildWithMargins(child, 0, 0); } + + public void setFixedLastItemHeight() { + fixedLastItemHeight = true; + } + + public void setMinimumLastViewHeight(int height) { + minimumHeight = height; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterTabsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterTabsView.java index cfe052676..7fbc47cfb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterTabsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FilterTabsView.java @@ -17,6 +17,8 @@ import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; @@ -29,12 +31,14 @@ import android.text.TextPaint; import android.text.TextUtils; import android.util.Property; import android.util.SparseIntArray; +import android.view.HapticFeedbackConstants; import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.core.content.ContextCompat; import androidx.core.graphics.ColorUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.ItemTouchHelper; @@ -50,6 +54,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; 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.ui.ActionBar.Theme; @@ -61,9 +66,16 @@ import tw.nekomimi.nekogram.NekoConfig; public class FilterTabsView extends FrameLayout { - public interface FilterTabsViewDelegate { - void onPageSelected(int page, boolean forward); + public int getCurrentTabStableId() { + return positionToStableId.get(currentPosition, -1); + } + public int getStableId(int selectedType) { + return positionToStableId.get(selectedType, -1); + } + + public interface FilterTabsViewDelegate { + void onPageSelected(Tab tab, boolean forward); void onPageScrolled(float progress); void onSamePageSelected(); @@ -81,11 +93,13 @@ public class FilterTabsView extends FrameLayout { boolean canPerformActions(); } - private class Tab { + public class Tab { public int id; public String title; public int titleWidth; public int counter; + public boolean isDefault; + public boolean isLocked; public Tab(int i, String t) { id = i; @@ -140,6 +154,7 @@ public class FilterTabsView extends FrameLayout { public float changeProgress; public boolean animateCounterChange; + private float locIconXOffset; float lastTextX; @@ -172,6 +187,8 @@ public class FilterTabsView extends FrameLayout { private float lastTabWidth; private float animateFromTabWidth; private float lastWidth; + private float rotation; + private float progressToLocked; public TabView(Context context) { super(context); @@ -215,11 +232,15 @@ public class FilterTabsView extends FrameLayout { @SuppressLint("DrawAllocation") @Override protected void onDraw(Canvas canvas) { - if (currentTab.id != Integer.MAX_VALUE && editingAnimationProgress != 0) { +// boolean reorderEnabled = (!currentTab.isDefault || UserConfig.getInstance(UserConfig.selectedAccount).isPremium()); + boolean reorderEnabled = (!currentTab.isDefault); + // TODO: NekoX try to unlock + boolean showRemove = !currentTab.isDefault && reorderEnabled; + if (reorderEnabled && editingAnimationProgress != 0) { canvas.save(); float p = editingAnimationProgress * (currentPosition % 2 == 0 ? 1.0f : -1.0f); canvas.translate(AndroidUtilities.dp(0.66f) * p, 0); - canvas.rotate(p, getMeasuredWidth() / 2, getMeasuredHeight() / 2); + canvas.rotate(p, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); } String key; String animateToKey; @@ -292,7 +313,7 @@ public class FilterTabsView extends FrameLayout { } - if (currentTab.id != Integer.MAX_VALUE && (isEditing || editingStartAnimationProgress != 0)) { + if (showRemove && (isEditing || editingStartAnimationProgress != 0)) { countWidth = (int) (countWidth + (AndroidUtilities.dp(20) - countWidth) * editingStartAnimationProgress); } @@ -347,7 +368,7 @@ public class FilterTabsView extends FrameLayout { } } - if (animateCounterEnter || counterText != null || currentTab.id != Integer.MAX_VALUE && (isEditing || editingStartAnimationProgress != 0)) { + if (animateCounterEnter || counterText != null || showRemove && (isEditing || editingStartAnimationProgress != 0)) { if (aBackgroundColorKey == null) { textCounterPaint.setColor(Theme.getColor(backgroundColorKey)); } else { @@ -379,7 +400,7 @@ public class FilterTabsView extends FrameLayout { } int countTop = (getMeasuredHeight() - AndroidUtilities.dp(20)) / 2; - if (currentTab.id != Integer.MAX_VALUE && (isEditing || editingStartAnimationProgress != 0) && counterText == null) { + if (showRemove && (isEditing || editingStartAnimationProgress != 0) && counterText == null) { counterPaint.setAlpha((int) (editingStartAnimationProgress * 255)); } else { counterPaint.setAlpha(255); @@ -408,7 +429,7 @@ public class FilterTabsView extends FrameLayout { y += (AndroidUtilities.dp(20) - (stableCounter.getLineBottom(0) - stableCounter.getLineTop(0))) / 2f; } float alpha = 1f; - if (currentTab.id != Integer.MAX_VALUE) { + if (showRemove) { alpha = (1.0f - editingStartAnimationProgress); } if (inCounter != null) { @@ -436,7 +457,7 @@ public class FilterTabsView extends FrameLayout { textCounterPaint.setAlpha(255); } else { if (counterText != null) { - if (currentTab.id != Integer.MAX_VALUE) { + if (showRemove) { textCounterPaint.setAlpha((int) (255 * (1.0f - editingStartAnimationProgress))); } canvas.drawText(counterText, rect.left + (rect.width() - counterWidth) / 2, countTop + AndroidUtilities.dp(14.5f), textCounterPaint); @@ -446,7 +467,7 @@ public class FilterTabsView extends FrameLayout { if (animateCounterEnter || animateCounterRemove) { canvas.restore(); } - if (currentTab.id != Integer.MAX_VALUE && (isEditing || editingStartAnimationProgress != 0)) { + if (showRemove && (isEditing || editingStartAnimationProgress != 0)) { deletePaint.setColor(textCounterPaint.getColor()); deletePaint.setAlpha((int) (255 * editingStartAnimationProgress)); int side = AndroidUtilities.dp(3); @@ -454,7 +475,7 @@ public class FilterTabsView extends FrameLayout { canvas.drawLine(rect.centerX() - side, rect.centerY() + side, rect.centerX() + side, rect.centerY() - side, deletePaint); } } - if (currentTab.id != Integer.MAX_VALUE && editingAnimationProgress != 0) { + if (reorderEnabled && editingAnimationProgress != 0) { canvas.restore(); } @@ -467,6 +488,38 @@ public class FilterTabsView extends FrameLayout { lastCounterWidth = counterWidth; lastTabWidth = tabWidth; lastWidth = getMeasuredWidth(); + + if (currentTab.isLocked || progressToLocked != 0) { + if (lockDrawable == null) { + lockDrawable = ContextCompat.getDrawable(getContext(), R.drawable.other_lockedfolders); + } + if (currentTab.isLocked && progressToLocked != 1f) { + progressToLocked += 16 / 150f; + } else if (!currentTab.isLocked){ + progressToLocked -= 16 / 150f; + } + progressToLocked = Utilities.clamp(progressToLocked, 1f, 0); + int unactiveColor = Theme.getColor(unactiveTextColorKey); + if (aUnactiveTextColorKey != null) { + unactiveColor = ColorUtils.blendARGB(unactiveColor, Theme.getColor(aUnactiveTextColorKey), animationValue); + } + if (lockDrawableColor != unactiveColor) { + lockDrawableColor = unactiveColor; + lockDrawable.setColorFilter(new PorterDuffColorFilter(unactiveColor, PorterDuff.Mode.MULTIPLY)); + } + int iconX = (int) ((getMeasuredWidth() - lockDrawable.getIntrinsicWidth()) / 2f + locIconXOffset); + int iconY = getMeasuredHeight() - AndroidUtilities.dp(12); + lockDrawable.setBounds(iconX, iconY, iconX + lockDrawable.getIntrinsicWidth(), iconY + lockDrawable.getIntrinsicHeight()); + if (progressToLocked != 1f) { + canvas.save(); + canvas.scale(progressToLocked, progressToLocked, lockDrawable.getBounds().centerX(), lockDrawable.getBounds().centerY()); + lockDrawable.draw(canvas); + canvas.restore(); + } else { + lockDrawable.draw(canvas); + } + + } } public boolean animateChange() { @@ -590,6 +643,16 @@ public class FilterTabsView extends FrameLayout { } else { info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK); } + if (currentTab != null) { + StringBuilder sb = new StringBuilder(); + sb.append(currentTab.title); + int unread = currentTab != null ? currentTab.counter : 0; + if (unread > 0) { + sb.append("\n"); + sb.append(LocaleController.formatPluralString("AccDescrUnreadCount", unread)); + } + info.setContentDescription(sb); + } } public void clearTransitionParams() { @@ -602,6 +665,30 @@ public class FilterTabsView extends FrameLayout { changeAnimator = null; invalidate(); } + + public void shakeLockIcon(float x, int num) { + if (num == 6) { + locIconXOffset = 0; + return; + } + AnimatorSet animatorSet = new AnimatorSet(); + ValueAnimator animator = ValueAnimator.ofFloat(0, AndroidUtilities.dp(x)); + animator.addUpdateListener(animation -> { + locIconXOffset = (float) animation.getAnimatedValue(); + invalidate(); + }); + animatorSet.playTogether(animator); + animatorSet.setDuration(50); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + shakeLockIcon(num == 5 ? 0 : -x, num + 1); + locIconXOffset = 0; + invalidate(); + } + }); + animatorSet.start(); + } } private TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); @@ -671,6 +758,8 @@ public class FilterTabsView extends FrameLayout { private int previousPosition; private int previousId; DefaultItemAnimator itemAnimator; + private Drawable lockDrawable; + private int lockDrawableColor; private Runnable animationRunnable = new Runnable() { @Override @@ -935,7 +1024,7 @@ public class FilterTabsView extends FrameLayout { delegate.onSamePageSelected(); return; } - scrollToTab(tabView.currentTab.id, position); + scrollToTab(tabView.currentTab, position); }); listView.setOnItemLongClickListener((view, position) -> { if (!delegate.canPerformActions() || isEditing || !delegate.didSelectTab((TabView) view, position == currentPosition)) { @@ -961,13 +1050,19 @@ public class FilterTabsView extends FrameLayout { return animatingIndicator; } - private void scrollToTab(int id, int position) { + private void scrollToTab(Tab tab, int position) { + if (tab.isLocked) { + if (delegate != null) { + delegate.onPageSelected(tab, false); + } + return; + } boolean scrollingForward = currentPosition < position; scrollingToChild = -1; previousPosition = currentPosition; previousId = selectedTabId; currentPosition = position; - selectedTabId = id; + selectedTabId = tab.id; if (animatingIndicator) { AndroidUtilities.cancelRunOnUIThread(animationRunnable); @@ -982,15 +1077,18 @@ public class FilterTabsView extends FrameLayout { AndroidUtilities.runOnUIThread(animationRunnable, 16); if (delegate != null) { - delegate.onPageSelected(id, scrollingForward); + delegate.onPageSelected(tab, scrollingForward); } scrollToChild(position); - if (NekoConfig.hideAllTab.Bool() && showAllChatsTab && id != Integer.MAX_VALUE) + if (NekoConfig.hideAllTab.Bool() && showAllChatsTab && !currentTabIsDefault()) toggleAllTabs(false); } public void selectFirstTab() { - scrollToTab(Integer.MAX_VALUE, 0); + if (tabs.isEmpty()) { + return; + } + scrollToTab(tabs.get(0), 0); } public void setAnimationIdicatorProgress(float value) { @@ -1031,7 +1129,7 @@ public class FilterTabsView extends FrameLayout { selectedTabId = -1; } - public void addTab(int id, int stableId, String text) { + public void addTab(int id, int stableId, String text, boolean isDefault, boolean isLocked) { int position = tabs.size(); if (position == 0 && selectedTabId == -1) { selectedTabId = id; @@ -1044,6 +1142,8 @@ public class FilterTabsView extends FrameLayout { } Tab tab = new Tab(id, text); + tab.isDefault = isDefault; + tab.isLocked = isLocked; allTabsWidth += tab.getWidth(true) + AndroidUtilities.dp(32); tabs.add(tab); } @@ -1091,6 +1191,10 @@ public class FilterTabsView extends FrameLayout { return positionToId.get(0, 0); } + public String getSelectorColorKey() { + return selectorColorKey; + } + private void updateTabsWidths() { positionToX.clear(); positionToWidth.clear(); @@ -1212,7 +1316,7 @@ public class FilterTabsView extends FrameLayout { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!tabs.isEmpty()) { int width = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(7) - AndroidUtilities.dp(7); - Tab firstTab = tabs.get(0); + Tab firstTab = findDefaultTab(); int tabWith = firstTab.getWidth(false); if (showAllChatsTab) firstTab.setTitle(allTabsWidth > width ? LocaleController.getString("FilterAllChatsShort", R.string.FilterAllChatsShort) : LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); @@ -1234,6 +1338,15 @@ public class FilterTabsView extends FrameLayout { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } + private Tab findDefaultTab() { + for (int i = 0; i < tabs.size(); i++) { + if (tabs.get(i).isDefault) { + return tabs.get(i); + } + } + return null; + } + @Override public void requestLayout() { if (ignoreLayout) { @@ -1345,10 +1458,14 @@ public class FilterTabsView extends FrameLayout { ArrayList filters = MessagesController.getInstance(UserConfig.selectedAccount).dialogFilters; for (int a = 0, N = filters.size(); a < N; a++) { MessagesController.DialogFilter filter = filters.get(a); - req.order.add(filters.get(a).id); + if (filter.isDefault()) { + req.order.add(0); + } else { + req.order.add(filter.id); + } } + MessagesController.getInstance(UserConfig.selectedAccount).lockFiltersInternal(); ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { - }); orderChanged = false; } @@ -1369,7 +1486,7 @@ public class FilterTabsView extends FrameLayout { requestLayout(); allTabsWidth = 0; if (showAllChatsTab) - tabs.get(0).setTitle(LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); + findDefaultTab().setTitle(LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); for (int b = 0; b < N; b++) { allTabsWidth += tabs.get(b).getWidth(true) + AndroidUtilities.dp(32); } @@ -1401,7 +1518,7 @@ public class FilterTabsView extends FrameLayout { adapter.notifyDataSetChanged(); allTabsWidth = 0; if (showAllChatsTab) - tabs.get(0).setTitle(LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); + findDefaultTab().setTitle(LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); for (int b = 0, N = tabs.size(); b < N; b++) { allTabsWidth += tabs.get(b).getWidth(true) + AndroidUtilities.dp(32); } @@ -1439,7 +1556,11 @@ public class FilterTabsView extends FrameLayout { @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { TabView tabView = (TabView) holder.itemView; + int oldId = tabView.currentTab != null ? tabView.getId() : -1; tabView.setTab(tabs.get(position), position); + if (oldId != tabView.getId()) { + tabView.progressToLocked = tabView.currentTab.isLocked ? 1f : 0; + } } @Override @@ -1448,9 +1569,9 @@ public class FilterTabsView extends FrameLayout { } public void swapElements(int fromIndex, int toIndex) { - int idx1 = fromIndex - 1; - int idx2 = toIndex - 1; - int count = tabs.size() - 1; + int idx1 = fromIndex; + int idx2 = toIndex; + int count = tabs.size(); if (!showAllChatsTab) { idx1++; idx2++; @@ -1560,6 +1681,56 @@ public class FilterTabsView extends FrameLayout { return listView; } + public boolean currentTabIsDefault() { + Tab defaultTab = findDefaultTab(); + if (defaultTab == null) { + return false; + } + return defaultTab.id == selectedTabId; + } + + public int getDefaultTabId() { + Tab defaultTab = findDefaultTab(); + if (defaultTab == null) { + return -1; + } + return defaultTab.id; + } + + public boolean isEmpty() { + return tabs.isEmpty(); + } + + public boolean isFirstTabSelected() { + if (tabs.isEmpty()) { + return true; + } + return selectedTabId == tabs.get(0).id; + } + + public boolean isLocked(int id) { + for (int i = 0; i < tabs.size(); i++) { + if (tabs.get(i).id == id) { + return tabs.get(i).isLocked; + } + } + return false; + } + + public void shakeLock(int id) { + for (int i = 0; i < listView.getChildCount(); i++) { + if (listView.getChildAt(i) instanceof TabView) { + TabView tabView = (TabView) listView.getChildAt(i); + if (tabView.currentTab.id == id) { + tabView.shakeLockIcon(1, 0); + tabView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + break; + } + } + } + } + + // NekoX show all chats tab public boolean showAllChatsTab = !NekoConfig.hideAllTab.Bool(); public void toggleAllTabs(boolean show) { @@ -1568,7 +1739,7 @@ public class FilterTabsView extends FrameLayout { showAllChatsTab = show; removeTabs(); if (showAllChatsTab) - addTab(Integer.MAX_VALUE, 0, LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); + addTab(Integer.MAX_VALUE, , LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); ArrayList filters = AccountInstance.getInstance(UserConfig.selectedAccount).getMessagesController().dialogFilters; for (int a = 0, N = filters.size(); a < N; a++) { MessagesController.DialogFilter dialogFilter = filters.get(a); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FiltersListBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FiltersListBottomSheet.java index a4466c09e..3acfc2287 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FiltersListBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FiltersListBottomSheet.java @@ -21,6 +21,9 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DialogObject; import org.telegram.messenger.LocaleController; @@ -35,9 +38,6 @@ import org.telegram.ui.DialogsActivity; import java.util.ArrayList; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class FiltersListBottomSheet extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -309,7 +309,7 @@ public class FiltersListBottomSheet extends BottomSheet implements NotificationC ArrayList filters = fragment.getMessagesController().dialogFilters; for (int a = 0, N = filters.size(); a < N; a++) { MessagesController.DialogFilter filter = filters.get(a); - if (!getDialogsCount(fragment, filter, selectedDialogs, true, true).isEmpty()) { + if (!getDialogsCount(fragment, filter, selectedDialogs, true, true).isEmpty() && !filter.isDefault()) { result.add(filter); } } @@ -395,7 +395,7 @@ public class FiltersListBottomSheet extends BottomSheet implements NotificationC if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == (MessagesController.DIALOG_FILTER_FLAG_CONTACTS | MessagesController.DIALOG_FILTER_FLAG_NON_CONTACTS)) { icon = R.drawable.baseline_person_24; } else if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0 && (filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) { - icon = R.drawable.menu_unread; + icon = R.drawable.msg_markunread; } else if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == MessagesController.DIALOG_FILTER_FLAG_CHANNELS) { icon = R.drawable.baseline_notifications_24; } else if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == MessagesController.DIALOG_FILTER_FLAG_GROUPS) { 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 c32188224..0b7ebaafd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FlickerLoadingView.java @@ -37,6 +37,9 @@ public class FlickerLoadingView extends View { public final static int REACTED_TYPE = 16; public final static int QR_TYPE = 17; public final static int CONTACT_TYPE = 18; + public final static int STICKERS_TYPE = 19; + public final static int LIMIT_REACHED_GROUPS = 21; + public final static int LIMIT_REACHED_LINKS = 22; private int gradientWidth; private LinearGradient gradient; @@ -71,6 +74,7 @@ public class FlickerLoadingView extends View { private float parentXOffset; FlickerLoadingView globalGradientView; + private boolean ignoreHeightCheck; public void setViewType(int type) { this.viewType = type; @@ -116,7 +120,7 @@ public class FlickerLoadingView extends View { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (isSingleCell) { - if (itemsCount > 1 && ignoreHeightCheck()) { + if (itemsCount > 1 && ignoreHeightCheck) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(getCellHeight(MeasureSpec.getSize(widthMeasureSpec)) * itemsCount, MeasureSpec.EXACTLY)); } else if (itemsCount > 1 && MeasureSpec.getSize(heightMeasureSpec) > 0) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(Math.min(MeasureSpec.getSize(heightMeasureSpec), getCellHeight(MeasureSpec.getSize(widthMeasureSpec)) * itemsCount), MeasureSpec.EXACTLY)); @@ -128,10 +132,6 @@ public class FlickerLoadingView extends View { } } - private boolean ignoreHeightCheck() { - return viewType == CONTACT_TYPE; - } - @Override protected void onDraw(Canvas canvas) { Paint paint = this.paint; @@ -209,6 +209,30 @@ public class FlickerLoadingView extends View { canvas.drawLine(AndroidUtilities.dp(textStart), h + getCellHeight(getMeasuredWidth()), getMeasuredWidth(), h + getCellHeight(getMeasuredWidth()), paint); + h += getCellHeight(getMeasuredWidth()); + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } + } else if (getViewType() == STICKERS_TYPE) { + int k = 0; + while (h <= getMeasuredHeight()) { + int r = AndroidUtilities.dp(20); + canvas.drawCircle(checkRtl(paddingLeft + AndroidUtilities.dp(9) + r), h + AndroidUtilities.dp(29), r, paint); + + int textStart = 76; + int titleWidth = k % 2 == 0 ? 92 : 128; + rectF.set(AndroidUtilities.dp(textStart), h + AndroidUtilities.dp(16), AndroidUtilities.dp(textStart + titleWidth), h + AndroidUtilities.dp(24)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(textStart), h + AndroidUtilities.dp(38), AndroidUtilities.dp(textStart + 164), h + AndroidUtilities.dp(46)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + canvas.drawLine(AndroidUtilities.dp(textStart), h + getCellHeight(getMeasuredWidth()), getMeasuredWidth(), h + getCellHeight(getMeasuredWidth()), paint); + h += getCellHeight(getMeasuredWidth()); k++; if (isSingleCell && k >= itemsCount) { @@ -552,6 +576,46 @@ public class FlickerLoadingView extends View { canvas.drawCircle(checkRtl(getWidth() - AndroidUtilities.dp(12) - r), h + AndroidUtilities.dp(24), r, paint); } + h += getCellHeight(getMeasuredWidth()); + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } + } else if (viewType == LIMIT_REACHED_GROUPS) { + int k = 0; + while (h <= getMeasuredHeight()) { + int r = AndroidUtilities.dp(46) >> 1; + canvas.drawCircle(checkRtl(AndroidUtilities.dp(20) + r), h + (AndroidUtilities.dp(58) >> 1), r, paint); + + rectF.set(AndroidUtilities.dp(74), h + AndroidUtilities.dp(16), AndroidUtilities.dp(140), h + AndroidUtilities.dp(24)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(74), h + AndroidUtilities.dp(38), AndroidUtilities.dp(260), h + AndroidUtilities.dp(46)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + h += getCellHeight(getMeasuredWidth()); + k++; + if (isSingleCell && k >= itemsCount) { + break; + } + } + } else if (viewType == LIMIT_REACHED_LINKS) { + int k = 0; + while (h <= getMeasuredHeight()) { + int r = AndroidUtilities.dp(48) >> 1; + canvas.drawCircle(checkRtl(AndroidUtilities.dp(20) + r), h + AndroidUtilities.dp(6) + r, r, paint); + + rectF.set(AndroidUtilities.dp(76), h + AndroidUtilities.dp(16), AndroidUtilities.dp(140), h + AndroidUtilities.dp(24)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + + rectF.set(AndroidUtilities.dp(76), h + AndroidUtilities.dp(38), AndroidUtilities.dp(260), h + AndroidUtilities.dp(46)); + checkRtl(rectF); + canvas.drawRoundRect(rectF, AndroidUtilities.dp(4), AndroidUtilities.dp(4), paint); + h += getCellHeight(getMeasuredWidth()); k++; if (isSingleCell && k >= itemsCount) { @@ -649,6 +713,8 @@ public class FlickerLoadingView extends View { return AndroidUtilities.dp(56); case LINKS_TYPE: return AndroidUtilities.dp(80); + case STICKERS_TYPE: + return AndroidUtilities.dp(58); case USERS_TYPE: case CONTACT_TYPE: return AndroidUtilities.dp(64); @@ -666,6 +732,10 @@ public class FlickerLoadingView extends View { return AndroidUtilities.dp(107); case REACTED_TYPE: return AndroidUtilities.dp(48); + case LIMIT_REACHED_GROUPS: + return AndroidUtilities.dp(58); + case LIMIT_REACHED_LINKS: + return AndroidUtilities.dp(60); } return 0; } @@ -714,4 +784,8 @@ public class FlickerLoadingView extends View { public Paint getPaint() { return paint; } + + public void setIgnoreHeightCheck(boolean ignore) { + this.ignoreHeightCheck = ignore; + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java index 3fc21b44c..c94c0c9c4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ForwardingPreviewView.java @@ -589,7 +589,7 @@ public class ForwardingPreviewView extends FrameLayout { 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_forward_send); + sendMessagesView.setTextAndIcon(LocaleController.getString("ForwardSendMessages", R.string.ForwardSendMessages), R.drawable.msg_send); if (forwardingMessagesParams.hasSenders) { actionItems.add(showSendersNameView); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java index 4f6919bee..f420c0574 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FragmentContextView.java @@ -267,8 +267,8 @@ public class FragmentContextView extends FrameLayout implements NotificationCent } @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); if (currentStyle == STYLE_INACTIVE_GROUP_CALL && timeLayout != null) { int width = (int) Math.ceil(timeLayout.getLineWidth(0)) + AndroidUtilities.dp(24); if (width != gradientWidth) { @@ -293,12 +293,12 @@ public class FragmentContextView extends FrameLayout implements NotificationCent matrix.postTranslate(-gradientWidth * 0.7f * moveProgress, 0); linearGradient.setLocalMatrix(matrix); int x = getMeasuredWidth() - width - AndroidUtilities.dp(10); - int y = AndroidUtilities.dp(12); - rect.set(0, 0, width, AndroidUtilities.dp(24)); + int y = AndroidUtilities.dp(10); + rect.set(0, 0, width, AndroidUtilities.dp(28)); canvas.save(); canvas.translate(x, y); - canvas.drawRoundRect(rect, AndroidUtilities.dp(12), AndroidUtilities.dp(12), gradientPaint); - canvas.translate(AndroidUtilities.dp(12), AndroidUtilities.dp(4)); + canvas.drawRoundRect(rect, AndroidUtilities.dp(16), AndroidUtilities.dp(16), gradientPaint); + canvas.translate(AndroidUtilities.dp(12), AndroidUtilities.dp(6)); timeLayout.draw(canvas); canvas.restore(); } @@ -394,7 +394,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent final int halfOutlineWidth = AndroidUtilities.dp(1); AndroidUtilities.rectTmp.set(halfOutlineWidth, halfOutlineWidth, getWidth() - halfOutlineWidth, getHeight() - halfOutlineWidth); - joinButtonFlicker.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(16)); + joinButtonFlicker.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(16), this); if (joinButtonFlicker.getProgress() < 1f && !joinButtonFlicker.repeatEnabled) { invalidate(); } @@ -2112,7 +2112,7 @@ public class FragmentContextView extends FrameLayout implements NotificationCent return; } boolean clipped = false; - if ((currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) && drawOverlay) { + if (currentStyle == STYLE_ACTIVE_GROUP_CALL || currentStyle == STYLE_CONNECTING_GROUP_CALL) { boolean mutedByAdmin = GroupCallActivity.groupCallInstance == null && Theme.getFragmentContextViewWavesDrawable().getState() == FragmentContextViewWavesDrawable.MUTE_BUTTON_STATE_MUTED_BY_ADMIN; Theme.getFragmentContextViewWavesDrawable().updateState(wasDraw); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GigagroupConvertAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GigagroupConvertAlert.java index e1c11c769..a3eed7f47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GigagroupConvertAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GigagroupConvertAlert.java @@ -40,7 +40,7 @@ public class GigagroupConvertAlert extends BottomSheet { super(context); background = new View(context); - background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + background.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16)); textView = new TextView(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCallRecordAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCallRecordAlert.java index 0534bfe70..3947f721b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCallRecordAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupCallRecordAlert.java @@ -17,6 +17,8 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -289,11 +291,31 @@ public class GroupCallRecordAlert extends BottomSheet { public Object instantiateItem(ViewGroup container, int position) { View view; - ImageView imageView = new ImageView(getContext()); + ImageView imageView = new ImageView(getContext()) { + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) { + viewPager.setCurrentItem(position, true); + } + } + }; + imageView.setOnClickListener((e) -> { + onStartRecord(position); + dismiss(); + }); + imageView.setFocusable(true); imageView.setTag(position); imageView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); imageView.setScaleType(ImageView.ScaleType.FIT_XY); imageView.setLayoutParams(new ViewGroup.LayoutParams(AndroidUtilities.dp(200), ViewGroup.LayoutParams.MATCH_PARENT)); + if (position == 0) { + imageView.setContentDescription(LocaleController.getString("VoipRecordAudio", R.string.VoipRecordAudio)); + } else if (position == 1) { + imageView.setContentDescription(LocaleController.getString("VoipRecordPortrait", R.string.VoipRecordPortrait)); + } else { + imageView.setContentDescription(LocaleController.getString("VoipRecordLandscape", R.string.VoipRecordLandscape)); + } view = imageView; int res; if (position == 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java index dbcb4e8a8..b4dbe499f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/GroupedPhotosListView.java @@ -743,6 +743,7 @@ public class GroupedPhotosListView extends View implements GestureDetector.OnGes } } receiver.setAlpha(drawAlpha); + receiver.setRoundRadius(AndroidUtilities.dp(2)); receiver.draw(canvas); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java index 21d3d65cd..d3f82697d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/HintView.java @@ -88,16 +88,16 @@ public class HintView extends FrameLayout { addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.LEFT | Gravity.TOP, 0, topArrow ? 6 : 0, 0, topArrow ? 0 : 6)); } else { textView.setGravity(Gravity.LEFT | Gravity.TOP); - textView.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(currentType == 7 || currentType == 8 || currentType == 9 ? 6 : 3), getThemedColor(Theme.key_chat_gifSaveHintBackground))); - if (currentType == TYPE_POLL_VOTE || currentType == 4) { - textView.setPadding(AndroidUtilities.dp(9), AndroidUtilities.dp(6), AndroidUtilities.dp(9), AndroidUtilities.dp(7)); - } else if (currentType == 2) { - textView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(6), AndroidUtilities.dp(7), AndroidUtilities.dp(7)); - } else if (currentType == 7 || currentType == 8 || currentType == 9) { - textView.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(7), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); - } else { - textView.setPadding(AndroidUtilities.dp(currentType == 0 ? 54 : 5), AndroidUtilities.dp(6), AndroidUtilities.dp(5), AndroidUtilities.dp(7)); - } + textView.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(6/*currentType == 7 || currentType == 8 || currentType == 9 ? 6 : 3*/), getThemedColor(Theme.key_chat_gifSaveHintBackground))); +// if (currentType == TYPE_POLL_VOTE || currentType == 4) { +// textView.setPadding(AndroidUtilities.dp(9), AndroidUtilities.dp(6), AndroidUtilities.dp(9), AndroidUtilities.dp(7)); +// } else if (currentType == 2) { +// textView.setPadding(AndroidUtilities.dp(7), AndroidUtilities.dp(6), AndroidUtilities.dp(7), AndroidUtilities.dp(7)); +// } else if (currentType == 7 || currentType == 8 || currentType == 9) { + textView.setPadding(AndroidUtilities.dp(currentType == 0 ? 54 : 8), AndroidUtilities.dp(7), AndroidUtilities.dp(8), AndroidUtilities.dp(8)); +// } else { +// textView.setPadding(AndroidUtilities.dp(currentType == 0 ? 54 : 5), AndroidUtilities.dp(6), AndroidUtilities.dp(5), AndroidUtilities.dp(7)); +// } addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 0, topArrow ? 6 : 0, 0, topArrow ? 0 : 6)); } 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 c2702245f..e4170538a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ImageUpdater.java @@ -459,10 +459,10 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega if (info.searchImage.photo != null) { TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(info.searchImage.photo.sizes, AndroidUtilities.getPhotoSize()); if (photoSize != null) { - File path = FileLoader.getPathToAttach(photoSize, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(photoSize, true); finalPath = path.getAbsolutePath(); if (!path.exists()) { - path = FileLoader.getPathToAttach(photoSize, false); + path = FileLoader.getInstance(currentAccount).getPathToAttach(photoSize, false); if (!path.exists()) { path = null; } @@ -724,7 +724,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega smallPhoto = ImageLoader.scaleAndSaveImage(bitmap, 150, 150, 80, false, 150, 150); if (smallPhoto != null) { try { - Bitmap b = BitmapFactory.decodeFile(FileLoader.getPathToAttach(smallPhoto, true).getAbsolutePath()); + Bitmap b = BitmapFactory.decodeFile(FileLoader.getInstance(currentAccount).getPathToAttach(smallPhoto, true).getAbsolutePath()); String key = smallPhoto.location.volume_id + "_" + smallPhoto.location.local_id + "@50_50"; ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key, true); } catch (Throwable ignore) { @@ -740,6 +740,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega convertingVideo = avatarObject; long startTime = avatarObject.videoEditedInfo.startTime < 0 ? 0 : avatarObject.videoEditedInfo.startTime; videoTimestamp = (avatarObject.videoEditedInfo.avatarStartTime - startTime) / 1000000.0; + avatarObject.videoEditedInfo.shouldLimitFps = false; NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.filePreparingStarted); NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.filePreparingFailed); NotificationCenter.getInstance(currentAccount).addObserver(ImageUpdater.this, NotificationCenter.fileNewChunkAvailable); @@ -864,11 +865,11 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega Bitmap bitmap = SendMessagesHelper.createVideoThumbnailAtTime(finalPath, (long) (videoTimestamp * 1000), null, true); if (bitmap != null) { - File path = FileLoader.getPathToAttach(smallPhoto, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(smallPhoto, true); if (path != null) { path.delete(); } - path = FileLoader.getPathToAttach(bigPhoto, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(bigPhoto, true); if (path != null) { path.delete(); } @@ -876,7 +877,7 @@ public class ImageUpdater implements NotificationCenter.NotificationCenterDelega smallPhoto = ImageLoader.scaleAndSaveImage(bitmap, 150, 150, 80, false, 150, 150); if (smallPhoto != null) { try { - Bitmap b = BitmapFactory.decodeFile(FileLoader.getPathToAttach(smallPhoto, true).getAbsolutePath()); + Bitmap b = BitmapFactory.decodeFile(FileLoader.getInstance(currentAccount).getPathToAttach(smallPhoto, true).getAbsolutePath()); String key = smallPhoto.location.volume_id + "_" + smallPhoto.location.local_id + "@50_50"; ImageLoader.getInstance().putImageToCache(new BitmapDrawable(b), key, true); } catch (Throwable ignore) { 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 7f159841b..1546798e8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -99,6 +99,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; +import java.util.Collections; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.ArrayBlockingQueue; @@ -158,7 +159,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private CameraGLThread cameraThread; private Size previewSize; private Size pictureSize; - private Size aspectRatio = SharedConfig.roundCamera16to9 ? new Size(16, 9) : new Size(4, 3); + private Size aspectRatio = SharedConfig.roundCamera16to9 ? new Size(1, 1) : new Size(4, 3); private TextureView textureView; private BackupImageView textureOverlayView; private CameraSession cameraSession; @@ -181,21 +182,6 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter " vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" + "}\n"; - private static final String FRAGMENT_SHADER = - "#extension GL_OES_EGL_image_external : require\n" + - "precision highp float;\n" + - "varying vec2 vTextureCoord;\n" + - "uniform float scaleX;\n" + - "uniform float scaleY;\n" + - "uniform float alpha;\n" + - "uniform samplerExternalOES sTexture;\n" + - "void main() {\n" + - " vec2 coord = vec2((vTextureCoord.x - 0.5) * scaleX, (vTextureCoord.y - 0.5) * scaleY);\n" + - " float coef = ceil(clamp(0.2601 - dot(coord, coord), 0.0, 1.0));\n" + - " vec3 color = texture2D(sTexture, vTextureCoord).rgb * coef + (1.0 - step(0.001, coef));\n" + - " gl_FragColor = vec4(color * alpha, alpha);\n" + - "}\n"; - private static final String FRAGMENT_SCREEN_SHADER = "#extension GL_OES_EGL_image_external : require\n" + "precision lowp float;\n" + @@ -229,6 +215,8 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private boolean updateTextureViewSize; private final Theme.ResourcesProvider resourcesProvider; + private final static int audioSampleRate = 48000; + @SuppressLint("ClickableViewAccessibility") public InstantCameraView(Context context, ChatActivity parentFragment, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -381,7 +369,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter float rad = AndroidUtilities.rectTmp.width() / 2f; canvas.drawRoundRect(AndroidUtilities.rectTmp, rad, rad, blackoutPaint); AndroidUtilities.rectTmp.inset(AndroidUtilities.dp(1), AndroidUtilities.dp(1)); - flickerDrawable.draw(canvas, AndroidUtilities.rectTmp, rad); + flickerDrawable.draw(canvas, AndroidUtilities.rectTmp, rad, null); invalidate(); } } @@ -936,8 +924,8 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter ArrayList previewSizes = selectedCamera.getPreviewSizes(); ArrayList pictureSizes = selectedCamera.getPictureSizes(); - previewSize = CameraController.chooseOptimalSize(previewSizes, 480, 270, aspectRatio); - pictureSize = CameraController.chooseOptimalSize(pictureSizes, 480, 270, aspectRatio); + previewSize = chooseOptimalSize(previewSizes); + pictureSize = chooseOptimalSize(pictureSizes); if (previewSize.mWidth != pictureSize.mWidth) { boolean found = false; for (int a = previewSizes.size() - 1; a >= 0; a--) { @@ -980,6 +968,30 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter return true; } + private Size chooseOptimalSize(ArrayList previewSizes) { + ArrayList sortedSizes = new ArrayList<>(); + for (int i = 0; i < previewSizes.size(); i++) { + if (Math.max(previewSizes.get(i).mHeight, previewSizes.get(i).mHeight) <= 1200 && Math.min(previewSizes.get(i).mHeight, previewSizes.get(i).mHeight) >= 320) { + sortedSizes.add(previewSizes.get(i)); + } + } + if (sortedSizes.isEmpty() || SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { + return CameraController.chooseOptimalSize(previewSizes, 480, 270, aspectRatio); + } + Collections.sort(sortedSizes, (o1, o2) -> { + float a1 = Math.min(o1.mHeight, o1.mWidth) / (float) Math.max(o1.mHeight, o1.mWidth); + float a2 = Math.min(o2.mHeight, o2.mWidth) / (float) Math.max(o2.mHeight, o2.mWidth); + + if (a1 < a2) { + return 1; + } else if (a1 > a2) { + return -1; + } + return 0; + }); + return sortedSizes.get(0); + } + private void createCamera(final SurfaceTexture surfaceTexture) { AndroidUtilities.runOnUIThread(() -> { if (cameraThread == null) { @@ -1426,8 +1438,8 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter GLES20.glGenTextures(1, cameraTexture, 0); GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, cameraTexture[0]); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); - GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); @@ -1676,7 +1688,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } buffer.offset[a] = audioPresentationTimeUs; buffer.read[a] = readResult; - int bufferDurationUs = 1000000 * readResult / 44100 / 2; + int bufferDurationUs = 1000000 * readResult / audioSampleRate / 2; audioPresentationTimeUs += bufferDurationUs; } if (buffer.results >= 0 || buffer.last) { @@ -2173,7 +2185,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private void prepareEncoder() { try { - int recordBufferSize = AudioRecord.getMinBufferSize(44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); + int recordBufferSize = AudioRecord.getMinBufferSize(audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); if (recordBufferSize <= 0) { recordBufferSize = 3584; } @@ -2184,7 +2196,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter for (int a = 0; a < 3; a++) { buffers.add(new AudioBufferInfo()); } - audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, 44100, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); + audioRecorder = new AudioRecord(MediaRecorder.AudioSource.DEFAULT, audioSampleRate, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, bufferSize); audioRecorder.startRecording(); if (BuildVars.LOGS_ENABLED) { FileLog.d("initied audio record with channels " + audioRecorder.getChannelCount() + " sample rate = " + audioRecorder.getSampleRate() + " bufferSize = " + bufferSize); @@ -2198,7 +2210,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter MediaFormat audioFormat = new MediaFormat(); audioFormat.setString(MediaFormat.KEY_MIME, AUDIO_MIME_TYPE); - audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, 44100); + audioFormat.setInteger(MediaFormat.KEY_SAMPLE_RATE, audioSampleRate); audioFormat.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1); audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, MessagesController.getInstance(currentAccount).roundAudioBitrate * 1024); audioFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, 2048 * AudioBufferInfo.MAX_SAMPLES); @@ -2318,7 +2330,7 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA); int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, VERTEX_SHADER); - int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, FRAGMENT_SHADER); + int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, createFragmentShader(previewSize)); if (vertexShader != 0 && fragmentShader != 0) { drawProgram = GLES20.glCreateProgram(); GLES20.glAttachShader(drawProgram, vertexShader); @@ -2525,6 +2537,51 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter } } + private String createFragmentShader(Size previewSize) { + if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW || Math.max(previewSize.getHeight(), previewSize.getWidth()) * 0.7f < MessagesController.getInstance(currentAccount).roundVideoSize) { + return "#extension GL_OES_EGL_image_external : require\n" + + "precision highp float;\n" + + "varying vec2 vTextureCoord;\n" + + "uniform float scaleX;\n" + + "uniform float scaleY;\n" + + "uniform float alpha;\n" + + "uniform samplerExternalOES sTexture;\n" + + "void main() {\n" + + " vec2 coord = vec2((vTextureCoord.x - 0.5) * scaleX, (vTextureCoord.y - 0.5) * scaleY);\n" + + " float coef = ceil(clamp(0.2601 - dot(coord, coord), 0.0, 1.0));\n" + + " vec3 color = texture2D(sTexture, vTextureCoord).rgb * coef + (1.0 - step(0.001, coef));\n" + + " gl_FragColor = vec4(color * alpha, alpha);\n" + + "}\n"; + } + //apply box blur + return "#extension GL_OES_EGL_image_external : require\n" + + "precision highp float;\n" + + "varying vec2 vTextureCoord;\n" + + "uniform float scaleX;\n" + + "uniform float scaleY;\n" + + "uniform float alpha;\n" + + "const float kernel = 1.0;\n" + + "const float pixelSizeX = 1.0 / " + previewSize.getWidth() + ".0;\n" + + "const float pixelSizeY = 1.0 / " + previewSize.getHeight() + ".0;\n" + + + "uniform samplerExternalOES sTexture;\n" + + "void main() {\n" + + " vec3 accumulation = vec3(0);\n" + + " vec3 weightsum = vec3(0);\n" + + " for (float x = -kernel; x <= kernel; x++){\n" + + " for (float y = -kernel; y <= kernel; y++){\n" + + " accumulation += texture2D(sTexture, vTextureCoord + vec2(x * pixelSizeX, y * pixelSizeY)).xyz;\n" + + " weightsum += 1.0;\n" + + " }\n" + + " }\n" + + " vec4 textColor = vec4(accumulation / weightsum, 1.0);\n" + + " vec2 coord = vec2((vTextureCoord.x - 0.5) * scaleX, (vTextureCoord.y - 0.5) * scaleY);\n" + + " float coef = ceil(clamp(0.2601 - dot(coord, coord), 0.0, 1.0));\n" + + " vec3 color = textColor.rgb * coef + (1.0 - step(0.001, coef));\n" + + " gl_FragColor = vec4(color * alpha, alpha);\n" + + "}\n"; + } + public class InstantViewCameraContainer extends FrameLayout { ImageReceiver imageReceiver; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java index 945a0f197..0976a0ab7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteLinkBottomSheet.java @@ -116,6 +116,7 @@ public class InviteLinkBottomSheet extends BottomSheet { this.chatId = chatId; this.permanent = permanent; this.isChannel = isChannel; + fixNavigationBar(getThemedColor(Theme.key_graySection)); if (this.users == null) { this.users = new HashMap<>(); @@ -307,7 +308,7 @@ public class InviteLinkBottomSheet extends BottomSheet { titleTextView.setSingleLine(true); titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); titleTextView.setEllipsize(TextUtils.TruncateAt.END); - titleTextView.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); + titleTextView.setPadding(AndroidUtilities.dp(23), 0, AndroidUtilities.dp(23), 0); titleTextView.setGravity(Gravity.CENTER_VERTICAL); titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); if (!permanent) { @@ -331,8 +332,8 @@ public class InviteLinkBottomSheet extends BottomSheet { titleTextView.setText(builder); } - containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, !titleVisible ? 0 : 48, 0, 0)); - containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, !titleVisible ? 48 : 50, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); + containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, !titleVisible ? 0 : 44, 0, 0)); + containerView.addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, !titleVisible ? 44 : 50, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 0)); updateRows(); loadUsers(); @@ -463,6 +464,7 @@ public class InviteLinkBottomSheet extends BottomSheet { emptyView = rowCount++; boolean needUsers = invite.usage > 0 || invite.usage_limit > 0 || invite.requested > 0; + boolean needLoadUsers = invite.usage > joinedUsers.size() || invite.request_needed && invite.requested > requestedUsers.size(); boolean usersLoaded = false; if (!joinedUsers.isEmpty()) { dividerRow = rowCount++; @@ -482,7 +484,7 @@ public class InviteLinkBottomSheet extends BottomSheet { emptyView3 = rowCount++; usersLoaded = true; } - if (needUsers) { + if (needUsers || needLoadUsers) { if (!usersLoaded) { dividerRow = rowCount++; loadingRow = rowCount++; 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 5fec41402..3f4a9baa0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InviteMembersBottomSheet.java @@ -130,6 +130,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica needSnapToTop = false; this.parentFragment = parentFragment; this.chatId = chatId; + fixNavigationBar(); searchView.searchEditText.setHint(LocaleController.getString("SearchForChats", R.string.SearchForChats)); @@ -1316,7 +1317,7 @@ public class InviteMembersBottomSheet extends UsersAlertBase implements Notifica if (activity instanceof LaunchActivity) { BaseFragment fragment = ((LaunchActivity) activity).getActionBarLayout().fragmentsStack.get(((LaunchActivity) activity).getActionBarLayout().fragmentsStack.size() - 1); if (fragment instanceof ChatActivity) { - ((ChatActivity) fragment).onEditTextDialogClose(true); + ((ChatActivity) fragment).onEditTextDialogClose(true, true); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java index caa2932bc..4151c3d62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallAlert.java @@ -17,6 +17,7 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; @@ -122,12 +123,13 @@ public class JoinCallAlert extends BottomSheet { background = new View(context); if (hasBackground) { - background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + background.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); } addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, withoutBackground ? 0 : 16, 16, 16)); for (int a = 0; a < 2; a++) { textView[a] = new EmojiTextView(context); + textView[a].setFocusable(false); textView[a].setLines(1); textView[a].setSingleLine(true); textView[a].setGravity(Gravity.CENTER_HORIZONTAL); @@ -139,6 +141,7 @@ public class JoinCallAlert extends BottomSheet { } else { textView[a].setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton)); } + textView[a].setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); textView[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView[a].setPadding(0, 0, 0, hasBackground ? 0 : AndroidUtilities.dp(13)); addView(textView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 24, 0, 24, 0)); @@ -153,7 +156,10 @@ public class JoinCallAlert extends BottomSheet { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(hasBackground ? 80 : 50), MeasureSpec.EXACTLY)); } + private CharSequence text; + public void setText(CharSequence text, boolean animated) { + this.text = text; if (!animated) { textView[0].setText(text); } else { @@ -180,6 +186,16 @@ public class JoinCallAlert extends BottomSheet { animatorSet.start(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Button"); + info.setClickable(true); + if (text != null) { +// info.setText(text); + } + } } public static void checkFewUsers(Context context, long did, AccountInstance accountInstance, MessagesStorage.BooleanCallback callback) { @@ -279,6 +295,7 @@ public class JoinCallAlert extends BottomSheet { this.delegate = delegate; currentType = type; + int backgroundColor; shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); if (type == TYPE_DISPLAY) { if (VoIPService.getSharedInstance() != null) { @@ -302,11 +319,12 @@ public class JoinCallAlert extends BottomSheet { } else { selectedPeer = chats.get(0); } - shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_voipgroup_inviteMembersBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor = Theme.getColor(Theme.key_voipgroup_inviteMembersBackground), PorterDuff.Mode.MULTIPLY)); } else { - shadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor = Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); selectedPeer = chats.get(0); } + fixNavigationBar(backgroundColor); ViewGroup internalLayout; if (currentType == TYPE_CREATE) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallByUrlAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallByUrlAlert.java index e8f388a61..06927bcd1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallByUrlAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinCallByUrlAlert.java @@ -41,7 +41,7 @@ public class JoinCallByUrlAlert extends BottomSheet { super(context); background = new View(context); - background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + background.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16)); textView = new TextView(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java index 3826156a0..8e5eb0aa8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinGroupAlert.java @@ -27,7 +27,9 @@ import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.BottomSheet; @@ -42,18 +44,24 @@ import androidx.recyclerview.widget.RecyclerView; public class JoinGroupAlert extends BottomSheet { private TLRPC.ChatInvite chatInvite; + private TLRPC.Chat currentChat; private String hash; private BaseFragment fragment; private TextView requestTextView; private RadialProgressView requestProgressView; - public JoinGroupAlert(final Context context, TLRPC.ChatInvite invite, String group, BaseFragment parentFragment) { - super(context, false); + public JoinGroupAlert(final Context context, TLObject obj, String group, BaseFragment parentFragment, Theme.ResourcesProvider resourcesProvider) { + super(context, false, resourcesProvider); setApplyBottomPadding(false); setApplyTopPadding(false); + fixNavigationBar(getThemedColor(Theme.key_windowBackgroundWhite)); fragment = parentFragment; - chatInvite = invite; + if (obj instanceof TLRPC.ChatInvite) { + chatInvite = (TLRPC.ChatInvite) obj; + } else if (obj instanceof TLRPC.Chat) { + currentChat = (TLRPC.Chat) obj; + } hash = group; LinearLayout linearLayout = new LinearLayout(context); @@ -69,50 +77,60 @@ public class JoinGroupAlert extends BottomSheet { ImageView closeView = new ImageView(context); closeView.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_listSelector))); - closeView.setColorFilter(Theme.getColor(Theme.key_sheet_other)); + closeView.setColorFilter(getThemedColor(Theme.key_sheet_other)); closeView.setImageResource(R.drawable.ic_layer_close); closeView.setOnClickListener((view) -> dismiss()); int closeViewPadding = AndroidUtilities.dp(8); closeView.setPadding(closeViewPadding, closeViewPadding, closeViewPadding, closeViewPadding); frameLayout.addView(closeView, LayoutHelper.createFrame(36, 36, Gravity.TOP | Gravity.END, 6, 8, 6, 0)); - String title; - AvatarDrawable avatarDrawable; - int participants_count; + String title = null, about = null; + AvatarDrawable avatarDrawable = null; + int participants_count = 0; BackupImageView avatarImageView = new BackupImageView(context); avatarImageView.setRoundRadius(AndroidUtilities.dp(35)); linearLayout.addView(avatarImageView, LayoutHelper.createLinear(70, 70, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 29, 0, 0)); - if (invite.chat != null) { - avatarDrawable = new AvatarDrawable(invite.chat); - title = invite.chat.title; - participants_count = invite.chat.participants_count; - avatarImageView.setForUserOrChat(invite.chat, avatarDrawable, invite); - } else { - avatarDrawable = new AvatarDrawable(); - avatarDrawable.setInfo(0, invite.title, null); - title = invite.title; - participants_count = invite.participants_count; - TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(invite.photo.sizes, 50); - avatarImageView.setImage(ImageLocation.getForPhoto(size, invite.photo), "50_50", avatarDrawable, invite); + if (chatInvite != null) { + if (chatInvite.chat != null) { + avatarDrawable = new AvatarDrawable(chatInvite.chat); + title = chatInvite.chat.title; + participants_count = chatInvite.chat.participants_count; + avatarImageView.setForUserOrChat(chatInvite.chat, avatarDrawable, chatInvite); + } else { + avatarDrawable = new AvatarDrawable(); + avatarDrawable.setInfo(0, chatInvite.title, null); + title = chatInvite.title; + participants_count = chatInvite.participants_count; + TLRPC.PhotoSize size = FileLoader.getClosestPhotoSizeWithSize(chatInvite.photo.sizes, 50); + avatarImageView.setImage(ImageLocation.getForPhoto(size, chatInvite.photo), "50_50", avatarDrawable, chatInvite); + } + about = chatInvite.about; + } else if (currentChat != null) { + avatarDrawable = new AvatarDrawable(currentChat); + title = currentChat.title; + TLRPC.ChatFull chatFull = MessagesController.getInstance(currentAccount).getChatFull(currentChat.id); + about = chatFull != null ? chatFull.about : null; + participants_count = Math.max(currentChat.participants_count, chatFull != null ? chatFull.participants_count : 0); + avatarImageView.setForUserOrChat(currentChat, avatarDrawable, currentChat); } TextView textView = new TextView(context); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - textView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + textView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); textView.setText(title); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); linearLayout.addView(textView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 10, 9, 10, participants_count > 0 ? 0 : 20)); - final boolean isChannel = invite.channel && !invite.megagroup || ChatObject.isChannelAndNotMegaGroup(invite.chat); - boolean hasAbout = !TextUtils.isEmpty(invite.about); + final boolean isChannel = chatInvite != null && (chatInvite.channel && !chatInvite.megagroup || ChatObject.isChannelAndNotMegaGroup(chatInvite.chat)) || ChatObject.isChannel(currentChat) && !currentChat.megagroup; + boolean hasAbout = !TextUtils.isEmpty(about); if (participants_count > 0) { textView = new TextView(context); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - textView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3)); + textView.setTextColor(getThemedColor(Theme.key_dialogTextGray3)); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); if (isChannel) { @@ -126,13 +144,13 @@ public class JoinGroupAlert extends BottomSheet { if (hasAbout) { TextView aboutTextView = new TextView(context); aboutTextView.setGravity(Gravity.CENTER); - aboutTextView.setText(invite.about); - aboutTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + aboutTextView.setText(about); + aboutTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlack)); aboutTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); linearLayout.addView(aboutTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 24, 10, 24, 20)); } - if (invite.request_needed) { + if (chatInvite == null || chatInvite.request_needed) { FrameLayout requestFrameLayout = new FrameLayout(getContext()); linearLayout.addView(requestFrameLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -158,32 +176,42 @@ public class JoinGroupAlert extends BottomSheet { requestProgressView.setVisibility(View.VISIBLE); } }, 400); - final TLRPC.TL_messages_importChatInvite request = new TLRPC.TL_messages_importChatInvite(); - request.hash = hash; - ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { - AndroidUtilities.runOnUIThread(() -> { - if (fragment == null || fragment.getParentActivity() == null) { - return; - } - if (error != null) { - if ("INVITE_REQUEST_SENT".equals(error.text)) { - setOnDismissListener(dialog -> { - Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(context, fragment.getResourceProvider()); - layout.imageView.setAnimation(R.raw.timer_3, 28, 28); - layout.titleTextView.setText(LocaleController.getString("RequestToJoinSent", R.string.RequestToJoinSent)); - String subTitle = isChannel - ? LocaleController.getString("RequestToJoinChannelSentDescription", R.string.RequestToJoinChannelSentDescription) - : LocaleController.getString("RequestToJoinGroupSentDescription", R.string.RequestToJoinGroupSentDescription); - layout.subtitleTextView.setText(subTitle); - Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); - }); - } else { - AlertsCreator.processError(currentAccount, error, fragment, request); + if (chatInvite == null && currentChat != null) { + MessagesController.getInstance(currentAccount).addUserToChat( + currentChat.id, + UserConfig.getInstance(currentAccount).getCurrentUser(), + 0, + null, + null, + true, + this::dismiss, + err -> { + if (err != null && "INVITE_REQUEST_SENT".equals(err.text)) { + setOnDismissListener(di -> showBulletin(getContext(), fragment, isChannel)); } + dismiss(); + return false; } - dismiss(); - }); - }, ConnectionsManager.RequestFlagFailOnServerErrors); + ); + } else { + final TLRPC.TL_messages_importChatInvite request = new TLRPC.TL_messages_importChatInvite(); + request.hash = hash; + ConnectionsManager.getInstance(currentAccount).sendRequest(request, (response, error) -> { + AndroidUtilities.runOnUIThread(() -> { + if (fragment == null || fragment.getParentActivity() == null) { + return; + } + if (error != null) { + if ("INVITE_REQUEST_SENT".equals(error.text)) { + setOnDismissListener(di -> showBulletin(getContext(), fragment, isChannel)); + } else { + AlertsCreator.processError(currentAccount, error, fragment, request); + } + } + dismiss(); + }); + }, ConnectionsManager.RequestFlagFailOnServerErrors); + } }); requestFrameLayout.addView(requestTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, Gravity.START, 16, 0, 16, 0)); @@ -191,10 +219,10 @@ public class JoinGroupAlert extends BottomSheet { descriptionTextView.setGravity(Gravity.CENTER); descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); descriptionTextView.setText(isChannel ? LocaleController.getString("RequestToJoinChannelDescription", R.string.RequestToJoinChannelDescription) : LocaleController.getString("RequestToJoinGroupDescription", R.string.RequestToJoinGroupDescription)); - descriptionTextView.setTextColor(Theme.getColor(Theme.key_dialogTextGray3)); + descriptionTextView.setTextColor(getThemedColor(Theme.key_dialogTextGray3)); linearLayout.addView(descriptionTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP, 24, 17, 24, 15)); - } else { - if (!invite.participants.isEmpty()) { + } else if (chatInvite != null) { + if (!chatInvite.participants.isEmpty()) { RecyclerListView listView = new RecyclerListView(context); listView.setPadding(0, 0, 0, AndroidUtilities.dp(8)); listView.setNestedScrollingEnabled(false); @@ -203,25 +231,25 @@ public class JoinGroupAlert extends BottomSheet { listView.setHorizontalScrollBarEnabled(false); listView.setVerticalScrollBarEnabled(false); listView.setAdapter(new UsersAdapter(context)); - listView.setGlowColor(Theme.getColor(Theme.key_dialogScrollGlow)); + listView.setGlowColor(getThemedColor(Theme.key_dialogScrollGlow)); linearLayout.addView(listView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 90, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0, 0, 7)); } View shadow = new View(context); - shadow.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + shadow.setBackgroundColor(getThemedColor(Theme.key_dialogShadowLine)); linearLayout.addView(shadow, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.getShadowHeight())); - PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(context, false); + PickerBottomLayout pickerBottomLayout = new PickerBottomLayout(context, false, resourcesProvider); linearLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); pickerBottomLayout.cancelButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.cancelButton.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + pickerBottomLayout.cancelButton.setTextColor(getThemedColor(Theme.key_dialogTextBlue2)); pickerBottomLayout.cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); pickerBottomLayout.cancelButton.setOnClickListener(view -> dismiss()); pickerBottomLayout.doneButton.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); pickerBottomLayout.doneButton.setVisibility(View.VISIBLE); pickerBottomLayout.doneButtonBadgeTextView.setVisibility(View.GONE); - pickerBottomLayout.doneButtonTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); - if (invite.channel && !invite.megagroup || ChatObject.isChannel(invite.chat) && !invite.chat.megagroup) { + pickerBottomLayout.doneButtonTextView.setTextColor(getThemedColor(Theme.key_dialogTextBlue2)); + if (chatInvite.channel && !chatInvite.megagroup || ChatObject.isChannel(chatInvite.chat) && !chatInvite.chat.megagroup) { pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("ProfileJoinChannel", R.string.ProfileJoinChannel).toUpperCase()); } else { pickerBottomLayout.doneButtonTextView.setText(LocaleController.getString("JoinGroup", R.string.JoinGroup)); @@ -263,6 +291,17 @@ public class JoinGroupAlert extends BottomSheet { } } + public static void showBulletin(Context context, BaseFragment fragment, boolean isChannel) { + Bulletin.TwoLineLottieLayout layout = new Bulletin.TwoLineLottieLayout(context, fragment.getResourceProvider()); + layout.imageView.setAnimation(R.raw.timer_3, 28, 28); + layout.titleTextView.setText(LocaleController.getString("RequestToJoinSent", R.string.RequestToJoinSent)); + String subTitle = isChannel + ? LocaleController.getString("RequestToJoinChannelSentDescription", R.string.RequestToJoinChannelSentDescription) + : LocaleController.getString("RequestToJoinGroupSentDescription", R.string.RequestToJoinGroupSentDescription); + layout.subtitleTextView.setText(subTitle); + Bulletin.make(fragment, layout, Bulletin.DURATION_LONG).show(); + } + private class UsersAdapter extends RecyclerListView.SelectionAdapter { private Context context; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinToSendSettingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinToSendSettingsView.java new file mode 100644 index 000000000..5e7c07448 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/JoinToSendSettingsView.java @@ -0,0 +1,218 @@ +package org.telegram.ui.Components; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.view.MotionEvent; +import android.view.View; +import android.widget.LinearLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.TextCheckCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; + +public class JoinToSendSettingsView extends LinearLayout { + + public HeaderCell joinHeaderCell; + public TextCheckCell joinToSendCell; + public TextCheckCell joinRequestCell; + public TextInfoPrivacyCell joinToSendInfoCell; + public TextInfoPrivacyCell joinRequestInfoCell; + + public boolean isJoinToSend, isJoinRequest; + private TLRPC.Chat currentChat; + + public JoinToSendSettingsView(Context context, TLRPC.Chat currentChat) { + super(context); + this.currentChat = currentChat; + + isJoinToSend = currentChat.join_to_send; + isJoinRequest = currentChat.join_request; + + setOrientation(LinearLayout.VERTICAL); + + joinHeaderCell = new HeaderCell(context, 23); + joinHeaderCell.setText(LocaleController.getString("ChannelSettingsJoinTitle", R.string.ChannelSettingsJoinTitle)); + joinHeaderCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + addView(joinHeaderCell); + + joinToSendCell = new TextCheckCell(context) { +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN && !isEnabled()) { +// return true; +// } +// if (event.getAction() == MotionEvent.ACTION_UP && !isEnabled()) { +// new AlertDialog.Builder(context) +// .setTitle(LocaleController.getString("UserRestrictionsCantModify", R.string.UserRestrictionsCantModify)) +// .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ChannelSettingsJoinToSendRestricted", R.string.ChannelSettingsJoinToSendRestricted, LocaleController.getString("EditAdminBanUsers", R.string.EditAdminBanUsers)))) +// .setPositiveButton(LocaleController.getString("OK", R.string.OK), null) +// .create() +// .show(); +// return false; +// } +// return super.onTouchEvent(event); +// } + }; + joinToSendCell.setBackground(Theme.getSelectorDrawable(true)); + joinToSendCell.setTextAndCheck(LocaleController.getString("ChannelSettingsJoinToSend", R.string.ChannelSettingsJoinToSend), isJoinToSend, isJoinToSend); + joinToSendCell.setEnabled(currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.ban_users); + joinToSendCell.setOnClickListener(e -> { + final boolean oldValue = isJoinToSend, newValue = !isJoinToSend; + final boolean oldJoinToRequest = isJoinRequest; + if (onJoinToSendToggle(newValue, () -> AndroidUtilities.runOnUIThread(() -> { + setJoinRequest(oldJoinToRequest); + setJoinToSend(oldValue); + }))) { + setJoinRequest(false); + setJoinToSend(newValue); + } + }); + addView(joinToSendCell); + + joinRequestCell = new TextCheckCell(context) { +// @Override +// public boolean onTouchEvent(MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN && !isEnabled()) { +// new AlertDialog.Builder(context) +// .setTitle(LocaleController.getString("UserRestrictionsCantModify", R.string.UserRestrictionsCantModify)) +// .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ChannelSettingsJoinToSendRestricted", R.string.ChannelSettingsJoinToSendRestricted, LocaleController.getString("EditAdminBanUsers", R.string.EditAdminBanUsers)))) +// .setPositiveButton(LocaleController.getString("OK", R.string.OK), null) +// .create() +// .show(); +// return false; +// } +// return super.onTouchEvent(event); +// } + }; + joinRequestCell.setBackground(Theme.getSelectorDrawable(true)); + joinRequestCell.setTextAndCheck(LocaleController.getString("ChannelSettingsJoinRequest", R.string.ChannelSettingsJoinRequest), isJoinRequest, false); + joinRequestCell.setPivotY(0); + joinRequestCell.setEnabled(currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.ban_users); + joinRequestCell.setOnClickListener(e -> { + final boolean oldValue = isJoinRequest, newValue = !isJoinRequest; + if (onJoinRequestToggle(newValue, () -> AndroidUtilities.runOnUIThread(() -> { + setJoinRequest(oldValue); + }))) { + setJoinRequest(newValue); + } + }); + addView(joinRequestCell); + + joinToSendInfoCell = new TextInfoPrivacyCell(context); + joinToSendInfoCell.setText(LocaleController.getString("ChannelSettingsJoinToSendInfo", R.string.ChannelSettingsJoinToSendInfo)); + addView(joinToSendInfoCell); + + joinRequestInfoCell = new TextInfoPrivacyCell(context); + joinRequestInfoCell.setText(LocaleController.getString("ChannelSettingsJoinRequestInfo", R.string.ChannelSettingsJoinRequestInfo)); + addView(joinRequestInfoCell); + + toggleValue = isJoinToSend ? 1f : 0f; + joinRequestCell.setVisibility(isJoinToSend ? View.VISIBLE : View.GONE); + updateToggleValue(toggleValue); + } + + public void setChat(TLRPC.Chat chat) { + this.currentChat = chat; + joinToSendCell.setEnabled(currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.ban_users); + joinRequestCell.setEnabled(currentChat.creator || currentChat.admin_rights != null && currentChat.admin_rights.ban_users); + } + + public boolean onJoinToSendToggle(boolean newValue, Runnable cancel) { + return true; + } + public boolean onJoinRequestToggle(boolean newValue, Runnable cancel) { + return true; + } + + private ValueAnimator toggleAnimator; + private float toggleValue; + + private void updateToggleValue(float value) { + toggleValue = value; + joinRequestCell.setAlpha(value); + joinRequestCell.setTranslationY((1f - value) * -AndroidUtilities.dp(16)); + joinRequestCell.setScaleY(1f - (1f - value) * .1f); + int joinRequestCellHeight = joinRequestCell.getMeasuredHeight() <= 0 ? AndroidUtilities.dp(50) : joinRequestCell.getMeasuredHeight(); + joinToSendInfoCell.setAlpha(1f - value); + joinToSendInfoCell.setTranslationY(-joinRequestCellHeight * (1f - value) + -AndroidUtilities.dp(4) * value); + joinRequestInfoCell.setAlpha(value); + joinRequestInfoCell.setTranslationY(-joinRequestCellHeight * (1f - value) + AndroidUtilities.dp(4) * (1f - value)); + requestLayout(); + } + + public void setJoinRequest(boolean newJoinRequest) { + isJoinRequest = newJoinRequest; + joinRequestCell.setChecked(newJoinRequest); + } + + public void setJoinToSend(boolean newJoinToSend) { + isJoinToSend = newJoinToSend; + + joinToSendCell.setChecked(isJoinToSend); + joinToSendCell.setDivider(isJoinToSend); + joinRequestCell.setChecked(isJoinRequest); + + if (toggleAnimator != null) { + toggleAnimator.cancel(); + } + toggleAnimator = ValueAnimator.ofFloat(toggleValue, isJoinToSend ? 1 : 0); + toggleAnimator.setDuration(200); + toggleAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + toggleAnimator.addUpdateListener(a -> updateToggleValue(toggleValue = (float) a.getAnimatedValue())); + toggleAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (!isJoinToSend) { + joinRequestCell.setVisibility(View.GONE); + } + } + }); + joinRequestCell.setVisibility(View.VISIBLE); + toggleAnimator.start(); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int y = 0; + joinHeaderCell.layout(0, y, r - l, y += joinHeaderCell.getMeasuredHeight()); + joinToSendCell.layout(0, y, r - l, y += joinToSendCell.getMeasuredHeight()); + joinRequestCell.layout(0, y, r - l, y += joinRequestCell.getMeasuredHeight()); + joinToSendInfoCell.layout(0, y, r - l, y + joinToSendInfoCell.getMeasuredHeight()); + joinRequestInfoCell.layout(0, y, r - l, y + joinRequestInfoCell.getMeasuredHeight()); + } + + private final int MAXSPEC = MeasureSpec.makeMeasureSpec(999999, MeasureSpec.AT_MOST); + + private int calcHeight() { + return (int) ( + joinHeaderCell.getMeasuredHeight() + + joinToSendCell.getMeasuredHeight() + + joinRequestCell.getMeasuredHeight() * toggleValue + + AndroidUtilities.lerp(joinToSendInfoCell.getMeasuredHeight(), joinRequestInfoCell.getMeasuredHeight(), toggleValue) + ); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + joinHeaderCell.measure(widthMeasureSpec, MAXSPEC); + joinToSendCell.measure(widthMeasureSpec, MAXSPEC); + joinRequestCell.measure(widthMeasureSpec, MAXSPEC); + joinToSendInfoCell.measure(widthMeasureSpec, MAXSPEC); + joinRequestInfoCell.measure(widthMeasureSpec, MAXSPEC); + super.onMeasure(widthMeasureSpec, + MeasureSpec.makeMeasureSpec( + calcHeight(), + MeasureSpec.EXACTLY + ) + ); + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java index b3bf1c24b..459507dff 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterDrawable.java @@ -36,14 +36,18 @@ public class LetterDrawable extends Drawable { private StringBuilder stringBuilder = new StringBuilder(5); public LetterDrawable() { + this(null); + } + + public LetterDrawable(Theme.ResourcesProvider resourcesProvider) { super(); if (namePaint == null) { namePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); } namePaint.setTextSize(AndroidUtilities.dp(28)); - paint.setColor(Theme.getColor(Theme.key_sharedMedia_linkPlaceholder)); - namePaint.setColor(Theme.getColor(Theme.key_sharedMedia_linkPlaceholderText)); + paint.setColor(Theme.getColor(Theme.key_sharedMedia_linkPlaceholder, resourcesProvider)); + namePaint.setColor(Theme.getColor(Theme.key_sharedMedia_linkPlaceholderText, resourcesProvider)); } public void setBackgroundColor(int value) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java index cb4832d85..345edf014 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java @@ -127,7 +127,7 @@ public class LineProgressView extends View { cellFlickerDrawable.repeatProgress = 1.2f; } cellFlickerDrawable.setParentWidth(getMeasuredWidth()); - cellFlickerDrawable.draw(canvas, rect, getHeight() / 2f); + cellFlickerDrawable.draw(canvas, rect, getHeight() / 2f, null); invalidate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java index 1b82f50d2..c4e6ba920 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkActionView.java @@ -90,6 +90,7 @@ public class LinkActionView extends LinearLayout { frameLayout.addView(linkView); optionsView = new ImageView(context); optionsView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_ab_other)); + optionsView.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); optionsView.setScaleType(ImageView.ScaleType.CENTER); frameLayout.addView(optionsView, LayoutHelper.createFrame(40, 48, Gravity.RIGHT | Gravity.CENTER_VERTICAL)); addView(frameLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 4, 0, 4, 0)); @@ -105,6 +106,7 @@ public class LinkActionView extends LinearLayout { spannableStringBuilder.append(LocaleController.getString("LinkActionCopy", R.string.LinkActionCopy)); spannableStringBuilder.append(".").setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(5)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); copyView.setText(spannableStringBuilder); + copyView.setContentDescription(LocaleController.getString("LinkActionCopy", R.string.LinkActionCopy)); copyView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(10), AndroidUtilities.dp(10), AndroidUtilities.dp(10)); copyView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); copyView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -119,6 +121,7 @@ public class LinkActionView extends LinearLayout { spannableStringBuilder.append(LocaleController.getString("LinkActionShare", R.string.LinkActionShare)); spannableStringBuilder.append(".").setSpan(new DialogCell.FixedWidthSpan(AndroidUtilities.dp(5)), spannableStringBuilder.length() - 1, spannableStringBuilder.length(), 0); shareView.setText(spannableStringBuilder); + shareView.setContentDescription(LocaleController.getString("LinkActionShare", R.string.LinkActionShare)); shareView.setPadding(AndroidUtilities.dp(10), AndroidUtilities.dp(10), AndroidUtilities.dp(10), AndroidUtilities.dp(10)); shareView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); @@ -217,7 +220,7 @@ public class LinkActionView extends LinearLayout { } subItem = new ActionBarMenuSubItem(context, true, false); - subItem.setTextAndIcon(LocaleController.getString("GetQRCode", R.string.GetQRCode), R.drawable.msg_qrcode); + subItem.setTextAndIcon(LocaleController.getString("GetQRCode", R.string.GetQRCode), R.drawable.wallet_qr); layout.addView(subItem, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); subItem.setOnClickListener(view12 -> { showQrCode(); 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 7bb73610b..6be71cf69 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkPath.java @@ -117,7 +117,11 @@ public class LinkPath extends Path { y += baselineShift; } if (useRoundRect) { - super.addRect(left - getRadius() / 2f, y, right + getRadius() / 2f, y2, dir); +// final CharSequence text = currentLayout.getText(); +// 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); } else { super.addRect(left, y, right, y2, dir); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java index 8ea4a6375..ee8dfb468 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LinkSpanDrawable.java @@ -1,5 +1,6 @@ package org.telegram.ui.Components; +import android.content.Context; import android.graphics.Canvas; import android.graphics.CornerPathEffect; import android.graphics.Paint; @@ -8,11 +9,18 @@ import android.graphics.Rect; import android.graphics.Region; import android.os.Build; import android.os.SystemClock; +import android.text.Layout; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.StaticLayout; import android.text.style.CharacterStyle; +import android.text.style.ClickableSpan; import android.util.Log; import android.util.Pair; +import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.widget.TextView; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -361,4 +369,108 @@ public class LinkSpanDrawable { } } } + + public static class LinksTextView extends TextView { + public interface OnLinkPress { + public void run(ClickableSpan span); + } + + private boolean isCustomLinkCollector; + private LinkCollector links; + private Theme.ResourcesProvider resourcesProvider; + + private LinkSpanDrawable pressedLink; + + private OnLinkPress onPressListener; + private OnLinkPress onLongPressListener; + + public LinksTextView(Context context) { + this(context, null); + } + + public LinksTextView(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.isCustomLinkCollector = false; + this.links = new LinkCollector(this); + this.resourcesProvider = resourcesProvider; + } + + public LinksTextView(Context context, LinkCollector customLinkCollector, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.isCustomLinkCollector = true; + this.links = customLinkCollector; + this.resourcesProvider = resourcesProvider; + } + + public void setOnLinkPressListener(OnLinkPress listener) { + onPressListener = listener; + } + + public void setOnLinkLongPressListener(OnLinkPress listener) { + onLongPressListener = listener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (links != null) { + Layout textLayout = getLayout(); + int x = (int) (event.getX() - getPaddingLeft()); + int y = (int) (event.getY() - getPaddingTop()); + final int line = textLayout.getLineForVertical(y); + final int off = textLayout.getOffsetForHorizontal(line, x); + final float left = getLayout().getLineLeft(line); + ClickableSpan span = null; + if (left <= x && left + textLayout.getLineWidth(line) >= x && y >= 0 && y <= textLayout.getHeight()) { + Spannable buffer = new SpannableString(textLayout.getText()); + ClickableSpan[] spans = buffer.getSpans(off, off, ClickableSpan.class); + if (spans.length != 0 && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { + span = spans[0]; + if (event.getAction() == MotionEvent.ACTION_DOWN) { + pressedLink = new LinkSpanDrawable(span, resourcesProvider, event.getX(), event.getY()); + links.addLink(pressedLink); + int start = buffer.getSpanStart(pressedLink.getSpan()); + int end = buffer.getSpanEnd(pressedLink.getSpan()); + LinkPath path = pressedLink.obtainNewPath(); + path.setCurrentLayout(textLayout, start, getPaddingTop()); + textLayout.getSelectionPath(start, end, path); + AndroidUtilities.runOnUIThread(() -> { + if (onLongPressListener != null) { + onLongPressListener.run(spans[0]); + pressedLink = null; + links.clear(); + } + }, ViewConfiguration.getLongPressTimeout()); + return true; + } + } + } + if (event.getAction() == MotionEvent.ACTION_UP) { + links.clear(); + if (pressedLink != null && pressedLink.getSpan() == span) { + if (onPressListener != null) { + onPressListener.run(pressedLink.getSpan()); + } else if (pressedLink.getSpan() != null) { + pressedLink.getSpan().onClick(this); + } + } + pressedLink = null; + return true; + } + if (event.getAction() == MotionEvent.ACTION_CANCEL) { + links.clear(); + pressedLink = null; + return true; + } + } + return pressedLink != null || super.onTouchEvent(event); + } + + @Override + protected void onDraw(Canvas canvas) { + if (!isCustomLinkCollector && links.draw(canvas)) { + invalidate(); + } + super.onDraw(canvas); + } + } } 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 225c47f72..ca4eac5b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MediaActivity.java @@ -206,7 +206,7 @@ public class MediaActivity extends BaseFragment implements SharedMediaLayout.Sha updateMediaCount(); } - }, SharedMediaLayout.VIEW_TYPE_MEDIA_ACTIVITY) { + }, SharedMediaLayout.VIEW_TYPE_MEDIA_ACTIVITY, getResourceProvider()) { @Override protected void onSelectedTabChanged() { updateMediaCount(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MentionsContainerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MentionsContainerView.java new file mode 100644 index 000000000..6b03ccfed --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MentionsContainerView.java @@ -0,0 +1,660 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.dynamicanimation.animation.DynamicAnimation; +import androidx.dynamicanimation.animation.FloatValueHolder; +import androidx.dynamicanimation.animation.SpringAnimation; +import androidx.dynamicanimation.animation.SpringForce; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.SharedConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Adapters.MentionsAdapter; +import org.telegram.ui.Adapters.PaddedListAdapter; +import org.telegram.ui.Cells.AboutLinkCell; +import org.telegram.ui.ContentPreviewViewer; + +public class MentionsContainerView extends BlurredFrameLayout { + + private final SizeNotifierFrameLayout sizeNotifierFrameLayout; + private final Theme.ResourcesProvider resourcesProvider; + + private MentionsListView listView; + private LinearLayoutManager linearLayoutManager; + private ExtendedGridLayoutManager gridLayoutManager; + + private PaddedListAdapter paddedAdapter; + private MentionsAdapter adapter; + + private float containerTop, containerBottom, containerPadding, listViewPadding; + + public MentionsContainerView(@NonNull Context context, long dialogId, int threadMessageId, SizeNotifierFrameLayout sizeNotifierFrameLayout, Theme.ResourcesProvider resourcesProvider) { + super(context, sizeNotifierFrameLayout); + this.sizeNotifierFrameLayout = sizeNotifierFrameLayout; + this.resourcesProvider = resourcesProvider; + this.drawBlur = false; + this.isTopView = false; + setVisibility(View.GONE); + setWillNotDraw(false); + + listViewPadding = (int) Math.min(AndroidUtilities.dp(36 * 3.5f), AndroidUtilities.displaySize.y * 0.22f); + + listView = new MentionsListView(context, resourcesProvider); + listView.setTranslationY(AndroidUtilities.dp(6)); + linearLayoutManager = new LinearLayoutManager(context) { + @Override + public boolean supportsPredictiveItemAnimations() { + return false; + } + + @Override + public void setReverseLayout(boolean reverseLayout) { + super.setReverseLayout(reverseLayout); + listView.setTranslationY((reverseLayout ? -1 : 1) * AndroidUtilities.dp(6)); + } + }; + linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); + gridLayoutManager = new ExtendedGridLayoutManager(context, 100, false, false) { + private Size size = new Size(); + + @Override + protected Size getSizeForItem(int i) { + if (i == 0) { + size.width = getWidth(); + size.height = paddedAdapter.getPadding(); + return size; + } else { + i--; + } + if (adapter.getBotContextSwitch() != null) { + i++; + } + size.width = 0; + size.height = 0; + Object object = adapter.getItem(i); + if (object instanceof TLRPC.BotInlineResult) { + TLRPC.BotInlineResult inlineResult = (TLRPC.BotInlineResult) object; + if (inlineResult.document != null) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(inlineResult.document.thumbs, 90); + size.width = thumb != null ? thumb.w : 100; + size.height = thumb != null ? thumb.h : 100; + for (int b = 0; b < inlineResult.document.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.document.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; + } + } + } else if (inlineResult.content != null) { + for (int b = 0; b < inlineResult.content.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.content.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; + } + } + } else if (inlineResult.thumb != null) { + for (int b = 0; b < inlineResult.thumb.attributes.size(); b++) { + TLRPC.DocumentAttribute attribute = inlineResult.thumb.attributes.get(b); + if (attribute instanceof TLRPC.TL_documentAttributeImageSize || attribute instanceof TLRPC.TL_documentAttributeVideo) { + size.width = attribute.w; + size.height = attribute.h; + break; + } + } + } else if (inlineResult.photo != null) { + TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(inlineResult.photo.sizes, AndroidUtilities.photoSize); + if (photoSize != null) { + size.width = photoSize.w; + size.height = photoSize.h; + } + } + } + return size; + } + + @Override + protected int getFlowItemCount() { + if (adapter.getBotContextSwitch() != null) { + return getItemCount() - 2; + } + return super.getFlowItemCount() - 1; + } + }; + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + if (position == 0) { + return 100; + } else { + position--; + } + Object object = adapter.getItem(position); + if (object instanceof TLRPC.TL_inlineBotSwitchPM) { + return 100; + } else if (object instanceof TLRPC.Document) { + return 20; + } else { + if (adapter.getBotContextSwitch() != null) { + position--; + } + return gridLayoutManager.getSpanSizeForItem(position); + } + } + }); + DefaultItemAnimator mentionItemAnimator = new DefaultItemAnimator(); + mentionItemAnimator.setAddDuration(150); + mentionItemAnimator.setMoveDuration(150); + mentionItemAnimator.setChangeDuration(150); + mentionItemAnimator.setRemoveDuration(150); + mentionItemAnimator.setTranslationInterpolator(CubicBezierInterpolator.DEFAULT); + mentionItemAnimator.setDelayAnimations(false); + listView.setItemAnimator(mentionItemAnimator); + listView.setClipToPadding(false); + listView.setLayoutManager(linearLayoutManager); + + adapter = new MentionsAdapter(context, false, dialogId, threadMessageId, new MentionsAdapter.MentionsAdapterDelegate() { + @Override + public void onItemCountUpdate(int oldCount, int newCount) { + if (listView.getLayoutManager() != gridLayoutManager && shown) { + AndroidUtilities.cancelRunOnUIThread(updateVisibilityRunnable); + AndroidUtilities.runOnUIThread(updateVisibilityRunnable); + } + } + + @Override + public void needChangePanelVisibility(boolean show) { + if (getNeededLayoutManager() != getCurrentLayoutManager() && canOpen() && adapter.getItemCountInternal() > 0) { + switchLayoutManagerOnEnd = true; + updateVisibility(false); + return; + } + if (show && !canOpen()) { + show = false; + } + if (show && adapter.getItemCountInternal() <= 0) { + show = false; + } + updateVisibility(show); + } + + @Override + public void onContextSearch(boolean searching) { + MentionsContainerView.this.onContextSearch(searching); + } + + @Override + public void onContextClick(TLRPC.BotInlineResult result) { + MentionsContainerView.this.onContextClick(result); + } + + }, resourcesProvider); + paddedAdapter = new PaddedListAdapter(adapter); + listView.setAdapter(paddedAdapter); + + addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + setReversed(false); + } + + protected boolean canOpen() { + return true; + } + protected void onOpen() {} + protected void onClose() {} + protected void onContextSearch(boolean searching) {} + protected void onContextClick(TLRPC.BotInlineResult result) {} + + private boolean shouldLiftMentions = false; + + public void onPanTransitionStart() { + shouldLiftMentions = isReversed(); // (getCurrentLayoutManager().getReverseLayout() ? getCurrentLayoutManager().findLastVisibleItemPosition() : getCurrentLayoutManager().findFirstVisibleItemPosition()) > 0; + } + + public void onPanTransitionUpdate(float translationY) { + if (shouldLiftMentions) { + setTranslationY(translationY); + } + } + + public void onPanTransitionEnd() {} + + + public MentionsListView getListView() { + return listView; + } + + public MentionsAdapter getAdapter() { + return adapter; + } + + public void setReversed(boolean reversed) { + scrollToFirst = true; + linearLayoutManager.setReverseLayout(reversed); + adapter.setIsReversed(reversed); + } + + public boolean isReversed() { + return listView.getLayoutManager() == linearLayoutManager && linearLayoutManager.getReverseLayout(); + } + + public LinearLayoutManager getCurrentLayoutManager() { + return listView.getLayoutManager() == linearLayoutManager ? linearLayoutManager : gridLayoutManager; + } + + public LinearLayoutManager getNeededLayoutManager() { + return (adapter.isStickers() || adapter.isBotContext()) && adapter.isMediaLayout() ? gridLayoutManager : linearLayoutManager; + } + + private Rect rect = new Rect(); + private Path path; + private Paint paint; + + public float clipBottom() { + if (getVisibility() != View.VISIBLE) { + return 0; + } + return isReversed() ? 0 : getMeasuredHeight() - containerTop; + } + + public float clipTop() { + if (getVisibility() != View.VISIBLE) { + return 0; + } + return isReversed() ? containerBottom : 0; + } + + @Override + public void dispatchDraw(Canvas canvas) { + boolean reversed = isReversed(); + boolean topPadding = (adapter.isStickers() || adapter.isBotContext()) && adapter.isMediaLayout() && adapter.getBotContextSwitch() == null; + containerPadding = AndroidUtilities.dp(2 + (topPadding ? 2 : 0)); + + float r = AndroidUtilities.dp(4); + if (reversed) { + int paddingViewTop = paddedAdapter.paddingViewAttached ? paddedAdapter.paddingView.getTop() : getHeight(); + float top = Math.max(0, paddingViewTop + listView.getTranslationY()) + containerPadding; + top = Math.min(top, (1f - hideT) * getHeight()); + rect.set(0, (int) (containerTop = 0), getMeasuredWidth(), (int) (containerBottom = top)); + r = Math.min(r, Math.abs(getMeasuredHeight() - containerBottom)); + if (r > 0) { + rect.top -= (int) r; + } + } else { + if (listView.getLayoutManager() == gridLayoutManager) { + containerPadding += AndroidUtilities.dp(2); + r += AndroidUtilities.dp(2); + } + int paddingViewBottom = paddedAdapter.paddingViewAttached ? paddedAdapter.paddingView.getBottom() : 0; + float top = containerTop = Math.max(0, paddingViewBottom + listView.getTranslationY()) - containerPadding; + top = Math.max(top, hideT * getHeight()); + rect.set(0, (int) (containerTop = top), getMeasuredWidth(), (int) (containerBottom = getMeasuredHeight())); + r = Math.min(r, Math.abs(containerTop)); + if (r > 0) { + rect.bottom += (int) r; + } + } + + if (paint == null) { + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setShadowLayer(dp(4), 0, 0, 0x1e000000); + } + paint.setColor(color != null ? color : getThemedColor(Theme.key_chat_messagePanelBackground)); + + if (SharedConfig.chatBlurEnabled() && sizeNotifierFrameLayout != null) { + if (r > 0) { + canvas.save(); + if (path == null) { + path = new Path(); + } else { + path.reset(); + } + AndroidUtilities.rectTmp.set(rect); + path.addRoundRect(AndroidUtilities.rectTmp, r, r, Path.Direction.CW); + canvas.clipPath(path); + } + sizeNotifierFrameLayout.drawBlurRect(canvas, getY(), rect, paint, reversed); + if (r > 0) { + canvas.restore(); + } + } else { + AndroidUtilities.rectTmp.set(rect); + canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, paint); + } + canvas.save(); + canvas.clipRect(rect); + super.dispatchDraw(canvas); + canvas.restore(); + } + + private Integer color; + public void setOverrideColor(int color) { + this.color = color; + invalidate(); + } + + + private boolean ignoreLayout = false; + + public void setIgnoreLayout(boolean ignore) { + ignoreLayout = ignore; + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + + private boolean scrollToFirst = false; + private boolean shown = false; + private Runnable updateVisibilityRunnable = () -> { + updateListViewTranslation(!shown, true); + }; + + public void updateVisibility(boolean show) { + if (show) { + boolean reversed = isReversed(); + if (!shown) { + scrollToFirst = true; + if (listView.getLayoutManager() == linearLayoutManager) { + linearLayoutManager.scrollToPositionWithOffset(0, reversed ? -100000 : 100000); + } + if (getVisibility() == View.GONE) { + hideT = 1; + listView.setTranslationY(reversed ? -(listViewPadding + AndroidUtilities.dp(12)) : (listView.computeVerticalScrollOffset() + listViewPadding)); + } + } + setVisibility(View.VISIBLE); + } else { + scrollToFirst = false; + } + shown = show; + AndroidUtilities.cancelRunOnUIThread(updateVisibilityRunnable); + if (listViewTranslationAnimator != null) { + listViewTranslationAnimator.cancel(); + } + AndroidUtilities.runOnUIThread(updateVisibilityRunnable); + if (show) { + onOpen(); + } else { + onClose(); + } + } + + public boolean isOpen() { + return shown; + } + + private SpringAnimation listViewTranslationAnimator; + private boolean listViewHiding = false; + private float hideT = 0; + private boolean switchLayoutManagerOnEnd = false; + + private void updateListViewTranslation(boolean forceZeroHeight, boolean animated) { + if (listView == null || paddedAdapter == null) { + return; + } + if (listViewHiding && listViewTranslationAnimator != null && listViewTranslationAnimator.isRunning() && forceZeroHeight) { + return; + } + boolean reversed = isReversed(); + float itemHeight; + if (forceZeroHeight) { + itemHeight = - containerPadding - AndroidUtilities.dp(6); + } else { + itemHeight = listView.computeVerticalScrollRange() - paddedAdapter.getPadding() + containerPadding; + } + float newTranslationY = (reversed ? -Math.max(0, listViewPadding - itemHeight) : -listViewPadding + Math.max(0, listViewPadding - itemHeight)); + if (forceZeroHeight && !reversed) { + newTranslationY += listView.computeVerticalScrollOffset(); // getMeasuredHeight() - containerTop; + } + setVisibility(View.VISIBLE); + if (listViewTranslationAnimator != null) { + listViewTranslationAnimator.cancel(); + } + if (animated) { + listViewHiding = forceZeroHeight; + final float fromTranslation = listView.getTranslationY(); + final float toTranslation = newTranslationY; + final float fromHideT = hideT; + final float toHideT = forceZeroHeight ? 1 : 0; + if (fromTranslation == toTranslation) { + listViewTranslationAnimator = null; + setVisibility(forceZeroHeight ? View.GONE : View.VISIBLE); + if (switchLayoutManagerOnEnd && forceZeroHeight) { + switchLayoutManagerOnEnd = false; + listView.setLayoutManager(getNeededLayoutManager()); + updateVisibility(shown = true); + } + } else { + listViewTranslationAnimator = + new SpringAnimation(new FloatValueHolder(fromTranslation)) + .setSpring( + new SpringForce(toTranslation) + .setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY) + .setStiffness(550.0f) + ); +// listViewTranslationAnimator = new SpringAnimation(listView, DynamicAnimation.TRANSLATION_Y, newTranslationY); +// listViewTranslationAnimator.getSpring().setStiffness(1500); +// listViewTranslationAnimator.getSpring().setDampingRatio(1); + listViewTranslationAnimator.addUpdateListener((anm, val, vel) -> { + listView.setTranslationY(val); + hideT = AndroidUtilities.lerp(fromHideT, toHideT, (val - fromTranslation) / (toTranslation - fromTranslation)); + }); + if (forceZeroHeight) { + listViewTranslationAnimator.addEndListener((a, cancelled, b, c) -> { + if (!cancelled) { + listViewTranslationAnimator = null; + setVisibility(forceZeroHeight ? View.GONE : View.VISIBLE); + if (switchLayoutManagerOnEnd && forceZeroHeight) { + switchLayoutManagerOnEnd = false; + listView.setLayoutManager(getNeededLayoutManager()); + updateVisibility(shown = true); + } + } + }); + } + listViewTranslationAnimator.start(); + } + } else { + hideT = forceZeroHeight ? 1 : 0; + listView.setTranslationY(newTranslationY); + if (forceZeroHeight) { + setVisibility(View.GONE); +// adapter.clear(true); + } + } + } + + public class MentionsListView extends RecyclerListView { + private boolean isScrolling, isDragging; + + public MentionsListView(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + setOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(RecyclerView recyclerView, int newState) { + isScrolling = newState != RecyclerView.SCROLL_STATE_IDLE; + isDragging = newState == RecyclerView.SCROLL_STATE_DRAGGING; + } + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + int lastVisibleItem; + if (getLayoutManager() == gridLayoutManager) { + lastVisibleItem = gridLayoutManager.findLastVisibleItemPosition(); + } else { + lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); + } + int visibleItemCount = lastVisibleItem == RecyclerView.NO_POSITION ? 0 : lastVisibleItem; + if (visibleItemCount > 0 && lastVisibleItem > adapter.getLastItemCount() - 5) { + adapter.searchForContextBotForNextOffset(); + } + } + }); + addItemDecoration(new RecyclerView.ItemDecoration() { + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.left = 0; + outRect.right = 0; + outRect.top = 0; + outRect.bottom = 0; + if (parent.getLayoutManager() == gridLayoutManager) { + int position = parent.getChildAdapterPosition(view); + if (position == 0) { + return; + } + position--; + if (adapter.isStickers()) { + return; + } else if (adapter.getBotContextSwitch() != null) { + if (position == 0) { + return; + } + position--; + if (!gridLayoutManager.isFirstRow(position)) { + outRect.top = AndroidUtilities.dp(2); + } + } else { + outRect.top = AndroidUtilities.dp(2); + } + outRect.right = gridLayoutManager.isLastInRow(position) ? 0 : AndroidUtilities.dp(2); + } + } + }); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + if (linearLayoutManager.getReverseLayout()) { + if (!isDragging && paddedAdapter != null && paddedAdapter.paddingView != null && paddedAdapter.paddingViewAttached && event.getY() > paddedAdapter.paddingView.getTop()) { + return false; + } + } else { + if (!isDragging && paddedAdapter != null && paddedAdapter.paddingView != null && paddedAdapter.paddingViewAttached && event.getY() < paddedAdapter.paddingView.getBottom()) { + return false; + } + } + boolean result = !isScrolling && ContentPreviewViewer.getInstance().onInterceptTouchEvent(event, listView, 0, null, resourcesProvider); + if (adapter.isStickers() && event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_MOVE) { + adapter.doSomeStickersAction(); + } + return super.onInterceptTouchEvent(event) || result; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (linearLayoutManager.getReverseLayout()) { + if (!isDragging && paddedAdapter != null && paddedAdapter.paddingView != null && paddedAdapter.paddingViewAttached && event.getY() > paddedAdapter.paddingView.getTop()) { + return false; + } + } else { + if (!isDragging && paddedAdapter != null && paddedAdapter.paddingView != null && paddedAdapter.paddingViewAttached && event.getY() < paddedAdapter.paddingView.getBottom()) { + return false; + } + } + return super.onTouchEvent(event); + } + + @Override + public void requestLayout() { + if (ignoreLayout) { + return; + } + super.requestLayout(); + } + + private int lastWidth; + private int lastHeight; + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int width = r - l; + int height = b - t; + + int position = -1, offset = 0; + boolean reversed = isReversed(); + LinearLayoutManager layoutManager = getCurrentLayoutManager(); + position = reversed ? layoutManager.findFirstVisibleItemPosition() : layoutManager.findLastVisibleItemPosition(); + View child = layoutManager.findViewByPosition(position); + if (child != null) { + offset = child.getTop() - (reversed ? 0 : lastHeight - height); + } + + super.onLayout(changed, l, t, r, b); + + if (scrollToFirst) { + ignoreLayout = true; + layoutManager.scrollToPositionWithOffset(0, 100000); + super.onLayout(false, l, t, r, b); + ignoreLayout = false; + scrollToFirst = false; + } else if (position != -1 && width == lastWidth && height - lastHeight != 0) { + ignoreLayout = true; + layoutManager.scrollToPositionWithOffset(position, offset, false); + super.onLayout(false, l, t, r, b); + ignoreLayout = false; + } + + lastHeight = height; + lastWidth = width; + } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + MentionsContainerView.this.invalidate(); + } + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + int height = MeasureSpec.getSize(heightSpec); + if (paddedAdapter != null) { + paddedAdapter.setPadding(height); + } + listViewPadding = (int) Math.min(AndroidUtilities.dp(36 * 3.5f), AndroidUtilities.displaySize.y * 0.22f); + super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(height + (int) listViewPadding, MeasureSpec.EXACTLY)); + } + + @Override + public void onScrolled(int dx, int dy) { + super.onScrolled(dx, dy); + MentionsContainerView.this.invalidate(); + } + } + + private Paint getThemedPaint(String paintKey) { + Paint paint = resourcesProvider.getPaint(paintKey); + return paint != null ? paint : Theme.getThemePaint(paintKey); + } + + private int getThemedColor(String key) { + Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; + return color != null ? color : Theme.getColor(key); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java index 816fc0ca2..7e5f1a891 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/MotionBackgroundDrawable.java @@ -76,6 +76,7 @@ public class MotionBackgroundDrawable extends Drawable { private Bitmap patternBitmap; private BitmapShader bitmapShader; private BitmapShader gradientShader; + private boolean disableGradientShaderScaling; private Matrix matrix; private boolean fastAnimation; @@ -377,12 +378,15 @@ public class MotionBackgroundDrawable extends Drawable { } public void setPatternBitmap(int intensity) { - setPatternBitmap(intensity, patternBitmap); + setPatternBitmap(intensity, patternBitmap, true); + } + public void setPatternBitmap(int intensity, Bitmap bitmap) { + setPatternBitmap(intensity, bitmap, true); } @SuppressLint("NewApi") - public void setPatternBitmap(int intensity, Bitmap bitmap) { + public void setPatternBitmap(int intensity, Bitmap bitmap, boolean doNotScale) { this.intensity = intensity; patternBitmap = bitmap; invalidateLegacy = true; @@ -399,8 +403,10 @@ public class MotionBackgroundDrawable extends Drawable { if (intensity < 0) { if (!useLegacyBitmap) { bitmapShader = new BitmapShader(currentBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); - gradientShader = new BitmapShader(patternBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + gradientShader = new BitmapShader(patternBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); + disableGradientShaderScaling = doNotScale; paint2.setShader(new ComposeShader(bitmapShader, gradientShader, PorterDuff.Mode.DST_IN)); + paint2.setFilterBitmap(true); matrix = new Matrix(); } else { createLegacyBitmap(); @@ -428,6 +434,7 @@ public class MotionBackgroundDrawable extends Drawable { this.patternAlpha = alpha; invalidateParent(); } + public void setBackgroundAlpha(float alpha) { this.backgroundAlpha = alpha; invalidateParent(); @@ -625,8 +632,10 @@ public class MotionBackgroundDrawable extends Drawable { height = bitmapHeight * maxScale; x = (w - width) / 2; y = (h - height) / 2; - matrix.setTranslate(x, y + tr); - matrix.preScale(maxScale, maxScale); + matrix.setTranslate((int) x, (int) (y + tr)); + if (!disableGradientShaderScaling || maxScale > 1.4f || maxScale < 0.8f) { + matrix.preScale(maxScale, maxScale); + } gradientShader.setLocalMatrix(matrix); paint2.setColorFilter(null); paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); @@ -758,8 +767,10 @@ public class MotionBackgroundDrawable extends Drawable { height = bitmapHeight * maxScale; x = (w - width) / 2; y = (h - height) / 2; - matrix.setTranslate(x, y + tr); - matrix.preScale(maxScale, maxScale); + matrix.setTranslate((int) x, (int) (y + tr)); + if (!disableGradientShaderScaling || maxScale > 1.4f || maxScale < 0.8f) { + matrix.preScale(maxScale, maxScale); + } gradientShader.setLocalMatrix(matrix); paint2.setColorFilter(null); paint2.setAlpha((int) ((Math.abs(intensity) / 100f) * alpha * patternAlpha)); 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 29f8077be..8bc11e338 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java @@ -22,10 +22,12 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; +import android.os.Build; import android.text.TextUtils; import android.util.SparseArray; import android.util.TypedValue; import android.view.Gravity; +import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -856,6 +858,11 @@ public class NumberPicker extends LinearLayout { int previous = mValue; mValue = current; updateInputTextView(); + if (Math.abs(previous - current) > 0.9f && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + try { + performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } if (notifyChange) { notifyChange(previous, current); } @@ -863,7 +870,7 @@ public class NumberPicker extends LinearLayout { invalidate(); } - private void changeValueByOne(boolean increment) { + protected void changeValueByOne(boolean increment) { mInputText.setVisibility(View.INVISIBLE); if (!moveToFinalScrollerPosition(mFlingScroller)) { moveToFinalScrollerPosition(mAdjustScroller); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java index 358316546..52bbcaca8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberTextView.java @@ -19,6 +19,7 @@ import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/OtherDocumentPlaceholderDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/OtherDocumentPlaceholderDrawable.java index c1c29648a..63f0dd1a5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/OtherDocumentPlaceholderDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/OtherDocumentPlaceholderDrawable.java @@ -18,6 +18,7 @@ import org.telegram.messenger.ImageLoader; 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 java.io.File; @@ -266,7 +267,7 @@ public class OtherDocumentPlaceholderDrawable extends RecyclableDrawable impleme String fileName = null; File cacheFile; if (TextUtils.isEmpty(parentMessageObject.messageOwner.attachPath) || !(new File(parentMessageObject.messageOwner.attachPath).exists())) { - cacheFile = FileLoader.getPathToMessage(parentMessageObject.messageOwner); + cacheFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToMessage(parentMessageObject.messageOwner); if (!cacheFile.exists()) { fileName = FileLoader.getAttachFileName(parentMessageObject.getDocument()); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/OverlayActionBarLayoutDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/OverlayActionBarLayoutDialog.java new file mode 100644 index 000000000..a65634d5d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/OverlayActionBarLayoutDialog.java @@ -0,0 +1,150 @@ +package org.telegram.ui.Components; + +import android.app.Dialog; +import android.content.Context; +import android.graphics.Color; +import android.os.Build; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.ActionBarLayout; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class OverlayActionBarLayoutDialog extends Dialog implements ActionBarLayout.ActionBarLayoutDelegate { + private Theme.ResourcesProvider resourcesProvider; + private ActionBarLayout actionBarLayout; + private FrameLayout frameLayout; + + public OverlayActionBarLayoutDialog(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, R.style.TransparentDialog); + this.resourcesProvider = resourcesProvider; + + actionBarLayout = new ActionBarLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + super.onMeasure(MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(530), MeasureSpec.getSize(widthMeasureSpec)), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(Math.min(AndroidUtilities.dp(528), MeasureSpec.getSize(heightMeasureSpec)), MeasureSpec.EXACTLY)); + } else { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + } + }; + actionBarLayout.init(new ArrayList<>()); + actionBarLayout.presentFragment(new EmptyFragment(), false, true, false, false); + actionBarLayout.setDelegate(this); + + frameLayout = new FrameLayout(context); + frameLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); + frameLayout.addView(actionBarLayout, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER)); + if (AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()) { + frameLayout.setBackgroundColor(0x99000000); + frameLayout.setOnClickListener(v -> onBackPressed()); + actionBarLayout.setRemoveActionBarExtraHeight(true); + VerticalPositionAutoAnimator.attach(actionBarLayout); + } + setContentView(frameLayout); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Window window = getWindow(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); + } + window.setWindowAnimations(R.style.DialogNoAnimation); + + WindowManager.LayoutParams params = window.getAttributes(); + params.width = ViewGroup.LayoutParams.MATCH_PARENT; + params.gravity = Gravity.TOP | Gravity.LEFT; + params.dimAmount = 0; + params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; + params.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + params.height = ViewGroup.LayoutParams.MATCH_PARENT; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; + } + window.setAttributes(params); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + window.setStatusBarColor(Color.TRANSPARENT); + } + + frameLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + frameLayout.setOnApplyWindowInsetsListener((v, insets) -> { + v.setPadding(0, 0, 0, insets.getSystemWindowInsetBottom()); + return insets; + }); + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + int color = Theme.getColor(Theme.key_windowBackgroundWhite, null, true); + AndroidUtilities.setLightNavigationBar(window, ColorUtils.calculateLuminance(color) >= 0.9); + } + } + + public void addFragment(BaseFragment fragment) { + actionBarLayout.presentFragment(fragment, AndroidUtilities.isTablet() && !AndroidUtilities.isInMultiwindow && !AndroidUtilities.isSmallTablet()); + } + + @Override + public void onBackPressed() { + actionBarLayout.onBackPressed(); + if (actionBarLayout.fragmentsStack.size() <= 1) { + dismiss(); + } + } + + @Override + public boolean onPreIme() { + return false; + } + + @Override + public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) { + return true; + } + + @Override + public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) { + return true; + } + + @Override + public boolean needCloseLastFragment(ActionBarLayout layout) { + if (layout.fragmentsStack.size() <= 1) { + dismiss(); + } + return true; + } + + @Override + public void onRebuildAllFragments(ActionBarLayout layout, boolean last) {} + + private static final class EmptyFragment extends BaseFragment { + @Override + public View createView(Context context) { + actionBar.setAddToContainer(false); + View v = new View(context); + v.setBackgroundColor(Color.TRANSPARENT); + return v; + } + } +} 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 8cf2fead4..e15b1a4a5 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 @@ -215,7 +215,7 @@ public class Painting { GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getTexture()); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glActiveTexture(GLES20.GL_TEXTURE1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, getPaintTexture()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java index 0bf3a9b62..a8da41094 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/ShaderSet.java @@ -15,7 +15,7 @@ public class ShaderSet { private static final String UNIFORMS = "uniforms"; private static final String PAINT_BRUSH_VSH = "precision highp float; uniform mat4 mvpMatrix; attribute vec4 inPosition; attribute vec2 inTexcoord; attribute float alpha; varying vec2 varTexcoord; varying float varIntensity; void main (void) { gl_Position = mvpMatrix * inPosition; varTexcoord = inTexcoord; varIntensity = alpha; }"; - private static final String PAINT_BRUSH_FSH = "precision highp float; varying vec2 varTexcoord; varying float varIntensity; uniform sampler2D texture; void main (void) { gl_FragColor = vec4(0, 0, 0, varIntensity * texture2D(texture, varTexcoord.st, 0.0).r); }"; + private static final String PAINT_BRUSH_FSH = "precision highp float; varying vec2 varTexcoord; varying float varIntensity; uniform sampler2D texture; void main (void) { gl_FragColor = vec4(1, 1, 1, varIntensity * texture2D(texture, varTexcoord.st, 0.0).r); }"; private static final String PAINT_BRUSHLIGHT_FSH = "precision highp float; varying vec2 varTexcoord; varying float varIntensity; uniform sampler2D texture; void main (void) { vec4 f = texture2D(texture, varTexcoord.st, 0.0); gl_FragColor = vec4(f.r * varIntensity, f.g, f.b, 0.0); }"; private static final String PAINT_BLIT_VSH = "precision highp float; uniform mat4 mvpMatrix; attribute vec4 inPosition; attribute vec2 inTexcoord; varying vec2 varTexcoord; void main (void) { gl_Position = mvpMatrix * inPosition; varTexcoord = inTexcoord; }"; private static final String PAINT_BLIT_FSH = "precision highp float; varying vec2 varTexcoord; uniform sampler2D texture; void main (void) { gl_FragColor = texture2D(texture, varTexcoord.st, 0.0); gl_FragColor.rgb *= gl_FragColor.a; }"; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Texture.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Texture.java index 284d86338..274acc267 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Texture.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Texture.java @@ -1,8 +1,11 @@ package org.telegram.ui.Components.Paint; import android.graphics.Bitmap; +import android.graphics.Color; import android.opengl.GLES20; +import androidx.core.graphics.ColorUtils; + import org.telegram.ui.Components.Size; import java.nio.ByteBuffer; @@ -52,7 +55,7 @@ public class Texture { GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); int width = bitmap.getWidth(); @@ -86,7 +89,7 @@ public class Texture { GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); int width = (int) size.width; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java index 1b6b87983..ff09b3bbf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Paint/Views/ColorPicker.java @@ -20,6 +20,7 @@ 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.Components.LayoutHelper; import org.telegram.ui.Components.Paint.Swatch; @@ -66,7 +67,7 @@ public class ColorPicker extends FrameLayout { 1.0f }; - private ImageView settingsButton; + public ImageView settingsButton; private ImageView undoButton; private Drawable shadowDrawable; @@ -90,6 +91,7 @@ public class ColorPicker extends FrameLayout { swatchStrokePaint.setStrokeWidth(AndroidUtilities.dp(1)); settingsButton = new ImageView(context); + settingsButton.setContentDescription(LocaleController.getString("AccDescrBrushType", R.string.AccDescrBrushType)); settingsButton.setScaleType(ImageView.ScaleType.CENTER); settingsButton.setImageResource(R.drawable.photo_paint_brush); addView(settingsButton, LayoutHelper.createFrame(46, 52)); @@ -100,6 +102,7 @@ public class ColorPicker extends FrameLayout { }); undoButton = new ImageView(context); + undoButton.setContentDescription(LocaleController.getString("Undo", R.string.Undo)); undoButton.setScaleType(ImageView.ScaleType.CENTER); undoButton.setImageResource(R.drawable.photo_undo); addView(undoButton, LayoutHelper.createFrame(46, 52)); 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 8e5e78cc5..08900ccc7 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 @@ -129,6 +129,10 @@ public class EditTextOutline extends EditTextBoldCursor { if (mFrameColor != 0) { paint.setColor(mFrameColor); Layout sl = getLayout(); + if (sl == null) { + super.onDraw(canvas); + return; + } if (lines == null || lines.length != sl.getLineCount()) { lines = new float[sl.getLineCount()]; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java index 8a7587146..715b89997 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PaintingOverlay.java @@ -13,6 +13,7 @@ import android.text.Layout; import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; +import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.FrameLayout; @@ -25,11 +26,14 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.Components.Paint.Views.EditTextOutline; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; public class PaintingOverlay extends FrameLayout { private Bitmap paintBitmap; - private ArrayList mediaEntities; + private HashMap mediaEntityViews; private boolean ignoreLayout; private Drawable backgroundDrawable; @@ -38,6 +42,7 @@ public class PaintingOverlay extends FrameLayout { } public void setData(String paintPath, ArrayList entities, boolean isVideo, boolean startAfterSet) { + setEntities(entities, isVideo, startAfterSet); if (paintPath != null) { paintBitmap = BitmapFactory.decodeFile(paintPath); setBackground(backgroundDrawable = new BitmapDrawable(paintBitmap)); @@ -45,28 +50,28 @@ public class PaintingOverlay extends FrameLayout { paintBitmap = null; setBackground(backgroundDrawable = null); } - setEntities(entities, isVideo, startAfterSet); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ignoreLayout = true; setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); - if (mediaEntities != null) { + if (mediaEntityViews != null) { int width = getMeasuredWidth(); int height = getMeasuredHeight(); - for (int a = 0, N = mediaEntities.size(); a < N; a++) { - VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); - if (entity.view == null) { + for (int a = 0, N = getChildCount(); a < N; a++) { + View child = getChildAt(a); + VideoEditedInfo.MediaEntity entity = mediaEntityViews.get(child); + if (entity == null) { continue; } - if (entity.view instanceof EditTextOutline) { - entity.view.measure(MeasureSpec.makeMeasureSpec(entity.viewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + if (child instanceof EditTextOutline) { + child.measure(MeasureSpec.makeMeasureSpec(entity.viewWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); float sc = entity.textViewWidth * width / entity.viewWidth; - entity.view.setScaleX(entity.scale * sc); - entity.view.setScaleY(entity.scale * sc); + child.setScaleX(entity.scale * sc); + child.setScaleY(entity.scale * sc); } else { - entity.view.measure(MeasureSpec.makeMeasureSpec((int) (width * entity.width), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (height * entity.height), MeasureSpec.EXACTLY)); + child.measure(MeasureSpec.makeMeasureSpec((int) (width * entity.width), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (height * entity.height), MeasureSpec.EXACTLY)); } } } @@ -98,28 +103,37 @@ public class PaintingOverlay extends FrameLayout { @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mediaEntities != null) { + if (mediaEntityViews != null) { int width = getMeasuredWidth(); int height = getMeasuredHeight(); - for (int a = 0, N = mediaEntities.size(); a < N; a++) { - VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); - if (entity.view == null) { + for (int a = 0, N = getChildCount(); a < N; a++) { + View child = getChildAt(a); + VideoEditedInfo.MediaEntity entity = mediaEntityViews.get(child); + if (entity == null) { continue; } - int x; - int y; - if (entity.view instanceof EditTextOutline) { - x = (int) (width * entity.textViewX) - entity.view.getMeasuredWidth() / 2; - y = (int) (height * entity.textViewY) - entity.view.getMeasuredHeight() / 2; + int x, y; + if (child instanceof EditTextOutline) { + x = (int) (width * entity.textViewX) - child.getMeasuredWidth() / 2; + y = (int) (height * entity.textViewY) - child.getMeasuredHeight() / 2; } else { x = (int) (width * entity.x); y = (int) (height * entity.y); } - entity.view.layout(x, y, x + entity.view.getMeasuredWidth(), y + entity.view.getMeasuredHeight()); + child.layout(x, y, x + child.getMeasuredWidth(), y + child.getMeasuredHeight()); } } } + public void reset() { + paintBitmap = null; + setBackground(backgroundDrawable = null); + if (mediaEntityViews != null) { + mediaEntityViews.clear(); + } + removeAllViews(); + } + public void showAll() { int count = getChildCount(); for (int a = 0; a < count; a++) { @@ -140,11 +154,12 @@ public class PaintingOverlay extends FrameLayout { } public void setEntities(ArrayList entities, boolean isVideo, boolean startAfterSet) { - mediaEntities = entities; - removeAllViews(); + reset(); + mediaEntityViews = new HashMap<>(); if (entities != null && !entities.isEmpty()) { - for (int a = 0, N = mediaEntities.size(); a < N; a++) { - VideoEditedInfo.MediaEntity entity = mediaEntities.get(a); + for (int a = 0, N = entities.size(); a < N; a++) { + VideoEditedInfo.MediaEntity entity = entities.get(a); + View child = null; if (entity.type == 0) { BackupImageView imageView = new BackupImageView(getContext()); imageView.setAspectFit(true); @@ -168,7 +183,7 @@ public class PaintingOverlay extends FrameLayout { if ((entity.subType & 2) != 0) { imageView.setScaleX(-1); } - entity.view = imageView; + entity.view = child = imageView; } else if (entity.type == 1) { EditTextOutline editText = new EditTextOutline(getContext()) { @Override @@ -211,10 +226,13 @@ public class PaintingOverlay extends FrameLayout { editText.setFrameColor(0); editText.setShadowLayer(5, 0, 1, 0x66000000); } - entity.view = editText; + entity.view = child = editText; + } + if (child != null) { + addView(child); + child.setRotation((float) (-entity.rotation / Math.PI * 180)); + mediaEntityViews.put(child, entity); } - addView(entity.view); - entity.view.setRotation((float) (-entity.rotation / Math.PI * 180)); } } } @@ -233,6 +251,13 @@ public class PaintingOverlay extends FrameLayout { if (backgroundDrawable != null) { backgroundDrawable.setAlpha((int) (255 * alpha)); } + final int count = getChildCount(); + for (int i = 0; i < count; ++i) { + View child = getChildAt(i); + if (child != null && child.getParent() == this) { + child.setAlpha(alpha); + } + } } public Bitmap getThumb() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhonebookShareAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhonebookShareAlert.java index 8883944f9..5fc1e3fc5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhonebookShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhonebookShareAlert.java @@ -37,6 +37,8 @@ import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; +import androidx.core.widget.NestedScrollView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ContactsController; @@ -56,8 +58,6 @@ import java.io.File; import java.util.ArrayList; import java.util.Locale; -import androidx.core.widget.NestedScrollView; - public class PhonebookShareAlert extends BottomSheet { private ListAdapter listAdapter; @@ -556,13 +556,13 @@ public class PhonebookShareAlert extends BottomSheet { final Bulletin.SimpleLayout layout = new Bulletin.SimpleLayout(context, resourcesProvider); if (item.type == 0) { layout.textView.setText(LocaleController.getString("PhoneCopied", R.string.PhoneCopied)); - layout.imageView.setImageResource(R.drawable.menu_calls); + layout.imageView.setImageResource(R.drawable.msg_calls); } else if (item.type == 1) { layout.textView.setText(LocaleController.getString("EmailCopied", R.string.EmailCopied)); - layout.imageView.setImageResource(R.drawable.menu_mail); + layout.imageView.setImageResource(R.drawable.msg_mention); } else { layout.textView.setText(LocaleController.getString("TextCopied", R.string.TextCopied)); - layout.imageView.setImageResource(R.drawable.menu_info); + layout.imageView.setImageResource(R.drawable.msg_info); } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { Bulletin.make((FrameLayout) containerView, layout, Bulletin.DURATION_SHORT).show(); @@ -1066,19 +1066,19 @@ public class PhonebookShareAlert extends BottomSheet { } else if (item.type == 3) { icon = R.drawable.baseline_link_24; } else if (item.type == 4) { - icon = R.drawable.profile_info; + icon = R.drawable.msg_info; } else if (item.type == 5) { icon = R.drawable.baseline_date_range_24; } else if (item.type == 6) { if ("ORG".equalsIgnoreCase(item.getRawType(true))) { - icon = R.drawable.menu_work; + icon = R.drawable.msg_work; } else { - icon = R.drawable.menu_jobtitle; + icon = R.drawable.msg_jobtitle; } } else if (item.type == 20) { - icon = R.drawable.menu_info; + icon = R.drawable.msg_info; } else { - icon = R.drawable.menu_info; + icon = R.drawable.msg_info; } } cell.setVCardItem(item, icon, position != getItemCount() - 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java index 093010cfa..14cf98032 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoCropView.java @@ -43,12 +43,15 @@ public class PhotoCropView extends FrameLayout { void onTapUp(); int getVideoThumbX(); void onVideoThumbClick(); + boolean rotate(); + boolean mirror(); } private PhotoCropViewDelegate delegate; - private CropView cropView; - private CropRotationWheel wheelView; + public boolean isReset = true; + public CropView cropView; + public CropRotationWheel wheelView; private boolean inBubbleMode; @@ -100,6 +103,7 @@ public class PhotoCropView extends FrameLayout { cropView.setListener(new CropView.CropViewListener() { @Override public void onChange(boolean reset) { + isReset = reset; if (delegate != null) { delegate.onChange(reset); } @@ -139,6 +143,7 @@ public class PhotoCropView extends FrameLayout { @Override public void onChange(float angle) { cropView.setRotation(angle); + isReset = false; if (delegate != null) { delegate.onChange(false); } @@ -156,12 +161,18 @@ public class PhotoCropView extends FrameLayout { @Override public boolean rotate90Pressed() { - return rotate(); + if (delegate != null) { + return delegate.rotate(); + } + return false; } @Override public boolean mirror() { - return PhotoCropView.this.mirror(); + if (delegate != null) { + return delegate.mirror(); + } + return false; } }); addView(wheelView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER | Gravity.BOTTOM, 0, 0, 0, 0)); @@ -218,11 +229,11 @@ public class PhotoCropView extends FrameLayout { return result; } - public boolean rotate() { + public boolean rotate(float diff) { if (wheelView != null) { wheelView.reset(false); } - return cropView.rotate90Degrees(); + return cropView.rotate(diff); } public boolean mirror() { @@ -315,8 +326,12 @@ public class PhotoCropView extends FrameLayout { } public void reset() { + reset(false); + } + + public void reset(boolean force) { wheelView.reset(true); - cropView.reset(); + cropView.reset(force); } public void onAppear() { 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 9e0e8cbf1..0bef17443 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java @@ -28,6 +28,9 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; @@ -41,9 +44,6 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - @SuppressLint("NewApi") public class PhotoFilterView extends FrameLayout implements FilterShaders.FilterShadersDelegate { @@ -442,7 +442,7 @@ public class PhotoFilterView extends FrameLayout implements FilterShaders.Filter tuneItem = new ImageView(context); tuneItem.setScaleType(ImageView.ScaleType.CENTER); - tuneItem.setImageResource(R.drawable.photo_tools); + tuneItem.setImageResource(R.drawable.msg_photo_settings); tuneItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); tuneItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); linearLayout.addView(tuneItem, LayoutHelper.createLinear(56, 48)); @@ -456,7 +456,7 @@ public class PhotoFilterView extends FrameLayout implements FilterShaders.Filter blurItem = new ImageView(context); blurItem.setScaleType(ImageView.ScaleType.CENTER); - blurItem.setImageResource(R.drawable.tool_blur); + blurItem.setImageResource(R.drawable.msg_photo_blur); blurItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); linearLayout.addView(blurItem, LayoutHelper.createLinear(56, 48)); blurItem.setOnClickListener(v -> { @@ -472,7 +472,7 @@ public class PhotoFilterView extends FrameLayout implements FilterShaders.Filter curveItem = new ImageView(context); curveItem.setScaleType(ImageView.ScaleType.CENTER); - curveItem.setImageResource(R.drawable.tool_curve); + curveItem.setImageResource(R.drawable.msg_photo_curve); curveItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); linearLayout.addView(curveItem, LayoutHelper.createLinear(56, 48)); curveItem.setOnClickListener(v -> { @@ -624,35 +624,35 @@ public class PhotoFilterView extends FrameLayout implements FilterShaders.Filter private void updateSelectedBlurType() { if (blurType == 0) { - Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.blur_off).mutate(); + Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.msg_blur_off).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); blurOffButton.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); blurOffButton.setTextColor(getThemedColor(Theme.key_dialogFloatingButton)); - blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial, 0, 0); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_radial, 0, 0); blurRadialButton.setTextColor(0xffffffff); - blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear, 0, 0); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_linear, 0, 0); blurLinearButton.setTextColor(0xffffffff); } else if (blurType == 1) { - blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off, 0, 0); + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_off, 0, 0); blurOffButton.setTextColor(0xffffffff); - Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.blur_radial).mutate(); + Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.msg_blur_radial).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); blurRadialButton.setTextColor(getThemedColor(Theme.key_dialogFloatingButton)); - blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_linear, 0, 0); + blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_linear, 0, 0); blurLinearButton.setTextColor(0xffffffff); } else if (blurType == 2) { - blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_off, 0, 0); + blurOffButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_off, 0, 0); blurOffButton.setTextColor(0xffffffff); - blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.blur_radial, 0, 0); + blurRadialButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.msg_blur_radial, 0, 0); blurRadialButton.setTextColor(0xffffffff); - Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.blur_linear).mutate(); + Drawable drawable = blurOffButton.getContext().getResources().getDrawable(R.drawable.msg_blur_linear).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); blurLinearButton.setCompoundDrawablesWithIntrinsicBounds(null, drawable, null, null); blurLinearButton.setTextColor(getThemedColor(Theme.key_dialogFloatingButton)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java index 10fb31a9d..78ddb1267 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPaintView.java @@ -12,6 +12,7 @@ import android.graphics.Color; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Looper; import android.text.TextUtils; @@ -36,6 +37,8 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.VideoEditedInfo; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -82,6 +85,7 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView private EntitiesContainerView entitiesView; private FrameLayout dimView; private FrameLayout textDimView; + private FrameLayout backgroundView; private FrameLayout selectionContainerView; private ColorPicker colorPicker; @@ -214,6 +218,13 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView textDimView.setVisibility(GONE); textDimView.setOnClickListener(v -> closeTextEnter(true)); + backgroundView = new FrameLayout(context); +// backgroundView.setBackgroundColor(0x7f000000); + Drawable backgroundDrawable = getResources().getDrawable(R.drawable.gradient_bottom).mutate(); + backgroundDrawable.setColorFilter(new PorterDuffColorFilter(0xff000000, PorterDuff.Mode.MULTIPLY)); + backgroundView.setBackground(backgroundDrawable); + addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 72, Gravity.FILL_HORIZONTAL | Gravity.BOTTOM)); + selectionContainerView = new FrameLayout(context) { @Override public boolean onTouchEvent(MotionEvent event) { @@ -291,21 +302,23 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView paintButton = new ImageView(context); paintButton.setScaleType(ImageView.ScaleType.CENTER); - paintButton.setImageResource(R.drawable.photo_paint); + paintButton.setContentDescription(LocaleController.getString("AccDescrPaint", R.string.AccDescrPaint)); + paintButton.setImageResource(R.drawable.msg_photo_draw); paintButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); toolsView.addView(paintButton, LayoutHelper.createFrame(54, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 0, 0, 56, 0)); paintButton.setOnClickListener(v -> selectEntity(null)); ImageView stickerButton = new ImageView(context); stickerButton.setScaleType(ImageView.ScaleType.CENTER); - stickerButton.setImageResource(R.drawable.photo_sticker); + stickerButton.setImageResource(R.drawable.msg_sticker); stickerButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); toolsView.addView(stickerButton, LayoutHelper.createFrame(54, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); stickerButton.setOnClickListener(v -> openStickersView()); ImageView textButton = new ImageView(context); textButton.setScaleType(ImageView.ScaleType.CENTER); - textButton.setImageResource(R.drawable.photo_paint_text); + textButton.setContentDescription(LocaleController.getString("AccDescrPlaceText", R.string.AccDescrPlaceText)); + textButton.setImageResource(R.drawable.msg_photo_text); textButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); toolsView.addView(textButton, LayoutHelper.createFrame(54, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 56, 0, 0, 0)); textButton.setOnClickListener(v -> createText(true)); @@ -402,13 +415,16 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView private void updateSettingsButton() { int resource = R.drawable.photo_paint_brush; + colorPicker.settingsButton.setContentDescription(LocaleController.getString("AccDescrBrushType", R.string.AccDescrBrushType)); if (currentEntityView != null) { if (currentEntityView instanceof StickerView) { - resource = R.drawable.photo_flip; + resource = R.drawable.msg_photo_flip; + colorPicker.settingsButton.setContentDescription(LocaleController.getString("AccDescrMirror", R.string.AccDescrMirror)); } else if (currentEntityView instanceof TextPaintView) { resource = R.drawable.photo_outline; + colorPicker.settingsButton.setContentDescription(LocaleController.getString("PaintOutlined", R.string.PaintOutlined)); } - paintButton.setImageResource(R.drawable.photo_paint); + paintButton.setImageResource(R.drawable.msg_photo_draw); paintButton.setColorFilter(null); } else { if (brushSwatch != null) { @@ -416,8 +432,9 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView brushSwatch = null; } paintButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); - paintButton.setImageResource(R.drawable.photo_paint); + paintButton.setImageResource(R.drawable.msg_photo_draw); } + backgroundView.setVisibility(currentEntityView instanceof TextPaintView ? View.INVISIBLE : View.VISIBLE); colorPicker.setSettingsButtonImage(resource); } @@ -456,6 +473,10 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView return toolsView; } + public FrameLayout getColorPickerBackground() { + return backgroundView; + } + public FrameLayout getCurtainView() { return curtainView; } @@ -514,7 +535,7 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView mediaEntity.document = stickerView.getSticker(); mediaEntity.parentObject = stickerView.getParentObject(); TLRPC.Document document = stickerView.getSticker(); - mediaEntity.text = FileLoader.getPathToAttach(document, true).getAbsolutePath(); + mediaEntity.text = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true).getAbsolutePath(); if (MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) { boolean isAnimatedSticker = MessageObject.isAnimatedStickerDocument(document, true); mediaEntity.subType |= isAnimatedSticker ? 1 : 4; @@ -729,6 +750,7 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView colorPicker.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY)); toolsView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(48), MeasureSpec.EXACTLY)); curtainView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.EXACTLY)); + backgroundView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(72), MeasureSpec.EXACTLY)); ignoreLayout = false; } @@ -755,6 +777,7 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView colorPicker.layout(0, actionBarHeight2, colorPicker.getMeasuredWidth(), actionBarHeight2 + colorPicker.getMeasuredHeight()); toolsView.layout(0, height - toolsView.getMeasuredHeight(), toolsView.getMeasuredWidth(), height); curtainView.layout(0, y, curtainView.getMeasuredWidth(), y + curtainView.getMeasuredHeight()); + backgroundView.layout(0, height - AndroidUtilities.dp(45) - backgroundView.getMeasuredHeight(), backgroundView.getMeasuredWidth(), height - AndroidUtilities.dp(45)); } @Override @@ -956,8 +979,12 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView tx = trX; ty = trY; } - view.setScaleX(scale * additionlScale); - view.setScaleY(scale * additionlScale); + float finalScale = scale * additionlScale; + if (Float.isNaN(finalScale)) { + finalScale = 1f; + } + view.setScaleX(finalScale); + view.setScaleY(finalScale); view.setTranslationX(tx); view.setTranslationY(ty); view.setRotation(rotation); @@ -1453,7 +1480,7 @@ public class PhotoPaintView extends FrameLayout implements EntityView.EntityView popupWindow.dismiss(); } }); - popupLayout.setShownFromBotton(true); + popupLayout.setShownFromBottom(true); } popupLayout.removeInnerViews(); 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 619d78277..1216b026a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java @@ -28,14 +28,11 @@ import android.text.TextWatcher; import android.text.style.ImageSpan; import android.util.TypedValue; import android.view.ActionMode; -import android.view.DragEvent; import android.view.Gravity; import android.view.KeyEvent; import android.view.Menu; -import android.view.MotionEvent; import android.view.View; import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -44,10 +41,10 @@ import androidx.core.graphics.ColorUtils; 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.NotificationCenter; -import org.telegram.messenger.FileLog; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; @@ -60,7 +57,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica private final ImageView doneButton; public int getCaptionLimitOffset() { - return captionMaxLength - codePointCount; + return MessagesController.getInstance(currentAccount).getCaptionMaxLengthLimit() - codePointCount; } public interface PhotoViewerCaptionEnterViewDelegate { @@ -100,7 +97,6 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica private boolean innerTextChange; private boolean popupAnimating; - private int captionMaxLength = 1024; private int codePointCount; private PhotoViewerCaptionEnterViewDelegate delegate; @@ -114,6 +110,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica private TextPaint lengthTextPaint; private String lengthText; private final Theme.ResourcesProvider resourcesProvider; + public int currentAccount = UserConfig.selectedAccount; public PhotoViewerCaptionEnterView(Context context, SizeNotifierFrameLayoutPhoto parent, final View window, Theme.ResourcesProvider resourcesProvider) { super(context); @@ -285,7 +282,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica @Override public void afterTextChanged(Editable editable) { - int charactersLeft = captionMaxLength - messageEditText.length(); + int charactersLeft = MessagesController.getInstance(currentAccount).getCaptionMaxLengthLimit() - messageEditText.length(); if (charactersLeft <= 128) { lengthText = String.format("%d", charactersLeft); } else { @@ -306,7 +303,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica int beforeLimit; codePointCount = Character.codePointCount(editable, 0, editable.length()); boolean sendButtonEnabledLocal = true; - if (captionMaxLength > 0 && (beforeLimit = captionMaxLength - codePointCount) <= 100) { + if (MessagesController.getInstance(currentAccount).getCaptionMaxLengthLimit() > 0 && (beforeLimit = MessagesController.getInstance(currentAccount).getCaptionMaxLengthLimit() - codePointCount) <= 100) { if (beforeLimit < -9999) { beforeLimit = -9999; } @@ -361,7 +358,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica doneButton.setImageDrawable(combinedDrawable); textFieldContainer.addView(doneButton, LayoutHelper.createLinear(48, 48, Gravity.BOTTOM)); doneButton.setOnClickListener(view -> { - if (captionMaxLength - codePointCount < 0) { + if (MessagesController.getInstance(currentAccount).getCaptionMaxLengthLimit() - codePointCount < 0) { AndroidUtilities.shakeView(captionLimitView, 2, 0); Vibrator v = (Vibrator) captionLimitView.getContext().getSystemService(Context.VIBRATOR_SERVICE); if (v != null) { @@ -380,6 +377,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica captionLimitView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); captionLimitView.setCenterAlign(true); addView(captionLimitView, LayoutHelper.createFrame(48, 20, Gravity.BOTTOM | Gravity.RIGHT, 3, 0, 3, 48)); + currentAccount = UserConfig.selectedAccount; } private void onLineCountChanged(int lineCountOld, int lineCountNew) { @@ -506,6 +504,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica public void onCreate() { NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); sizeNotifierLayout.setDelegate(this); } @@ -516,6 +515,7 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica } keyboardVisible = false; NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.emojiLoaded); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); if (sizeNotifierLayout != null) { sizeNotifierLayout.setDelegate(null); } @@ -534,7 +534,6 @@ public class PhotoViewerCaptionEnterView extends FrameLayout implements Notifica if (delegate != null) { delegate.onTextChanged(messageEditText.getText()); } - captionMaxLength = MessagesController.getInstance(UserConfig.selectedAccount).maxCaptionLength; } public int getSelectionLength() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerWebView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerWebView.java index 9e6fb69f6..ff4da892d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerWebView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerWebView.java @@ -252,8 +252,12 @@ public class PhotoViewerWebView extends FrameLayout { return progressBar.getVisibility() != View.VISIBLE; } + public boolean isInAppOnly() { + return isYouTube && "inapp".equals(MessagesController.getInstance(currentAccount).youtubePipType); + } + public boolean openInPip() { - boolean inAppOnly = isYouTube && "inapp".equals(MessagesController.getInstance(currentAccount).youtubePipType); + boolean inAppOnly = isInAppOnly(); if (!inAppOnly && !checkInlinePermissions()) { return false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java index d9bae9b35..20d0b87fc 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java @@ -30,21 +30,27 @@ public class PickerBottomLayout extends FrameLayout { public TextView middleButtonTextView; public TextView doneButtonTextView; public TextView doneButtonBadgeTextView; + private Theme.ResourcesProvider resourcesProvider; public PickerBottomLayout(Context context) { - this(context, true); + this(context, true, null); } public PickerBottomLayout(Context context, boolean darkTheme) { - super(context); + this(context, darkTheme, null); + } - setBackgroundColor(Theme.getColor(darkTheme ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite)); + public PickerBottomLayout(Context context, boolean darkTheme, Theme.ResourcesProvider resourcesProvider) { + super(context); + this.resourcesProvider = resourcesProvider; + + setBackgroundColor(Theme.getColor(darkTheme ? Theme.key_dialogBackground : Theme.key_windowBackgroundWhite, resourcesProvider)); cancelButton = new TextView(context); cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - cancelButton.setTextColor(Theme.getColor(Theme.key_picker_enabledButton)); + cancelButton.setTextColor(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider)); cancelButton.setGravity(Gravity.CENTER); - cancelButton.setBackgroundDrawable(Theme.createSelectorDrawable(0x0f000000, 0)); + cancelButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider) & 0x0fffffff, 0)); cancelButton.setPadding(AndroidUtilities.dp(33), 0, AndroidUtilities.dp(33), 0); cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase()); cancelButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -72,16 +78,16 @@ public class PickerBottomLayout extends FrameLayout { doneButton = new LinearLayout(context); doneButton.setOrientation(LinearLayout.HORIZONTAL); - doneButton.setBackgroundDrawable(Theme.createSelectorDrawable(0x0f000000, 0)); + doneButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider) & 0x0fffffff, 0)); doneButton.setPadding(AndroidUtilities.dp(33), 0, AndroidUtilities.dp(33), 0); rightLayout.addView(doneButton); doneButtonBadgeTextView = new TextView(context); doneButtonBadgeTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); doneButtonBadgeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); - doneButtonBadgeTextView.setTextColor(Theme.getColor(Theme.key_picker_badgeText)); + doneButtonBadgeTextView.setTextColor(Theme.getColor(Theme.key_picker_badgeText, resourcesProvider)); doneButtonBadgeTextView.setGravity(Gravity.CENTER); - Drawable drawable = Theme.createRoundRectDrawable(AndroidUtilities.dp(11), Theme.getColor(Theme.key_picker_badge)); + Drawable drawable = Theme.createRoundRectDrawable(AndroidUtilities.dp(11), Theme.getColor(Theme.key_picker_badge, resourcesProvider)); doneButtonBadgeTextView.setBackgroundDrawable(drawable); doneButtonBadgeTextView.setMinWidth(AndroidUtilities.dp(23)); doneButtonBadgeTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1)); @@ -89,7 +95,7 @@ public class PickerBottomLayout extends FrameLayout { doneButtonTextView = new TextView(context); doneButtonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton)); + doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider)); doneButtonTextView.setGravity(Gravity.CENTER); doneButtonTextView.setCompoundDrawablePadding(AndroidUtilities.dp(8)); doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase()); @@ -103,18 +109,18 @@ public class PickerBottomLayout extends FrameLayout { if (disable) { doneButtonTextView.setTag(Theme.key_picker_disabledButton); - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_disabledButton)); + doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_disabledButton, resourcesProvider)); doneButton.setEnabled(false); } else { doneButtonTextView.setTag(Theme.key_picker_enabledButton); - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton)); + doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider)); } } else { doneButtonBadgeTextView.setVisibility(View.VISIBLE); doneButtonBadgeTextView.setText(String.format("%d", count)); doneButtonTextView.setTag(Theme.key_picker_enabledButton); - doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton)); + doneButtonTextView.setTextColor(Theme.getColor(Theme.key_picker_enabledButton, resourcesProvider)); if (disable) { doneButton.setEnabled(true); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoOverlay.java index 95396a278..589981a04 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoOverlay.java @@ -22,7 +22,6 @@ import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.os.Build; -import android.view.GestureDetector; import android.view.Gravity; import android.view.MotionEvent; import android.view.ScaleGestureDetector; @@ -36,12 +35,13 @@ import android.widget.FrameLayout; import android.widget.ImageView; import androidx.core.math.MathUtils; -import androidx.core.view.GestureDetectorCompat; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.FloatPropertyCompat; import androidx.dynamicanimation.animation.SpringAnimation; import androidx.dynamicanimation.animation.SpringForce; +import com.google.android.exoplayer2.C; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.R; @@ -87,7 +87,7 @@ public class PipVideoOverlay { private FrameLayout controlsView; private ScaleGestureDetector scaleGestureDetector; - private GestureDetectorCompat gestureDetector; + private GestureDetectorFixDoubleTap gestureDetector; private boolean isScrolling; private boolean isScrollDisallowed; private View consumingChild; @@ -103,12 +103,7 @@ public class PipVideoOverlay { private boolean isVisible; - private boolean postedDismissControls; - private Runnable dismissControlsCallback = () -> { - toggleControls(isShowingControls = false); - postedDismissControls = false; - }; - + private VideoForwardDrawable videoForwardDrawable = new VideoForwardDrawable(false); private int mVideoWidth, mVideoHeight; private EmbedBottomSheet parentSheet; private PhotoViewer photoViewer; @@ -134,6 +129,86 @@ public class PipVideoOverlay { AndroidUtilities.runOnUIThread(this.progressRunnable, 500); }; + private boolean canLongClick; + private float[] longClickStartPoint = new float[2]; + private Runnable longClickCallback = this::onLongClick; + + private boolean postedDismissControls; + private Runnable dismissControlsCallback = () -> { + if (photoViewer != null && photoViewer.getVideoPlayerRewinder().rewindCount > 0) { + AndroidUtilities.runOnUIThread(this.dismissControlsCallback, 1500); + return; + } + toggleControls(isShowingControls = false); + postedDismissControls = false; + }; + + public static void onRewindCanceled() { + instance.onRewindCanceledInternal(); + } + + private void onRewindCanceledInternal() { + videoForwardDrawable.setShowing(false); + } + + public static void onUpdateRewindProgressUi(long timeDiff, float progress, boolean rewindByBackSeek) { + instance.onUpdateRewindProgressUiInternal(timeDiff, progress, rewindByBackSeek); + } + + private void onUpdateRewindProgressUiInternal(long timeDiff, float progress, boolean rewindByBackSeek) { + videoForwardDrawable.setTime(0); + if (rewindByBackSeek) { + videoProgress = progress; + + if (videoProgressView != null) { + videoProgressView.invalidate(); + } + if (controlsView != null) { + controlsView.invalidate(); + } + } + } + + public static void onRewindStart(boolean rewindForward) { + instance.onRewindStartInternal(rewindForward); + } + + private void onRewindStartInternal(boolean rewindForward) { + videoForwardDrawable.setOneShootAnimation(false); + videoForwardDrawable.setLeftSide(!rewindForward); + videoForwardDrawable.setShowing(true); + if (videoProgressView != null) { + videoProgressView.invalidate(); + } + if (controlsView != null) { + controlsView.invalidate(); + } + } + + protected void onLongClick() { + if (photoViewer == null || photoViewer.getVideoPlayer() == null || isDismissing || isVideoCompleted || isScrolling || scaleGestureDetector.isInProgress() || !canLongClick) { + return; + } + + VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); + boolean forward = longClickStartPoint[0] >= getSuggestedWidth() * scaleFactor * 0.5f; + + long current = videoPlayer.getCurrentPosition(); + long total = videoPlayer.getDuration(); + if (current == C.TIME_UNSET || total < 15 * 1000) { + return; + } + + photoViewer.getVideoPlayerRewinder().startRewind(videoPlayer, forward, photoViewer.getCurrentVideoSpeed()); + + if (!isShowingControls) { + toggleControls(isShowingControls = true); + if (!postedDismissControls) { + AndroidUtilities.runOnUIThread(dismissControlsCallback, 1500); + postedDismissControls = true; + } + } + } private PipConfig getPipConfig() { if (pipConfig == null) { @@ -170,6 +245,7 @@ public class PipVideoOverlay { aspectRatio = mVideoHeight / (float) mVideoWidth; maxScaleFactor = (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) - AndroidUtilities.dp(SIDE_PADDING_DP * 2)) / (float) getSuggestedWidth(); + videoForwardDrawable.setPlayScaleFactor(aspectRatio < 1 ? 0.6f : 0.45f); } return aspectRatio; } @@ -264,6 +340,20 @@ public class PipVideoOverlay { isScrolling = false; isVisible = false; isDismissing = false; + canLongClick = false; + + cancelRewind(); + AndroidUtilities.cancelRunOnUIThread(longClickCallback); + } + + private void cancelRewind() { + if (photoViewer == null) { + return; + } + + if (photoViewer.getVideoPlayerRewinder().rewindCount > 0) { + photoViewer.getVideoPlayerRewinder().cancelRewind(); + } } public static void updatePlayButton() { @@ -436,6 +526,9 @@ public class PipVideoOverlay { public boolean onScaleBegin(ScaleGestureDetector detector) { if (isScrolling) { isScrolling = false; + canLongClick = false; + cancelRewind(); + AndroidUtilities.cancelRunOnUIThread(longClickCallback); } isScrollDisallowed = true; windowLayoutParams.width = (int) (getSuggestedWidth() * maxScaleFactor); @@ -489,7 +582,7 @@ public class PipVideoOverlay { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { scaleGestureDetector.setStylusScaleEnabled(false); } - gestureDetector = new GestureDetectorCompat(context, new GestureDetector.SimpleOnGestureListener() { + gestureDetector = new GestureDetectorFixDoubleTap(context, new GestureDetectorFixDoubleTap.OnGestureListener() { private float startPipX, startPipY; @Override @@ -510,7 +603,7 @@ public class PipVideoOverlay { } @Override - public boolean onSingleTapUp(MotionEvent e) { + public boolean onSingleTapConfirmed(MotionEvent e) { if (controlsAnimator != null) { return true; } @@ -531,6 +624,78 @@ public class PipVideoOverlay { return true; } + @Override + public boolean onDoubleTap(MotionEvent e) { + if (photoViewer == null || photoViewer.getVideoPlayer() == null || isDismissing || isVideoCompleted || isScrolling || scaleGestureDetector.isInProgress() || !canLongClick) { + return false; + } + + VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); + boolean forward = e.getX() >= getSuggestedWidth() * scaleFactor * 0.5f; + + long current = videoPlayer.getCurrentPosition(); + long total = videoPlayer.getDuration(); + if (current == C.TIME_UNSET || total < 15 * 1000) { + return false; + } + + long old = current; + if (forward) { + current += 10000; + } else { + current -= 10000; + } + if (old != current) { + boolean apply = true; + if (current > total) { + current = total; + } else if (current < 0) { + if (current < -9000) { + apply = false; + } + current = 0; + } + if (apply) { + videoForwardDrawable.setOneShootAnimation(true); + videoForwardDrawable.setLeftSide(!forward); + videoForwardDrawable.addTime(10000); + videoPlayer.seekTo(current); + onUpdateRewindProgressUiInternal(forward ? 10000 : -10000, current / (float) total, true); + if (!isShowingControls) { + toggleControls(isShowingControls = true); + if (!postedDismissControls) { + postedDismissControls = true; + AndroidUtilities.runOnUIThread(dismissControlsCallback, 2500); + } + } + } + return true; + } + + return false; + } + + @Override + public boolean onSingleTapUp(MotionEvent e) { + if (!hasDoubleTap()) { + return onSingleTapConfirmed(e); + } + return super.onSingleTapUp(e); + } + + @Override + public boolean hasDoubleTap() { + if (photoViewer == null || photoViewer.getVideoPlayer() == null || isDismissing || isVideoCompleted || isScrolling || scaleGestureDetector.isInProgress() || !canLongClick) { + return false; + } + + VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); + + long current = videoPlayer.getCurrentPosition(); + long total = videoPlayer.getDuration(); + return current != C.TIME_UNSET && total >= 15 * 1000; + } + @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (isScrolling && !isScrollDisallowed) { @@ -558,6 +723,10 @@ public class PipVideoOverlay { pipXSpring.cancel(); pipYSpring.cancel(); + + canLongClick = false; + cancelRewind(); + AndroidUtilities.cancelRunOnUIThread(longClickCallback); } } if (isScrolling) { @@ -606,14 +775,32 @@ public class PipVideoOverlay { @Override public boolean dispatchTouchEvent(MotionEvent ev) { - int action = ev.getAction(); + int action = ev.getActionMasked(); + if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN) { + if (ev.getPointerCount() == 1) { + canLongClick = true; + longClickStartPoint = new float[]{ev.getX(), ev.getY()}; + AndroidUtilities.runOnUIThread(longClickCallback, 500); + } else { + canLongClick = false; + cancelRewind(); + AndroidUtilities.cancelRunOnUIThread(longClickCallback); + } + } + + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_POINTER_UP) { + canLongClick = false; + cancelRewind(); + AndroidUtilities.cancelRunOnUIThread(longClickCallback); + } + if (consumingChild != null) { MotionEvent newEvent = MotionEvent.obtain(ev); newEvent.offsetLocation(consumingChild.getX(), consumingChild.getY()); boolean consumed = consumingChild.dispatchTouchEvent(ev); newEvent.recycle(); - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_POINTER_UP) { consumingChild = null; } @@ -626,7 +813,7 @@ public class PipVideoOverlay { boolean scaleDetector = scaleGestureDetector.onTouchEvent(temp); temp.recycle(); boolean detector = !scaleGestureDetector.isInProgress() && gestureDetector.onTouchEvent(ev); - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_POINTER_UP) { isScrolling = false; isScrollDisallowed = false; @@ -734,7 +921,25 @@ public class PipVideoOverlay { } contentFrameLayout.addView(innerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - controlsView = new FrameLayout(context); + videoForwardDrawable.setDelegate(new VideoForwardDrawable.VideoForwardDrawableDelegate() { + @Override + public void onAnimationEnd() {} + + @Override + public void invalidate() { + controlsView.invalidate(); + } + }); + controlsView = new FrameLayout(context) { + @Override + protected void onDraw(Canvas canvas) { + if (videoForwardDrawable.isAnimating()) { + videoForwardDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom()); + videoForwardDrawable.draw(canvas); + } + } + }; + controlsView.setWillNotDraw(false); controlsView.setAlpha(0f); View scrim = new View(context); scrim.setBackgroundColor(0x4C000000); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java deleted file mode 100644 index d1e4f983b..000000000 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PipVideoView.java +++ /dev/null @@ -1,667 +0,0 @@ -/* - * This is the source code of Telegram for Android v. 5.x.x. - * It is licensed under GNU GPL v. 2 or later. - * You should have received a copy of the license in this archive (see LICENSE). - * - * Copyright Nikolai Kudashov, 2013-2018. - */ - -package org.telegram.ui.Components; - -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.os.Build; -import androidx.annotation.Keep; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.TextureView; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.WindowManager; -import android.view.animation.DecelerateInterpolator; -import android.webkit.WebView; -import android.widget.FrameLayout; -import android.widget.ImageView; - -import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; - -import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.ApplicationLoader; -import org.telegram.messenger.FileLog; -import org.telegram.messenger.R; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.PhotoViewer; - -import java.util.ArrayList; - -public class PipVideoView { - - private FrameLayout windowView; - private EmbedBottomSheet parentSheet; - private PhotoViewer photoViewer; - private Activity parentActivity; - private View controlsView; - private int videoWidth; - private int videoHeight; - - private boolean isInAppOnly; - - private WindowManager.LayoutParams windowLayoutParams; - private WindowManager windowManager; - private SharedPreferences preferences; - private DecelerateInterpolator decelerateInterpolator; - - private AnimatorSet animatorSet; - - private class MiniControlsView extends FrameLayout { - - private Paint progressPaint; - private Paint progressInnerPaint; - private boolean isVisible = true; - private AnimatorSet currentAnimation; - private ImageView playButton; - private float progress; - private boolean isCompleted; - private float bufferedPosition; - - private Runnable hideRunnable = () -> show(false, true); - - private Runnable progressRunnable = new Runnable() { - @Override - public void run() { - if (photoViewer == null) { - return; - } - VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); - if (videoPlayer == null) { - return; - } - setProgress(videoPlayer.getCurrentPosition() / (float) videoPlayer.getDuration()); - if (photoViewer == null) { - setBufferedProgress(videoPlayer.getBufferedPosition() / (float) videoPlayer.getDuration()); - } - - AndroidUtilities.runOnUIThread(progressRunnable, 1000); - } - }; - - public MiniControlsView(Context context, boolean fullControls) { - super(context); - - ImageView inlineButton = new ImageView(context); - inlineButton.setScaleType(ImageView.ScaleType.CENTER); - inlineButton.setImageResource(R.drawable.ic_outinline); - addView(inlineButton, LayoutHelper.createFrame(56, 48, Gravity.RIGHT | Gravity.TOP)); - inlineButton.setOnClickListener(v -> { - if (parentSheet != null) { - parentSheet.exitFromPip(); - } else if (photoViewer != null) { - photoViewer.exitFromPip(); - } - }); - - if (fullControls) { - progressPaint = new Paint(); - progressPaint.setColor(0xff19a7e8); - progressInnerPaint = new Paint(); - progressInnerPaint.setColor(0xff959197); - - setWillNotDraw(false); - playButton = new ImageView(context); - playButton.setScaleType(ImageView.ScaleType.CENTER); - addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.CENTER)); - playButton.setOnClickListener(v -> { - if (photoViewer == null) { - return; - } - VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); - if (videoPlayer == null) { - return; - } - if (videoPlayer.isPlaying()) { - videoPlayer.pause(); - } else { - videoPlayer.play(); - } - updatePlayButton(); - }); - } - - setOnTouchListener((v, event) -> true); - updatePlayButton(); - show(false, false); - } - - private void updatePlayButton() { - if (photoViewer == null) { - return; - } - VideoPlayer videoPlayer = photoViewer.getVideoPlayer(); - if (videoPlayer == null) { - return; - } - AndroidUtilities.cancelRunOnUIThread(progressRunnable); - if (!videoPlayer.isPlaying()) { - if (isCompleted) { - playButton.setImageResource(R.drawable.ic_againinline); - } else { - playButton.setImageResource(R.drawable.ic_playinline); - } - } else { - playButton.setImageResource(R.drawable.ic_pauseinline); - AndroidUtilities.runOnUIThread(progressRunnable, 500); - } - } - - public void setBufferedProgress(float position) { - bufferedPosition = position; - invalidate(); - } - - public void setProgress(float value) { - progress = value; - invalidate(); - } - - public void show(boolean value, boolean animated) { - if (isVisible == value) { - return; - } - isVisible = value; - if (currentAnimation != null) { - currentAnimation.cancel(); - } - if (isVisible) { - if (animated) { - currentAnimation = new AnimatorSet(); - currentAnimation.playTogether(ObjectAnimator.ofFloat(this, View.ALPHA, 1.0f)); - currentAnimation.setDuration(150); - currentAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animator) { - currentAnimation = null; - } - }); - currentAnimation.start(); - } else { - setAlpha(1.0f); - } - } else { - if (animated) { - currentAnimation = new AnimatorSet(); - currentAnimation.playTogether(ObjectAnimator.ofFloat(this, View.ALPHA, 0.0f)); - currentAnimation.setDuration(150); - currentAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animator) { - currentAnimation = null; - } - }); - currentAnimation.start(); - } else { - setAlpha(0.0f); - } - } - checkNeedHide(); - } - - private void checkNeedHide() { - AndroidUtilities.cancelRunOnUIThread(hideRunnable); - if (isVisible) { - AndroidUtilities.runOnUIThread(hideRunnable, 3000); - } - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - if (!isVisible) { - show(true, true); - return true; - } else { - checkNeedHide(); - } - } - return super.onInterceptTouchEvent(ev); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (currentAnimation != null) { - return true; - } - return super.onTouchEvent(event); - } - - @Override - public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - super.requestDisallowInterceptTouchEvent(disallowIntercept); - checkNeedHide(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - checkNeedHide(); - } - - @Override - protected void onDraw(Canvas canvas) { - int width = getMeasuredWidth(); - int height = getMeasuredHeight(); - - int progressLineY = height - AndroidUtilities.dp(3); - int progressLineX = 0; - int cy = height - AndroidUtilities.dp(7); - int progressX = progressLineX + (int) ((width - progressLineX) * progress); - if (bufferedPosition != 0) { - canvas.drawRect(progressLineX, progressLineY, progressLineX + (width - progressLineX) * bufferedPosition, progressLineY + AndroidUtilities.dp(3), progressInnerPaint); - } - canvas.drawRect(progressLineX, progressLineY, progressX, progressLineY + AndroidUtilities.dp(3), progressPaint); - } - } - - public PipVideoView(boolean inAppOnly) { - isInAppOnly = inAppOnly; - } - - public TextureView show(Activity activity, EmbedBottomSheet sheet, View controls, float aspectRatio, int rotation, WebView webview) { - return show(activity, null, sheet, controls, aspectRatio, rotation, webview); - } - - public TextureView show(Activity activity, PhotoViewer viewer, float aspectRatio, int rotation, WebView webview) { - return show(activity, viewer, null, null, aspectRatio, rotation, webview); - } - - public TextureView show(Activity activity, PhotoViewer viewer, float aspectRatio, int rotation) { - return show(activity, viewer, null, null, aspectRatio, rotation, null); - } - - public TextureView show(Activity activity, PhotoViewer viewer, EmbedBottomSheet sheet, View controls, float aspectRatio, int rotation, WebView webview) { - - parentSheet = sheet; - parentActivity = activity; - photoViewer = viewer; - - windowView = new FrameLayout(activity) { - - private float startX; - private float startY; - private boolean dragging; - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - float x = event.getRawX(); - float y = event.getRawY(); - if (event.getAction() == MotionEvent.ACTION_DOWN) { - startX = x; - startY = y; - } else if (event.getAction() == MotionEvent.ACTION_MOVE && !dragging) { - if (Math.abs(startX - x) >= AndroidUtilities.getPixelsInCM(0.3f, true) || Math.abs(startY - y) >= AndroidUtilities.getPixelsInCM(0.3f, false)) { - dragging = true; - startX = x; - startY = y; - if (controlsView != null) { - ((ViewParent) controlsView).requestDisallowInterceptTouchEvent(true); - } - return true; - } - } - - if (dragging) { - if (event.getAction() == MotionEvent.ACTION_MOVE) { - float dx = (x - startX); - float dy = (y - startY); - windowLayoutParams.x += dx; - windowLayoutParams.y += dy; - int maxDiff = videoWidth / 2; - if (windowLayoutParams.x < -maxDiff) { - windowLayoutParams.x = -maxDiff; - } else if (windowLayoutParams.x > AndroidUtilities.displaySize.x - windowLayoutParams.width + maxDiff) { - windowLayoutParams.x = AndroidUtilities.displaySize.x - windowLayoutParams.width + maxDiff; - } - float alpha = 1.0f; - if (windowLayoutParams.x < 0) { - alpha = 1.0f + windowLayoutParams.x / (float) maxDiff * 0.5f; - } else if (windowLayoutParams.x > AndroidUtilities.displaySize.x - windowLayoutParams.width) { - alpha = 1.0f - (windowLayoutParams.x - AndroidUtilities.displaySize.x + windowLayoutParams.width) / (float) maxDiff * 0.5f; - } - if (windowView.getAlpha() != alpha) { - windowView.setAlpha(alpha); - } - maxDiff = 0; - if (windowLayoutParams.y < -maxDiff) { - windowLayoutParams.y = -maxDiff; - } else if (windowLayoutParams.y > AndroidUtilities.displaySize.y - windowLayoutParams.height + maxDiff) { - windowLayoutParams.y = AndroidUtilities.displaySize.y - windowLayoutParams.height + maxDiff; - } - windowManager.updateViewLayout(windowView, windowLayoutParams); - startX = x; - startY = y; - } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { - dragging = false; - animateToBoundsMaybe(); - } - return true; - } else { - return super.dispatchTouchEvent(event); - } - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (animatorSet != null) { - animatorSet.cancel(); - animatorSet = null; - } - } - }; - - if (aspectRatio > 1) { - videoWidth = AndroidUtilities.dp(192); - videoHeight = (int) (videoWidth / aspectRatio); - } else { - videoHeight = AndroidUtilities.dp(192); - videoWidth = (int) (videoHeight * aspectRatio); - } - - AspectRatioFrameLayout aspectRatioFrameLayout = new AspectRatioFrameLayout(activity); - aspectRatioFrameLayout.setAspectRatio(aspectRatio, rotation); - windowView.addView(aspectRatioFrameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); - - TextureView textureView; - if (webview != null) { - ViewGroup parent = (ViewGroup) webview.getParent(); - if (parent != null) { - parent.removeView(webview); - } - aspectRatioFrameLayout.addView(webview, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - textureView = null; - } else { - textureView = new TextureView(activity); - aspectRatioFrameLayout.addView(textureView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - } - - if (controls == null) { - controlsView = new MiniControlsView(activity, viewer != null); - } else { - controlsView = controls; - } - windowView.addView(controlsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - if (isInAppOnly) { - windowManager = activity.getWindowManager(); - } else { - windowManager = (WindowManager) ApplicationLoader.applicationContext.getSystemService(Context.WINDOW_SERVICE); - } - - preferences = ApplicationLoader.applicationContext.getSharedPreferences("pipconfig", Context.MODE_PRIVATE); - - int sidex = preferences.getInt("sidex", 1); - int sidey = preferences.getInt("sidey", 0); - float px = preferences.getFloat("px", 0); - float py = preferences.getFloat("py", 0); - - try { - windowLayoutParams = new WindowManager.LayoutParams(); - windowLayoutParams.width = videoWidth; - windowLayoutParams.height = videoHeight; - windowLayoutParams.x = getSideCoord(true, sidex, px, videoWidth); - windowLayoutParams.y = getSideCoord(false, sidey, py, videoHeight); - windowLayoutParams.format = PixelFormat.TRANSLUCENT; - windowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT; - if (isInAppOnly) { - windowLayoutParams.type = WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; - } else { - if (Build.VERSION.SDK_INT >= 26) { - windowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - } else { - windowLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; - } - } - windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; - windowManager.addView(windowView, windowLayoutParams); - } catch (Exception e) { - FileLog.e(e); - return null; - } - - return textureView; - } - - public void onVideoCompleted() { - if (controlsView instanceof MiniControlsView) { - MiniControlsView miniControlsView = (MiniControlsView) controlsView; - miniControlsView.isCompleted = true; - miniControlsView.progress = 0; - miniControlsView.bufferedPosition = 0; - miniControlsView.updatePlayButton(); - miniControlsView.invalidate(); - miniControlsView.show(true, true); - } - } - - public void setBufferedProgress(float progress) { - if (controlsView instanceof MiniControlsView) { - ((MiniControlsView) controlsView).setBufferedProgress(progress); - } - } - - public void updatePlayButton() { - if (controlsView instanceof MiniControlsView) { - MiniControlsView miniControlsView = (MiniControlsView) controlsView; - miniControlsView.updatePlayButton(); - miniControlsView.invalidate(); - } - } - - private static int getSideCoord(boolean isX, int side, float p, int sideSize) { - int total; - if (isX) { - total = AndroidUtilities.displaySize.x - sideSize; - } else { - total = AndroidUtilities.displaySize.y - sideSize - (ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight); - } - int result; - if (side == 0) { - result = AndroidUtilities.dp(10); - } else if (side == 1) { - result = total - AndroidUtilities.dp(10); - } else { - result = Math.round((total - AndroidUtilities.dp(20)) * p) + AndroidUtilities.dp(10); - } - if (!isX) { - result += ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight; - } - return result; - } - - public void close() { - try { - windowManager.removeView(windowView); - } catch (Exception e) { - //don't promt - } - parentSheet = null; - photoViewer = null; - parentActivity = null; - } - - public void onConfigurationChanged() { - int sidex = preferences.getInt("sidex", 1); - int sidey = preferences.getInt("sidey", 0); - float px = preferences.getFloat("px", 0); - float py = preferences.getFloat("py", 0); - windowLayoutParams.x = getSideCoord(true, sidex, px, videoWidth); - windowLayoutParams.y = getSideCoord(false, sidey, py, videoHeight); - windowManager.updateViewLayout(windowView, windowLayoutParams); - } - - private void animateToBoundsMaybe() { - int startX = getSideCoord(true, 0, 0, videoWidth); - int endX = getSideCoord(true, 1, 0, videoWidth); - int startY = getSideCoord(false, 0, 0, videoHeight); - int endY = getSideCoord(false, 1, 0, videoHeight); - ArrayList animators = null; - SharedPreferences.Editor editor = preferences.edit(); - int maxDiff = AndroidUtilities.dp(20); - boolean slideOut = false; - if (Math.abs(startX - windowLayoutParams.x) <= maxDiff || windowLayoutParams.x < 0 && windowLayoutParams.x > -videoWidth / 4) { - if (animators == null) { - animators = new ArrayList<>(); - } - editor.putInt("sidex", 0); - if (windowView.getAlpha() != 1.0f) { - animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 1.0f)); - } - animators.add(ObjectAnimator.ofInt(this, "x", startX)); - } else if (Math.abs(endX - windowLayoutParams.x) <= maxDiff || windowLayoutParams.x > AndroidUtilities.displaySize.x - videoWidth && windowLayoutParams.x < AndroidUtilities.displaySize.x - videoWidth / 4 * 3) { - if (animators == null) { - animators = new ArrayList<>(); - } - editor.putInt("sidex", 1); - if (windowView.getAlpha() != 1.0f) { - animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 1.0f)); - } - animators.add(ObjectAnimator.ofInt(this, "x", endX)); - } else if (windowView.getAlpha() != 1.0f) { - if (animators == null) { - animators = new ArrayList<>(); - } - if (windowLayoutParams.x < 0) { - animators.add(ObjectAnimator.ofInt(this, "x", -videoWidth)); - } else { - animators.add(ObjectAnimator.ofInt(this, "x", AndroidUtilities.displaySize.x)); - } - slideOut = true; - } else { - editor.putFloat("px", (windowLayoutParams.x - startX) / (float) (endX - startX)); - editor.putInt("sidex", 2); - } - if (!slideOut) { - if (Math.abs(startY - windowLayoutParams.y) <= maxDiff || windowLayoutParams.y <= (ActionBar.getCurrentActionBarHeight() + AndroidUtilities.statusBarHeight)) { - if (animators == null) { - animators = new ArrayList<>(); - } - editor.putInt("sidey", 0); - animators.add(ObjectAnimator.ofInt(this, "y", startY)); - } else if (Math.abs(endY - windowLayoutParams.y) <= maxDiff) { - if (animators == null) { - animators = new ArrayList<>(); - } - editor.putInt("sidey", 1); - animators.add(ObjectAnimator.ofInt(this, "y", endY)); - } else { - editor.putFloat("py", (windowLayoutParams.y - startY) / (float) (endY - startY)); - editor.putInt("sidey", 2); - } - editor.commit(); - } - if (animators != null) { - if (decelerateInterpolator == null) { - decelerateInterpolator = new DecelerateInterpolator(); - } - animatorSet = new AnimatorSet(); - animatorSet.setInterpolator(decelerateInterpolator); - animatorSet.setDuration(150); - if (slideOut) { - animators.add(ObjectAnimator.ofFloat(windowView, View.ALPHA, 0.0f)); - animatorSet.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - animatorSet = null; - if (parentSheet != null) { - parentSheet.destroy(); - } else if (photoViewer != null) { - photoViewer.destroyPhotoViewer(); - } - } - }); - } - animatorSet.playTogether(animators); - animatorSet.start(); - } - } - - public static Rect getPipRect(float aspectRatio) { - SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("pipconfig", Context.MODE_PRIVATE); - int sidex = preferences.getInt("sidex", 1); - int sidey = preferences.getInt("sidey", 0); - float px = preferences.getFloat("px", 0); - float py = preferences.getFloat("py", 0); - - int videoWidth; - int videoHeight; - if (aspectRatio > 1) { - videoWidth = AndroidUtilities.dp(192); - videoHeight = (int) (videoWidth / aspectRatio); - } else { - videoHeight = AndroidUtilities.dp(192); - videoWidth = (int) (videoHeight * aspectRatio); - } - - return new Rect(getSideCoord(true, sidex, px, videoWidth), getSideCoord(false, sidey, py, videoHeight), videoWidth, videoHeight); - } - - @Keep - public int getX() { - return windowLayoutParams.x; - } - - @Keep - public int getY() { - return windowLayoutParams.y; - } - - @Keep - public void setX(int value) { - windowLayoutParams.x = value; - try { - windowManager.updateViewLayout(windowView, windowLayoutParams); - } catch (Exception ignore) { - - } - } - - @Keep - public void setY(int value) { - windowLayoutParams.y = value; - try { - windowManager.updateViewLayout(windowView, windowLayoutParams); - } catch (Exception ignore) { - - } - } - - @Keep - public int getWidth() { - return windowLayoutParams.width; - } - - @Keep - public int getHeight() { - return windowLayoutParams.height; - } - - @Keep - public void setWidth(int value) { - windowLayoutParams.width = videoWidth = value; - windowManager.updateViewLayout(windowView, windowLayoutParams); - } - - @Keep - public void setHeight(int value) { - windowLayoutParams.height = videoHeight = value; - windowManager.updateViewLayout(windowView, windowLayoutParams); - } -} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java index 8ec79ace3..888ba8150 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PollVotesAlert.java @@ -442,6 +442,7 @@ public class PollVotesAlert extends BottomSheet { public PollVotesAlert(ChatActivity parentFragment, MessageObject message) { super(parentFragment.getParentActivity(), true); + fixNavigationBar(); messageObject = message; chatActivity = parentFragment; TLRPC.TL_messageMediaPoll mediaPoll = (TLRPC.TL_messageMediaPoll) messageObject.messageOwner.media; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java index e08cb5a76..edebe846a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java @@ -283,7 +283,7 @@ public class PopupAudioView extends BaseCell implements SeekBar.SeekBarDelegate, public void updateButtonState() { String fileName = currentMessageObject.getFileName(); - File cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + File cacheFile = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); if (cacheFile.exists()) { DownloadController.getInstance(currentAccount).removeLoadingFileObserver(this); boolean playing = MediaController.getInstance().isPlayingMessage(currentMessageObject); 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 5be49f989..c1b166ea0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupSwipeBackLayout.java @@ -12,6 +12,7 @@ import android.graphics.Rect; import android.graphics.RectF; import android.util.SparseIntArray; import android.view.GestureDetector; +import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; @@ -56,6 +57,9 @@ public class PopupSwipeBackLayout extends FrameLayout { private int notificationIndex; Theme.ResourcesProvider resourcesProvider; + private int lastHeightReported = -1; + private IntCallback onHeightUpdateListener; + private Rect hitRect = new Rect(); public PopupSwipeBackLayout(@NonNull Context context, Theme.ResourcesProvider resourcesProvider) { @@ -146,11 +150,22 @@ public class PopupSwipeBackLayout extends FrameLayout { } public void invalidateTransforms() { + invalidateTransforms(true); + } - if (!onSwipeBackProgressListeners.isEmpty()) { - for (int i = 0; i < onSwipeBackProgressListeners.size(); i++) { - onSwipeBackProgressListeners.get(i).onSwipeBackProgress(this, toProgress, transitionProgress); + + float lastToProgress; + float lastTransitionProgress; + + public void invalidateTransforms(boolean applyBackScaleY) { + if (lastToProgress != toProgress || lastTransitionProgress != transitionProgress) { + if (!onSwipeBackProgressListeners.isEmpty()) { + for (int i = 0; i < onSwipeBackProgressListeners.size(); i++) { + onSwipeBackProgressListeners.get(i).onSwipeBackProgress(this, toProgress, transitionProgress); + } } + lastToProgress = toProgress; + lastTransitionProgress = transitionProgress; } View backgroundView = getChildAt(0); @@ -185,7 +200,9 @@ public class PopupSwipeBackLayout extends FrameLayout { h += p.getPaddingTop() + p.getPaddingBottom(); p.updateAnimation = false; p.setBackScaleX(w / p.getMeasuredWidth()); - p.setBackScaleY(h / p.getMeasuredHeight()); + if (applyBackScaleY) { + p.setBackScaleY(h / p.getMeasuredHeight()); + } p.updateAnimation = true; for (int i = 0; i < getChildCount(); i++) { @@ -197,12 +214,20 @@ public class PopupSwipeBackLayout extends FrameLayout { invalidate(); } + public boolean isForegroundOpen() { + return transitionProgress > 0; + } + @Override public boolean dispatchTouchEvent(MotionEvent ev) { - if (processTouchEvent(ev)) + if (processTouchEvent(ev)) { return true; - + } int act = ev.getActionMasked(); + if (mRect != null && !mRect.contains(ev.getX(), ev.getY()) && act == MotionEvent.ACTION_DOWN) { +// return false; + } + if (act == MotionEvent.ACTION_DOWN && !mRect.contains(ev.getX(), ev.getY())) { callOnClick(); return true; @@ -248,7 +273,9 @@ public class PopupSwipeBackLayout extends FrameLayout { if (isProcessingSwipe) { clearFlags(); animateToState(transitionProgress >= 0.5f ? 1 : 0, 0); - } else if (isSwipeDisallowed) clearFlags(); + } else if (isSwipeDisallowed) { + clearFlags(); + } return false; } } @@ -281,6 +308,9 @@ public class PopupSwipeBackLayout extends FrameLayout { public void onAnimationEnd(Animator animation) { NotificationCenter.getInstance(selectedAccount).onAnimationFinish(notificationIndex); transitionProgress = f; + if (f <= 0) { + currentForegroundIndex = -1; + } invalidateTransforms(); isAnimationInProgress = false; } @@ -313,7 +343,9 @@ public class PopupSwipeBackLayout extends FrameLayout { } public void closeForeground(boolean animated) { - if (isAnimationInProgress) return; + if (isAnimationInProgress) { + return; + } if (!animated) { currentForegroundIndex = -1; transitionProgress = 0; @@ -328,7 +360,12 @@ public class PopupSwipeBackLayout extends FrameLayout { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { for (int i = 0; i < getChildCount(); i++) { View ch = getChildAt(i); - ch.layout(0, 0, ch.getMeasuredWidth(), ch.getMeasuredHeight()); + 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); + } else { + ch.layout(0, 0, ch.getMeasuredWidth(), ch.getMeasuredHeight()); + } } } @@ -344,31 +381,48 @@ public class PopupSwipeBackLayout extends FrameLayout { return; } View backgroundView = getChildAt(0); - float fW = backgroundView.getMeasuredWidth(), fH = backgroundView.getMeasuredHeight(); - float w, h; + float fY = backgroundView.getTop(), fW = backgroundView.getMeasuredWidth(), fH = backgroundView.getMeasuredHeight(); + float y, w, h; if (currentForegroundIndex == -1 || currentForegroundIndex >= getChildCount()) { + y = fY; w = fW; h = fH; } else { View foregroundView = getChildAt(currentForegroundIndex); - float tW = foregroundView.getMeasuredWidth(), tH = overrideForegroundHeight != 0 ? overrideForegroundHeight : foregroundView.getMeasuredHeight(); + float tY = foregroundView.getTop(); + float tW = foregroundView.getMeasuredWidth(); + float tH = overrideForegroundHeight != 0 ? overrideForegroundHeight : foregroundView.getMeasuredHeight(); if (backgroundView.getMeasuredWidth() == 0 || backgroundView.getMeasuredHeight() == 0 || foregroundView.getMeasuredWidth() == 0 || foregroundView.getMeasuredHeight() == 0) { + y = fY; w = fW; h = fH; } else { - w = fW + (tW - fW) * transitionProgress; - h = fH + (tH - fH) * transitionProgress; + y = AndroidUtilities.lerp(fY, tY, transitionProgress); + w = AndroidUtilities.lerp(fW, tW, transitionProgress); + h = AndroidUtilities.lerp(fH, tH, transitionProgress); } } int s = canvas.save(); mPath.rewind(); int rad = AndroidUtilities.dp(6); - mRect.set(0, 0, w, h); + mRect.set(0, y, w, y + h); mPath.addRoundRect(mRect, rad, rad, Path.Direction.CW); canvas.clipPath(mPath); super.dispatchDraw(canvas); canvas.restoreToCount(s); + + if (onHeightUpdateListener != null && lastHeightReported != mRect.height()) { + onHeightUpdateListener.run(lastHeightReported = (int) mRect.height()); + } + } + + public interface IntCallback { + public void run(int height); + } + + public void setOnHeightUpdateListener(IntCallback onHeightUpdateListener) { + this.onHeightUpdateListener = onHeightUpdateListener; } /** @@ -413,7 +467,7 @@ public class PopupSwipeBackLayout extends FrameLayout { } } - public void setNewForegroundHeight(int index, int height) { + public void setNewForegroundHeight(int index, int height, boolean animated) { overrideHeightIndex.put(index, height); if (index != currentForegroundIndex) { return; @@ -423,30 +477,33 @@ public class PopupSwipeBackLayout extends FrameLayout { } if (foregroundAnimator != null) { foregroundAnimator.cancel(); + foregroundAnimator = null; } - View fg = getChildAt(currentForegroundIndex); - float fromH = overrideForegroundHeight != 0 ? overrideForegroundHeight : fg.getMeasuredHeight(); - float toH = height; + if (animated) { + View fg = getChildAt(currentForegroundIndex); + float fromH = overrideForegroundHeight != 0 ? overrideForegroundHeight : fg.getMeasuredHeight(); + float toH = height; - ValueAnimator animator = ValueAnimator.ofFloat(fromH, toH).setDuration(240); - animator.setInterpolator(Easings.easeInOutQuad); - animator.addUpdateListener(animation -> { - overrideForegroundHeight = (float) animation.getAnimatedValue(); + ValueAnimator animator = ValueAnimator.ofFloat(fromH, toH).setDuration(240); + animator.setInterpolator(Easings.easeInOutQuad); + animator.addUpdateListener(animation -> { + overrideForegroundHeight = (float) animation.getAnimatedValue(); + invalidateTransforms(); + }); + isAnimationInProgress = true; + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + isAnimationInProgress = false; + foregroundAnimator = null; + } + }); + animator.start(); + foregroundAnimator = animator; + } else { + overrideForegroundHeight = height; invalidateTransforms(); - }); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - isAnimationInProgress = false; - } - - @Override - public void onAnimationStart(Animator animation) { - isAnimationInProgress = true; - } - }); - animator.start(); - foregroundAnimator = animator; + } } public void setForegroundColor(int color) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/AboutPremiumView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/AboutPremiumView.java new file mode 100644 index 000000000..08143feed --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/AboutPremiumView.java @@ -0,0 +1,42 @@ +package org.telegram.ui.Components.Premium; + +import android.content.Context; +import android.util.TypedValue; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class AboutPremiumView extends LinearLayout { + + public AboutPremiumView(@NonNull Context context) { + super(context); + setOrientation(VERTICAL); + setPadding(AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + + TextView textView = new TextView(context); + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setText(LocaleController.getString("AboutPremiumTitle", R.string.AboutPremiumTitle)); + addView(textView); + + TextView description = new TextView(context); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString("AboutPremiumDescription", R.string.AboutPremiumDescription))); + addView(description, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0, 0)); + + TextView description2 = new TextView(context); + description2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + description2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + description2.setText(AndroidUtilities.replaceTags(LocaleController.getString("AboutPremiumDescription2", R.string.AboutPremiumDescription2))); + addView(description2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 24, 0, 0)); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/CarouselView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/CarouselView.java new file mode 100644 index 000000000..a6bbd9c27 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/CarouselView.java @@ -0,0 +1,397 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.view.GestureDetector; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Interpolator; +import android.view.animation.OvershootInterpolator; +import android.widget.OverScroller; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public class CarouselView extends View implements PagerHeaderView { + + private final ArrayList drawingObjects; + private final ArrayList drawingObjectsSorted; + + float lastFlingX; + float lastFlingY; + int cX, cY; + + float offsetAngle = 0f; + boolean firstScroll = true; + boolean firstScroll1 = true; + boolean firstScrollEnabled = true; + GestureDetector gestureDetector; + boolean autoPlayEnabled = true; + static final Interpolator sQuinticInterpolator = t -> { + t -= 1.0f; + return t * t * t * t * t + 1.0f; + }; + + Comparator comparator = Comparator.comparingInt(value -> (int) (value.yRelative * 100)); + + OverScroller overScroller; + ValueAnimator autoScrollAnimation; + boolean scrolled; + private Runnable autoScrollRunnable = new Runnable() { + @Override + public void run() { + if (!autoPlayEnabled) { + return; + } + scrollToInternal(offsetAngle + 360f / drawingObjects.size()); + } + }; + + public CarouselView(Context context, ArrayList drawingObjects) { + super(context); + overScroller = new OverScroller(getContext(), sQuinticInterpolator); + gestureDetector = new GestureDetector(context, new GestureDetector.OnGestureListener() { + + double lastAngle; + + @Override + public boolean onDown(MotionEvent motionEvent) { + if (motionEvent.getY() > 0.2 * getMeasuredHeight() && motionEvent.getY() < 0.9 * getMeasuredHeight()) { + getParent().requestDisallowInterceptTouchEvent(true); + } + if (autoScrollAnimation != null) { + autoScrollAnimation.removeAllListeners(); + autoScrollAnimation.cancel(); + autoScrollAnimation = null; + } + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + overScroller.abortAnimation(); + lastAngle = Math.atan2((motionEvent.getX() - cX), (motionEvent.getY() - cY)); + float aStep = 360f / drawingObjects.size(); + lastSelected = ((int) (offsetAngle / aStep)); + for (int i = 0; i < drawingObjects.size(); i++) { + drawingObjects.get(i).hideAnimation(); + } + return true; + } + + @Override + public void onShowPress(MotionEvent motionEvent) { + + } + + @Override + public boolean onSingleTapUp(MotionEvent motionEvent) { + float x = motionEvent.getX(); + float y = motionEvent.getY(); + for (int i = drawingObjectsSorted.size() - 1; i >= 0; i--) { + if (drawingObjectsSorted.get(i).checkTap(x, y)) { + + if (drawingObjectsSorted.get(i).angle % 360 != 270) { + double toAngle = (270 - drawingObjectsSorted.get(i).angle % 360 + 180) % 360; + if (toAngle > 180.0) { + toAngle = -(360 - toAngle); + } + scrollToInternal(offsetAngle + (float) toAngle); + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } + return true; + } + } + return false; + } + + @Override + public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float dx, float dy) { + double angle = Math.atan2((motionEvent1.getX() - cX), (motionEvent1.getY() - cY)); + double dAngle = lastAngle - angle; + lastAngle = angle; + offsetAngle += Math.toDegrees(dAngle); + checkSelectedHaptic(); + invalidate(); + return true; + } + + @Override + public void onLongPress(MotionEvent motionEvent) { + + } + + @Override + public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float velocityX, float velocityY) { + lastFlingX = lastFlingY = 0; + double angle = Math.atan2((motionEvent1.getX() - cX), (motionEvent1.getY() - cY)); + float xVelocity = (float) (Math.cos(angle) * velocityX - Math.sin(angle) * velocityY); + overScroller.fling(0, 0, (int) xVelocity, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE); + if (overScroller.isFinished()) { + scheduleAutoscroll(); + } + invalidate(); + return true; + } + + }); + this.drawingObjects = drawingObjects; + this.drawingObjectsSorted = new ArrayList<>(drawingObjects); + for (int i = 0; i < drawingObjects.size() / 2; i++) { + drawingObjects.get(i).y = drawingObjects.size() / (float) i; + drawingObjects.get(drawingObjects.size() - 1 - i).y = drawingObjects.size() / (float) i; + } + Collections.sort(drawingObjects, comparator); + for (int i = 0; i < drawingObjects.size(); i++) { + drawingObjects.get(i).carouselView = this; + } + } + + private void checkSelectedHaptic() { + float aStep = 360f / drawingObjects.size(); + int selected = ((int) (offsetAngle / aStep)); + if (lastSelected != selected) { + lastSelected = selected; + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } + } + + private void scrollToInternal(float scrollTo) { + if (Math.abs(scrollTo - offsetAngle) < 1 && autoScrollAnimation == null) { + return; + } + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + if (autoScrollAnimation != null) { + autoScrollAnimation.removeAllListeners(); + autoScrollAnimation.cancel(); + autoScrollAnimation = null; + } + float from = offsetAngle; + autoScrollAnimation = ValueAnimator.ofFloat(0f, 1f); + autoScrollAnimation.addUpdateListener(animation -> { + float f = (float) animation.getAnimatedValue(); + offsetAngle = from * (1f - f) + scrollTo * f; + invalidate(); + }); + autoScrollAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + offsetAngle = scrollTo; + autoScrollAnimation = null; + invalidate(); + AndroidUtilities.runOnUIThread(() -> { + if (!drawingObjectsSorted.isEmpty()) { + drawingObjectsSorted.get(drawingObjectsSorted.size() - 1).select(); + } + scheduleAutoscroll(); + }); + } + }); + autoScrollAnimation.setInterpolator(new OvershootInterpolator()); + autoScrollAnimation.setDuration(600); + autoScrollAnimation.start(); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + scrolled = true; + } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { + scrolled = false; + getParent().requestDisallowInterceptTouchEvent(false); + invalidate(); + } + return gestureDetector.onTouchEvent(event); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + cX = getMeasuredWidth() >> 1; + cY = getMeasuredHeight() >> 1; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + for (int k = 0; k < 2; k++) { + for (int i = 0; i < drawingObjectsSorted.size(); i++) { + drawingObjectsSorted.get(i).onAttachToWindow(this, k); + } + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + for (int i = 0; i < drawingObjects.size(); i++) { + drawingObjects.get(i).onDetachFromWindow(); + } + } + + int lastSelected; + + @Override + protected void onDraw(Canvas canvas) { + double aStep = 360.0 / drawingObjects.size(); + + if (overScroller.computeScrollOffset()) { + //fling + final int x = overScroller.getCurrX(); + float dx = lastFlingX - x; + if (lastFlingX != 0 && Math.abs(dx * 0.08f) < 0.3f) { + overScroller.abortAnimation(); + } + lastFlingX = x; + offsetAngle += dx * 0.08f; + checkSelectedHaptic(); + invalidate(); + scheduleAutoscroll(); + } else if (firstScroll1 || firstScroll || (!scrolled && autoScrollAnimation == null && Math.abs((offsetAngle - 90) % aStep) > 2)) { + if (firstScroll1) { + offsetAngle += 90 + aStep; + } + float dif = (float) ((offsetAngle - 90) % aStep); + if (Math.abs(dif) > aStep / 2) { + if (dif < 0) { + dif += aStep; + } else { + dif -= aStep; + } + } + firstScroll1 = false; + if (firstScroll && firstScrollEnabled) { + firstScroll = false; + offsetAngle -= 180; + scrollToInternal(offsetAngle - dif + 180); + } else { + scrollToInternal(offsetAngle - dif); + } + } + + float r = (Math.min(getMeasuredWidth(), getMeasuredHeight() * 1.3f) - AndroidUtilities.dp(140)) * 0.5f; + float rY = r * 0.6f; + for (int i = 0; i < drawingObjects.size(); i++) { + DrawingObject object = drawingObjects.get(i); + object.angle = offsetAngle + aStep * i; + double s = Math.cos(Math.toRadians(object.angle)); + double p = s; + double totalAngle = object.angle - 30.0 * p; + object.x = (float) Math.cos(Math.toRadians(totalAngle)) * r + cX; + object.yRelative = (float) Math.sin(Math.toRadians(totalAngle)); + object.y = object.yRelative * rY + cY; + } + + Collections.sort(drawingObjectsSorted, comparator); + + for (int i = 0; i < drawingObjectsSorted.size(); i++) { + DrawingObject object = drawingObjectsSorted.get(i); + float s = 0.2f + 0.7f * (object.yRelative + 1f) / 2f; + object.draw(canvas, object.x, object.y, s); + } + invalidate(); + } + + void scheduleAutoscroll() { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + if (!autoPlayEnabled) { + return; + } + AndroidUtilities.runOnUIThread(autoScrollRunnable, 3000); + } + + @Override + public void setOffset(float translationX) { + if (translationX >= getMeasuredWidth() || translationX <= -getMeasuredWidth()) { + overScroller.abortAnimation(); + if (autoScrollAnimation != null) { + autoScrollAnimation.removeAllListeners(); + autoScrollAnimation.cancel(); + autoScrollAnimation = null; + } + firstScroll = true; + firstScroll1 = true; + offsetAngle = 0; + } + setAutoPlayEnabled(translationX == 0); + setFirstScrollEnabled(Math.abs(translationX) < getMeasuredWidth() * 0.2f); + float s = Utilities.clamp(Math.abs(translationX) / getMeasuredWidth(), 1f, 0f); + setScaleX(1f - s); + setScaleY(1f - s); + } + + public void autoplayToNext() { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + if (!autoPlayEnabled) { + return; + } + DrawingObject drawingObject = drawingObjectsSorted.get(drawingObjectsSorted.size() - 1); + int i = drawingObjects.indexOf(drawingObject); + i--; + if (i < 0) { + i = drawingObjects.size() - 1; + } + drawingObjects.get(i).select(); + AndroidUtilities.runOnUIThread(autoScrollRunnable, 16); + } + + public static class DrawingObject { + + public float x, y; + public double angle; + float yRelative; + CarouselView carouselView; + + public DrawingObject() { + } + + public void onAttachToWindow(View parentView, int i) { + + } + + public void onDetachFromWindow() { + + } + + public void draw(Canvas canvas, float cX, float cY, float scale) { + + } + + public boolean checkTap(float x, float y) { + return false; + } + + public void select() { + + } + + public void hideAnimation() { + + } + } + + + void setAutoPlayEnabled(boolean autoPlayEnabled) { + if (this.autoPlayEnabled != autoPlayEnabled) { + this.autoPlayEnabled = autoPlayEnabled; + if (autoPlayEnabled) { + scheduleAutoscroll(); + } else { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + } + invalidate(); + } + } + + void setFirstScrollEnabled(boolean b) { + if (firstScrollEnabled != b) { + this.firstScrollEnabled = b; + invalidate(); + } + } +} + diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/DoubledLimitsBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/DoubledLimitsBottomSheet.java new file mode 100644 index 000000000..c4258b740 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/DoubledLimitsBottomSheet.java @@ -0,0 +1,378 @@ +package org.telegram.ui.Components.Premium; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Canvas; +import android.os.Bundle; +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.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.FixedHeightEmptyCell; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; + +public class DoubledLimitsBottomSheet extends BottomSheetWithRecyclerListView implements NotificationCenter.NotificationCenterDelegate { + + final ArrayList limits = new ArrayList<>(); + + int rowCount; + int headerRow; + int limitsStartRow; + int limitsStartEnd; + int lastViewRow; + + FrameLayout titleLayout; + TextView titleView; + ImageView titleImage; + + PremiumButtonView premiumButtonView; + PremiumPreviewFragment premiumPreviewFragment; + + float titleProgress; + + PremiumGradient.GradientTools gradientTools; + private int totalGradientHeight; + private BaseFragment baseFragment; + + private View divider; + + public DoubledLimitsBottomSheet(BaseFragment fragment, int currentAccount) { + super(fragment, false, false); + this.baseFragment = fragment; + gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4); + gradientTools.x1 = 0; + gradientTools.y1 = 0; + gradientTools.x2 = 0; + gradientTools.y2 = 1f; + + clipToActionBar = true; + MessagesController messagesController = MessagesController.getInstance(currentAccount); + limits.add(new Limit( + LocaleController.getString("GroupsAndChannelsLimitTitle", R.string.GroupsAndChannelsLimitTitle), + LocaleController.formatString("GroupsAndChannelsLimitSubtitle", R.string.GroupsAndChannelsLimitSubtitle, messagesController.channelsLimitPremium), + messagesController.channelsLimitDefault, messagesController.channelsLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("PinChatsLimitTitle", R.string.PinChatsLimitTitle), + LocaleController.formatString("PinChatsLimitSubtitle", R.string.PinChatsLimitSubtitle, messagesController.dialogFiltersPinnedLimitPremium), + messagesController.dialogFiltersPinnedLimitDefault, messagesController.dialogFiltersPinnedLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("PublicLinksLimitTitle", R.string.PublicLinksLimitTitle), + LocaleController.formatString("PublicLinksLimitSubtitle", R.string.PublicLinksLimitSubtitle, messagesController.publicLinksLimitPremium), + messagesController.publicLinksLimitDefault, messagesController.publicLinksLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("SavedGifsLimitTitle", R.string.SavedGifsLimitTitle), + LocaleController.formatString("SavedGifsLimitSubtitle", R.string.SavedGifsLimitSubtitle, messagesController.savedGifsLimitPremium), + messagesController.savedGifsLimitDefault, messagesController.savedGifsLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("FavoriteStickersLimitTitle", R.string.FavoriteStickersLimitTitle), + LocaleController.formatString("FavoriteStickersLimitSubtitle", R.string.FavoriteStickersLimitSubtitle, messagesController.stickersFavedLimitPremium), + messagesController.stickersFavedLimitDefault, messagesController.stickersFavedLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("BioLimitTitle", R.string.BioLimitTitle), + LocaleController.formatString("BioLimitSubtitle", R.string.BioLimitSubtitle, messagesController.stickersFavedLimitPremium), + messagesController.aboutLengthLimitDefault, messagesController.aboutLengthLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("CaptionsLimitTitle", R.string.CaptionsLimitTitle), + LocaleController.formatString("CaptionsLimitSubtitle", R.string.CaptionsLimitSubtitle, messagesController.stickersFavedLimitPremium), + messagesController.captionLengthLimitDefault, messagesController.captionLengthLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("FoldersLimitTitle", R.string.FoldersLimitTitle), + LocaleController.formatString("FoldersLimitSubtitle", R.string.FoldersLimitSubtitle, messagesController.dialogFiltersLimitPremium), + messagesController.dialogFiltersLimitDefault, messagesController.dialogFiltersLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("ChatPerFolderLimitTitle", R.string.ChatPerFolderLimitTitle), + LocaleController.formatString("ChatPerFolderLimitSubtitle", R.string.ChatPerFolderLimitSubtitle, messagesController.dialogFiltersChatsLimitPremium), + messagesController.dialogFiltersChatsLimitDefault, messagesController.dialogFiltersChatsLimitPremium + )); + limits.add(new Limit( + LocaleController.getString("ConnectedAccountsLimitTitle", R.string.ConnectedAccountsLimitTitle), + LocaleController.formatString("ConnectedAccountsLimitSubtitle", R.string.ConnectedAccountsLimitSubtitle, 4), + UserConfig.MAX_ACCOUNT_DEFAULT_COUNT, UserConfig.MAX_ACCOUNT_COUNT + )); + + rowCount = 0; + headerRow = rowCount++; + limitsStartRow = rowCount; + rowCount += limits.size(); + limitsStartEnd = rowCount; + //lastViewRow = rowCount++; + + titleLayout = new FrameLayout(getContext()); + titleView = new TextView(getContext()); + titleView.setText(LocaleController.getString("DoubledLimits", R.string.DoubledLimits)); + titleView.setGravity(Gravity.CENTER); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleLayout.addView(titleView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + + titleImage = new ImageView(getContext()); + titleImage.setImageDrawable(PremiumGradient.getInstance().createGradientDrawable(ContextCompat.getDrawable(getContext(), R.drawable.other_2x_large))); + titleLayout.addView(titleImage, LayoutHelper.createFrame(40, 28, Gravity.CENTER_VERTICAL)); + containerView.addView(titleLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 40)); + + divider = new View(getContext()) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawRect(0, 0, getMeasuredWidth(), 1, Theme.dividerPaint); + } + }; + divider.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + containerView.addView(divider, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 72, Gravity.BOTTOM, 0, 0, 0, 0)); + + premiumButtonView = new PremiumButtonView(getContext(), true); + premiumButtonView.buttonTextView.setText(PremiumPreviewFragment.getPremiumButtonText(currentAccount)); + + containerView.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM, 16, 0, 16, 12)); + + premiumButtonView.buttonLayout.setOnClickListener((view) -> { + if (!UserConfig.getInstance(currentAccount).isPremium()) { + PremiumPreviewFragment.buyPremium(fragment, "double_limits"); + } + dismiss(); + }); + premiumButtonView.overlayTextView.setOnClickListener((v) -> { + dismiss(); + }); + recyclerListView.setPadding(0, 0, 0, AndroidUtilities.dp(48 + 24)); + bindPremium(UserConfig.getInstance(getCurrentAccount()).isPremium()); + } + + private void bindPremium(boolean hasPremium) { + if (hasPremium) { + premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), false, false); + } + } + + @Override + protected void onPreMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onPreMeasure(widthMeasureSpec, heightMeasureSpec); + measureGradient(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(heightMeasureSpec)); + } + + @Override + protected void onPreDraw(Canvas canvas, int top, float progressToFullView) { + float minTop = AndroidUtilities.statusBarHeight + (actionBar.getMeasuredHeight() - AndroidUtilities.statusBarHeight - AndroidUtilities.dp(40)) / 2f; + float fromIconX = (titleLayout.getMeasuredWidth() - titleView.getMeasuredWidth() - titleImage.getMeasuredWidth() - AndroidUtilities.dp(6)) / 2f; + float toIconX = AndroidUtilities.dp(72) - titleImage.getMeasuredWidth() - AndroidUtilities.dp(6); + float fromX = fromIconX + titleImage.getMeasuredWidth() + AndroidUtilities.dp(6); + float toX = AndroidUtilities.dp(72); + + float fromY = Math.max(top + AndroidUtilities.dp(24), minTop); + float toY = minTop; + + if (progressToFullView > 0 && titleProgress != 1f) { + titleProgress += 16f / 150f; + if (titleProgress > 1f) { + titleProgress = 1f; + } + containerView.invalidate(); + } else if (progressToFullView == 0 && titleProgress != 0) { + titleProgress -= 16f / 150f; + if (titleProgress < 0) { + titleProgress = 0; + } + containerView.invalidate(); + } + + titleLayout.setTranslationY(fromY * (1f - titleProgress) + toY * titleProgress); + titleView.setTranslationX(fromX * (1f - titleProgress) + toX * titleProgress); + titleImage.setTranslationX(fromIconX * (1f - titleProgress) + toIconX * titleProgress); + titleImage.setAlpha(1f - titleProgress); + float s = 0.6f + 0.4f * (1f - titleProgress); + titleImage.setScaleX(s); + titleImage.setScaleY(s); + } + + @Override + protected CharSequence getTitle() { + return null; + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return new RecyclerListView.SelectionAdapter() { + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + Context context = parent.getContext(); + View view; + switch (viewType) { + default: + case 0: + LimitCell limitCell = new LimitCell(context); + limitCell.previewView.setParentViewForGradien(containerView); + limitCell.previewView.setStaticGradinet(gradientTools); + view = limitCell; + break; + case 1: + view = new FixedHeightEmptyCell(context, 40 + 24); + break; + case 2: + view = new FixedHeightEmptyCell(context, 16); + 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) { + if (holder.getItemViewType() == 0) { + LimitCell limitCell = (LimitCell) holder.itemView; + limitCell.setData(limits.get(position - limitsStartRow)); + limitCell.previewView.gradientYOffset = limits.get(position - limitsStartRow).yOffset; + limitCell.previewView.gradientTotalHeight = totalGradientHeight; + } + } + + @Override + public int getItemCount() { + return rowCount; + } + + @Override + public int getItemViewType(int position) { + if (position == headerRow) { + return 1; + } else if (position == lastViewRow) { + return 2; + } + return 0; + } + }; + } + + public void setParentFragment(PremiumPreviewFragment premiumPreviewFragment) { + this.premiumPreviewFragment = premiumPreviewFragment; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.premiumPromoUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + public void dismiss() { + super.dismiss(); + + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.premiumPromoUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.billingProductDetailsUpdated || id == NotificationCenter.premiumPromoUpdated) { + premiumButtonView.buttonTextView.setText(PremiumPreviewFragment.getPremiumButtonText(currentAccount)); + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + bindPremium(UserConfig.getInstance(currentAccount).isPremium()); + } + } + + + private class LimitCell extends LinearLayout { + + TextView title; + TextView subtitle; + LimitPreviewView previewView; + + public LimitCell(@NonNull Context context) { + super(context); + setOrientation(VERTICAL); + setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0); + + title = new TextView(context); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(title, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 0, 16, 0)); + + subtitle = new TextView(context); + subtitle.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText)); + subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + addView(subtitle, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 1, 16, 0)); + + previewView = new LimitPreviewView(context, 0, 10, 20); + addView(previewView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 8, 0, 21)); + } + + @SuppressLint("SetTextI18n") + public void setData(Limit limit) { + title.setText(limit.title); + subtitle.setText(limit.subtitle); + previewView.premiumCount.setText(Integer.toString(limit.premiumLimit)); + previewView.defaultCount.setText(Integer.toString(limit.defaultLimit)); + } + } + + private void measureGradient(int w, int h) { + int yOffset = 0; + LimitCell dummyCell = new LimitCell(getContext()); + for (int i = 0; i < limits.size(); i++) { + dummyCell.setData(limits.get(i)); + dummyCell.measure(View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.AT_MOST)); + limits.get(i).yOffset = yOffset; + yOffset += dummyCell.getMeasuredHeight(); + } + + totalGradientHeight = yOffset; + } + + + private static class Limit { + final String title; + final String subtitle; + final int defaultLimit; + final int premiumLimit; + final int current = -1; + public int yOffset; + + private Limit(String title, String subtitle, int defaultLimit, int premiumLimit) { + this.title = title; + this.subtitle = subtitle; + this.defaultLimit = defaultLimit; + this.premiumLimit = premiumLimit; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java new file mode 100644 index 000000000..ab7ae9416 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconRenderer.java @@ -0,0 +1,148 @@ +package org.telegram.ui.Components.Premium.GLIcon; + +import android.content.Context; +import android.graphics.Bitmap; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.opengl.Matrix; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.ui.ActionBar.Theme; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +public class GLIconRenderer implements GLSurfaceView.Renderer { + + private int mWidth; + private int mHeight; + public Star3DIcon star; + public float angleX = 0; + public float angleX2 = 0; + public float angleY = 0; + + private static final float Z_NEAR = 1f; + private static final float Z_FAR = 200f; + + private final float[] mMVPMatrix = new float[16]; + private final float[] mProjectionMatrix = new float[16]; + private final float[] mViewMatrix = new float[16]; + private final float[] mRotationMatrix = new float[16]; + Context context; + + Bitmap backgroundBitmap; + + public float gradientStartX; + public float gradientStartY; + public float gradientScaleX; + public float gradientScaleY; + + int color1; + int color2; + + public String colorKey1 = Theme.key_premiumStartGradient1; + public String colorKey2 = Theme.key_premiumStartGradient2; + + private final int style; + public final static int FRAGMENT_STYLE = 0; + public final static int DIALOG_STYLE = 1; + public boolean isDarkBackground; + + public GLIconRenderer(Context context, int style) { + this.context = context; + this.style = style; + updateColors(); + } + + public static int loadShader(int type, String shaderSrc) { + int shader; + int[] compiled = new int[1]; + + shader = GLES20.glCreateShader(type); + + if (shader == 0) { + return 0; + } + + GLES20.glShaderSource(shader, shaderSrc); + GLES20.glCompileShader(shader); + GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); + + if (compiled[0] == 0) { + throw new RuntimeException("Could not compile program: " + + GLES20.glGetShaderInfoLog(shader) + " " + shaderSrc); + } + + return shader; + } + + public static void checkGlError(String glOperation, int program) { + int error; + while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { + throw new RuntimeException(glOperation + ": glError " + error + GLES20.glGetShaderInfoLog(program)); + } + } + + public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { + GLES20.glClearColor(0f, 0f, 0f, 0f); + if (star != null) { + star.destroy(); + } + star = new Star3DIcon(context); + if (backgroundBitmap != null) { + star.setBackground(backgroundBitmap); + } + if (isDarkBackground) { + star.spec1 = 1f; + star.spec2 = 0.2f; + } + + } + + public void onDrawFrame(GL10 glUnused) { + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); + + GLES20.glEnable(GLES20.GL_DEPTH_TEST); + Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 100, 0f, 0f, 0f, 0f, 1.0f, 0.0f); + Matrix.setIdentityM(mRotationMatrix, 0); + + Matrix.translateM(mRotationMatrix, 0, 0, angleX2, 0); + + Matrix.rotateM(mRotationMatrix, 0, -angleY, 1f, 0, 0f); + Matrix.rotateM(mRotationMatrix, 0, -angleX, 0, 1.0f, 0); + + Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mRotationMatrix, 0); + Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); + + if (star != null) { + star.gradientColor1 = color1; + star.gradientColor2 = color2; + star.draw(mMVPMatrix, mRotationMatrix, mWidth, mHeight, gradientStartX, gradientScaleX, gradientStartY, gradientScaleY); + } + + } + + public void onSurfaceChanged(GL10 glUnused, int width, int height) { + mWidth = width; + mHeight = height; + + GLES20.glViewport(0, 0, mWidth, mHeight); + float aspect = (float) width / height; + + Matrix.perspectiveM(mProjectionMatrix, 0, 53.13f, aspect, Z_NEAR, Z_FAR); + } + + public void setBackground(Bitmap gradientTextureBitmap) { + if (star != null) { + star.setBackground(gradientTextureBitmap); + } + backgroundBitmap = gradientTextureBitmap; + } + + public void updateColors() { + color1 = Theme.getColor(colorKey1); + color2 = Theme.getColor(colorKey2); + isDarkBackground = style == DIALOG_STYLE && ColorUtils.calculateLuminance(Theme.getColor(Theme.key_dialogBackground)) < 0.5f; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconTextureView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconTextureView.java new file mode 100644 index 000000000..f2d20f1a1 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/GLIconTextureView.java @@ -0,0 +1,737 @@ +package org.telegram.ui.Components.Premium.GLIcon; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.SurfaceTexture; +import android.opengl.GLUtils; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.TextureView; +import android.view.animation.LinearInterpolator; +import android.view.animation.OvershootInterpolator; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.EmuDetector; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.Utilities; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.Premium.StarParticlesView; + +import java.util.ArrayList; +import java.util.Collections; + +import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.egl.EGLContext; +import javax.microedition.khronos.egl.EGLDisplay; +import javax.microedition.khronos.egl.EGLSurface; +import javax.microedition.khronos.opengles.GL10; +import javax.microedition.khronos.opengles.GL11; + + +public class GLIconTextureView extends TextureView implements TextureView.SurfaceTextureListener { + + public boolean touched; + public GLIconRenderer mRenderer; + + private static final int EGL_OPENGL_ES2_BIT = 4; + private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + + private SurfaceTexture mSurface; + private EGLDisplay mEglDisplay; + private EGLSurface mEglSurface; + private EGLContext mEglContext; + private EGL10 mEgl; + private EGLConfig eglConfig; + private GL10 mGl; + + private int targetFrameDurationMillis; + + private int surfaceHeight; + private int surfaceWidth; + + public boolean isRunning = false; + private boolean paused = true; + private boolean rendererChanged = false; + private boolean dialogIsVisible = false; + + private RenderThread thread; + + private int targetFps; + + private long idleDelay = 2000; + + private final int animationsCount = 5; + int animationPointer; + ArrayList animationIndexes = new ArrayList<>(); + boolean attached; + StarParticlesView starParticlesView; + + public GLIconTextureView(Context context, int style) { + super(context); + setOpaque(false); + setRenderer(new GLIconRenderer(context, style)); + initialize(context); + + gestureDetector = new GestureDetector(context, new GestureDetector.OnGestureListener() { + @Override + public boolean onDown(MotionEvent motionEvent) { + if (backAnimation != null) { + backAnimation.removeAllListeners(); + backAnimation.cancel(); + backAnimation = null; + } + if (animatorSet != null) { + animatorSet.removeAllListeners(); + animatorSet.cancel(); + animatorSet = null; + } + AndroidUtilities.cancelRunOnUIThread(idleAnimation); + touched = true; + return true; + } + + @Override + public void onShowPress(MotionEvent motionEvent) { + + } + + @Override + public boolean onSingleTapUp(MotionEvent motionEvent) { + float rad = getMeasuredWidth() / 2f; + float toAngleX = (40 + Utilities.random.nextInt(30)) * (rad - motionEvent.getX()) / rad; + float toAngleY = (40 + Utilities.random.nextInt(30)) * (rad - motionEvent.getY()) / rad; + AndroidUtilities.runOnUIThread(() -> { + if (backAnimation != null) { + backAnimation.removeAllListeners(); + backAnimation.cancel(); + backAnimation = null; + } + if (animatorSet != null) { + animatorSet.removeAllListeners(); + animatorSet.cancel(); + animatorSet = null; + } + if (Math.abs(mRenderer.angleX) > 10) { + startBackAnimation(); + return; + } + AndroidUtilities.cancelRunOnUIThread(idleAnimation); + animatorSet = new AnimatorSet(); + int inTime = 220; + + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleX, toAngleX); + v1.addUpdateListener(xUpdater); + v1.setDuration(inTime); + v1.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + + ValueAnimator v2 = ValueAnimator.ofFloat(toAngleX, 0); + v2.addUpdateListener(xUpdater); + v2.setStartDelay(inTime); + v2.setDuration(600); + v2.setInterpolator(AndroidUtilities.overshootInterpolator); + + ValueAnimator v3 = ValueAnimator.ofFloat(mRenderer.angleY, toAngleY); + v3.addUpdateListener(yUpdater); + v3.setDuration(inTime); + v3.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + + ValueAnimator v4 = ValueAnimator.ofFloat(toAngleY, 0); + v4.addUpdateListener(yUpdater); + v4.setStartDelay(inTime); + v4.setDuration(600); + v4.setInterpolator(AndroidUtilities.overshootInterpolator); + + animatorSet.playTogether(v1, v2, v3, v4); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRenderer.angleX = 0; + animatorSet = null; + scheduleIdleAnimation(idleDelay); + } + }); + animatorSet.start(); + }, 16); + + return true; + } + + @Override + public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { + mRenderer.angleX += v * 0.5f; + mRenderer.angleY += v1 * 0.05f; + return true; + } + + @Override + public void onLongPress(MotionEvent motionEvent) { + GLIconTextureView.this.onLongPress(); + } + + @Override + public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) { + return false; + } + + }); + gestureDetector.setIsLongpressEnabled(true); + for (int i = 0; i < animationsCount; i++) { + animationIndexes.add(i); + } + Collections.shuffle(animationIndexes); + } + + public void onLongPress() { + + } + + + public synchronized void setRenderer(GLIconRenderer renderer) { + mRenderer = renderer; + rendererChanged = true; + } + + + private void initialize(Context context) { + targetFps = (int) AndroidUtilities.screenRefreshRate; + setSurfaceTextureListener(this); + } + + + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + startThread(surface, width, height); + } + + public void startThread(SurfaceTexture surface, int width, int height) { + thread = new RenderThread(); + mSurface = surface; + setDimensions(width, height); + targetFrameDurationMillis = Math.max(0, (int) ((1 / (float) targetFps) * 1000) - 1); + thread.start(); + } + + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + setDimensions(width, height); + if (mRenderer != null) { + mRenderer.onSurfaceChanged(mGl, width, height); + } + } + + public synchronized void setPaused(boolean isPaused) { + paused = isPaused; + } + + public synchronized boolean isPaused() { + return paused; + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { + stopThread(); + return false; + } + + public void stopThread() { + if (thread != null) { + isRunning = false; + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + thread = null; + } + + } + + private boolean shouldSleep() { + return isPaused() || mRenderer == null; + } + + public void setBackgroundBitmap(Bitmap gradientTextureBitmap) { + mRenderer.setBackground(gradientTextureBitmap); + } + + + private class RenderThread extends Thread { + @Override + public void run() { + isRunning = true; + + initGL(); + checkGlError(); + + long lastFrameTime = System.currentTimeMillis(); + + while (isRunning) { + while (mRenderer == null) { + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // Ignore + } + } + + if (rendererChanged) { + initializeRenderer(mRenderer); + rendererChanged = false; + } + + if (!shouldSleep()) { + lastFrameTime = System.currentTimeMillis(); + drawSingleFrame(); + } + + try { + if (shouldSleep()) + Thread.sleep(100); + else { + long thisFrameTime = System.currentTimeMillis(); + long timDiff = thisFrameTime - lastFrameTime; + while (timDiff < targetFrameDurationMillis) { + thisFrameTime = System.currentTimeMillis(); + timDiff = thisFrameTime - lastFrameTime; + } + } + } catch (InterruptedException ignore) { + } + } + } + + } + + private synchronized void initializeRenderer(GLIconRenderer renderer) { + if (renderer != null && isRunning) { + renderer.onSurfaceCreated(mGl, eglConfig); + renderer.onSurfaceChanged(mGl, surfaceWidth, surfaceHeight); + } + } + + private synchronized void drawSingleFrame() { + checkCurrent(); + if (mRenderer != null) { + mRenderer.onDrawFrame(mGl); + } + checkGlError(); + mEgl.eglSwapBuffers(mEglDisplay, mEglSurface); + } + + public void setDimensions(int width, int height) { + surfaceWidth = width; + surfaceHeight = height; + } + + private void checkCurrent() { + if (!mEglContext.equals(mEgl.eglGetCurrentContext()) + || !mEglSurface.equals(mEgl + .eglGetCurrentSurface(EGL10.EGL_DRAW))) { + checkEglError(); + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, + mEglSurface, mEglContext)) { + throw new RuntimeException( + "eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl + .eglGetError())); + } + checkEglError(); + } + } + + private void checkEglError() { + final int error = mEgl.eglGetError(); + if (error != EGL10.EGL_SUCCESS) { + FileLog.e("cannot swap buffers!"); + } + } + + + private void checkGlError() { + final int error = mGl.glGetError(); + if (error != GL11.GL_NO_ERROR) { + FileLog.e("GL error = 0x" + Integer.toHexString(error)); + } + } + + private void initGL() { + + mEgl = (EGL10) EGLContext.getEGL(); + mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { + throw new RuntimeException("eglGetDisplay failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + int[] version = new int[2]; + if (!mEgl.eglInitialize(mEglDisplay, version)) { + throw new RuntimeException("eglInitialize failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + int[] configsCount = new int[1]; + EGLConfig[] configs = new EGLConfig[1]; + int[] configSpec; + if (EmuDetector.with(getContext()).detect()) { + configSpec = new int[] { + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 16, //was 0 + EGL10.EGL_NONE + }; + } else { + configSpec = new int[] { + EGL10.EGL_RENDERABLE_TYPE, + EGL_OPENGL_ES2_BIT, + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_ALPHA_SIZE, 8, + EGL10.EGL_DEPTH_SIZE, 16, //was 0 + EGL10.EGL_STENCIL_SIZE, 0, + EGL10.EGL_SAMPLE_BUFFERS, 1, + EGL10.EGL_NONE + }; + } + eglConfig = null; + if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, + configsCount)) { + throw new IllegalArgumentException( + "eglChooseConfig failed " + + GLUtils.getEGLErrorString(mEgl + .eglGetError())); + } else if (configsCount[0] > 0) { + eglConfig = configs[0]; + } + if (eglConfig == null) { + throw new RuntimeException("eglConfig not initialized"); + } + int[] attrib_list = { + EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE + }; + mEglContext = mEgl.eglCreateContext(mEglDisplay, + eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list); + checkEglError(); + mEglSurface = mEgl.eglCreateWindowSurface( + mEglDisplay, eglConfig, mSurface, null); + checkEglError(); + if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { + int error = mEgl.eglGetError(); + if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { + FileLog.e("eglCreateWindowSurface returned EGL10.EGL_BAD_NATIVE_WINDOW"); + return; + } + throw new RuntimeException( + "eglCreateWindowSurface failed " + + GLUtils.getEGLErrorString(error)); + } + if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, + mEglSurface, mEglContext)) { + throw new RuntimeException("eglMakeCurrent failed " + + GLUtils.getEGLErrorString(mEgl.eglGetError())); + } + checkEglError(); + mGl = (GL10) mEglContext.getGL(); + checkEglError(); + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surface) { + } + + + GestureDetector gestureDetector; + ValueAnimator backAnimation; + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN) { + getParent().requestDisallowInterceptTouchEvent(true); + } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) { + touched = false; + startBackAnimation(); + getParent().requestDisallowInterceptTouchEvent(false); + } + return gestureDetector.onTouchEvent(event); + } + + private void startBackAnimation() { + cancelAnimatons(); + float fromX = mRenderer.angleX; + float fromY = mRenderer.angleY; + float fromX2 = mRenderer.angleX2; + float sum = fromX + fromY; + backAnimation = ValueAnimator.ofFloat(1f, 0f); + backAnimation.addUpdateListener(valueAnimator -> { + float v = (float) valueAnimator.getAnimatedValue(); + mRenderer.angleX = v * fromX; + mRenderer.angleX2 = v * fromX2; + mRenderer.angleY = v * fromY; + + }); + backAnimation.setDuration(600); + backAnimation.setInterpolator(new OvershootInterpolator()); + backAnimation.start(); + if (starParticlesView != null) { + starParticlesView.flingParticles(Math.abs(sum)); + } + scheduleIdleAnimation(idleDelay); + } + + private void cancelAnimatons() { + if (backAnimation != null) { + backAnimation.removeAllListeners(); + backAnimation.cancel(); + backAnimation = null; + } + if (animatorSet != null) { + animatorSet.removeAllListeners(); + animatorSet.cancel(); + animatorSet = null; + } + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + attached = true; + rendererChanged = true; + scheduleIdleAnimation(idleDelay); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + cancelAnimatons(); + attached = false; + } + + AnimatorSet animatorSet = new AnimatorSet(); + + Runnable idleAnimation = new Runnable() { + @Override + public void run() { + if ((animatorSet != null && animatorSet.isRunning()) || (backAnimation != null && backAnimation.isRunning())) { + scheduleIdleAnimation(idleDelay); + } else { + startIdleAnimation(); + } + } + }; + + ValueAnimator.AnimatorUpdateListener xUpdater2 = valueAnimator -> { + mRenderer.angleX2 = (float) valueAnimator.getAnimatedValue(); + }; + + ValueAnimator.AnimatorUpdateListener xUpdater = valueAnimator -> { + mRenderer.angleX = (float) valueAnimator.getAnimatedValue(); + }; + + ValueAnimator.AnimatorUpdateListener yUpdater = valueAnimator -> { + mRenderer.angleY = (float) valueAnimator.getAnimatedValue(); + }; + + private void scheduleIdleAnimation(long time) { + AndroidUtilities.cancelRunOnUIThread(idleAnimation); + if (dialogIsVisible) { + return; + } + AndroidUtilities.runOnUIThread(idleAnimation, time); + } + + + private void startIdleAnimation() { + if (!attached) { + return; + } + + int i = animationIndexes.get(animationPointer); + animationPointer++; + if (animationPointer >= animationIndexes.size()) { + Collections.shuffle(animationIndexes); + animationPointer = 0; + } + + if (i == 0) { + pullAnimation(); + } else if (i == 1) { + slowFlipAination(); + } else if (i == 2) { + sleepAnimation(); + } else { + flipAnimation(); + } + } + + private void slowFlipAination() { + animatorSet = new AnimatorSet(); + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleX, 360); + v1.addUpdateListener(xUpdater); + v1.setDuration(8000); + v1.setInterpolator(CubicBezierInterpolator.DEFAULT); + + animatorSet.playTogether(v1); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRenderer.angleX = 0; + animatorSet = null; + scheduleIdleAnimation(idleDelay); + } + }); + animatorSet.start(); + } + + private void pullAnimation() { + int i = Math.abs(Utilities.random.nextInt() % 4); + animatorSet = new AnimatorSet(); + if (i == 0) { + int a = 48; + + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleY, a); + v1.addUpdateListener(yUpdater); + v1.setDuration(2300); + v1.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + + + ValueAnimator v2 = ValueAnimator.ofFloat(a, 0); + v2.addUpdateListener(yUpdater); + v2.setDuration(500); + v2.setStartDelay(2300); + v2.setInterpolator(AndroidUtilities.overshootInterpolator); + animatorSet.playTogether(v1, v2); + } else { + int a = 485; + if (i == 2) { + a = -485; + } + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleY, a); + v1.addUpdateListener(xUpdater); + v1.setDuration(3000); + v1.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + + + ValueAnimator v2 = ValueAnimator.ofFloat(a, 0); + v2.addUpdateListener(xUpdater); + v2.setDuration(1000); + v2.setStartDelay(3000); + v2.setInterpolator(AndroidUtilities.overshootInterpolator); + animatorSet.playTogether(v1, v2); + } + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRenderer.angleX = 0; + animatorSet = null; + scheduleIdleAnimation(idleDelay); + } + }); + animatorSet.start(); + } + + private void flipAnimation() { + animatorSet = new AnimatorSet(); + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleX, 180); + v1.addUpdateListener(xUpdater); + v1.setDuration(600); + v1.setInterpolator(CubicBezierInterpolator.DEFAULT); + + ValueAnimator v2 = ValueAnimator.ofFloat(180, 360); + v2.addUpdateListener(xUpdater); + v2.setDuration(600); + v2.setStartDelay(2000); + v2.setInterpolator(CubicBezierInterpolator.DEFAULT); + animatorSet.playTogether(v1, v2); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRenderer.angleX = 0; + animatorSet = null; + scheduleIdleAnimation(idleDelay); + } + }); + animatorSet.start(); + } + + private void sleepAnimation() { + animatorSet = new AnimatorSet(); + ValueAnimator v1 = ValueAnimator.ofFloat(mRenderer.angleX, 184); + v1.addUpdateListener(xUpdater); + v1.setDuration(600); + v1.setInterpolator(CubicBezierInterpolator.EASE_OUT); + + ValueAnimator v2 = ValueAnimator.ofFloat(mRenderer.angleY, 50); + v2.addUpdateListener(yUpdater); + v2.setDuration(600); + v2.setInterpolator(CubicBezierInterpolator.EASE_OUT); + + + ValueAnimator v3 = ValueAnimator.ofFloat(180, 0); + v3.addUpdateListener(xUpdater); + v3.setDuration(800); + v3.setStartDelay(10000); + v3.setInterpolator(AndroidUtilities.overshootInterpolator); + + ValueAnimator v4 = ValueAnimator.ofFloat(60, 0); + v4.addUpdateListener(yUpdater); + v4.setDuration(800); + v4.setStartDelay(10000); + v4.setInterpolator(AndroidUtilities.overshootInterpolator); + + ValueAnimator v5 = ValueAnimator.ofFloat(0, 2, -3, 2, -1, 2, -3, 2, -1, 0); + v5.addUpdateListener(xUpdater2); + v5.setDuration(10000); + v5.setInterpolator(new LinearInterpolator()); + + + animatorSet.playTogether(v1, v2, v3, v4, v5); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRenderer.angleX = 0; + animatorSet = null; + scheduleIdleAnimation(idleDelay); + } + }); + animatorSet.start(); + } + + public void setStarParticlesView(StarParticlesView starParticlesView) { + this.starParticlesView = starParticlesView; + } + + public void startEnterAnimation(int angle, long delay) { + if (mRenderer != null) { + mRenderer.angleX = -180; + AndroidUtilities.runOnUIThread(new Runnable() { + @Override + public void run() { + startBackAnimation(); + } + }, delay); + + } + } + + public void setDialogVisible(boolean isVisible) { + dialogIsVisible = isVisible; + if (isVisible) { + AndroidUtilities.cancelRunOnUIThread(idleAnimation); + startBackAnimation(); + } else { + scheduleIdleAnimation(idleDelay); + } + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/ObjLoader.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/ObjLoader.java new file mode 100644 index 000000000..527b7fa9f --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/ObjLoader.java @@ -0,0 +1,69 @@ +package org.telegram.ui.Components.Premium.GLIcon; + +import android.content.Context; + +import java.io.DataInputStream; +import java.io.IOException; +import java.util.ArrayList; + +public final class ObjLoader { + + public int numFaces; + + public float[] normals; + public float[] textureCoordinates; + public float[] positions; + + public ObjLoader(Context context, String file) { + ArrayList vertices = new ArrayList<>(); + ArrayList normals = new ArrayList<>(); + ArrayList textures = new ArrayList<>(); + + try { + DataInputStream inputStream = new DataInputStream(context.getAssets().open(file)); + int n = inputStream.readInt(); + for (int i = 0; i < n; i++) { + vertices.add(inputStream.readFloat()); + } + + n = inputStream.readInt(); + for (int i = 0; i < n; i++) { + textures.add(inputStream.readFloat()); + } + + n = inputStream.readInt(); + for (int i = 0; i < n; i++) { + normals.add(inputStream.readFloat()); + } + + n = inputStream.readInt(); + + numFaces = n; + this.normals = new float[numFaces * 3]; + textureCoordinates = new float[numFaces * 2]; + positions = new float[numFaces * 3]; + int positionIndex = 0; + int normalIndex = 0; + int textureIndex = 0; + + for (int i = 0; i < n; i++) { + int index = 3 * inputStream.readInt(); + positions[positionIndex++] = vertices.get(index++); + positions[positionIndex++] = vertices.get(index++); + positions[positionIndex++] = vertices.get(index); + + index = 2 * inputStream.readInt(); + textureCoordinates[normalIndex++] = textures.get(index++); + textureCoordinates[normalIndex++] = 1 - textures.get(index); + + index = 3 * inputStream.readInt(); + this.normals[textureIndex++] = normals.get(index++); + this.normals[textureIndex++] = normals.get(index++); + this.normals[textureIndex++] = normals.get(index); + } + + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Star3DIcon.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Star3DIcon.java new file mode 100644 index 000000000..a67f527a3 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/GLIcon/Star3DIcon.java @@ -0,0 +1,280 @@ +package org.telegram.ui.Components.Premium.GLIcon; + +import android.content.Context; +import android.content.res.AssetManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; +import android.opengl.GLES20; +import android.opengl.GLUtils; + +import org.telegram.ui.ActionBar.Theme; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; +import java.nio.charset.StandardCharsets; + +public class Star3DIcon { + private int mProgramObject; + private int mMVPMatrixHandle; + private int mWorldMatrixHandle; + private FloatBuffer mVertices; + private FloatBuffer mTextures; + private FloatBuffer mNormals; + + private int mTextureUniformHandle; + private int mNormalMapUniformHandle; + private int mBackgroundTextureUniformHandle; + private int mBackgroundTextureHandle; + private int mTextureCoordinateHandle; + private int mNormalCoordinateHandle; + private int xOffsetHandle; + private int alphaHandle; + private int mTextureDataHandle; + float xOffset; + + int trianglesCount; + float enterAlpha = 0f; + + public float spec1 = 0f; + public float spec2 = 0f; + public float diffuse = 1f; + public int gradientColor1; + public int gradientColor2; + public float normalSpec = 0.2f; + public int normalSpecColor = Color.WHITE; + public int specColor = Color.WHITE; + + int specHandleTop; + int specHandleBottom; + int diffuseHandle; + int gradientColor1Handle; + int gradientColor2Handle; + int normalSpecHandle; + int normalSpecColorHandle; + int specColorHandle; + int resolutionHandle; + int gradientPositionHandle; + + Bitmap texture; + Bitmap backgroundBitmap; + + public Star3DIcon(Context context) { + ObjLoader starObj = new ObjLoader(context, "models/star.binobj"); + + mVertices = ByteBuffer.allocateDirect(starObj.positions.length * 4) + .order(ByteOrder.nativeOrder()).asFloatBuffer(); + mVertices.put(starObj.positions).position(0); + + mTextures = ByteBuffer.allocateDirect(starObj.textureCoordinates.length * 4) + .order(ByteOrder.nativeOrder()).asFloatBuffer(); + mTextures.put(starObj.textureCoordinates).position(0); + + mNormals = ByteBuffer.allocateDirect(starObj.normals.length * 4) + .order(ByteOrder.nativeOrder()).asFloatBuffer(); + mNormals.put(starObj.normals).position(0); + + trianglesCount = starObj.positions.length; + + generateTexture(); + + int vertexShader; + int fragmentShader; + int programObject; + int[] linked = new int[1]; + + vertexShader = GLIconRenderer.loadShader(GLES20.GL_VERTEX_SHADER, loadFromAsset(context, "shaders/vertex2.glsl")); + fragmentShader = GLIconRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER, loadFromAsset(context, "shaders/fragment2.glsl")); + + programObject = GLES20.glCreateProgram(); + GLES20.glAttachShader(programObject, vertexShader); + GLES20.glAttachShader(programObject, fragmentShader); + GLES20.glBindAttribLocation(programObject, 0, "vPosition"); + GLES20.glLinkProgram(programObject); + GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0); + + mProgramObject = programObject; + init(context); + } + + private void init(Context context) { + GLES20.glUseProgram(mProgramObject); + + mTextureCoordinateHandle = GLES20.glGetAttribLocation(mProgramObject, "a_TexCoordinate"); + mNormalCoordinateHandle = GLES20.glGetAttribLocation(mProgramObject, "a_Normal"); + + mTextureUniformHandle = GLES20.glGetUniformLocation(mProgramObject, "u_Texture"); + mNormalMapUniformHandle = GLES20.glGetUniformLocation(mProgramObject, "u_NormalMap"); + mBackgroundTextureUniformHandle = GLES20.glGetUniformLocation(mProgramObject, "u_BackgroundTexture"); + xOffsetHandle = GLES20.glGetUniformLocation(mProgramObject, "f_xOffset"); + alphaHandle = GLES20.glGetUniformLocation(mProgramObject, "f_alpha"); + mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramObject, "uMVPMatrix"); + mWorldMatrixHandle = GLES20.glGetUniformLocation(mProgramObject, "world"); + + specHandleTop = GLES20.glGetUniformLocation(mProgramObject, "spec1"); + specHandleBottom = GLES20.glGetUniformLocation(mProgramObject, "spec2"); + diffuseHandle = GLES20.glGetUniformLocation(mProgramObject, "u_diffuse"); + gradientColor1Handle = GLES20.glGetUniformLocation(mProgramObject, "gradientColor1"); + gradientColor2Handle = GLES20.glGetUniformLocation(mProgramObject, "gradientColor2"); + normalSpecColorHandle = GLES20.glGetUniformLocation(mProgramObject, "normalSpecColor"); + normalSpecHandle = GLES20.glGetUniformLocation(mProgramObject, "normalSpec"); + specColorHandle = GLES20.glGetUniformLocation(mProgramObject, "specColor"); + resolutionHandle = GLES20.glGetUniformLocation(mProgramObject, "resolution"); + gradientPositionHandle = GLES20.glGetUniformLocation(mProgramObject, "gradientPosition"); + + mTextures.position(0); + GLES20.glVertexAttribPointer(mTextureCoordinateHandle, 2, GLES20.GL_FLOAT, false, 0, mTextures); + GLES20.glEnableVertexAttribArray(mTextureCoordinateHandle); + + mNormals.position(0); + GLES20.glVertexAttribPointer(mNormalCoordinateHandle, 3, GLES20.GL_FLOAT, false, 0, mNormals); + GLES20.glEnableVertexAttribArray(mNormalCoordinateHandle); + + mVertices.position(0); + GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, mVertices); + GLES20.glEnableVertexAttribArray(0); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureDataHandle); + + Bitmap bitmap1 = getBitmapFromAsset(context, "flecks.png"); + + final int[] normalMap = new int[1]; + GLES20.glGenTextures(1, normalMap, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, normalMap[0]); + + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); + + GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap1, 0); + bitmap1.recycle(); + + final int[] backgroundBitmapHandel = new int[1]; + GLES20.glGenTextures(1, backgroundBitmapHandel, 0); + mBackgroundTextureHandle = backgroundBitmapHandel[0]; + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundBitmapHandel[0]); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBackgroundTextureHandle); + + + GLES20.glActiveTexture(GLES20.GL_TEXTURE1); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, normalMap[0]); + GLES20.glUniform1i(mNormalMapUniformHandle, 1); + + GLES20.glActiveTexture(GLES20.GL_TEXTURE2); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, backgroundBitmapHandel[0]); + GLES20.glUniform1i(mBackgroundTextureUniformHandle, 2); + + } + + private void generateTexture() { + texture = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(texture); + Paint paint = new Paint(); + paint.setShader(new LinearGradient(0, 100, 150, 0, new int[]{Theme.getColor(Theme.key_premiumGradient1), Theme.getColor(Theme.key_premiumGradient2), Theme.getColor(Theme.key_premiumGradient3), Theme.getColor(Theme.key_premiumGradient4)}, new float[]{0, 0.5f, 0.78f, 1f}, Shader.TileMode.CLAMP)); + canvas.drawRect(0, 0, 100, 100, paint); + + final int[] textureHandle = new int[1]; + GLES20.glGenTextures(1, textureHandle, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle[0]); + + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, texture, 0); + mTextureDataHandle = textureHandle[0]; + } + + public void draw(float[] mvpMatrix, float[] worldMatrix, int width, int height, float gradientStartX, float gradientScaleX, float gradientStartY, float gradientScaleY) { + if (backgroundBitmap != null) { + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mBackgroundTextureHandle); + GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, backgroundBitmap, 0); + backgroundBitmap = null; + } + GLES20.glUniform1i(mTextureUniformHandle, 0); + GLES20.glUniform1f(xOffsetHandle, xOffset); + GLES20.glUniform1f(alphaHandle, enterAlpha); + GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); + GLES20.glUniformMatrix4fv(mWorldMatrixHandle, 1, false, worldMatrix, 0); + GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, trianglesCount / 3); + + GLES20.glUniform1f(specHandleTop, spec1); + GLES20.glUniform1f(specHandleBottom, spec2); + GLES20.glUniform1f(diffuseHandle, diffuse); + GLES20.glUniform1f(normalSpecHandle, normalSpec); + + GLES20.glUniform3f(gradientColor1Handle, Color.red(gradientColor1) / 255f, Color.green(gradientColor1) / 255f, Color.blue(gradientColor1) / 255f); + GLES20.glUniform3f(gradientColor2Handle, Color.red(gradientColor2) / 255f, Color.green(gradientColor2) / 255f, Color.blue(gradientColor2) / 255f); + GLES20.glUniform3f(normalSpecColorHandle, Color.red(normalSpecColor) / 255f, Color.green(normalSpecColor) / 255f, Color.blue(normalSpecColor) / 255f); + GLES20.glUniform3f(specColorHandle, Color.red(specColor) / 255f, Color.green(specColor) / 255f, Color.blue(specColor) / 255f); + GLES20.glUniform2f(resolutionHandle, width, height); + GLES20.glUniform4f(gradientPositionHandle, gradientStartX, gradientScaleX, gradientStartY, gradientScaleY); + + if (enterAlpha < 1f) { + enterAlpha += 16 / 220f; + if (enterAlpha > 1) { + enterAlpha = 1f; + } + } + xOffset += 0.0005f; + if (xOffset > 1) { + xOffset -= 1f; + } + } + + public String loadFromAsset(Context context, String name) { + StringBuilder sb = new StringBuilder(); + InputStream is = null; + try { + is = context.getAssets().open(name); + + BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); + String str; + while ((str = br.readLine()) != null) { + if (str.startsWith("//")) { + continue; + } + sb.append(str); + } + br.close(); + is.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return sb.toString(); + } + + public static Bitmap getBitmapFromAsset(Context context, String filePath) { + AssetManager assetManager = context.getAssets(); + + InputStream istr; + Bitmap bitmap = null; + try { + istr = assetManager.open(filePath); + bitmap = BitmapFactory.decodeStream(istr); + } catch (IOException e) { + // handle exception + } + + return bitmap; + } + + public void setBackground(Bitmap gradientTextureBitmap) { + backgroundBitmap = gradientTextureBitmap; + } + + public void destroy() { + GLES20.glDeleteProgram(mProgramObject); + } + +} \ No newline at end of file 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 new file mode 100644 index 000000000..95178df81 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitPreviewView.java @@ -0,0 +1,523 @@ +package org.telegram.ui.Components.Premium; + +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.CornerPathEffect; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PathEffect; +import android.text.Layout; +import android.text.SpannableStringBuilder; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.OvershootInterpolator; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.EmptyStubSpan; +import org.telegram.ui.Components.LayoutHelper; + +import java.util.ArrayList; + +public class LimitPreviewView extends LinearLayout { + + public int gradientTotalHeight; + boolean wasAnimation; + CounterView limitIcon; + + boolean inc; + float progress; + + int icon; + + TextView premiumCount; + TextView defaultCount; + private float position; + private View parentVideForGradient; + PremiumGradient.GradientTools staticGradient; + int gradientYOffset; + boolean wasHaptic; + boolean animationCanPlay = true; + LinearLayout limitsContainer; + private boolean premiumLocked; + + @SuppressLint("SetTextI18n") + public LimitPreviewView(@NonNull Context context, int icon, int currentValue, int premiumLimit) { + super(context); + this.icon = icon; + setOrientation(VERTICAL); + setClipChildren(false); + setClipToPadding(false); + if (icon != 0) { + setPadding(0, AndroidUtilities.dp(16), 0, 0); + limitIcon = new CounterView(context); + + setIconValue(currentValue); + + limitIcon.setPadding(AndroidUtilities.dp(24), AndroidUtilities.dp(6), AndroidUtilities.dp(24), AndroidUtilities.dp(14)); + addView(limitIcon, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.LEFT)); + } + limitsContainer = new LinearLayout(context) { + + Paint grayPaint = new Paint(); + + @Override + protected void dispatchDraw(Canvas canvas) { + grayPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(6), AndroidUtilities.dp(6), grayPaint); + + canvas.save(); + canvas.clipRect(getMeasuredWidth() / 2f, 0, getMeasuredWidth(), getMeasuredHeight()); + Paint paint = PremiumGradient.getInstance().getMainGradientPaint(); + if (parentVideForGradient != null) { + View parent = parentVideForGradient; + if (staticGradient != null) { + paint = staticGradient.paint; + staticGradient.gradientMatrixLinear(gradientTotalHeight, -gradientYOffset); + } else { + float y = 0; + View child = this; + while (child != parent) { + y += child.getY(); + child = (View) child.getParent(); + } + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, parent.getMeasuredWidth(), parent.getMeasuredHeight(), getGlobalXOffset() - getLeft(), -y); + } + + } else { + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, LimitPreviewView.this.getMeasuredWidth(), LimitPreviewView.this.getMeasuredHeight(), getGlobalXOffset() - getLeft(), -getTop()); + } + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(6), AndroidUtilities.dp(6), paint); + canvas.restore(); + if (staticGradient == null) { + invalidate(); + } + super.dispatchDraw(canvas); + } + }; + limitsContainer.setOrientation(LinearLayout.HORIZONTAL); + + FrameLayout limitLayout = new FrameLayout(context); + + TextView freeTextView = new TextView(context); + freeTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + freeTextView.setText(LocaleController.getString("LimitFree", R.string.LimitFree)); + freeTextView.setGravity(Gravity.CENTER_VERTICAL); + freeTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + freeTextView.setPadding(AndroidUtilities.dp(12), 0, 0, 0); + + defaultCount = new TextView(context); + defaultCount.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + defaultCount.setText(Integer.toString(premiumLimit)); + defaultCount.setGravity(Gravity.CENTER_VERTICAL); + defaultCount.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + + limitLayout.addView(freeTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.LEFT, 0, 0, 36, 0)); + limitLayout.addView(defaultCount, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.RIGHT, 0, 0, 12, 0)); + + limitsContainer.addView(limitLayout, LayoutHelper.createLinear(0, 30, 1f)); + + FrameLayout limitLayout2 = new FrameLayout(context); + + TextView limitTextView = new TextView(context); + limitTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + limitTextView.setText(LocaleController.getString("LimitPremium", R.string.LimitPremium)); + limitTextView.setGravity(Gravity.CENTER_VERTICAL); + limitTextView.setTextColor(Color.WHITE); + limitTextView.setPadding(AndroidUtilities.dp(12), 0, 0, 0); + + premiumCount = new TextView(context); + premiumCount.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + premiumCount.setText(Integer.toString(premiumLimit)); + premiumCount.setGravity(Gravity.CENTER_VERTICAL); + premiumCount.setTextColor(Color.WHITE); + + limitLayout2.addView(limitTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.LEFT, 0, 0, 36, 0)); + limitLayout2.addView(premiumCount, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 30, Gravity.RIGHT, 0, 0, 12, 0)); + + limitsContainer.addView(limitLayout2, LayoutHelper.createLinear(0, 30, 1f)); + + addView(limitsContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 14, icon == 0 ? 0 : 12, 14, 0)); + } + + public void setIconValue(int currentValue) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append("d ").setSpan(new ColoredImageSpan(icon), 0, 1, 0); + spannableStringBuilder.append(Integer.toString(currentValue)); + limitIcon.setText(spannableStringBuilder); + } + + private float getGlobalXOffset() { + return -LimitPreviewView.this.getMeasuredWidth() * 0.1f * progress - LimitPreviewView.this.getMeasuredWidth() * 0.2f; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (staticGradient == null) { + if (inc) { + progress += 16f / 1000f; + if (progress > 3) { + inc = false; + } + } else { + progress -= 16f / 1000f; + if (progress < 1) { + inc = true; + } + } + invalidate(); + } + super.dispatchDraw(canvas); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (!wasAnimation && limitIcon != null && animationCanPlay && !premiumLocked) { + int padding = AndroidUtilities.dp(14); + float fromX = 0; + float toX = padding + (getMeasuredWidth() - padding * 2) * position - limitIcon.getMeasuredWidth() / 2f; + float fromProgressCenter = 0.5f; + float toProgressCenter = 0.5f; + if (toX > getMeasuredWidth() - padding - limitIcon.getMeasuredWidth()) { + toX = getMeasuredWidth() - padding - limitIcon.getMeasuredWidth(); + toProgressCenter = 1f; + } + limitIcon.setAlpha(1f); + limitIcon.setTranslationX(fromX); + limitIcon.setPivotX(limitIcon.getMeasuredWidth() / 2f); + limitIcon.setPivotY(limitIcon.getMeasuredHeight()); + limitIcon.setScaleX(0); + limitIcon.setScaleY(0); + limitIcon.createAnimationLayouts(); + + ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1f); + float finalToX = toX; + float finalToProgressCenter = toProgressCenter; + valueAnimator.addUpdateListener(animation -> { + float v = (float) animation.getAnimatedValue(); + float moveValue = Math.min(1f, v); + if (v > 1f) { + if (!wasHaptic) { + wasHaptic = true; + limitIcon.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } + limitIcon.setRotation((v - 1f) * 60); + } else { + limitIcon.setRotation(0); + } + limitIcon.setTranslationX(fromX * (1f - moveValue) + finalToX * moveValue); + float arrowCenter = fromProgressCenter * (1f - moveValue) + finalToProgressCenter * moveValue; + limitIcon.setArrowCenter(arrowCenter); + float scale = Math.min(1, moveValue * 2f); + limitIcon.setScaleX(scale); + limitIcon.setScaleY(scale); + limitIcon.setPivotX(limitIcon.getMeasuredWidth() * arrowCenter); + }); + + valueAnimator.setInterpolator(new OvershootInterpolator()); + valueAnimator.setDuration(1000); + valueAnimator.setStartDelay(200); + valueAnimator.start(); + + wasAnimation = true; + } else if (premiumLocked) { + int padding = AndroidUtilities.dp(14); + float toX = padding + (getMeasuredWidth() - padding * 2) * 0.5f - limitIcon.getMeasuredWidth() / 2f; + if (!wasAnimation && animationCanPlay) { + wasAnimation = true; + limitIcon.animate().alpha(1).scaleX(1).scaleY(1).setDuration(200).setInterpolator(new OvershootInterpolator()).start(); + } else if (!wasAnimation) { + limitIcon.setAlpha(0); + limitIcon.setScaleX(0); + limitIcon.setScaleY(0); + } else { + limitIcon.setAlpha(1f); + limitIcon.setScaleX(1f); + limitIcon.setScaleY(1f); + } + limitIcon.setTranslationX(toX); + } else if (limitIcon != null){ + limitIcon.setAlpha(0); + } + } + + public void setType(int type) { + if (type == LimitReachedBottomSheet.TYPE_LARGE_FILE) { + if (limitIcon != null) { + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append("d ").setSpan(new ColoredImageSpan(icon), 0, 1, 0); + spannableStringBuilder.append(UserConfig.getInstance(UserConfig.selectedAccount).isPremium() ? "4 GB" : "2 GB"); + limitIcon.setText(spannableStringBuilder); + } + premiumCount.setText("4 GB"); + } + } + + public void setBagePosition(float position) { + this.position = position; + } + + public void setParentViewForGradien(ViewGroup containerView) { + parentVideForGradient = containerView; + } + + public void setStaticGradinet(PremiumGradient.GradientTools gradientTools) { + staticGradient = gradientTools; + } + + public void setDelayedAnimation() { + animationCanPlay = false; + } + + public void startDelayedAnimation() { + animationCanPlay = true; + requestLayout(); + } + + public void setPremiumLocked() { + limitsContainer.setVisibility(View.GONE); + limitIcon.setPadding(AndroidUtilities.dp(24), AndroidUtilities.dp(3), AndroidUtilities.dp(24), AndroidUtilities.dp(3)); + premiumLocked = true; + } + + private class LimitTextView extends LinearLayout { + + public LimitTextView(Context context) { + super(context); + } + + } + + private class CounterView extends View { + + Path path = new Path(); + PathEffect pathEffect = new CornerPathEffect(AndroidUtilities.dp(6)); + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + + StaticLayout textLayout; + float textWidth; + CharSequence text; + + ArrayList animatedLayouts = new ArrayList(); + StaticLayout animatedStableLayout; + boolean animationInProgress; + + float arrowCenter; + boolean invalidatePath; + + public CounterView(Context context) { + super(context); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textPaint.setTextSize(AndroidUtilities.dp(22)); + textPaint.setColor(Color.WHITE); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + textWidth = textPaint.measureText(text, 0, text.length()); + textLayout = new StaticLayout(text, textPaint, (int) textWidth + AndroidUtilities.dp(12), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + setMeasuredDimension((int) (textWidth + getPaddingRight() + getPaddingLeft()), AndroidUtilities.dp(44) + AndroidUtilities.dp(8)); + updatePath(); + } + + private void updatePath() { + int h = getMeasuredHeight() - AndroidUtilities.dp(8); + float widthHalf = getMeasuredWidth() * arrowCenter; + float x2 = Utilities.clamp(widthHalf + AndroidUtilities.dp(8), getMeasuredWidth(), 0); + float x3 = Utilities.clamp(widthHalf + AndroidUtilities.dp(10), getMeasuredWidth(), 0); + + path.rewind(); + path.moveTo(widthHalf - AndroidUtilities.dp(24), h - h / 2f - AndroidUtilities.dp(2)); + path.lineTo(widthHalf - AndroidUtilities.dp(24), h); + path.lineTo(widthHalf - AndroidUtilities.dp(8), h); + path.lineTo(widthHalf, h + AndroidUtilities.dp(8)); + if (arrowCenter < 0.7f) { + path.lineTo(x2, h); + } + path.lineTo(x3, h); + path.lineTo(x3, h - h / 2f - AndroidUtilities.dp(2)); + path.close(); + } + + @Override + protected void onDraw(Canvas canvas) { + int h = getMeasuredHeight() - AndroidUtilities.dp(8); + if (premiumLocked) { + h = getMeasuredHeight(); + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, LimitPreviewView.this.getMeasuredWidth(), LimitPreviewView.this.getMeasuredHeight(), getGlobalXOffset() - getX(), -getTop()); + AndroidUtilities.rectTmp.set(0, AndroidUtilities.dp(3), getMeasuredWidth(), h - AndroidUtilities.dp(3)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, h / 2f, h / 2f, PremiumGradient.getInstance().getMainGradientPaint()); + } else { + if (invalidatePath) { + invalidatePath = false; + updatePath(); + } + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, LimitPreviewView.this.getMeasuredWidth(), LimitPreviewView.this.getMeasuredHeight(), getGlobalXOffset() - getX(), -getTop()); + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), h); + canvas.drawRoundRect(AndroidUtilities.rectTmp, h / 2f, h / 2f, PremiumGradient.getInstance().getMainGradientPaint()); + PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(pathEffect); + canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint()); + PremiumGradient.getInstance().getMainGradientPaint().setPathEffect(null); + invalidate(); + } + + float x = (getMeasuredWidth() - textLayout.getWidth()) / 2f; + float y = (h - textLayout.getHeight()) / 2f; + if (!animationInProgress) { + if (textLayout != null) { + canvas.save(); + canvas.translate(x, y); + textLayout.draw(canvas); + canvas.restore(); + } + } else { + canvas.save(); + canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight() - AndroidUtilities.dp(8)); + if (animatedStableLayout != null) { + canvas.save(); + canvas.translate(x, y); + animatedStableLayout.draw(canvas); + canvas.restore(); + } + for (int i = 0; i < animatedLayouts.size(); i++) { + AnimatedLayout animatedLayout = animatedLayouts.get(i); + canvas.save(); + if (animatedLayout.direction) { + canvas.translate(x + animatedLayout.x, y - h * 10 * animatedLayout.progress + h * (10 - animatedLayout.staticLayouts.size())); + for (int j = 0; j < animatedLayout.staticLayouts.size(); j++) { + canvas.translate(0, h); + animatedLayout.staticLayouts.get(j).draw(canvas); + } + } else { + canvas.translate(x + animatedLayout.x, y + h * 10 * animatedLayout.progress - h * (10 - animatedLayout.staticLayouts.size())); + for (int j = 0; j < animatedLayout.staticLayouts.size(); j++) { + canvas.translate(0, -h); + animatedLayout.staticLayouts.get(j).draw(canvas); + } + } + canvas.restore(); + } + + canvas.restore(); + } + } + + @Override + public void setTranslationX(float translationX) { + if (translationX != getTranslationX()) { + super.setTranslationX(translationX); + invalidate(); + } + } + + void createAnimationLayouts() { + animatedLayouts.clear(); + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(text); + + boolean direction = true; + int directionCount = 0; + for (int i = 0; i < text.length(); i++) { + if (Character.isDigit(text.charAt(i))) { + AnimatedLayout animatedLayout = new AnimatedLayout(); + animatedLayouts.add(animatedLayout); + animatedLayout.x = textLayout.getSecondaryHorizontal(i); + animatedLayout.direction = direction; + if (directionCount >= 1) { + direction = !direction; + directionCount = 0; + } + directionCount++; + + int digit = text.charAt(i) - '0'; + if (digit == 0) { + digit = 10; + } + for (int j = 1; j <= digit; j++) { + int k = j; + if (k == 10) { + k = 0; + } + String str = "" + k; + StaticLayout staticLayout = new StaticLayout(str, textPaint, (int) textWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + animatedLayout.staticLayouts.add(staticLayout); + } + spannableStringBuilder.setSpan(new EmptyStubSpan(), i, i + 1, 0); + } + } + animatedStableLayout = new StaticLayout(spannableStringBuilder, textPaint, (int) textWidth + AndroidUtilities.dp(12), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); + for (int i = 0; i < animatedLayouts.size(); i++) { + animationInProgress = true; + AnimatedLayout layout = animatedLayouts.get(i); + layout.valueAnimator = ValueAnimator.ofFloat(0, 1f); + layout.valueAnimator.addUpdateListener(animation -> { + layout.progress = (float) animation.getAnimatedValue(); + invalidate(); + }); + layout.valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + layout.valueAnimator = null; + checkAnimationComplete(); + } + }); + layout.valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT); + layout.valueAnimator.setDuration(750); + layout.valueAnimator.setStartDelay((animatedLayouts.size() - 1 - i) * 60L); + layout.valueAnimator.start(); + } + } + + private void checkAnimationComplete() { + for (int i = 0; i < animatedLayouts.size(); i++) { + if (animatedLayouts.get(i).valueAnimator != null) { + return; + } + } + animatedLayouts.clear(); + animationInProgress = false; + invalidate(); + } + + public void setText(CharSequence text) { + this.text = text; + } + + public void setArrowCenter(float v) { + if (arrowCenter != v) { + arrowCenter = v; + invalidatePath = true; + invalidate(); + } + } + + private class AnimatedLayout { + ArrayList staticLayouts = new ArrayList<>(); + float progress; + public boolean direction; + float x; + ValueAnimator valueAnimator; + } + } +} 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 new file mode 100644 index 000000000..a1867019c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/LimitReachedBottomSheet.java @@ -0,0 +1,714 @@ +package org.telegram.ui.Components.Premium; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Canvas; +import android.text.SpannableStringBuilder; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ChatObject; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.AdminedChannelCell; +import org.telegram.ui.Cells.GroupCreateUserCell; +import org.telegram.ui.Cells.HeaderCell; +import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.FlickerLoadingView; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerItemsEnterAnimator; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; +import java.util.HashSet; + +public class LimitReachedBottomSheet extends BottomSheetWithRecyclerListView { + + public static final int TYPE_PIN_DIALOGS = 0; + public static final int TYPE_PUBLIC_LINKS = 2; + public static final int TYPE_FOLDERS = 3; + public static final int TYPE_CHATS_IN_FOLDER = 4; + public static final int TYPE_TO_MANY_COMMUNITIES = 5; + public static final int TYPE_LARGE_FILE = 6; + public static final int TYPE_ACCOUNTS = 7; + + public static final int TYPE_CAPTION = 8; + public static final int TYPE_GIFS = 9; + public static final int TYPE_STICKERS = 10; + + public static String limitTypeToServerString(int type) { + switch (type) { + case TYPE_PIN_DIALOGS: + return "double_limits__dialog_pinned"; + case TYPE_TO_MANY_COMMUNITIES: + return "double_limits__channels"; + case TYPE_PUBLIC_LINKS: + return "double_limits__channels_public"; + case TYPE_FOLDERS: + return "double_limits__dialog_filters"; + case TYPE_CHATS_IN_FOLDER: + return "double_limits__dialog_filters_chats"; + case TYPE_LARGE_FILE: + return "double_limits__upload_max_fileparts"; + case TYPE_CAPTION: + return "double_limits__caption_length"; + case TYPE_GIFS: + return "double_limits__saved_gifs"; + case TYPE_STICKERS: + return "double_limits__stickers_faved"; + } + return null; + } + + final int type; + ArrayList chats = new ArrayList<>(); + + int rowCount; + int headerRow = -1; + int dividerRow = -1; + int chatsTitleRow = -1; + int chatStartRow = -1; + int loadingRow = -1; + + public boolean parentIsChannel; + private int currentValue = -1; + LimitPreviewView limitPreviewView; + HashSet selectedChats = new HashSet<>(); + + private ArrayList inactiveChats = new ArrayList<>(); + private ArrayList inactiveChatsSignatures = new ArrayList<>(); + + PremiumButtonView premiumButtonView; + public Runnable onSuccessRunnable; + public Runnable onShowPremiumScreenRunnable; + private boolean loading = false; + RecyclerItemsEnterAnimator enterAnimator; + BaseFragment parentFragment; + View divider; + LimitParams limitParams; + private boolean isVeryLargeFile; + + public LimitReachedBottomSheet(BaseFragment fragment, Context context, int type, int currentAccount) { + super(fragment, false, hasFixedSize(type)); + fixNavigationBar(); + parentFragment = fragment; + this.type = type; + this.currentAccount = currentAccount; + updateRows(); + if (type == TYPE_PUBLIC_LINKS) { + loadAdminedChannels(); + } else if (type == TYPE_TO_MANY_COMMUNITIES) { + loadInactiveChannels(); + } + } + + @Override + public void onViewCreated(FrameLayout containerView) { + super.onViewCreated(containerView); + Context context = containerView.getContext(); + + premiumButtonView = new PremiumButtonView(context, true); + updatePremiumButtonText(); + + if (!hasFixedSize) { + divider = new View(context) { + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawRect(0, 0, getMeasuredWidth(), 1, Theme.dividerPaint); + } + }; + divider.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + containerView.addView(divider, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 72, Gravity.BOTTOM, 0, 0, 0, 0)); + } + containerView.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM, 16, 0, 16, 12)); + recyclerListView.setPadding(0, 0, 0, AndroidUtilities.dp(72)); + recyclerListView.setOnItemClickListener((view, position) -> { + if (view instanceof AdminedChannelCell) { + AdminedChannelCell adminedChannelCell = ((AdminedChannelCell) view); + TLRPC.Chat chat = adminedChannelCell.getCurrentChannel(); + if (selectedChats.contains(chat)) { + selectedChats.remove(chat); + } else { + selectedChats.add(chat); + } + adminedChannelCell.setChecked(selectedChats.contains(chat), true); + updateButton(); + } else if (view instanceof GroupCreateUserCell) { + GroupCreateUserCell cell = (GroupCreateUserCell) view; + TLRPC.Chat chat = (TLRPC.Chat) cell.getObject(); + if (selectedChats.contains(chat)) { + selectedChats.remove(chat); + } else { + selectedChats.add(chat); + } + cell.setChecked(selectedChats.contains(chat), true); + updateButton(); + } + }); + recyclerListView.setOnItemLongClickListener((view, position) -> { + recyclerListView.getOnItemClickListener().onItemClick(view, position); + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + return false; + }); + premiumButtonView.buttonLayout.setOnClickListener(v -> { + if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumLocked || isVeryLargeFile) { + dismiss(); + return; + } + if (parentFragment == null) { + return; + } + if (parentFragment.getVisibleDialog() != null) { + parentFragment.getVisibleDialog().dismiss(); + } + parentFragment.presentFragment(new PremiumPreviewFragment(limitTypeToServerString(type))); + if (onShowPremiumScreenRunnable != null) { + onShowPremiumScreenRunnable.run(); + } + dismiss(); + }); + premiumButtonView.overlayTextView.setOnClickListener(v -> { + if (selectedChats.isEmpty()) { + return; + } + if (type == TYPE_PUBLIC_LINKS) { + revokeSelectedLinks(); + } else if (type == TYPE_TO_MANY_COMMUNITIES) { + leaveFromSelectedGroups(); + } + }); + enterAnimator = new RecyclerItemsEnterAnimator(recyclerListView, true); + } + + public void updatePremiumButtonText() { + if (UserConfig.getInstance(currentAccount).isPremium() || MessagesController.getInstance(currentAccount).premiumLocked || isVeryLargeFile) { + premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.OK)); + premiumButtonView.hideIcon(); + } else { + premiumButtonView.buttonTextView.setText(LocaleController.getString("IncreaseLimit", R.string.IncreaseLimit)); + premiumButtonView.setIcon(type == TYPE_ACCOUNTS ? R.raw.addone_icon : R.raw.double_icon); + } + } + + private void leaveFromSelectedGroups() { + TLRPC.User currentUser = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); + ArrayList chats = new ArrayList<>(selectedChats); + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(LocaleController.formatPluralString("LeaveCommunities", chats.size())); + if (chats.size() == 1) { + TLRPC.Chat channel = chats.get(0); + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ChannelLeaveAlertWithName", R.string.ChannelLeaveAlertWithName, channel.title))); + } else { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("ChatsLeaveAlert", R.string.ChatsLeaveAlert))); + } + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(LocaleController.getString("RevokeButton", R.string.RevokeButton), (dialogInterface, interface2) -> { + dismiss(); + for (int i = 0; i < chats.size(); i++) { + TLRPC.Chat chat = chats.get(i); + MessagesController.getInstance(currentAccount).putChat(chat, false); + MessagesController.getInstance(currentAccount).deleteParticipantFromChat(chat.id, currentUser, null); + } + }); + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + } + + private void updateButton() { + if (selectedChats.size() > 0) { + String str = null; + if (type == TYPE_PUBLIC_LINKS) { + str = LocaleController.formatPluralString("RevokeLinks", selectedChats.size()); + } else if (type == TYPE_TO_MANY_COMMUNITIES) { + str = LocaleController.formatPluralString("LeaveCommunities", selectedChats.size()); + } + premiumButtonView.setOverlayText(str, true, true); + } else { + premiumButtonView.clearOverlayText(); + } + } + + private static boolean hasFixedSize(int type) { + if (type == TYPE_PIN_DIALOGS || type == TYPE_FOLDERS || type == TYPE_CHATS_IN_FOLDER || type == TYPE_LARGE_FILE || type == TYPE_ACCOUNTS) { + return true; + } + return false; + } + + @Override + public CharSequence getTitle() { + return LocaleController.getString("LimitReached", R.string.LimitReached); + } + + @Override + public RecyclerListView.SelectionAdapter createAdapter() { + return new RecyclerListView.SelectionAdapter() { + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 1 || holder.getItemViewType() == 4; + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + default: + case 0: + view = new HeaderView(context); + break; + case 1: + view = new AdminedChannelCell(context, new View.OnClickListener() { + @Override + public void onClick(View v) { + AdminedChannelCell cell = (AdminedChannelCell) v.getParent(); + final ArrayList channels = new ArrayList<>(); + channels.add(cell.getCurrentChannel()); + revokeLinks(channels); + } + }, true, 9); + break; + case 2: + view = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray)); + break; + case 3: + view = new HeaderCell(context); + view.setPadding(0, 0, 0, AndroidUtilities.dp(8)); + break; + case 4: + view = new GroupCreateUserCell(context, 1, 8, false); + break; + case 5: + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, null); + flickerLoadingView.setViewType(type == TYPE_PUBLIC_LINKS ? FlickerLoadingView.LIMIT_REACHED_LINKS : FlickerLoadingView.LIMIT_REACHED_GROUPS); + flickerLoadingView.setIsSingleCell(true); + flickerLoadingView.setIgnoreHeightCheck(true); + flickerLoadingView.setItemsCount(10); + view = flickerLoadingView; + 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) { + if (holder.getItemViewType() == 4) { + TLRPC.Chat chat = inactiveChats.get(position - chatStartRow); + GroupCreateUserCell cell = (GroupCreateUserCell) holder.itemView; + String signature = inactiveChatsSignatures.get(position - chatStartRow); + cell.setObject(chat, chat.title, signature, true); + cell.setChecked(selectedChats.contains(chat), false); + } else if (holder.getItemViewType() == 1) { + TLRPC.Chat chat = chats.get(position - chatStartRow); + AdminedChannelCell adminedChannelCell = (AdminedChannelCell) holder.itemView; + TLRPC.Chat oldChat = adminedChannelCell.getCurrentChannel(); + adminedChannelCell.setChannel(chat, false); + adminedChannelCell.setChecked(selectedChats.contains(chat), oldChat == chat); + } else if (holder.getItemViewType() == 3) { + HeaderCell headerCell = (HeaderCell) holder.itemView; + if (type == TYPE_PUBLIC_LINKS) { + headerCell.setText(LocaleController.getString("YourPublicCommunities", R.string.YourPublicCommunities)); + } else { + headerCell.setText(LocaleController.getString("LastActiveCommunities", R.string.LastActiveCommunities)); + } + } + } + + @Override + public int getItemViewType(int position) { + if (headerRow == position) { + return 0; + } else if (dividerRow == position) { + return 2; + } else if (chatsTitleRow == position) { + return 3; + } else if (loadingRow == position) { + return 5; + } + if (type == TYPE_TO_MANY_COMMUNITIES) { + return 4; + } else { + return 1; + } + } + + @Override + public int getItemCount() { + return rowCount; + } + }; + } + + public void setCurrentValue(int currentValue) { + this.currentValue = currentValue; + } + + public void setVeryLargeFile(boolean b) { + isVeryLargeFile = b; + updatePremiumButtonText(); + } + + + private class HeaderView extends LinearLayout { + + @SuppressLint("SetTextI18n") + public HeaderView(Context context) { + super(context); + setOrientation(LinearLayout.VERTICAL); + setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0); + + limitParams = getLimitParams(type, currentAccount); + int icon = limitParams.icon; + String descriptionStr; + boolean premiumLocked = MessagesController.getInstance(currentAccount).premiumLocked; + if (premiumLocked) { + descriptionStr = limitParams.descriptionStrLocked; + } else { + descriptionStr = (UserConfig.getInstance(currentAccount).isPremium() || isVeryLargeFile) ? limitParams.descriptionStrPremium : limitParams.descriptionStr; + } + int defaultLimit = limitParams.defaultLimit; + int premiumLimit = limitParams.premiumLimit; + int currentValue = LimitReachedBottomSheet.this.currentValue; + float position = 0.5f; + + if (type == TYPE_FOLDERS) { + currentValue = MessagesController.getInstance(currentAccount).dialogFilters.size() - 1; + } else if (type == TYPE_ACCOUNTS) { + currentValue = UserConfig.getActivatedAccountsCount(); + } + if (type == TYPE_PIN_DIALOGS) { + int pinnedCount = 0; + ArrayList dialogs = MessagesController.getInstance(currentAccount).getDialogs(0); + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog = dialogs.get(a); + if (dialog instanceof TLRPC.TL_dialogFolder) { + continue; + } + if (dialog.pinned) { + pinnedCount++; + } + } + currentValue = pinnedCount; + } + + if (UserConfig.getInstance(currentAccount).isPremium() || isVeryLargeFile) { + currentValue = premiumLimit; + position = 1f; + } else { + if (currentValue < 0) { + currentValue = defaultLimit; + } + if (type == TYPE_ACCOUNTS) { + if (currentValue > defaultLimit) { + position = (float) (currentValue - defaultLimit) / (float) (premiumLimit - defaultLimit); + } + } else { + position = currentValue / (float) premiumLimit; + } + } + + limitPreviewView = new LimitPreviewView(context, icon, currentValue, premiumLimit); + limitPreviewView.setBagePosition(position); + limitPreviewView.setType(type); + limitPreviewView.defaultCount.setVisibility(View.GONE); + if (premiumLocked) { + limitPreviewView.setPremiumLocked(); + } else { + if (UserConfig.getInstance(currentAccount).isPremium() || isVeryLargeFile) { + limitPreviewView.premiumCount.setVisibility(View.GONE); + if (type == TYPE_LARGE_FILE) { + limitPreviewView.defaultCount.setText("2 GB"); + } else { + limitPreviewView.defaultCount.setText(Integer.toString(defaultLimit)); + } + limitPreviewView.defaultCount.setVisibility(View.VISIBLE); + } + } + + if (type == TYPE_PUBLIC_LINKS || type == TYPE_TO_MANY_COMMUNITIES) { + limitPreviewView.setDelayedAnimation(); + } + + + addView(limitPreviewView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 0, 0, 0)); + + TextView title = new TextView(context); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + if (type == TYPE_LARGE_FILE) { + title.setText(LocaleController.getString("FileTooLarge", R.string.FileTooLarge)); + } else { + title.setText(LocaleController.getString("LimitReached", R.string.LimitReached)); + } + 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, 22, 0, 10)); + + TextView description = new TextView(context); + description.setText(AndroidUtilities.replaceTags(descriptionStr)); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + description.setGravity(Gravity.CENTER_HORIZONTAL); + description.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(description, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, 24, 0, 24, 24)); + } + } + + private static LimitParams getLimitParams(int type, int currentAccount) { + LimitParams limitParams = new LimitParams(); + if (type == TYPE_PIN_DIALOGS) { + limitParams.defaultLimit = MessagesController.getInstance(currentAccount).dialogFiltersPinnedLimitDefault; + limitParams.premiumLimit = MessagesController.getInstance(currentAccount).dialogFiltersPinnedLimitPremium; + limitParams.icon = R.drawable.msg_limit_pin; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedPinDialogs", R.string.LimitReachedPinDialogs, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedPinDialogsPremium", R.string.LimitReachedPinDialogsPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedPinDialogsLocked", R.string.LimitReachedPinDialogsLocked, limitParams.defaultLimit); + } else if (type == TYPE_PUBLIC_LINKS) { + limitParams.defaultLimit = MessagesController.getInstance(currentAccount).publicLinksLimitDefault; + limitParams.premiumLimit = MessagesController.getInstance(currentAccount).publicLinksLimitPremium; + limitParams.icon = R.drawable.msg_limit_links; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedPublicLinks", R.string.LimitReachedPublicLinks, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedPublicLinksPremium", R.string.LimitReachedPublicLinksPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedPublicLinksLocked", R.string.LimitReachedPublicLinksLocked, limitParams.defaultLimit); + } else if (type == TYPE_FOLDERS) { + limitParams.defaultLimit = MessagesController.getInstance(currentAccount).dialogFiltersLimitDefault; + limitParams.premiumLimit = MessagesController.getInstance(currentAccount).dialogFiltersLimitPremium; + limitParams.icon = R.drawable.msg_limit_folder; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedFolders", R.string.LimitReachedFolders, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedFoldersPremium", R.string.LimitReachedFoldersPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedFoldersLocked", R.string.LimitReachedFoldersLocked, limitParams.defaultLimit); + } else if (type == TYPE_CHATS_IN_FOLDER) { + limitParams.defaultLimit = MessagesController.getInstance(currentAccount).dialogFiltersChatsLimitDefault; + limitParams.premiumLimit = MessagesController.getInstance(currentAccount).dialogFiltersChatsLimitPremium; + limitParams.icon = R.drawable.msg_limit_chats; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedChatInFolders", R.string.LimitReachedChatInFolders, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedChatInFoldersPremium", R.string.LimitReachedChatInFoldersPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedChatInFoldersLocked", R.string.LimitReachedChatInFoldersLocked, limitParams.defaultLimit); + } else if (type == TYPE_TO_MANY_COMMUNITIES) { + limitParams.defaultLimit = MessagesController.getInstance(currentAccount).channelsLimitDefault; + limitParams.premiumLimit = MessagesController.getInstance(currentAccount).channelsLimitPremium; + limitParams.icon = R.drawable.msg_limit_groups; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedCommunities", R.string.LimitReachedCommunities, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedCommunitiesPremium", R.string.LimitReachedCommunitiesPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedCommunitiesLocked", R.string.LimitReachedCommunitiesLocked, limitParams.defaultLimit); + } else if (type == TYPE_LARGE_FILE) { + limitParams.defaultLimit = 100; + limitParams.premiumLimit = 200; + limitParams.icon = R.drawable.msg_limit_folder; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedFileSize", R.string.LimitReachedFileSize, "2 GB", "4 GB"); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedFileSizePremium", R.string.LimitReachedFileSizePremium, "4 GB"); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedFileSizeLocked", R.string.LimitReachedFileSizeLocked, "2 GB"); + } else if (type == TYPE_ACCOUNTS) { + limitParams.defaultLimit = 3; + limitParams.premiumLimit = 4; + limitParams.icon = R.drawable.msg_limit_accounts; + limitParams.descriptionStr = LocaleController.formatString("LimitReachedAccounts", R.string.LimitReachedAccounts, limitParams.defaultLimit, limitParams.premiumLimit); + limitParams.descriptionStrPremium = LocaleController.formatString("LimitReachedAccountsPremium", R.string.LimitReachedAccountsPremium, limitParams.premiumLimit); + limitParams.descriptionStrLocked = LocaleController.formatString("LimitReachedAccountsPremium", R.string.LimitReachedAccountsPremium, limitParams.defaultLimit); + } + return limitParams; + } + + boolean loadingAdminedChannels; + + private void loadAdminedChannels() { + loadingAdminedChannels = true; + loading = true; + updateRows(); + TLRPC.TL_channels_getAdminedPublicChannels req = new TLRPC.TL_channels_getAdminedPublicChannels(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + loadingAdminedChannels = false; + if (response != null) { + TLRPC.TL_messages_chats res = (TLRPC.TL_messages_chats) response; + chats.clear(); + chats.addAll(res.chats); + loading = false; + enterAnimator.showItemsAnimated(chatsTitleRow + 4); + int savedTop = 0; + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + if (recyclerListView.getChildAt(i) instanceof HeaderView) { + savedTop = recyclerListView.getChildAt(i).getTop(); + break; + } + } + updateRows(); + if (headerRow >= 0 && savedTop != 0) { + ((LinearLayoutManager) recyclerListView.getLayoutManager()).scrollToPositionWithOffset(headerRow + 1, savedTop); + } + } + + int currentValue = Math.max(chats.size(), limitParams.defaultLimit); + limitPreviewView.setIconValue(currentValue); + limitPreviewView.setBagePosition(currentValue / (float) limitParams.premiumLimit); + limitPreviewView.startDelayedAnimation(); + })); + } + + private void updateRows() { + rowCount = 0; + dividerRow = -1; + chatStartRow = -1; + loadingRow = -1; + headerRow = rowCount++; + if (!hasFixedSize(type)) { + dividerRow = rowCount++; + chatsTitleRow = rowCount++; + if (loading) { + loadingRow = rowCount++; + } else { + chatStartRow = rowCount; + if (type == TYPE_TO_MANY_COMMUNITIES) { + rowCount += inactiveChats.size(); + } else { + rowCount += chats.size(); + } + } + } + notifyDataSetChanged(); + } + + + private void revokeSelectedLinks() { + final ArrayList channels = new ArrayList<>(selectedChats); + revokeLinks(channels); + } + + private void revokeLinks(ArrayList channels) { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(LocaleController.formatPluralString("RevokeLinks", channels.size())); + if (channels.size() == 1) { + TLRPC.Chat channel = channels.get(0); + if (parentIsChannel) { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("RevokeLinkAlertChannel", R.string.RevokeLinkAlertChannel, MessagesController.getInstance(currentAccount).linkPrefix + "/" + channel.username, channel.title))); + } else { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("RevokeLinkAlert", R.string.RevokeLinkAlert, MessagesController.getInstance(currentAccount).linkPrefix + "/" + channel.username, channel.title))); + } + } else { + if (parentIsChannel) { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("RevokeLinksAlertChannel", R.string.RevokeLinksAlertChannel))); + } else { + builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("RevokeLinksAlert", R.string.RevokeLinksAlert))); + } + } + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + builder.setPositiveButton(LocaleController.getString("RevokeButton", R.string.RevokeButton), (dialogInterface, interface2) -> { + dismiss(); + for (int i = 0; i < channels.size(); i++) { + TLRPC.TL_channels_updateUsername req1 = new TLRPC.TL_channels_updateUsername(); + TLRPC.Chat channel = channels.get(i); + req1.channel = MessagesController.getInputChannel(channel); + req1.username = ""; + ConnectionsManager.getInstance(currentAccount).sendRequest(req1, (response1, error1) -> { + if (response1 instanceof TLRPC.TL_boolTrue) { + AndroidUtilities.runOnUIThread(onSuccessRunnable); + } + }, ConnectionsManager.RequestFlagInvokeAfter); + } + }); + AlertDialog alertDialog = builder.create(); + alertDialog.show(); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + } + + private void loadInactiveChannels() { + loading = true; + updateRows(); + TLRPC.TL_channels_getInactiveChannels inactiveChannelsRequest = new TLRPC.TL_channels_getInactiveChannels(); + ConnectionsManager.getInstance(currentAccount).sendRequest(inactiveChannelsRequest, ((response, error) -> { + 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++) { + TLRPC.Chat chat = chats.chats.get(i); + int currentDate = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + int date = chats.dates.get(i); + int daysDif = (currentDate - date) / 86400; + + String dateFormat; + if (daysDif < 30) { + dateFormat = LocaleController.formatPluralString("Days", daysDif); + } else if (daysDif < 365) { + dateFormat = LocaleController.formatPluralString("Months", daysDif / 30); + } else { + dateFormat = LocaleController.formatPluralString("Years", daysDif / 365); + } + if (ChatObject.isMegagroup(chat)) { + String members = LocaleController.formatPluralString("Members", chat.participants_count); + signatures.add(LocaleController.formatString("InactiveChatSignature", R.string.InactiveChatSignature, members, dateFormat)); + } else if (ChatObject.isChannel(chat)) { + signatures.add(LocaleController.formatString("InactiveChannelSignature", R.string.InactiveChannelSignature, dateFormat)); + } else { + String members = LocaleController.formatPluralString("Members", chat.participants_count); + signatures.add(LocaleController.formatString("InactiveChatSignature", R.string.InactiveChatSignature, members, dateFormat)); + } + } + AndroidUtilities.runOnUIThread(() -> { + inactiveChatsSignatures.clear(); + inactiveChats.clear(); + inactiveChatsSignatures.addAll(signatures); + inactiveChats.addAll(chats.chats); + loading = false; + enterAnimator.showItemsAnimated(chatsTitleRow + 4); + int savedTop = 0; + for (int i = 0; i < recyclerListView.getChildCount(); i++) { + if (recyclerListView.getChildAt(i) instanceof HeaderView) { + savedTop = recyclerListView.getChildAt(i).getTop(); + break; + } + } + updateRows(); + if (headerRow >= 0 && savedTop != 0) { + ((LinearLayoutManager) recyclerListView.getLayoutManager()).scrollToPositionWithOffset(headerRow + 1, savedTop); + } + + int currentValue = Math.max(inactiveChats.size(), limitParams.defaultLimit); + limitPreviewView.setIconValue(currentValue); + limitPreviewView.setBagePosition(currentValue / (float) limitParams.premiumLimit); + limitPreviewView.startDelayedAnimation(); + }); + } + })); + } + + public static class LimitParams { + int icon = 0; + String descriptionStr = null; + String descriptionStrPremium = null; + String descriptionStrLocked = null; + int defaultLimit = 0; + int premiumLimit = 0; + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/MatrixParticlesDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/MatrixParticlesDrawable.java new file mode 100644 index 000000000..6b297113d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/MatrixParticlesDrawable.java @@ -0,0 +1,163 @@ +package org.telegram.ui.Components.Premium; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.text.TextPaint; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + + +public class MatrixParticlesDrawable { + + RectF excludeRect = new RectF(); + Bitmap[] bitmaps = new Bitmap[16]; + + int size; + Rect drawingRect = new Rect(); + ArrayList[] particles; + MatrixTextParticle[][] matrixTextParticles; + Paint paint = new Paint(); + + void init() { + size = AndroidUtilities.dp(16); + TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); + textPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rcondensedbold.ttf")); + textPaint.setTextSize(size); + textPaint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumStartSmallStarsColor2), 30)); + textPaint.setTextAlign(Paint.Align.CENTER); + for (int i = 0; i < 16; i++) { + char c = (char) (i < 10 ? ('0' + i) : ('A' + (i - 10))); + bitmaps[i] = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmaps[i]); + canvas.drawText(Character.toString(c), size >> 1, size, textPaint); + } + } + + void onDraw(Canvas canvas) { + int nx = drawingRect.width() / size; + int ny = drawingRect.height() / size; + if (nx == 0 || ny == 0) { + return; + } + long currentTime = System.currentTimeMillis(); + if (particles == null || particles.length != nx + 1) { + particles = new ArrayList[nx + 1]; + for (int x = 0; x <= nx; x++) { + particles[x] = new ArrayList<>(); + Particle particle = new Particle(); + particle.init(ny, currentTime); + particles[x].add(particle); + } + } + + if (matrixTextParticles == null || matrixTextParticles.length != nx + 1 || matrixTextParticles[0].length != ny + 1) { + matrixTextParticles = new MatrixTextParticle[nx + 1][]; + for (int x = 0; x <= nx; x++) { + matrixTextParticles[x] = new MatrixTextParticle[ny + 1]; + for (int y = 0; y <= ny; y++) { + matrixTextParticles[x][y] = new MatrixTextParticle(); + matrixTextParticles[x][y].init(currentTime); + } + } + } + + + for (int x = 0; x <= nx; x++) { + ArrayList list = particles[x]; + for (int i = 0; i < list.size(); i++) { + Particle particle = list.get(i); + if (currentTime - particle.time > 50) { + particle.y++; + particle.time = currentTime; + if (particle.y - particle.len >= ny) { + if (list.size() == 1) { + particle.reset(currentTime); + } else { + list.remove(particle); + i--; + } + } + if (particle.y > particle.len && i == list.size() - 1 && Math.abs(Utilities.fastRandom.nextInt(4)) == 0) { + Particle newParticle = new Particle(); + newParticle.reset(currentTime); + list.add(newParticle); + } + } + int n = Math.min(particle.y, ny + 1); + for (int y = Math.max(0, particle.y - particle.len); y < n; y++) { + float finalX = size * x; + float finalY = size * y; + if (!excludeRect.contains(finalX, finalY)) { + float alpha = Utilities.clamp(0.2f + 0.8f * (1f - (particle.y - y) / (float) (particle.len - 1)), 1f, 0f); + matrixTextParticles[x][y].draw(canvas, finalX, finalY, currentTime, alpha); + } + } + } +// for (int y = 0; y <= ny; y++) { +// matrixTextParticles[x][y].draw(canvas, size * x, size * y, currentTime); +// } + } + } + + private class Particle { + int y; + int len = 5; + long time; + + public void init(int ny, long currentTime) { + y = Math.abs(Utilities.fastRandom.nextInt() % ny); + time = currentTime; + len = 4 + Math.abs(Utilities.fastRandom.nextInt() % 6); + } + + public void reset(long currentTime) { + y = 0; + time = currentTime; + len = 4 + Math.abs(Utilities.fastRandom.nextInt() % 6); + } + } + + private class MatrixTextParticle { + int index; + int nextIndex; + long lastUpdateTime; + long nextUpdateTime; + + public void init(long time) { + index = Math.abs(Utilities.fastRandom.nextInt() % 16); + nextIndex = Math.abs(Utilities.fastRandom.nextInt() % 16); + lastUpdateTime = time; + nextUpdateTime = time + Math.abs(Utilities.fastRandom.nextInt() % 300) + 150; + } + + public void draw(Canvas canvas, float x, float y, long currentTime, float alpha) { + if (nextUpdateTime - currentTime < 150) { + float p = Utilities.clamp(1f - (nextUpdateTime - currentTime) / 150f, 1f, 0); + paint.setAlpha((int) ((1f - p) * alpha * 255)); + canvas.drawBitmap(bitmaps[index], x, y, paint); + paint.setAlpha((int) (p * alpha * 255)); + canvas.drawBitmap(bitmaps[nextIndex], x, y, paint); + paint.setAlpha(255); + if (p >= 1) { + index = nextIndex; + lastUpdateTime = currentTime; + nextIndex = Math.abs(Utilities.fastRandom.nextInt() % 16); + nextUpdateTime = currentTime + Math.abs(Utilities.fastRandom.nextInt() % 300) + 150; + } + } else { + paint.setAlpha((int) (alpha * 255)); + canvas.drawBitmap(bitmaps[index], x, y, paint); + } + + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PagerHeaderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PagerHeaderView.java new file mode 100644 index 000000000..df03e5fe8 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PagerHeaderView.java @@ -0,0 +1,5 @@ +package org.telegram.ui.Components.Premium; + +public interface PagerHeaderView { + void setOffset(float v); +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumAppIconsPreviewView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumAppIconsPreviewView.java new file mode 100644 index 000000000..198875d97 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumAppIconsPreviewView.java @@ -0,0 +1,126 @@ +package org.telegram.ui.Components.Premium; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.view.Gravity; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.Utilities; +import org.telegram.ui.Cells.AppIconsSelectorCell; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.LauncherIconController; + +import java.util.ArrayList; +import java.util.List; + +public class PremiumAppIconsPreviewView extends FrameLayout implements PagerHeaderView { + private List icons = new ArrayList<>(); + private AppIconsSelectorCell.AdaptiveIconImageView topIcon, bottomLeftIcon, bottomRightIcon; + boolean isEmpty; + + public PremiumAppIconsPreviewView(Context context) { + super(context); + + for (LauncherIconController.LauncherIcon icon : LauncherIconController.LauncherIcon.values()) { + if (icon.premium) { + icons.add(icon); + } + if (icons.size() == 3) { + break; + } + } + + if (icons.size() < 3) { + FileLog.e(new IllegalArgumentException("There should be at least 3 premium icons!")); + isEmpty = true; + return; + } + + topIcon = newIconView(context, icons.get(0)); + bottomLeftIcon = newIconView(context, icons.get(1)); + bottomRightIcon = newIconView(context, icons.get(2)); + } + + private AppIconsSelectorCell.AdaptiveIconImageView newIconView(Context ctx, LauncherIconController.LauncherIcon icon) { + AppIconsSelectorCell.AdaptiveIconImageView iconImageView = new AppIconsSelectorCell.AdaptiveIconImageView(ctx) { + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + { + paint.setColor(Color.WHITE); + } + + @Override + public void draw(Canvas canvas) { + AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(AppIconsSelectorCell.ICONS_ROUND_RADIUS), AndroidUtilities.dp(AppIconsSelectorCell.ICONS_ROUND_RADIUS), paint); + + super.draw(canvas); + } + }; + iconImageView.setLayoutParams(LayoutHelper.createFrame(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER, 0, 52, 0, 0)); + iconImageView.setForeground(icon.foreground); + iconImageView.setBackgroundResource(icon.background); + iconImageView.setPadding(AndroidUtilities.dp(8)); + iconImageView.setBackgroundOuterPadding(AndroidUtilities.dp(32)); + addView(iconImageView); + return iconImageView; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (isEmpty) { + return; + } + int minSide = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)); + int size = AndroidUtilities.dp(76); + LayoutParams params = (LayoutParams) topIcon.getLayoutParams(); + params.width = params.height = size; + params.bottomMargin = (int) (size + minSide * 0.1f); + + params = (LayoutParams) bottomLeftIcon.getLayoutParams(); + params.width = params.height = size; + params.rightMargin = (int) (size * 0.95f); + + params = (LayoutParams) bottomRightIcon.getLayoutParams(); + params.width = params.height = size; + params.leftMargin = (int) (size * 0.95f); + } + + @Override + public void setOffset(float translationX) { + if (isEmpty) { + return; + } + float progress = translationX / getMeasuredWidth(); + + float rightProgress = CubicBezierInterpolator.EASE_IN.getInterpolation(progress); + bottomRightIcon.setTranslationX(rightProgress * (getRight() - bottomRightIcon.getRight() + bottomRightIcon.getWidth() * 1.5f + AndroidUtilities.dp(32))); + bottomRightIcon.setTranslationY(rightProgress * AndroidUtilities.dp(16)); + float scale = AndroidUtilities.lerp(1f, 1.5f, rightProgress); + scale = Utilities.clamp(scale, 1f, 0); + bottomRightIcon.setScaleX(scale); + bottomRightIcon.setScaleY(scale); + + topIcon.setTranslationY(progress * (getTop() - topIcon.getTop() - topIcon.getHeight() * 1.8f - AndroidUtilities.dp(32))); + topIcon.setTranslationX(progress * AndroidUtilities.dp(16)); + scale = AndroidUtilities.lerp(1f, 1.8f, progress); + scale = Utilities.clamp(scale, 1f, 0); + topIcon.setScaleX(scale); + topIcon.setScaleY(scale); + + float leftProgress = CubicBezierInterpolator.EASE_OUT.getInterpolation(progress); + bottomLeftIcon.setTranslationX(leftProgress * (getLeft() - bottomLeftIcon.getLeft() - bottomLeftIcon.getWidth() * 2.5f + AndroidUtilities.dp(32))); + bottomLeftIcon.setTranslationY(leftProgress * (getBottom() - bottomLeftIcon.getBottom() + bottomLeftIcon.getHeight() * 2.5f + AndroidUtilities.dp(32))); + scale = AndroidUtilities.lerp(1f, 2.5f, progress); + scale = Utilities.clamp(scale, 1f, 0); + bottomLeftIcon.setScaleX(scale); + bottomLeftIcon.setScaleY(scale); + } +} 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 new file mode 100644 index 000000000..e8a53bff2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumButtonView.java @@ -0,0 +1,211 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.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; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieImageView; +import org.telegram.ui.Components.voip.CellFlickerDrawable; + +public class PremiumButtonView extends FrameLayout { + + private Paint paintOverlayPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + private float progress; + private boolean inc; + public TextView buttonTextView; + public TextView overlayTextView; + + private boolean showOverlay; + private float overlayProgress; + public FrameLayout buttonLayout; + ValueAnimator overlayAnimator; + + Path path = new Path(); + CellFlickerDrawable flickerDrawable; + private boolean drawOverlayColor; + + RLottieImageView iconView; + + public PremiumButtonView(@NonNull Context context, boolean createOverlayTextView) { + super(context); + flickerDrawable = new CellFlickerDrawable(); + flickerDrawable.animationSpeedScale = 1.2f; + flickerDrawable.drawFrame = false; + flickerDrawable.repeatProgress = 4f; + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.HORIZONTAL); + buttonTextView = new TextView(context); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(Color.WHITE); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + iconView = new RLottieImageView(context); + iconView.setColorFilter(Color.WHITE); + iconView.setVisibility(View.GONE); + + buttonLayout = new FrameLayout(context); + buttonLayout.addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER)); + buttonLayout.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 120))); + + linearLayout.addView(buttonTextView, LayoutHelper.createLinear(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + linearLayout.addView(iconView, LayoutHelper.createLinear(24, 24, 0, Gravity.CENTER_VERTICAL, 4, 0, 0, 0)); + addView(buttonLayout); + + if (createOverlayTextView) { + overlayTextView = new TextView(context); + overlayTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + overlayTextView.setGravity(Gravity.CENTER); + overlayTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + overlayTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + overlayTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + overlayTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, 120))); + addView(overlayTextView); + + paintOverlayPaint.setColor(Theme.getColor(Theme.key_featuredStickers_addButton)); + updateOverlayProgress(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (overlayProgress != 1f || !drawOverlayColor) { + if (inc) { + progress += 16f / 1000f; + if (progress > 3) { + inc = false; + } + } else { + progress -= 16f / 1000f; + if (progress < 1) { + inc = true; + } + } + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), PremiumGradient.getInstance().getMainGradientPaint()); + invalidate(); + } + + if (!BuildVars.IS_BILLING_UNAVAILABLE) { + flickerDrawable.setParentWidth(getMeasuredWidth()); + flickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(8), null); + } + + if (overlayProgress != 0 && drawOverlayColor) { + paintOverlayPaint.setAlpha((int) (255 * overlayProgress)); + if (overlayProgress != 1f) { + path.rewind(); + path.addCircle(getMeasuredWidth() / 2f, getMeasuredHeight() / 2f, Math.max(getMeasuredWidth(), getMeasuredHeight()) * 1.4f * overlayProgress, Path.Direction.CW); + canvas.save(); + canvas.clipPath(path); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), paintOverlayPaint); + canvas.restore(); + } else { + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), paintOverlayPaint); + } + + } + + super.dispatchDraw(canvas); + } + + public void setOverlayText(String text, boolean drawOverlayColor, boolean animated) { + showOverlay = true; + this.drawOverlayColor = drawOverlayColor; + overlayTextView.setText(text); + updateOverlay(animated); + } + + + private void updateOverlay(boolean animated) { + if (overlayAnimator != null) { + overlayAnimator.removeAllListeners(); + overlayAnimator.cancel(); + } + if (!animated) { + overlayProgress = showOverlay ? 1f : 0; + updateOverlayProgress(); + return; + } + overlayAnimator = ValueAnimator.ofFloat(overlayProgress, showOverlay ? 1f : 0); + overlayAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + overlayProgress = (float) animation.getAnimatedValue(); + updateOverlayProgress(); + } + }); + overlayAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + overlayProgress = showOverlay ? 1f : 0f; + updateOverlayProgress(); + } + }); + overlayAnimator.setDuration(250); + overlayAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + overlayAnimator.start(); + } + + private void updateOverlayProgress() { + overlayTextView.setAlpha(overlayProgress); + overlayTextView.setTranslationY(AndroidUtilities.dp(12) * (1f - overlayProgress)); + buttonLayout.setAlpha(1f - overlayProgress); + buttonLayout.setTranslationY(-AndroidUtilities.dp(12) * (overlayProgress)); + buttonLayout.setVisibility(overlayProgress == 1f ? View.INVISIBLE : View.VISIBLE); + overlayTextView.setVisibility(overlayProgress == 0 ? View.INVISIBLE : View.VISIBLE); + invalidate(); + } + + public void clearOverlayText() { + showOverlay = false; + updateOverlay(true); + } + + public void setIcon(int id) { + iconView.setAnimation(id, 24, 24); + flickerDrawable.progress = 2f; + flickerDrawable.setOnRestartCallback(() -> { + iconView.getAnimatedDrawable().setCurrentFrame(0, true); + iconView.playAnimation(); + }); + invalidate(); + iconView.setVisibility(View.VISIBLE); + } + + public void hideIcon() { + flickerDrawable.setOnRestartCallback(null); + iconView.setVisibility(View.GONE); + } + + public void setButton(String text, View.OnClickListener clickListener) { + buttonTextView.setText(text); + buttonLayout.setOnClickListener(clickListener); + } +} 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 new file mode 100644 index 000000000..9fcde5d80 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumFeatureBottomSheet.java @@ -0,0 +1,518 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.os.Bundle; +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.ImageView; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.UserConfig; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ChatActivity; +import org.telegram.ui.Components.BottomPagesView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RLottieDrawable; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; + +public class PremiumFeatureBottomSheet extends BottomSheet implements NotificationCenter.NotificationCenterDelegate { + + BaseFragment fragment; + + private PremiumButtonView premiumButtonView; + ArrayList premiumFeatures = new ArrayList<>(); + + float containerViewsProgress; + boolean containerViewsForward; + ViewPager viewPager; + FrameLayout content; + int contentHeight; + + private FrameLayout buttonContainer; + boolean enterAnimationIsRunning; + SvgHelper.SvgDrawable svgIcon; + private final int startType; + private final boolean onlySelectedType; + + public PremiumFeatureBottomSheet(BaseFragment fragment, int startType, boolean onlySelectedType) { + super(fragment.getParentActivity(), false); + this.fragment = fragment; + this.startType = startType; + this.onlySelectedType = onlySelectedType; + + String svg = RLottieDrawable.readRes(null, R.raw.star_loader); + svgIcon = SvgHelper.getDrawable(svg); + Context context = fragment.getParentActivity(); + FrameLayout frameLayout = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (isPortrait) { + contentHeight = MeasureSpec.getSize(widthMeasureSpec); + } else { + contentHeight = (int) (MeasureSpec.getSize(heightMeasureSpec) * 0.65f); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + }; + + + PremiumPreviewFragment.fillPremiumFeaturesList(premiumFeatures, fragment.getCurrentAccount()); + + int selectedPosition = 0; + for (int i = 0; i < premiumFeatures.size(); i++) { + if (premiumFeatures.get(i).type == PremiumPreviewFragment.PREMIUM_FEATURE_LIMITS) { + premiumFeatures.remove(i); + i--; + continue; + } + if (premiumFeatures.get(i).type == startType) { + selectedPosition = i; + break; + } + } + + if (onlySelectedType) { + PremiumPreviewFragment.PremiumFeatureData selectedFeature = premiumFeatures.get(selectedPosition); + premiumFeatures.clear(); + premiumFeatures.add(selectedFeature); + selectedPosition = 0; + } + + PremiumPreviewFragment.PremiumFeatureData featureData = premiumFeatures.get(selectedPosition); + + setApplyBottomPadding(false); + useBackgroundTopPadding = false; + PremiumGradient.GradientTools gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradientBottomSheet1, Theme.key_premiumGradientBottomSheet2, Theme.key_premiumGradientBottomSheet3, null); + gradientTools.x1 = 0; + gradientTools.y1 = 1.1f; + gradientTools.x2 = 1.5f; + gradientTools.y2 = -0.2f; + gradientTools.exactly = true; + content = new FrameLayout(context) { + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int h = contentHeight; + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h + AndroidUtilities.dp(2), MeasureSpec.EXACTLY)); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), 0, 0); + AndroidUtilities.rectTmp.set(0, AndroidUtilities.dp(2), getMeasuredWidth(), getMeasuredHeight() + AndroidUtilities.dp(18)); + canvas.save(); + canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(12) - 1, AndroidUtilities.dp(12) - 1, gradientTools.paint); + canvas.restore(); + super.dispatchDraw(canvas); + } + }; + + FrameLayout closeLayout = new FrameLayout(context); + ImageView closeImage = new ImageView(context); + closeImage.setImageResource(R.drawable.msg_close); + closeImage.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(12), ColorUtils.setAlphaComponent(Color.WHITE, 40), ColorUtils.setAlphaComponent(Color.WHITE, 100))); + closeLayout.addView(closeImage, LayoutHelper.createFrame(24, 24, Gravity.CENTER)); + closeLayout.setOnClickListener(v -> dismiss()); + frameLayout.addView(content, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 16, 0, 0)); + + viewPager = new ViewPager(context) { + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int h = AndroidUtilities.dp(100); + if (getChildCount() > 0) { + getChildAt(0).measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + h = getChildAt(0).getMeasuredHeight(); + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY)); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + try { + return super.onInterceptTouchEvent(ev); + } catch (Exception e) { + return false; + } + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + if (enterAnimationIsRunning) { + return false; + } + return super.onTouchEvent(ev); + } + }; + viewPager.setOffscreenPageLimit(0); + PagerAdapter pagerAdapter = new PagerAdapter() { + @Override + public int getCount() { + return premiumFeatures.size(); + } + + @NonNull + @Override + public Object instantiateItem(@NonNull ViewGroup container, int position) { + ViewPage viewPage = new ViewPage(context, position); + container.addView(viewPage); + viewPage.position = position; + viewPage.setFeatureDate(premiumFeatures.get(position)); + return viewPage; + } + + @Override + public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + container.removeView((View) object); + } + + @Override + public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { + return view == object; + } + }; + viewPager.setAdapter(pagerAdapter); + viewPager.setCurrentItem(selectedPosition); + frameLayout.addView(viewPager, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 100, 0, 0, 18, 0, 0)); + + frameLayout.addView(closeLayout, LayoutHelper.createFrame(52, 52, Gravity.RIGHT | Gravity.TOP, 0, 16, 0, 0)); + BottomPagesView bottomPages = new BottomPagesView(context, viewPager, premiumFeatures.size()); + viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { + + int selectedPosition; + int toPosition; + float progress; + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + bottomPages.setPageOffset(position, positionOffset); + selectedPosition = position; + toPosition = positionOffsetPixels > 0 ? selectedPosition + 1 : selectedPosition - 1; + progress = positionOffset; + checkPage(); + } + + @Override + public void onPageSelected(int i) { + checkPage(); + } + + private void checkPage() { + for (int i = 0; i < viewPager.getChildCount(); i++) { + ViewPage page = (ViewPage) viewPager.getChildAt(i); + float offset = 0; + if (!enterAnimationIsRunning || !(page.topView instanceof PremiumAppIconsPreviewView)) { + if (page.position == selectedPosition) { + page.topHeader.setOffset(offset = -page.getMeasuredWidth() * progress); + } else if (page.position == toPosition) { + page.topHeader.setOffset(offset = -page.getMeasuredWidth() * progress + page.getMeasuredWidth()); + } else { + page.topHeader.setOffset(page.getMeasuredWidth()); + } + } + + if (page.topView instanceof PremiumAppIconsPreviewView) { + page.setTranslationX(-offset); + page.title.setTranslationX(offset); + page.description.setTranslationX(offset); + } + } + containerViewsProgress = progress; + containerViewsForward = toPosition > selectedPosition; + } + + @Override + public void onPageScrollStateChanged(int i) { + + } + }); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.addView(frameLayout); + linearLayout.setOrientation(LinearLayout.VERTICAL); + bottomPages.setColor(Theme.key_chats_unreadCounterMuted, Theme.key_chats_actionBackground); + if (!onlySelectedType) { + linearLayout.addView(bottomPages, LayoutHelper.createLinear(11 * premiumFeatures.size(), 5, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 10)); + } + premiumButtonView = new PremiumButtonView(context, true); + premiumButtonView.buttonLayout.setOnClickListener(v -> { + if (fragment.getVisibleDialog() != null) { + fragment.getVisibleDialog().dismiss(); + } + if (fragment instanceof ChatActivity) { + ((ChatActivity) fragment).closeMenu(); + } + if (onlySelectedType) { + fragment.presentFragment(new PremiumPreviewFragment(PremiumPreviewFragment.featureTypeToServerString(featureData.type))); + } else { + PremiumPreviewFragment.buyPremium(fragment, PremiumPreviewFragment.featureTypeToServerString(featureData.type)); + } + dismiss(); + }); + premiumButtonView.overlayTextView.setOnClickListener(v -> { + dismiss(); + }); + buttonContainer = new FrameLayout(context); + + buttonContainer.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + buttonContainer.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + linearLayout.addView(buttonContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM)); + + if (UserConfig.getInstance(currentAccount).isPremium()) { + premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), false, false); + } + + ScrollView scrollView = new ScrollView(context); + scrollView.addView(linearLayout); + setCustomView(scrollView); + + MediaDataController.getInstance(currentAccount).preloadPremiumPreviewStickers(); + setButtonText(); + } + + private void setButtonText() { + if (onlySelectedType) { + if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { + premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumReactions)); + premiumButtonView.setIcon(R.raw.unlock_icon); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.AboutTelegramPremium)); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { + premiumButtonView.buttonTextView.setText(LocaleController.getString(R.string.UnlockPremiumIcons)); + premiumButtonView.setIcon(R.raw.unlock_icon); + } + } else { + premiumButtonView.buttonTextView.setText(PremiumPreviewFragment.getPremiumButtonText(currentAccount)); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.premiumPromoUpdated); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + public void dismiss() { + super.dismiss(); + + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.premiumPromoUpdated); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.billingProductDetailsUpdated || id == NotificationCenter.premiumPromoUpdated) { + setButtonText(); + } else if (id == NotificationCenter.currentUserPremiumStatusChanged) { + if (UserConfig.getInstance(currentAccount).isPremium()) { + premiumButtonView.setOverlayText(LocaleController.getString("OK", R.string.OK), false, true); + } else { + premiumButtonView.clearOverlayText(); + } + } + } + + + private class ViewPage extends LinearLayout { + + public int position; + TextView title; + TextView description; + PagerHeaderView topHeader; + View topView; + + public ViewPage(Context context, int p) { + super(context); + setOrientation(VERTICAL); + topView = getViewForPosition(context, p); + addView(topView); + topHeader = (PagerHeaderView) topView; + + title = new TextView(context); + title.setGravity(Gravity.CENTER_HORIZONTAL); + title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 20, 21, 0)); + + description = new TextView(context); + description.setGravity(Gravity.CENTER_HORIZONTAL); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + description.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + if (!onlySelectedType) { + description.setLines(2); + } + addView(description, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 10, 21, 16)); + setClipChildren(false); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + topView.getLayoutParams().height = contentHeight; + description.setVisibility(isPortrait ? View.VISIBLE : View.GONE); + MarginLayoutParams layoutParams = (MarginLayoutParams) title.getLayoutParams(); + if (isPortrait) { + layoutParams.topMargin = AndroidUtilities.dp(20); + layoutParams.bottomMargin = 0; + } else { + layoutParams.topMargin = AndroidUtilities.dp(10); + layoutParams.bottomMargin = AndroidUtilities.dp(10); + } + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == topView) { + if (child instanceof CarouselView) { + return super.drawChild(canvas, child, drawingTime); + } + canvas.save(); + canvas.clipRect(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); + boolean b = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return b; + } else { + return super.drawChild(canvas, child, drawingTime); + } + } + + void setFeatureDate(PremiumPreviewFragment.PremiumFeatureData featureData) { + + if (onlySelectedType) { + if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { + title.setText(LocaleController.getString("AdditionalReactions", R.string.AdditionalReactions)); + description.setText(LocaleController.getString("AdditionalReactionsDescription", R.string.AdditionalReactionsDescription)); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + title.setText(LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds)); + description.setText(LocaleController.getString("PremiumPreviewNoAdsDescription2", R.string.PremiumPreviewNoAdsDescription2)); + } else if (startType == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { + title.setText(LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon)); + description.setText(LocaleController.getString("PremiumPreviewAppIconDescription2", R.string.PremiumPreviewAppIconDescription2)); + } + } else { + title.setText(featureData.title); + description.setText(featureData.description); + } + } + } + + View getViewForPosition(Context context, int position) { + PremiumPreviewFragment.PremiumFeatureData featureData = premiumFeatures.get(position); + if (featureData.type == PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS) { + ArrayList drawingObjects = new ArrayList<>(); + List list = MediaDataController.getInstance(currentAccount).getEnabledReactionsList(); + List premiumLockedReactions = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + if (list.get(i).premium) { + premiumLockedReactions.add(list.get(i)); + } + } + for (int i = 0; i < premiumLockedReactions.size(); i++) { + ReactionDrawingObject drawingObject = new ReactionDrawingObject(i); + drawingObject.set(premiumLockedReactions.get(i)); + drawingObjects.add(drawingObject); + } + + HashMap sortRulesMap = new HashMap<>(); + sortRulesMap.put("\uD83D\uDC4C", 1); + sortRulesMap.put("\uD83D\uDE0D", 2); + sortRulesMap.put("\uD83E\uDD21", 3); + sortRulesMap.put("\uD83D\uDD4A", 4); + sortRulesMap.put("\uD83E\uDD71", 5); + sortRulesMap.put("\uD83E\uDD74", 6); + sortRulesMap.put("\uD83D\uDC33", 7); + Collections.sort(drawingObjects, (o1, o2) -> { + int i1 = sortRulesMap.containsKey(o1.reaction.reaction) ? sortRulesMap.get(o1.reaction.reaction) : Integer.MAX_VALUE; + int i2 = sortRulesMap.containsKey(o2.reaction.reaction) ? sortRulesMap.get(o2.reaction.reaction) : Integer.MAX_VALUE; + return i2 - i1; + }); + + CarouselView carouselView = new CarouselView(context, drawingObjects); + return carouselView; + } else if (featureData.type == PremiumPreviewFragment.PREMIUM_FEATURE_STICKERS) { + PremiumStickersPreviewRecycler recyclerListView = new PremiumStickersPreviewRecycler(context, currentAccount) { + @Override + public void setOffset(float v) { + setAutoPlayEnabled(v == 0); + super.setOffset(v); + } + }; + return recyclerListView; + } else if (featureData.type == PremiumPreviewFragment.PREMIUM_FEATURE_APPLICATION_ICONS) { + return new PremiumAppIconsPreviewView(context); + } + VideoScreenPreview preview = new VideoScreenPreview(context, svgIcon, currentAccount, featureData.type); + return preview; + } + + @Override + protected boolean onCustomOpenAnimation() { + if (viewPager.getChildCount() > 0) { + ViewPage page = (ViewPage) viewPager.getChildAt(0); + if (page.topView instanceof PremiumAppIconsPreviewView) { + PremiumAppIconsPreviewView premiumAppIconsPreviewView = (PremiumAppIconsPreviewView) page.topView; + ValueAnimator valueAnimator = ValueAnimator.ofFloat(page.getMeasuredWidth(), 0); + premiumAppIconsPreviewView.setOffset(page.getMeasuredWidth()); + enterAnimationIsRunning = true; + valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + premiumAppIconsPreviewView.setOffset((Float) animation.getAnimatedValue()); + } + }); + valueAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + enterAnimationIsRunning = false; + premiumAppIconsPreviewView.setOffset(0); + super.onAnimationEnd(animation); + } + }); + valueAnimator.setDuration(500); + valueAnimator.setStartDelay(100); + valueAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + valueAnimator.start(); + } + } + return super.onCustomOpenAnimation(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumGradient.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumGradient.java new file mode 100644 index 000000000..2a4ff24d1 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumGradient.java @@ -0,0 +1,205 @@ +package org.telegram.ui.Components.Premium; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.PorterDuffXfermode; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; + +import androidx.core.content.ContextCompat; + +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.ui.ActionBar.Theme; + +public class PremiumGradient { + + private final GradientTools mainGradient = new GradientTools(Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4); + private final Paint mainGradientPaint = mainGradient.paint; + Paint lockedPremiumPaint; + + private final static int size = 100; + private final static int sizeHalf = 100 >> 1; + + private static PremiumGradient instance; + + public Drawable premiumStarColoredDrawable; + public Drawable premiumStarDrawableMini; + public InternalDrawable premiumStarMenuDrawable; + public InternalDrawable premiumStarMenuDrawable2; + + private int lastStarColor; + + public static PremiumGradient getInstance() { + if (instance == null) { + instance = new PremiumGradient(); + } + return instance; + } + + private PremiumGradient() { + premiumStarDrawableMini = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_premium_liststar).mutate(); + premiumStarMenuDrawable = createGradientDrawable(ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_settings_premium)); + premiumStarMenuDrawable2 = createGradientDrawable(ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_premium_normal)); + premiumStarColoredDrawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_premium_liststar).mutate(); + mainGradient.chekColors(); + checkIconColors(); + } + + public InternalDrawable createGradientDrawable(Drawable drawable) { + int width = drawable.getIntrinsicWidth(); + int height = drawable.getMinimumHeight(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, width, height); + drawable.draw(canvas); + + mainGradient.paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + mainGradient.gradientMatrix(0, 0, width, height, -width, 0); + canvas.drawRect(0, 0, width, height, mainGradient.paint); + mainGradient.paint.setXfermode(null); + + return new InternalDrawable(drawable, bitmap, mainGradient.colors); + } + + public void checkIconColors() { + if (Theme.getColor(Theme.key_chats_verifiedBackground) != lastStarColor) { + lastStarColor = Theme.getColor(Theme.key_chats_verifiedBackground); + premiumStarDrawableMini.setColorFilter(new PorterDuffColorFilter(lastStarColor, PorterDuff.Mode.MULTIPLY)); + } + premiumStarMenuDrawable = checkColors(premiumStarMenuDrawable); + premiumStarMenuDrawable2 = checkColors(premiumStarMenuDrawable2); + } + + private InternalDrawable checkColors(InternalDrawable internalDrawable) { + if (mainGradient.colors[0] != internalDrawable.colors[0] || mainGradient.colors[1] != internalDrawable.colors[1] || mainGradient.colors[2] != internalDrawable.colors[2] || mainGradient.colors[3] != internalDrawable.colors[3]) { + return createGradientDrawable(internalDrawable.originDrawable); + } + return internalDrawable; + } + + public void updateMainGradientMatrix(int x, int y, int width, int height, float xOffset, float yOffset) { + mainGradient.gradientMatrix(x, y, width, height, xOffset, yOffset); + } + + public static class InternalDrawable extends BitmapDrawable { + + public int[] colors; + Drawable originDrawable; + + public InternalDrawable(Drawable originDrawable, Bitmap bitmap, int[] colors) { + super(ApplicationLoader.applicationContext.getResources(), bitmap); + this.originDrawable = originDrawable; + this.colors = new int[colors.length]; + System.arraycopy(colors, 0, this.colors, 0, colors.length); + } + + @Override + public void setColorFilter(ColorFilter colorFilter) { + + } + + @Override + public void setColorFilter(int color, PorterDuff.Mode mode) { + + } + } + + public Paint getMainGradientPaint() { + if (MessagesController.getInstance(UserConfig.selectedAccount).premiumLocked) { + if (lockedPremiumPaint == null) { + lockedPremiumPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + lockedPremiumPaint.setColor(Theme.getColor(Theme.key_featuredStickers_addButton)); + return lockedPremiumPaint; + } else { + return mainGradientPaint; + } + } + public static class GradientTools { + + public float cx = 0.5f; + public float cy = 0.5f; + Shader shader; + Matrix matrix = new Matrix(); + public final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + + final String colorKey1, colorKey2, colorKey3, colorKey4; + final int colors[] = new int[4]; + public boolean exactly; + + public float x1 = 0f, y1 = 1f, x2 = 1.5f, y2 = 0f; + + public GradientTools(String colorKey1, String colorKey2, String colorKey3, String colorKey4) { + this.colorKey1 = colorKey1; + this.colorKey2 = colorKey2; + this.colorKey3 = colorKey3; + this.colorKey4 = colorKey4; + } + + public void gradientMatrix(int x, int y, int x1, int y1, float xOffset, float yOffset) { + chekColors(); + if (exactly) { + int height = y1 - y; + float sx = (x1 - x) / (float) size; + float sy = height / (float) size; + + matrix.reset(); + matrix.postScale(sx, sy, 100 * cx, 100 * cy); + matrix.postTranslate(xOffset, yOffset); + shader.setLocalMatrix(matrix); + } else { + int height = y1 - y; + int gradientHeight = height + height; + float sx = (x1 - x) / (float) size; + float sy = gradientHeight / (float) size; + + chekColors(); + matrix.reset(); + matrix.postScale(sx, sy, 75, sizeHalf); + matrix.postTranslate(xOffset, -gradientHeight + yOffset); + shader.setLocalMatrix(matrix); + } + } + + private void chekColors() { + int c1 = Theme.getColor(colorKey1); + int c2 = Theme.getColor(colorKey2); + int c3 = colorKey3 == null ? 0 : Theme.getColor(colorKey3); + int c4 = colorKey4 == null ? 0 : Theme.getColor(colorKey4); + if (colors[0] != c1 || colors[1] != c2 || colors[2] != c3 || colors[3] != c4) { + colors[0] = c1; + colors[1] = c2; + colors[2] = c3; + colors[3] = c4; + if (c3 == 0) { + shader = new LinearGradient(size * x1, size * y1, size * x2, size * y2, new int[]{colors[0], colors[1]}, new float[]{0, 1f}, Shader.TileMode.CLAMP); + } else if (c4 == 0) { + shader = new LinearGradient(size * x1, size * y1, size * x2, size * y2, new int[]{colors[0], colors[1], colors[2]}, new float[]{0, 0.5f, 1f}, Shader.TileMode.CLAMP); + } else { + shader = new LinearGradient(size * x1, size * y1, size * x2, size * y2, new int[]{colors[0], colors[1], colors[2], colors[3]}, new float[]{0, 0.5f, 0.78f, 1f}, Shader.TileMode.CLAMP); + } + shader.setLocalMatrix(matrix); + paint.setShader(shader); + } + } + + public void gradientMatrixLinear(float totalHeight, float offset) { + chekColors(); + + matrix.reset(); + matrix.postScale(1f, totalHeight / 100f, 0, 0); + matrix.postTranslate(0, offset); + shader.setLocalMatrix(matrix); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java new file mode 100644 index 000000000..5e0e8efc9 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumLockIconView.java @@ -0,0 +1,227 @@ +package org.telegram.ui.Components.Premium; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Shader; +import android.widget.ImageView; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.voip.CellFlickerDrawable; + +public class PremiumLockIconView extends ImageView { + + public static int TYPE_REACTIONS = 0; + public static int TYPE_STICKERS_PREMIUM_LOCKED = 1; + + private final int type; + public boolean isEnter; + private float[] colorFloat = new float[3]; + StarParticlesView.Drawable starParticles; + private boolean locked; + + public PremiumLockIconView(Context context, int type) { + super(context); + this.type = type; + setImageResource(type == TYPE_REACTIONS ? R.drawable.msg_premium_lock2 : R.drawable.msg_mini_premiumlock); + if (type == TYPE_REACTIONS) { + starParticles = new StarParticlesView.Drawable(5); + starParticles.updateColors(); + starParticles.roundEffect = false; + starParticles.size3 = starParticles.size2 = 4; + starParticles.size1 = 2; + starParticles.speedScale = 0.1f; + starParticles.init(); + } + } + + int currentColor = Color.WHITE; + int color1, color2; + Shader shader = null; + + Path path = new Path(); + Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + Paint oldShaderPaint; + ImageReceiver imageReceiver; + float shaderCrossfadeProgress = 1f; + boolean waitingImage; + boolean wasDrawn; + + CellFlickerDrawable cellFlickerDrawable = new CellFlickerDrawable(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (type == TYPE_REACTIONS) { + path.rewind(); + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + path.addCircle(AndroidUtilities.rectTmp.width() / 2f, AndroidUtilities.rectTmp.centerY(), AndroidUtilities.rectTmp.width() / 2f, Path.Direction.CW); + AndroidUtilities.rectTmp.set(getMeasuredWidth() / 2f + AndroidUtilities.dp(2.5f), getMeasuredHeight() / 2f + AndroidUtilities.dpf2(5.7f), getMeasuredWidth() - AndroidUtilities.dpf2(0.2f), getMeasuredHeight()); + path.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(2f), AndroidUtilities.dp(2f), Path.Direction.CW); + path.close(); + + starParticles.rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + starParticles.rect.inset(AndroidUtilities.dp(6), AndroidUtilities.dp(6)); + } else { + updateGradient(); + } + } + + public void setColor(int color) { + if (currentColor != color) { + currentColor = color; + if (type == TYPE_REACTIONS) { + paint.setColor(color); + } else { + updateGradient(); + } + invalidate(); + } + } + + + @Override + protected void onDraw(Canvas canvas) { + if (waitingImage) { + if (imageReceiver.getBitmap() != null) { + waitingImage = false; + setColor(getDominantColor(imageReceiver.getBitmap())); + } else { + invalidate(); + } + } + if (type == TYPE_REACTIONS) { + if (currentColor != 0) { + canvas.drawPath(path, paint); + } else { + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -AndroidUtilities.dp(24), 0); + canvas.drawPath(path, PremiumGradient.getInstance().getMainGradientPaint()); + } + cellFlickerDrawable.setParentWidth(getMeasuredWidth() / 2); + cellFlickerDrawable.drawFrame = false; + cellFlickerDrawable.draw(canvas, path, this); + canvas.save(); + canvas.clipPath(path); + starParticles.onDraw(canvas); + canvas.restore(); + invalidate(); + } else { + float cx = getMeasuredWidth() / 2f; + float cy = getMeasuredHeight() / 2f; + if (oldShaderPaint == null) { + shaderCrossfadeProgress = 1f; + } + if (shaderCrossfadeProgress != 1f) { + paint.setAlpha((int) (255 * shaderCrossfadeProgress)); + canvas.drawCircle(cx, cy, cx, oldShaderPaint); + canvas.drawCircle(cx, cy, cx, paint); + shaderCrossfadeProgress += 16 / 150f; + if (shaderCrossfadeProgress > 1f) { + shaderCrossfadeProgress = 1f; + oldShaderPaint = null; + } + invalidate(); + paint.setAlpha(255); + } else { + canvas.drawCircle(cx, cy, cx, paint); + } + } + super.onDraw(canvas); + wasDrawn = true; + } + + public void setImageReceiver(ImageReceiver imageReceiver) { + this.imageReceiver = imageReceiver; + waitingImage = true; + } + + public static int getDominantColor(Bitmap bitmap) { + if (bitmap == null) { + return Color.WHITE; + } + float stepH = (bitmap.getHeight() - 1) / 10f; + float stepW = (bitmap.getWidth() - 1) / 10f; + int r = 0, g = 0, b = 0; + int amount = 0; + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + int x = (int) (stepW * i); + int y = (int) (stepH * j); + int pixel = bitmap.getPixel(x, y); + if (pixel != Color.TRANSPARENT) { + r += Color.red(pixel); + g += Color.green(pixel); + b += Color.blue(pixel); + amount++; + } + } + } + if (amount == 0) { + return 0; + } + return Color.argb(255, r / amount, g / amount, b / amount); + } + + private void updateGradient() { + if (getMeasuredHeight() != 0 && getMeasuredWidth() != 0) { + int c1 = currentColor; + int c2; + Color.colorToHSV(c1, colorFloat); + colorFloat[1] *= locked ? 2 : 1; + if (colorFloat[2] > 0.7f) { + colorFloat[2] = 0.7f; + } + int baseColor = Color.HSVToColor(colorFloat); + + c2 = ColorUtils.blendARGB(baseColor, Theme.getColor(Theme.key_windowBackgroundWhite), 0.5f); + c1 = ColorUtils.blendARGB(baseColor, Theme.getColor(Theme.key_windowBackgroundWhite), 0.4f); + + if (shader == null || color1 != c1 || color2 != c2) { + if (wasDrawn) { + oldShaderPaint = paint; + oldShaderPaint.setAlpha(255); + shaderCrossfadeProgress = 0; + } + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + shader = new LinearGradient(0, getMeasuredHeight(), 0, 0, new int[]{color1 = c1, color2 = c2}, null, Shader.TileMode.CLAMP); + paint.setShader(shader); + invalidate(); + } + } + } + + public void setWaitingImage() { + waitingImage = true; + wasDrawn = false; + invalidate(); + } + + public void play(int delay) { + isEnter = true; + cellFlickerDrawable.progress = 0; + cellFlickerDrawable.repeatEnabled = false; + invalidate(); + animate().scaleX(1.1f).scaleY(1.1f).setStartDelay(delay).setInterpolator(AndroidUtilities.overshootInterpolator).setDuration(300); + } + + public void resetAnimation() { + isEnter = false; + setScaleX(0); + setScaleY(0); + } + + public void setLocked(boolean locked) { + if (type != TYPE_REACTIONS) { + setImageResource(locked ? R.drawable.msg_mini_premiumlock : R.drawable.msg_mini_stickerstar); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumNotAvailableBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumNotAvailableBottomSheet.java new file mode 100644 index 000000000..6877ef8a7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumNotAvailableBottomSheet.java @@ -0,0 +1,72 @@ +package org.telegram.ui.Components.Premium; + +import android.content.ActivityNotFoundException; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class PremiumNotAvailableBottomSheet extends BottomSheet { + + public PremiumNotAvailableBottomSheet(BaseFragment fragment) { + super(fragment.getParentActivity(), false); + Context context = fragment.getParentActivity(); + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + TextView title = new TextView(context); + title.setGravity(Gravity.START); + title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + + linearLayout.addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 16, 21, 0)); + + TextView description = new TextView(context); + description.setGravity(Gravity.START); + description.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + description.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + linearLayout.addView(description, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 21, 15, 21, 16)); + + TextView buttonTextView = new TextView(context); + buttonTextView.setPadding(AndroidUtilities.dp(34), 0, AndroidUtilities.dp(34), 0); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 8)); + buttonTextView.setText(LocaleController.getString(R.string.InstallOfficialApp)); + buttonTextView.setOnClickListener(v -> { + try { + v.getContext().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=org.telegram.messenger"))); + } catch (ActivityNotFoundException e) { + FileLog.e(e); + } + }); + + FrameLayout buttonContainer = new FrameLayout(context); + buttonContainer.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + buttonContainer.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + linearLayout.addView(buttonContainer, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM)); + + title.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.SubscribeToPremiumOfficialAppNeeded))); + description.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.SubscribeToPremiumOfficialAppNeededDescription))); + ScrollView scrollView = new ScrollView(context); + scrollView.addView(linearLayout); + setCustomView(scrollView); + } +} 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 new file mode 100644 index 000000000..3d5f76979 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java @@ -0,0 +1,453 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.app.Dialog; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ContactsController; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.SimpleTextView; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Components.BottomSheetWithRecyclerListView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.GLIcon.GLIconRenderer; +import org.telegram.ui.Components.Premium.GLIcon.GLIconTextureView; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.PremiumFeatureCell; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; + +public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView { + + ArrayList premiumFeatures = new ArrayList<>(); + int currentAccount; + TLRPC.User user; + + PremiumFeatureCell dummyCell; + int totalGradientHeight; + + int rowCount; + int paddingRow; + int featuresStartRow; + int featuresEndRow; + int sectionRow; + int helpUsRow; + int buttonRow; + + PremiumGradient.GradientTools gradientTools; + StarParticlesView starParticlesView; + GLIconTextureView iconTextureView; + ViewGroup iconContainer; + BaseFragment fragment; + + public float startEnterFromX; + public float startEnterFromY; + public float startEnterFromX1; + public float startEnterFromY1; + public float startEnterFromScale; + public SimpleTextView startEnterFromView; + + int[] coords = new int[2]; + float enterTransitionProgress = 0; + boolean enterTransitionInProgress; + ValueAnimator enterAnimator; + + public PremiumPreviewBottomSheet(BaseFragment fragment, int currentAccount, TLRPC.User user) { + super(fragment, false, false); + this.fragment = fragment; + topPadding = 0.26f; + this.user = user; + this.currentAccount = currentAccount; + dummyCell = new PremiumFeatureCell(getContext()); + PremiumPreviewFragment.fillPremiumFeaturesList(premiumFeatures, currentAccount); + + gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4); + gradientTools.exactly = true; + gradientTools.x1 = 0; + gradientTools.y1 = 1f; + gradientTools.x2 = 0; + gradientTools.y2 = 0f; + gradientTools.cx = 0; + gradientTools.cy = 0; + + paddingRow = rowCount++; + featuresStartRow = rowCount; + rowCount += premiumFeatures.size(); + featuresEndRow = rowCount; + sectionRow = rowCount++; + if (!UserConfig.getInstance(currentAccount).isPremium()) { + buttonRow = rowCount++; + } + recyclerListView.setPadding(AndroidUtilities.dp(6), 0, AndroidUtilities.dp(6), 0); + recyclerListView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { + @Override + public void onItemClick(View view, int position) { + if (view instanceof PremiumFeatureCell) { + PremiumFeatureCell cell = (PremiumFeatureCell) view; + PremiumPreviewFragment.sentShowFeaturePreview(currentAccount, cell.data.type); + if (cell.data.type == PremiumPreviewFragment.PREMIUM_FEATURE_LIMITS) { + DoubledLimitsBottomSheet bottomSheet = new DoubledLimitsBottomSheet(fragment, currentAccount); + showDialog(bottomSheet); + } else { + showDialog(new PremiumFeatureBottomSheet(fragment, cell.data.type, false)); + } + } + } + }); + + MediaDataController.getInstance(currentAccount).preloadPremiumPreviewStickers(); + PremiumPreviewFragment.sentShowScreenStat("profile"); + } + + private void showDialog(Dialog dialog) { + iconTextureView.setDialogVisible(true); + starParticlesView.setPaused(true); + dialog.setOnDismissListener(dialog1 -> { + iconTextureView.setDialogVisible(false); + starParticlesView.setPaused(false); + }); + dialog.show(); + } + + @Override + public void onViewCreated(FrameLayout containerView) { + super.onViewCreated(containerView); + + PremiumButtonView premiumButtonView = new PremiumButtonView(getContext(), false); + premiumButtonView.setButton(PremiumPreviewFragment.getPremiumButtonText(currentAccount), new View.OnClickListener() { + @Override + public void onClick(View v) { + PremiumPreviewFragment.sentPremiumButtonClick(); + PremiumPreviewFragment.buyPremium(fragment, "profile"); + } + }); + + FrameLayout buttonContainer = new FrameLayout(getContext()); + + View buttonDivider = new View(getContext()); + buttonDivider.setBackgroundColor(Theme.getColor(Theme.key_divider)); + buttonContainer.addView(buttonDivider, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1)); + buttonDivider.getLayoutParams().height = 1; + AndroidUtilities.updateViewVisibilityAnimated(buttonDivider, true, 1f, false); + + if (!UserConfig.getInstance(currentAccount).isPremium()) { + buttonContainer.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + buttonContainer.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + containerView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM)); + } + } + + @Override + protected void onPreMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onPreMeasure(widthMeasureSpec, heightMeasureSpec); + measureGradient(View.MeasureSpec.getSize(widthMeasureSpec), View.MeasureSpec.getSize(heightMeasureSpec)); + container.getLocationOnScreen(coords); + + } + + @Override + protected CharSequence getTitle() { + return LocaleController.getString("TelegramPremium", R.string.TelegramPremium); + } + + @Override + protected RecyclerListView.SelectionAdapter createAdapter() { + return new Adapter(); + } + + private class Adapter extends RecyclerListView.SelectionAdapter { + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + case 0: + LinearLayout linearLayout = new LinearLayout(context) { + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == iconTextureView && enterTransitionInProgress) { + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + }; + iconContainer = linearLayout; + 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), Theme.getColor(Theme.key_dialogBackground), 0.5f)); + iconTextureView.setBackgroundBitmap(bitmap); + iconTextureView.mRenderer.colorKey1 = Theme.key_premiumGradient1; + iconTextureView.mRenderer.colorKey2 = Theme.key_premiumGradient2; + iconTextureView.mRenderer.updateColors(); + linearLayout.addView(iconTextureView, LayoutHelper.createLinear(160, 160, Gravity.CENTER_HORIZONTAL)); + + TextView titleView = new TextView(context); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setGravity(Gravity.CENTER_HORIZONTAL); + titleView.setText(LocaleController.getString("TelegramPremium", R.string.TelegramPremium)); + titleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + titleView.setLinkTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteLinkText)); + linearLayout.addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 40, 0, 40, 0)); + + TextView subtitleView = new TextView(context); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setGravity(Gravity.CENTER_HORIZONTAL); + subtitleView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + linearLayout.addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 9, 16, 20)); + + titleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString("TelegramPremiumUserDialogTitle", R.string.TelegramPremiumUserDialogTitle, ContactsController.formatName(user.first_name, user.last_name)), () -> { + + })); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString("TelegramPremiumUserDialogSubtitle", R.string.TelegramPremiumUserDialogSubtitle))); + + starParticlesView = new StarParticlesView(context); + FrameLayout frameLayout = new FrameLayout(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + starParticlesView.setTranslationY(iconTextureView.getTop() + iconTextureView.getMeasuredHeight() / 2f - starParticlesView.getMeasuredHeight() / 2f); + } + }; + frameLayout.setClipChildren(false); + frameLayout.addView(starParticlesView); + frameLayout.addView(linearLayout); + + starParticlesView.drawable.useGradient = true; + starParticlesView.drawable.init(); + iconTextureView.setStarParticlesView(starParticlesView); + + view = frameLayout; + break; + default: + case 1: + view = new PremiumFeatureCell(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + AndroidUtilities.rectTmp.set(imageView.getLeft(), imageView.getTop(), imageView.getRight(), imageView.getBottom()); + gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), totalGradientHeight, 0, -data.yOffset); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), gradientTools.paint); + super.dispatchDraw(canvas); + } + }; + break; + case 2: + view = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray)); + break; + case 3: + view = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(68), MeasureSpec.EXACTLY)); + } + }; + break; + case 4: + view = new AboutPremiumView(context); + 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) { + if (position >= featuresStartRow && position < featuresEndRow) { + ((PremiumFeatureCell) holder.itemView).setData(premiumFeatures.get(position - featuresStartRow), position != featuresEndRow - 1); + } + } + + @Override + public int getItemCount() { + return rowCount; + } + + @Override + public int getItemViewType(int position) { + if (position == paddingRow) { + return 0; + } else if (position >= featuresStartRow && position < featuresEndRow) { + return 1; + } else if (position == sectionRow) { + return 2; + } else if (position == buttonRow) { + return 3; + } else if (position == helpUsRow) { + return 4; + } + return super.getItemViewType(position); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == 1; + } + } + + private void measureGradient(int w, int h) { + int yOffset = 0; + for (int i = 0; i < premiumFeatures.size(); i++) { + dummyCell.setData(premiumFeatures.get(i), false); + dummyCell.measure(View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.AT_MOST)); + premiumFeatures.get(i).yOffset = yOffset; + yOffset += dummyCell.getMeasuredHeight(); + } + + totalGradientHeight = yOffset; + } + + @Override + public void show() { + super.show(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.stopAllHeavyOperations, 4); + } + + @Override + public void dismiss() { + super.dismiss(); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 4); + if (enterAnimator != null) { + enterAnimator.cancel(); + } + } + + @Override + protected void mainContainerDispatchDraw(Canvas canvas) { + super.mainContainerDispatchDraw(canvas); + if (startEnterFromView != null && enterTransitionInProgress) { + canvas.save(); + + float[] points = new float[]{startEnterFromX, startEnterFromY}; + startEnterFromView.getMatrix().mapPoints(points); + Drawable startEnterFromDrawable = startEnterFromView.getRightDrawable(); + float cxFrom = -coords[0] + startEnterFromX1 + points[0]; + float cyFrom = -coords[1] + startEnterFromY1 + points[1]; + + float fromSize = startEnterFromScale * startEnterFromDrawable.getIntrinsicWidth(); + float toSize = iconTextureView.getMeasuredHeight() * 0.8f; + float toSclale = toSize / fromSize; + float bigIconFromScale = fromSize / toSize; + + float cxTo = iconTextureView.getMeasuredWidth() / 2f; + View view = iconTextureView; + while (view != container) { + cxTo += view.getX(); + view = (View) view.getParent(); + } + float cyTo = iconTextureView.getY() + ((View) iconTextureView.getParent()).getY() + ((View) iconTextureView.getParent().getParent()).getY() + iconTextureView.getMeasuredHeight() / 2f; + + float x = AndroidUtilities.lerp(cxFrom, cxTo, CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(enterTransitionProgress)); + float y = AndroidUtilities.lerp(cyFrom, cyTo, enterTransitionProgress); + + if (startEnterFromDrawable != null) { + float s = startEnterFromScale * (1f - enterTransitionProgress) + toSclale * enterTransitionProgress; + canvas.save(); + canvas.scale(s, s, x, y); + startEnterFromDrawable.setBounds( + (int) x - startEnterFromDrawable.getIntrinsicWidth() / 2, + (int) y - startEnterFromDrawable.getIntrinsicHeight() / 2, + (int) x + startEnterFromDrawable.getIntrinsicWidth() / 2, + (int) y + startEnterFromDrawable.getIntrinsicHeight() / 2); + startEnterFromDrawable.setAlpha((int) (255 * (1f - Utilities.clamp(enterTransitionProgress, 1, 0)))); + startEnterFromDrawable.draw(canvas); + startEnterFromDrawable.setAlpha(0); + canvas.restore(); + + s = AndroidUtilities.lerp(bigIconFromScale, 1, enterTransitionProgress); + canvas.scale(s, s, x, y); + canvas.translate(x - iconTextureView.getMeasuredWidth() / 2f, y - iconTextureView.getMeasuredHeight() / 2f); + // canvas.saveLayerAlpha(0, 0, iconTextureView.getMeasuredWidth(), iconTextureView.getMeasuredHeight(), (int) (255 * enterTransitionProgress), Canvas.ALL_SAVE_FLAG); + iconTextureView.draw(canvas); + // canvas.restore(); + } + canvas.restore(); + } + } + + @Override + protected boolean onCustomOpenAnimation() { + if (startEnterFromView == null) { + return true; + } + enterAnimator = ValueAnimator.ofFloat(0, 1f); + enterTransitionProgress = 0f; + enterTransitionInProgress = true; + iconContainer.invalidate(); + startEnterFromView.getRightDrawable().setAlpha(0); + startEnterFromView.invalidate(); + iconTextureView.startEnterAnimation(-360, 100); + enterAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + enterTransitionProgress = (float) animation.getAnimatedValue(); + container.invalidate(); + } + }); + enterAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + enterTransitionInProgress = false; + enterTransitionProgress = 1f; + iconContainer.invalidate(); + ValueAnimator iconAlphaBack = ValueAnimator.ofInt(0, 255); + Drawable drawable = startEnterFromView.getRightDrawable(); + iconAlphaBack.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + drawable.setAlpha((Integer) animation.getAnimatedValue()); + startEnterFromView.invalidate(); + } + }); + iconAlphaBack.start(); + super.onAnimationEnd(animation); + } + }); + enterAnimator.setDuration(600); + enterAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + enterAnimator.start(); + return super.onCustomOpenAnimation(); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumStickersPreviewRecycler.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumStickersPreviewRecycler.java new file mode 100644 index 000000000..8eaba8caf --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumStickersPreviewRecycler.java @@ -0,0 +1,454 @@ +package org.telegram.ui.Components.Premium; + +import android.content.Context; +import android.graphics.Canvas; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +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.MessageObject; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.RecyclerListView; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +public class PremiumStickersPreviewRecycler extends RecyclerListView implements NotificationCenter.NotificationCenterDelegate, PagerHeaderView { + + private final ArrayList premiumStickers = new ArrayList<>(); + LinearLayoutManager layoutManager; + boolean firstMeasure = true; + boolean firstDraw = true; + private final int currentAccount; + + boolean hasSelectedView; + boolean haptic; + Runnable autoScrollRunnable = new Runnable() { + @Override + public void run() { + if (!autoPlayEnabled) { + return; + } + if (!sortedView.isEmpty()) { + StickerView stickerView = sortedView.get(sortedView.size() - 1); + int adapterPosition = getChildAdapterPosition(stickerView); + if (adapterPosition >= 0) { + adapterPosition++; + View view = layoutManager.findViewByPosition(adapterPosition); + if (view != null) { + haptic = false; + drawEffectForView(view, true); + smoothScrollBy(0, view.getTop() - (getMeasuredHeight() - view.getMeasuredHeight()) / 2, AndroidUtilities.overshootInterpolator); + } + } + } + scheduleAutoScroll(); + } + }; + + CubicBezierInterpolator interpolator = new CubicBezierInterpolator(0, 0.5f, 0.5f, 1f); + ArrayList sortedView = new ArrayList<>(); + Comparator comparator = (o1, o2) -> (int) (o1.progress * 100 - o2.progress * 100); + + View oldSelectedView; + private boolean checkEffect; + private int size; + int selectStickerOnNextLayout = -1; + + public PremiumStickersPreviewRecycler(Context context, int currentAccount) { + super(context); + this.currentAccount = currentAccount; + setLayoutManager(layoutManager = new LinearLayoutManager(context)); + setAdapter(new Adapter()); + setClipChildren(false); + + setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + if (recyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) { + drawEffectForView(null, true); + } + invalidate(); + } + + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + haptic = true; + } + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + StickerView scrollToView = null; + for (int i = 0; i < recyclerView.getChildCount(); i++) { + StickerView view = (StickerView) getChildAt(i); + if (scrollToView == null || view.progress > scrollToView.progress) { + scrollToView = view; + } + } + if (scrollToView != null) { + drawEffectForView(scrollToView, true); + haptic = false; + smoothScrollBy(0, scrollToView.getTop() - (getMeasuredHeight() - scrollToView.getMeasuredHeight()) / 2, AndroidUtilities.overshootInterpolator); + } + scheduleAutoScroll(); + } else { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + } + } + }); + + setOnItemClickListener((view, position) -> { + if (view != null) { + drawEffectForView(view, true); + haptic = false; + smoothScrollBy(0, view.getTop() - (getMeasuredHeight() - view.getMeasuredHeight()) / 2, AndroidUtilities.overshootInterpolator); + } + }); + + MediaDataController.getInstance(currentAccount).preloadPremiumPreviewStickers(); + setStickers(); + } + + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + if (MeasureSpec.getSize(heightSpec) > MeasureSpec.getSize(widthSpec)) { + size = MeasureSpec.getSize(widthSpec); + } else { + size = MeasureSpec.getSize(heightSpec); + } + super.onMeasure(widthSpec, heightSpec); + } + + private void scheduleAutoScroll() { + if (!autoPlayEnabled) { + return; + } + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + AndroidUtilities.runOnUIThread(autoScrollRunnable, 2700); + } + + private void drawEffectForView(View view, boolean animated) { + hasSelectedView = view != null; + for (int i = 0; i < getChildCount(); i++) { + StickerView child = (StickerView) getChildAt(i); + if (child == view) { + child.setDrawImage(true, true, animated); + } else { + child.setDrawImage(!hasSelectedView, false, animated); + } + } + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (firstMeasure && !premiumStickers.isEmpty() && getChildCount() > 0) { + firstMeasure = false; + AndroidUtilities.runOnUIThread(() -> { + int startPosition = Integer.MAX_VALUE >> 1; + startPosition -= startPosition % premiumStickers.size(); + layoutManager.scrollToPositionWithOffset(selectStickerOnNextLayout = startPosition, (getMeasuredHeight() - getChildAt(0).getMeasuredHeight()) >> 1); + drawEffectForView(null, false); + }); + } + if (selectStickerOnNextLayout > 0) { + ViewHolder holder = findViewHolderForAdapterPosition(selectStickerOnNextLayout); + if (holder != null) { + drawEffectForView(holder.itemView, false); + } + selectStickerOnNextLayout = -1; + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (!isVisible) { + return; + } + sortedView.clear(); + for (int i = 0; i < getChildCount(); i++) { + StickerView child = (StickerView) getChildAt(i); + float cY = (getMeasuredHeight() >> 1) + child.getMeasuredHeight(); + float p = (child.getTop() + child.getMeasuredHeight() + (child.getMeasuredHeight() >> 1)) / cY; + if (p > 1) { + p = 2 - p; + } + p = Utilities.clamp(p, 1f, 0f); + child.progress = p; + child.view.setTranslationX(-getMeasuredWidth() * 2f * (1f - interpolator.getInterpolation(p))); + sortedView.add(child); + } + Collections.sort(sortedView, comparator); + if ((firstDraw || checkEffect) && sortedView.size() > 0 && !premiumStickers.isEmpty()) { + drawEffectForView(oldSelectedView = sortedView.get(sortedView.size() - 1), !firstDraw); + firstDraw = false; + checkEffect = false; + } else if (oldSelectedView != sortedView.get(sortedView.size() - 1)) { + oldSelectedView = sortedView.get(sortedView.size() - 1); + if (haptic) { + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + } + } + for (int i = 0; i < sortedView.size(); i++) { + canvas.save(); + canvas.translate(sortedView.get(i).getX(), sortedView.get(i).getY()); + sortedView.get(i).draw(canvas); + canvas.restore(); + } + } + + @Override + public boolean drawChild(Canvas canvas, View child, long drawingTime) { + return true; + } + + boolean isVisible; + + @Override + public void setOffset(float translationX) { + float p = Math.abs(translationX / (float) getMeasuredWidth()); + boolean localVisible = p < 1f; + if (isVisible != localVisible) { + isVisible = localVisible; + invalidate(); + } + } + + private class Adapter extends RecyclerListView.SelectionAdapter { + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = new StickerView(parent.getContext()); + 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 (premiumStickers.isEmpty()) { + return; + } + StickerView stickerView = (StickerView) holder.itemView; + stickerView.setSticker(premiumStickers.get(position % premiumStickers.size())); + stickerView.setDrawImage(!hasSelectedView, false, false); + } + + @Override + public int getItemCount() { + return Integer.MAX_VALUE; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return false; + } + + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.premiumStickersPreviewLoaded); + scheduleAutoScroll(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.premiumStickersPreviewLoaded); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.premiumStickersPreviewLoaded) { + setStickers(); + } + } + + private void setStickers() { + premiumStickers.clear(); + premiumStickers.addAll(MediaDataController.getInstance(currentAccount).premiumPreviewStickers); + getAdapter().notifyDataSetChanged(); + invalidate(); + } + + private class StickerView extends FrameLayout { + + public float progress; + View view; + ImageReceiver centerImage; + ImageReceiver effectImage; + boolean drawEffect; + boolean animateImage = true; + private float effectProgress; + private float animateImageProgress; + TLRPC.Document document; + boolean update; + + public StickerView(Context context) { + super(context); + view = new View(context) { + + @Override + public void draw(Canvas canvas) { + super.draw(canvas); + if (update) { + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(document, Theme.key_windowBackgroundGray, 0.5f); + centerImage.setImage(ImageLocation.getForDocument(document), null, svgThumb, "webp", null, 1); + if (MessageObject.isPremiumSticker(document)) { + effectImage.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), "140_140", null, null, "tgs", null, 1); + } + } + + if (drawEffect) { + if (effectProgress == 0f) { + effectProgress = 1f; + if (effectImage.getLottieAnimation() != null) { + effectImage.getLottieAnimation().setCurrentFrame(0, false); + } + } + if (effectImage.getLottieAnimation() != null) { + effectImage.getLottieAnimation().start(); + } + if (effectImage.getLottieAnimation() != null && effectImage.getLottieAnimation().isLastFrame() && autoPlayEnabled) { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + AndroidUtilities.runOnUIThread(autoScrollRunnable, 0); + } + } else { + if (effectImage.getLottieAnimation() != null) { + effectImage.getLottieAnimation().stop(); + } + } + + if (animateImage) { + if (centerImage.getLottieAnimation() != null) { + centerImage.getLottieAnimation().start(); + } + } else { + if (centerImage.getLottieAnimation() != null) { + centerImage.getLottieAnimation().stop(); + } + } + + if (animateImage && animateImageProgress != 1f) { + animateImageProgress += 16f / 150f; + invalidate(); + } else if (!animateImage && animateImageProgress != 0) { + animateImageProgress -= 16f / 150f; + invalidate(); + } + animateImageProgress = Utilities.clamp(animateImageProgress, 1f, 0f); + + if (drawEffect && effectProgress != 1f) { + effectProgress += 16f / 150f; + invalidate(); + } else if (!drawEffect && effectProgress != 0) { + effectProgress -= 16f / 150f; + invalidate(); + } + effectProgress = Utilities.clamp(effectProgress, 1f, 0f); + + float smallImageSize = PremiumStickersPreviewRecycler.this.size * 0.45f; + float size = smallImageSize * 1.499267f; + float x = getMeasuredWidth() - size; + float y = (getMeasuredHeight() - size) / 2f; + centerImage.setImageCoords(size - smallImageSize - size * 0.02f + x, (size - smallImageSize) / 2f + y, smallImageSize, smallImageSize); + centerImage.setAlpha(0.3f + 0.7f * animateImageProgress); + centerImage.draw(canvas); + + if (effectProgress != 0) { + effectImage.setImageCoords(x, y, size, size); + effectImage.setAlpha(effectProgress); + effectImage.draw(canvas); + } + } + }; + centerImage = new ImageReceiver(view); + effectImage = new ImageReceiver(view); + centerImage.setAllowStartAnimation(false); + effectImage.setAllowStartAnimation(false); + setClipChildren(false); + addView(view, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.RIGHT | Gravity.CENTER_VERTICAL)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int size = (int) (PremiumStickersPreviewRecycler.this.size * 0.6f); + view.getLayoutParams().width = view.getLayoutParams().height = size - AndroidUtilities.dp(16); + super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec((int) (size * 0.7f), MeasureSpec.EXACTLY)); + } + + public void setSticker(TLRPC.Document document) { + this.document = document; + update = true; + } + + public void setDrawImage(boolean animateImage, boolean drawEffect, boolean animated) { + if (this.drawEffect != drawEffect) { + this.drawEffect = drawEffect; + if (!animated) { + effectProgress = drawEffect ? 1f : 0f; + } + view.invalidate(); + } + if (this.animateImage != animateImage) { + this.animateImage = animateImage; + if (!animated) { + animateImageProgress = animateImage ? 1f : 0f; + } + view.invalidate(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + centerImage.onAttachedToWindow(); + effectImage.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + centerImage.onDetachedFromWindow(); + effectImage.onDetachedFromWindow(); + } + } + + boolean autoPlayEnabled; + + public void setAutoPlayEnabled(boolean b) { + if (autoPlayEnabled != b) { + autoPlayEnabled = b; + if (autoPlayEnabled) { + scheduleAutoScroll(); + checkEffect = true; + invalidate(); + } else { + AndroidUtilities.cancelRunOnUIThread(autoScrollRunnable); + drawEffectForView(null, true); + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ProfilePremiumCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ProfilePremiumCell.java new file mode 100644 index 000000000..42215a772 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ProfilePremiumCell.java @@ -0,0 +1,49 @@ +package org.telegram.ui.Components.Premium; + +import android.content.Context; +import android.graphics.Canvas; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.TextCell; + +public class ProfilePremiumCell extends TextCell { + + StarParticlesView.Drawable drawable = new StarParticlesView.Drawable(6); + + public ProfilePremiumCell(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); + drawable.size1 = 6; + drawable.size2 = 6; + drawable.size3 = 6; + drawable.useGradient = true; + drawable.speedScale = 3f; + drawable.minLifeTime = 600; + drawable.randLifeTime = 500; + drawable.startFromCenter = true; + drawable.type = StarParticlesView.Drawable.TYPE_SETTINGS; + + drawable.init(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + float cx = imageView.getX() + imageView.getWidth() / 2f; + float cy = imageView.getPaddingTop() + imageView.getY() + imageView.getHeight() / 2f - AndroidUtilities.dp(3); + drawable.rect.set( + cx - AndroidUtilities.dp(4), cy - AndroidUtilities.dp(4), + cx + AndroidUtilities.dp(4), cy + AndroidUtilities.dp(4) + ); + if (changed) { + drawable.resetPositions(); + } + } + + @Override + protected void dispatchDraw(Canvas canvas) { + drawable.onDraw(canvas); + invalidate(); + super.dispatchDraw(canvas); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ReactionDrawingObject.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ReactionDrawingObject.java new file mode 100644 index 000000000..1cf886f66 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/ReactionDrawingObject.java @@ -0,0 +1,185 @@ +package org.telegram.ui.Components.Premium; + +import android.graphics.Canvas; +import android.graphics.Rect; +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.SvgHelper; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Reactions.ReactionsEffectOverlay; + +public class ReactionDrawingObject extends CarouselView.DrawingObject { + + private View parentView; + ImageReceiver imageReceiver = new ImageReceiver(); + ImageReceiver actionReceiver = new ImageReceiver(); + ImageReceiver effectImageReceiver = new ImageReceiver(); + TLRPC.TL_availableReaction reaction; + private int position; + long lastSelectedTime; + private boolean selected; + android.graphics.Rect rect = new Rect(); + + private float selectedProgress; + + public ReactionDrawingObject(int i) { + position = i; + } + + @Override + public void onAttachToWindow(View parentView, int i) { + this.parentView = parentView; + if (i == 0) { + imageReceiver.setParentView(parentView); + imageReceiver.onAttachedToWindow(); + imageReceiver.setLayerNum(Integer.MAX_VALUE); + + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(reaction.activate_animation, Theme.key_windowBackgroundGray, 0.5f); +// imageReceiver.setImage(ImageLocation.getForDocument(reaction.appear_animation), "60_60_nolimit", null, null, svgThumb, 0, "tgs", reaction, 0); +// imageReceiver.setAutoRepeat(0); +// if (imageReceiver.getLottieAnimation() != null) { +// imageReceiver.getLottieAnimation().setCurrentFrame(0, false); +// } +// imageReceiver.startAnimation(); +// + + actionReceiver.setParentView(parentView); + actionReceiver.onAttachedToWindow(); + actionReceiver.setLayerNum(Integer.MAX_VALUE); + + actionReceiver.setAllowStartLottieAnimation(false); + actionReceiver.setImage(ImageLocation.getForDocument(reaction.activate_animation), "50_50_nolimit", null, null, svgThumb, 0, "tgs", reaction, 0); + actionReceiver.setAutoRepeat(0); + if (actionReceiver.getLottieAnimation() != null) { + actionReceiver.getLottieAnimation().setCurrentFrame(0, false); + actionReceiver.getLottieAnimation().stop(); + } + } else { + effectImageReceiver.setParentView(parentView); + effectImageReceiver.onAttachedToWindow(); + effectImageReceiver.setLayerNum(Integer.MAX_VALUE); + + effectImageReceiver.setAllowStartLottieAnimation(false); + int size = ReactionsEffectOverlay.sizeForBigReaction(); + effectImageReceiver.setImage(ImageLocation.getForDocument(reaction.around_animation), size + "_" + size, null, null, null, 0, "tgs", reaction, 0); + effectImageReceiver.setAutoRepeat(0); + if (effectImageReceiver.getLottieAnimation() != null) { + effectImageReceiver.getLottieAnimation().setCurrentFrame(0, false); + effectImageReceiver.getLottieAnimation().stop(); + } + } + } + + @Override + public void onDetachFromWindow() { + imageReceiver.onDetachedFromWindow(); + imageReceiver.setParentView(null); + effectImageReceiver.onDetachedFromWindow(); + effectImageReceiver.setParentView(null); + actionReceiver.onDetachedFromWindow(); + actionReceiver.setParentView(null); + } + + @Override + public void draw(Canvas canvas, float cX, float cY, float globalScale) { + int imageSize = (int) (AndroidUtilities.dp(120) * globalScale); + int effectSize = (int) (AndroidUtilities.dp(350) * globalScale); + rect.set((int) (cX - imageSize / 2f), (int) (cY - imageSize / 2f), + (int) (cX + imageSize / 2f), (int) (cY + imageSize / 2f)); + + + imageReceiver.setImageCoords(cX - imageSize / 2f, cY - imageSize / 2f, imageSize, imageSize); + actionReceiver.setImageCoords(cX - imageSize / 2f, cY - imageSize / 2f, imageSize, imageSize); + + if (actionReceiver.getLottieAnimation() != null && actionReceiver.getLottieAnimation().hasBitmap()) { + actionReceiver.draw(canvas); + if (actionReceiver.getLottieAnimation() != null && actionReceiver.getLottieAnimation().isLastFrame()) { + // selected = false; + } else if (selected && actionReceiver.getLottieAnimation() != null && !actionReceiver.getLottieAnimation().isRunning()) { + actionReceiver.getLottieAnimation().start(); + } + } + if (selected || selectedProgress != 0) { + effectImageReceiver.setImageCoords(cX - effectSize / 2f, cY - effectSize / 2f, effectSize, effectSize); + effectImageReceiver.setAlpha(selectedProgress); + if (selectedProgress != 1f) { + float s = 0.7f + selectedProgress * 0.3f; + canvas.save(); + canvas.scale(s, s, cX, cY); + effectImageReceiver.draw(canvas); + canvas.restore(); + } else { + effectImageReceiver.draw(canvas); + } + + if (selected && effectImageReceiver.getLottieAnimation() != null && effectImageReceiver.getLottieAnimation().isLastFrame()) { + carouselView.autoplayToNext(); + } + + if (selected && effectImageReceiver.getLottieAnimation() != null && !effectImageReceiver.getLottieAnimation().isRunning() && !effectImageReceiver.getLottieAnimation().isLastFrame()) { + effectImageReceiver.getLottieAnimation().start(); + } + if (selected && effectImageReceiver.getLottieAnimation() != null && !effectImageReceiver.getLottieAnimation().isRunning() && effectImageReceiver.getLottieAnimation().isLastFrame()) { + selected = false; + } + if (selected && selectedProgress != 1f) { + selectedProgress += 16f / 200f; + if (selectedProgress > 1f) { + selectedProgress = 1f; + } + } else if (!selected) { + selectedProgress -= 16f / 200f; + if (selectedProgress < 0) { + selectedProgress = 0; + } + } + } + } + + @Override + public boolean checkTap(float x, float y) { + if (rect.contains((int) x, (int) y)) { + select(); + return true; + } + return false; + } + + @Override + public void select() { + if (selected) { + return; + } + selected = true; + if (selectedProgress == 0) { + selectedProgress = 1f; + } + lastSelectedTime = System.currentTimeMillis(); + if (effectImageReceiver.getLottieAnimation() != null) { + effectImageReceiver.getLottieAnimation().setCurrentFrame(0, false); + effectImageReceiver.getLottieAnimation().start(); + } + + if (actionReceiver.getLottieAnimation() != null) { + actionReceiver.getLottieAnimation().setCurrentFrame(0, false); + actionReceiver.getLottieAnimation().start(); + } + + parentView.invalidate(); + } + + @Override + public void hideAnimation() { + super.hideAnimation(); + selected = false; + } + + public void set(TLRPC.TL_availableReaction reaction) { + this.reaction = reaction; + } +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/SpeedLineParticles.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/SpeedLineParticles.java new file mode 100644 index 000000000..b56e7ab0c --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/SpeedLineParticles.java @@ -0,0 +1,127 @@ +package org.telegram.ui.Components.Premium; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; + +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; + +import java.util.ArrayList; + +public class SpeedLineParticles { + + public static class Drawable { + + public RectF rect = new RectF(); + public RectF screenRect = new RectF(); + public boolean paused; + private Paint paint = new Paint(); + private float lines[]; + + ArrayList particles = new ArrayList<>(); + public float speedScale = 1f; + + public final int count; + public boolean useGradient; + public int size1 = 14, size2 = 12, size3 = 10; + public long minLifeTime = 2000; + private int lastColor; + private final float dt = 1000 / AndroidUtilities.screenRefreshRate; + + public Drawable(int count) { + this.count = count; + lines = new float[count * 4]; + } + + public void init() { + if (particles.isEmpty()) { + for (int i = 0; i < count; i++) { + particles.add(new Drawable.Particle()); + } + } + updateColors(); + } + + public void updateColors() { + int c = ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumStartSmallStarsColor2), 80); + if (lastColor != c) { + lastColor = c; + paint.setColor(lastColor); + } + } + + + + public void resetPositions() { + long time = System.currentTimeMillis(); + for (int i = 0; i < particles.size(); i++) { + particles.get(i).genPosition(time, true); + } + } + + public void onDraw(Canvas canvas) { + long time = System.currentTimeMillis(); + for (int i = 0; i < particles.size(); i++) { + Drawable.Particle particle = particles.get(i); + if (paused) { + particle.draw(canvas, i, pausedTime); + } else { + particle.draw(canvas, i, time); + } + if (time > particle.lifeTime || !screenRect.contains(particle.x, particle.y)) { + particle.genPosition(time, false); + } + } + canvas.drawLines(lines, paint); + } + + long pausedTime; + + private class Particle { + private float x, y; + private float vecX, vecY; + private int starIndex; + private long lifeTime; + private int alpha; + float inProgress; + + public void draw(Canvas canvas, int index, long time) { + lines[4 * index ] = x; + lines[4 * index + 1] = y; + lines[4 * index + 2] = x + AndroidUtilities.dp(30) * vecX; + lines[4 * index + 3] = y + AndroidUtilities.dp(30) * vecY; + if (!paused) { + float speed = AndroidUtilities.dp(4) * (dt / 660f) * speedScale; + x += vecX * speed; + y += vecY * speed; + + if (inProgress != 1f) { + inProgress += dt / 200; + if (inProgress > 1f) { + inProgress = 1f; + } + } + } + } + + public void genPosition(long time, boolean reset) { + lifeTime = time + minLifeTime + Utilities.fastRandom.nextInt(1000); + RectF currentRect = reset ? screenRect : rect; + float randX = currentRect.left + Math.abs(Utilities.fastRandom.nextInt() % currentRect.width()); + float randY = currentRect.top + Math.abs(Utilities.fastRandom.nextInt() % currentRect.height()); + x = randX; + y = randY; + double a = Math.atan2(x - rect.centerX(), y - rect.centerY()); + vecX = (float) Math.sin(a); + vecY = (float) Math.cos(a); + alpha = (int) (255 * ((50 + Utilities.fastRandom.nextInt(50)) / 100f)); + + inProgress = 0; + } + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java new file mode 100644 index 000000000..86ca1d858 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/StarParticlesView.java @@ -0,0 +1,514 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.CornerPathEffect; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.RectF; +import android.view.View; + +import androidx.core.content.ContextCompat; +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.SvgHelper; +import org.telegram.messenger.Utilities; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.GLIconSettingsView; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.ArrayList; + +public class StarParticlesView extends View { + + public Drawable drawable; + int size; + boolean distributionAlgorithm; + + public StarParticlesView(Context context) { + super(context); + + int particlesCount = 50; + if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH) { + particlesCount = 200; + } else if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_AVERAGE) { + particlesCount = 100; + } + + drawable = new Drawable(particlesCount); + drawable.type = 100; + drawable.roundEffect = true; + drawable.useRotate = true; + drawable.useBlur = true; + drawable.checkBounds = true; + drawable.size1 = 4; + drawable.k1 = drawable.k2 = drawable.k3 = 0.98f; + drawable.init(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int sizeInternal = getMeasuredWidth() << 16 + getMeasuredHeight(); + drawable.rect.set(0, 0, AndroidUtilities.dp(140), AndroidUtilities.dp(140)); + drawable.rect.offset((getMeasuredWidth() - drawable.rect.width()) / 2, (getMeasuredHeight() - drawable.rect.height()) / 2); + drawable.rect2.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + if (size != sizeInternal) { + size = sizeInternal; + drawable.resetPositions(); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + drawable.onDraw(canvas); + if (!drawable.paused) { + invalidate(); + } + } + + public void flingParticles(float sum) { + float maxSpeed = 15f; + if (sum < 60) { + maxSpeed = 5f; + } else if (sum < 180) { + maxSpeed = 9f; + } + AnimatorSet animatorSet = new AnimatorSet(); + ValueAnimator.AnimatorUpdateListener updateListener = animation -> drawable.speedScale = (float) animation.getAnimatedValue(); + + ValueAnimator a1 = ValueAnimator.ofFloat(1f, maxSpeed); + a1.addUpdateListener(updateListener); + a1.setDuration(600); + + ValueAnimator a2 = ValueAnimator.ofFloat(maxSpeed, 1f); + a2.addUpdateListener(updateListener); + a2.setDuration(2000); + animatorSet.playTogether(a1, a2); + animatorSet.start(); + } + + public static class Drawable { + + public RectF rect = new RectF(); + public RectF rect2 = new RectF(); + public RectF excludeRect = new RectF(); + private final Bitmap[] stars = new Bitmap[3]; + public boolean paused; + public boolean startFromCenter; + private Paint paint = new Paint(); + + ArrayList particles = new ArrayList<>(); + public float speedScale = 1f; + + public final int count; + public boolean useGradient; + public int size1 = 14, size2 = 12, size3 = 10; + public float k1 = 0.85f, k2 = 0.85f, k3 = 0.9f; + public long minLifeTime = 2000; + public int randLifeTime = 1000; + private int lastColor; + private final float dt = 1000 / AndroidUtilities.screenRefreshRate; + private boolean distributionAlgorithm; + Matrix matrix = new Matrix(); + Matrix matrix2 = new Matrix(); + Matrix matrix3 = new Matrix(); + float[] points1; + float[] points2; + float[] points3; + int pointsCount1, pointsCount2, pointsCount3; + public boolean useRotate; + public boolean checkBounds = false; + public boolean checkTime = true; + public boolean isCircle = true; + public boolean useBlur = false; + public boolean roundEffect = true; + public int type = -1; + public String colorKey = Theme.key_premiumStartSmallStarsColor; + + public final static int TYPE_SETTINGS = 101; + + public Drawable(int count) { + this.count = count; + distributionAlgorithm = count < 50; + } + + public void init() { + if (useRotate) { + points1 = new float[count * 2]; + points2 = new float[count * 2]; + points3 = new float[count * 2]; + } + generateBitmaps(); + if (particles.isEmpty()) { + for (int i = 0; i < count; i++) { + particles.add(new Particle()); + } + } + } + + public void updateColors() { + int c = Theme.getColor(colorKey); + if (lastColor != c) { + lastColor = c; + generateBitmaps(); + } + } + + private void generateBitmaps() { + for (int i = 0; i < 3; i++) { + int size; + float k = k1; + Bitmap bitmap; + if (i == 0) { + size = AndroidUtilities.dp(size1); + } else if (i == 1) { + k = k2; + size = AndroidUtilities.dp(size2); + } else { + k = k3; + size = AndroidUtilities.dp(size3); + } + + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT) { + int res; + if (i == 0) { + res = R.raw.premium_object_folder; + } else if (i == 1) { + res = R.raw.premium_object_bubble; + } else { + res = R.raw.premium_object_settings; + } + stars[i] = SvgHelper.getBitmap(res, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey), 30)); + continue; + } + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + int res; + if (i == 0) { + res = R.raw.premium_object_adsbubble; + } else if (i == 1) { + res = R.raw.premium_object_like; + } else { + res = R.raw.premium_object_noads; + } + stars[i] = SvgHelper.getBitmap(res, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey), 30)); + continue; + } + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS) { + int res; + if (i == 0) { + res = R.raw.premium_object_video2; + } else if (i == 1) { + res = R.raw.premium_object_video; + } else { + res = R.raw.premium_object_user; + } + stars[i] = SvgHelper.getBitmap(res, size, size, ColorUtils.setAlphaComponent(Theme.getColor(colorKey), 30)); + continue; + } + + bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + stars[i] = bitmap; + + Canvas canvas = new Canvas(bitmap); + + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_PROFILE_BADGE && (i == 1 || i == 2)) { + android.graphics.drawable.Drawable drawable = ContextCompat.getDrawable(ApplicationLoader.applicationContext, R.drawable.msg_premium_liststar); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(colorKey), PorterDuff.Mode.MULTIPLY)); + drawable.setBounds(0, 0, size, size); + drawable.draw(canvas); + continue; + } + Path path = new Path(); + int sizeHalf = size >> 1; + int mid = (int) (sizeHalf * k); + path.moveTo(0, sizeHalf); + path.lineTo(mid, mid); + path.lineTo(sizeHalf, 0); + path.lineTo(size - mid, mid); + path.lineTo(size, sizeHalf); + path.lineTo(size - mid, size - mid); + path.lineTo(sizeHalf, size); + path.lineTo(mid, size - mid); + path.lineTo(0, sizeHalf); + path.close(); + + Paint paint = new Paint(); + if (useGradient) { + if (size >= AndroidUtilities.dp(10)) { + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, size, size, -2 * size, 0); + } else { + PremiumGradient.getInstance().updateMainGradientMatrix(0, 0, size, size, -4 * size, 0); + } + Paint paint1 = PremiumGradient.getInstance().getMainGradientPaint(); + if (roundEffect) { + paint1.setPathEffect(new CornerPathEffect(AndroidUtilities.dpf2(size1 / 5f))); + } + paint1.setAlpha(120); + canvas.drawPath(path, paint1); + paint1.setPathEffect(null); + paint1.setAlpha(255); + } else { + if (type == 100) { + paint.setColor(ColorUtils.setAlphaComponent(Theme.getColor(colorKey), 200)); + } else { + paint.setColor(Theme.getColor(colorKey)); + } + if (roundEffect) { + paint.setPathEffect(new CornerPathEffect(AndroidUtilities.dpf2(size1 / 5f))); + } + canvas.drawPath(path, paint); + } + if (useBlur) { + Utilities.stackBlurBitmap(bitmap, 2); + } + } + } + + + public void resetPositions() { + long time = System.currentTimeMillis(); + for (int i = 0; i < particles.size(); i++) { + particles.get(i).genPosition(time); + } + } + + float a; + float a1; + float a2; + + public void onDraw(Canvas canvas) { + onDraw(canvas, 1f); + } + + public void onDraw(Canvas canvas, float alpha) { + long time = System.currentTimeMillis(); + if (useRotate) { + matrix.reset(); + a += 360f * (16f / 40000f); + a1 += 360f * (16f / 50000f); + a2 += 360f * (16f / 60000f); + matrix.setRotate(a, rect.centerX(), rect.centerY()); + matrix2.setRotate(a1, rect.centerX(), rect.centerY()); + matrix3.setRotate(a2, rect.centerX(), rect.centerY()); + + pointsCount1 = 0; + pointsCount2 = 0; + pointsCount3 = 0; + for (int i = 0; i < particles.size(); i++) { + Particle particle = particles.get(i); + particle.updatePoint(); + } + matrix.mapPoints(points1, 0, points1, 0, pointsCount1); + matrix2.mapPoints(points2, 0, points2, 0, pointsCount2); + matrix3.mapPoints(points3, 0, points3, 0, pointsCount3); + pointsCount1 = 0; + pointsCount2 = 0; + pointsCount3 = 0; + } + + for (int i = 0; i < particles.size(); i++) { + Particle particle = particles.get(i); + if (paused) { + particle.draw(canvas, pausedTime, alpha); + } else { + particle.draw(canvas, time,alpha); + } + if (checkTime) { + if (time > particle.lifeTime) { + particle.genPosition(time); + } + } + if (checkBounds) { + if (!rect2.contains(particle.drawingX, particle.drawingY)) { + particle.genPosition(time); + } + } + } + } + + long pausedTime; + + private class Particle { + private float x, y; + private float x2, y2; + private float drawingX, drawingY; + private float vecX, vecY; + private int starIndex; + private long lifeTime; + private int alpha; + private float randomRotate; + float inProgress; + + public void updatePoint() { + if (starIndex == 0) { + points1[2 * pointsCount1] = x; + points1[2 * pointsCount1 + 1] = y; + pointsCount1++; + } else if (starIndex == 1) { + points2[2 * pointsCount2] = x; + points2[2 * pointsCount2 + 1] = y; + pointsCount2++; + } else if (starIndex == 2) { + points3[2 * pointsCount3] = x; + points3[2 * pointsCount3 + 1] = y; + pointsCount3++; + } + } + + public void draw(Canvas canvas, long time, float alpha) { + if (useRotate) { + if (starIndex == 0) { + drawingX = points1[2 * pointsCount1]; + drawingY = points1[2 * pointsCount1 + 1]; + pointsCount1++; + } else if (starIndex == 1) { + drawingX = points2[2 * pointsCount2]; + drawingY = points2[2 * pointsCount2 + 1]; + pointsCount2++; + } else if (starIndex == 2) { + drawingX = points3[2 * pointsCount3]; + drawingY = points3[2 * pointsCount3 + 1]; + pointsCount3++; + } + } else { + drawingX = x; + drawingY = y; + } + boolean skipDraw = false; + if (!excludeRect.isEmpty() && excludeRect.contains(drawingX, drawingY)) { + skipDraw = true; + } + if (!skipDraw) { + canvas.save(); + canvas.translate(drawingX, drawingY); + if (randomRotate != 0) { + canvas.rotate(randomRotate, stars[starIndex].getWidth() / 2f, stars[starIndex].getHeight() / 2f); + } + if (inProgress < 1f || GLIconSettingsView.smallStarsSize != 1f) { + float s = AndroidUtilities.overshootInterpolator.getInterpolation(inProgress) * GLIconSettingsView.smallStarsSize; + canvas.scale(s, s, 0, 0); + } + float outProgress = 0f; + if (checkTime && lifeTime - time < 200) { + outProgress = 1f - (lifeTime - time) / 150f; + outProgress = Utilities.clamp(outProgress, 1f, 0f); + } + paint.setAlpha((int) (this.alpha * (1f - outProgress) * alpha)); + canvas.drawBitmap(stars[starIndex], -(stars[starIndex].getWidth() >> 1), -(stars[starIndex].getHeight() >> 1), paint); + canvas.restore(); + } + if (!paused) { + float speed = AndroidUtilities.dp(4) * (dt / 660f) * speedScale; + x += vecX * speed; + y += vecY * speed; + + if (inProgress != 1f) { + inProgress += dt / 200; + if (inProgress > 1f) { + inProgress = 1f; + } + } + } + } + + public void genPosition(long time) { + starIndex = Math.abs(Utilities.fastRandom.nextInt() % stars.length); + lifeTime = time + minLifeTime + Utilities.fastRandom.nextInt(randLifeTime); + randomRotate = 0; + + if (distributionAlgorithm) { + float bestDistance = 0; + float bestX = rect.left + Math.abs(Utilities.fastRandom.nextInt() % rect.width()); + float bestY = rect.top + Math.abs(Utilities.fastRandom.nextInt() % rect.height()); + for (int k = 0; k < 10; k++) { + float randX = rect.left + Math.abs(Utilities.fastRandom.nextInt() % rect.width()); + float randY = rect.top + Math.abs(Utilities.fastRandom.nextInt() % rect.height()); + float minDistance = Integer.MAX_VALUE; + for (int j = 0; j < particles.size(); j++) { + float rx; + float ry; + if (startFromCenter) { + rx = particles.get(j).x2 - randX; + ry = particles.get(j).y2 - randY; + } else { + rx = particles.get(j).x - randX; + ry = particles.get(j).y - randY; + } + float distance = rx * rx + ry * ry; + if (distance < minDistance) { + minDistance = distance; + } + } + if (minDistance > bestDistance) { + bestDistance = minDistance; + bestX = randX; + bestY = randY; + } + } + + x = bestX; + y = bestY; + } else { + if (isCircle) { + float r = (Math.abs(Utilities.fastRandom.nextInt() % 1000) / 1000f) * rect.width(); + float a = Math.abs(Utilities.fastRandom.nextInt() % 360); + x = rect.centerX() + (float) (r * Math.sin(Math.toRadians(a))); + y = rect.centerY() + (float) (r * Math.cos(Math.toRadians(a))); + } else { + x = rect.left + Math.abs(Utilities.fastRandom.nextInt() % rect.width()); + y = rect.top + Math.abs(Utilities.fastRandom.nextInt() % rect.height()); + } + } + + double a = Math.atan2(x - rect.centerX(), y - rect.centerY()); + vecX = (float) Math.sin(a); + vecY = (float) Math.cos(a); + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS) { + alpha = (int) (120 * ((50 + Utilities.fastRandom.nextInt(50)) / 100f)); + } else { + alpha = (int) (255 * ((50 + Utilities.fastRandom.nextInt(50)) / 100f)); + } + if ((type == PremiumPreviewFragment.PREMIUM_FEATURE_PROFILE_BADGE && (starIndex == 1 || starIndex == 2)) || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS) { + randomRotate = (int) (45 * ((Utilities.fastRandom.nextInt() % 100) / 100f)); + } + if (type != TYPE_SETTINGS) { + inProgress = 0; + } + if (startFromCenter) { + x2 = x; + y2 = y; + x = rect.centerX();// + (x - rect.centerX()) * 0.3f; + y = rect.centerY();// + (y - rect.centerY()) * 0.3f; + } + } + } + } + + public void setPaused(boolean paused) { + if (paused == drawable.paused) { + return; + } + drawable.paused = paused; + if (paused) { + drawable.pausedTime = System.currentTimeMillis(); + } else { + for (int i = 0; i < drawable.particles.size(); i++) { + drawable.particles.get(i).lifeTime += System.currentTimeMillis() - drawable.pausedTime; + } + invalidate(); + } + } +} + diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java new file mode 100644 index 000000000..e4a1c9d85 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/VideoScreenPreview.java @@ -0,0 +1,561 @@ +package org.telegram.ui.Components.Premium; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.SurfaceTexture; +import android.graphics.drawable.Drawable; +import android.media.MediaMetadataRetriever; +import android.net.Uri; +import android.os.Build; +import android.view.TextureView; +import android.widget.FrameLayout; + +import androidx.core.graphics.ColorUtils; +import androidx.core.graphics.drawable.RoundedBitmapDrawable; +import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + +import com.google.android.exoplayer2.ExoPlayer; +import com.google.android.exoplayer2.ui.AspectRatioFrameLayout; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.FileLoader; +import org.telegram.messenger.ImageLoader; +import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.VideoPlayer; +import org.telegram.ui.Components.voip.CellFlickerDrawable; +import org.telegram.ui.PremiumPreviewFragment; + +import java.io.File; + +public class VideoScreenPreview extends FrameLayout implements PagerHeaderView, NotificationCenter.NotificationCenterDelegate { + + private final SvgHelper.SvgDrawable svgIcon; + Paint phoneFrame1 = new Paint(Paint.ANTI_ALIAS_FLAG); + Paint phoneFrame2 = new Paint(Paint.ANTI_ALIAS_FLAG); + + boolean fromTop = false; + File file; + float aspectRatio; + String attachFileName; + ImageReceiver imageReceiver = new ImageReceiver(this); + + private void checkVideo() { + if (file != null && file.exists()) { + MediaMetadataRetriever retriever = new MediaMetadataRetriever(); + retriever.setDataSource(ApplicationLoader.applicationContext, Uri.fromFile(file)); + int width = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)); + int height = Integer.valueOf(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)); + retriever.release(); + aspectRatio = width / (float) height; + + if (allowPlay) { + runVideoPlayer(); + } + } + } + + int currentAccount; + int type; + boolean visible; + boolean attached; + boolean play; + boolean allowPlay; + boolean firstFrameRendered; + + float progress; + VideoPlayer videoPlayer; + AspectRatioFrameLayout aspectRatioFrameLayout; + TextureView textureView; + + RoundedBitmapDrawable roundedBitmapDrawable; + CellFlickerDrawable.DrawableInterface cellFlickerDrawable; + private float roundRadius; + StarParticlesView.Drawable starDrawable; + SpeedLineParticles.Drawable speedLinesDrawable; + private final static float[] speedScaleVideoTimestamps = new float[]{0.02f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 0.02f}; + private MatrixParticlesDrawable matrixParticlesDrawable; + + + public VideoScreenPreview(Context context, SvgHelper.SvgDrawable svgDrawable, int currentAccount, int type) { + super(context); + this.currentAccount = currentAccount; + this.type = type; + this.svgIcon = svgDrawable; + + phoneFrame1.setColor(Color.BLACK); + phoneFrame2.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_premiumGradient2), Color.BLACK, 0.5f)); + imageReceiver.setLayerNum(Integer.MAX_VALUE); + setVideo(); + + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_UPLOAD_LIMIT) { + matrixParticlesDrawable = new MatrixParticlesDrawable(); + matrixParticlesDrawable.init(); + } else if (type == PremiumPreviewFragment.PREMIUM_FEATURE_PROFILE_BADGE || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS) { + starDrawable = new StarParticlesView.Drawable(40); + starDrawable.speedScale = 3; + starDrawable.type = type; + + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + starDrawable.size1 = 14; + starDrawable.size2 = 18; + starDrawable.size3 = 18; + } else { + starDrawable.size1 = 14; + starDrawable.size2 = 16; + starDrawable.size3 = 15; + } + starDrawable.k1 = starDrawable.k2 = starDrawable.k3 = 0.98f; + starDrawable.speedScale = 4; + starDrawable.colorKey = Theme.key_premiumStartSmallStarsColor2; + starDrawable.init(); + } else if (type == PremiumPreviewFragment.PREMIUM_FEATURE_DOWNLOAD_SPEED) { + speedLinesDrawable = new SpeedLineParticles.Drawable(200); + speedLinesDrawable.init(); + } else { + int particlesCount = 100; + if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH) { + particlesCount = 800; + } else if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_AVERAGE) { + particlesCount = 400; + } + starDrawable = new StarParticlesView.Drawable(particlesCount); + starDrawable.colorKey = Theme.key_premiumStartSmallStarsColor2; + starDrawable.size1 = 8; + starDrawable.size1 = 6; + starDrawable.size1 = 4; + starDrawable.k1 = starDrawable.k2 = starDrawable.k3 = 0.98f; + starDrawable.useRotate = true; + starDrawable.speedScale = 4; + starDrawable.checkBounds = true; + starDrawable.checkTime = true; + starDrawable.useBlur = true; + starDrawable.roundEffect = false; + starDrawable.init(); + } + + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_UPLOAD_LIMIT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS) { + fromTop = true; + } + + + aspectRatioFrameLayout = new AspectRatioFrameLayout(context) { + + Path clipPath = new Path(); + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + clipPath.reset(); + if (fromTop) { + AndroidUtilities.rectTmp.set(0, -roundRadius, getMeasuredWidth(), getMeasuredHeight()); + } else { + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), (int) (getMeasuredHeight() + roundRadius)); + } + float rad = roundRadius - AndroidUtilities.dp(3); + clipPath.addRoundRect(AndroidUtilities.rectTmp, new float[]{rad, rad, rad, rad, rad, rad, rad, rad}, Path.Direction.CW); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + canvas.save(); + canvas.clipPath(clipPath); + super.dispatchDraw(canvas); + canvas.restore(); + } + }; + + aspectRatioFrameLayout.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIT); + textureView = new TextureView(context); + aspectRatioFrameLayout.addView(textureView); + setWillNotDraw(false); + addView(aspectRatioFrameLayout); + } + + private void setVideo() { + TLRPC.TL_help_premiumPromo premiumPromo = MediaDataController.getInstance(currentAccount).getPremiumPromo(); + String typeString = PremiumPreviewFragment.featureTypeToServerString(type); + if (premiumPromo != null) { + int index = -1; + for (int i = 0; i < premiumPromo.video_sections.size(); i++) { + if (premiumPromo.video_sections.get(i).equals(typeString)) { + index = i; + break; + } + } + if (index >= 0) { + TLRPC.Document document = premiumPromo.videos.get(index); + Drawable drawable = null; + for (int i = 0; i < document.thumbs.size(); i++) { + if (document.thumbs.get(i) instanceof TLRPC.TL_photoStrippedSize) { + roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), ImageLoader.getStrippedPhotoBitmap(document.thumbs.get(i).bytes, "b")); + CellFlickerDrawable flickerDrawable = new CellFlickerDrawable(); + flickerDrawable.repeatProgress = 4f; + flickerDrawable.progress = 3.5f; + flickerDrawable.frameInside = true; + cellFlickerDrawable = flickerDrawable.getDrawableInterface(this, svgIcon); + CombinedDrawable combinedDrawable = new CombinedDrawable(roundedBitmapDrawable, cellFlickerDrawable) { + @Override + public void setBounds(int left, int top, int right, int bottom) { + if (fromTop) { + super.setBounds(left, (int) (top - roundRadius), right, bottom); + } else { + super.setBounds(left, top, right, (int) (bottom + roundRadius)); + } + } + }; + combinedDrawable.setFullsize(true); + drawable = combinedDrawable; + } + } + attachFileName = FileLoader.getAttachFileName(document); + imageReceiver.setImage(null, null, drawable, null, null, 1); + FileLoader.getInstance(currentAccount).loadFile(document, null, 1, 0); + Utilities.globalQueue.postRunnable(() -> { + File file = FileLoader.getInstance(currentAccount).getPathToAttach(document); + AndroidUtilities.runOnUIThread(() -> { + this.file = file; + checkVideo(); + }); + }); + + } + } + } + + int size; + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); + int measuredHeight = MeasureSpec.getSize(heightMeasureSpec); + int size = (int) (MeasureSpec.getSize(heightMeasureSpec) * 0.9f); + float h = size; + float w = size * 0.671f; + + float horizontalPadding = (measuredWidth - w) / 2f; + roundRadius = size * 0.0671f; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + aspectRatioFrameLayout.invalidateOutline(); + } + if (fromTop) { + AndroidUtilities.rectTmp.set(horizontalPadding, 0, measuredWidth - horizontalPadding, h); + } else { + AndroidUtilities.rectTmp.set(horizontalPadding, measuredHeight - h, measuredWidth - horizontalPadding, measuredHeight); + } + aspectRatioFrameLayout.getLayoutParams().width = (int) AndroidUtilities.rectTmp.width(); + aspectRatioFrameLayout.getLayoutParams().height = (int) AndroidUtilities.rectTmp.height(); + ((MarginLayoutParams) aspectRatioFrameLayout.getLayoutParams()).leftMargin = (int) AndroidUtilities.rectTmp.left; + ((MarginLayoutParams) aspectRatioFrameLayout.getLayoutParams()).topMargin = (int) AndroidUtilities.rectTmp.top; + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + int sizeInternal = getMeasuredWidth() << 16 + getMeasuredHeight(); + + int size = (int) (getMeasuredHeight() * 0.9f); + float h = size; + float w = size * 0.671f; + float horizontalPadding = (getMeasuredWidth() - w) / 2f; + + if (fromTop) { + AndroidUtilities.rectTmp.set(horizontalPadding, -roundRadius, getMeasuredWidth() - horizontalPadding, h); + } else { + AndroidUtilities.rectTmp.set(horizontalPadding, getMeasuredHeight() - h, getMeasuredWidth() - horizontalPadding, getMeasuredHeight() + roundRadius); + } + + if (this.size != sizeInternal) { + this.size = sizeInternal; + if (matrixParticlesDrawable != null) { + matrixParticlesDrawable.drawingRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + matrixParticlesDrawable.excludeRect.set(AndroidUtilities.rectTmp); + matrixParticlesDrawable.excludeRect.inset(AndroidUtilities.dp(16), AndroidUtilities.dp(16)); + } + if (starDrawable != null) { + if (type == PremiumPreviewFragment.PREMIUM_FEATURE_PROFILE_BADGE || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT || type == PremiumPreviewFragment.PREMIUM_FEATURE_ADS || type == PremiumPreviewFragment.PREMIUM_FEATURE_ANIMATED_AVATARS) { + starDrawable.rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + starDrawable.rect.inset(AndroidUtilities.dp(30), AndroidUtilities.dp(30)); + } else { + int getParticlesWidth = (int) (AndroidUtilities.rectTmp.width() * 0.4f); + starDrawable.rect.set( + AndroidUtilities.rectTmp.centerX() - getParticlesWidth, + AndroidUtilities.rectTmp.centerY() - getParticlesWidth, + AndroidUtilities.rectTmp.centerX() + getParticlesWidth, + AndroidUtilities.rectTmp.centerY() + getParticlesWidth); + starDrawable.rect2.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + } + starDrawable.resetPositions(); + starDrawable.excludeRect.set(AndroidUtilities.rectTmp); + starDrawable.excludeRect.inset(AndroidUtilities.dp(10), AndroidUtilities.dp(10)); + } + if (speedLinesDrawable != null) { + speedLinesDrawable.rect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + speedLinesDrawable.screenRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + speedLinesDrawable.rect.inset(AndroidUtilities.dp(100), AndroidUtilities.dp(100)); + speedLinesDrawable.rect.offset(0, getMeasuredHeight() * 0.1f); + speedLinesDrawable.resetPositions(); + } + } + } + + + @Override + protected void dispatchDraw(Canvas canvas) { + if ((starDrawable != null || speedLinesDrawable != null || matrixParticlesDrawable != null) && progress < 0.5f) { + float s = (float) Math.pow(1f - progress, 2f); + canvas.save(); + canvas.scale(s, s, getMeasuredWidth() / 2f, getMeasuredHeight() / 2f); + if (matrixParticlesDrawable != null) { + matrixParticlesDrawable.onDraw(canvas); + } else if (starDrawable != null) { + starDrawable.onDraw(canvas); + } else if (speedLinesDrawable != null) { + float videoSpeedScale = 0.2f; + + if (videoPlayer != null) { + float p = videoPlayer.getCurrentPosition() / (float) videoPlayer.getDuration(); + p = Utilities.clamp(p, 1f, 0); + float step = 1f / (speedScaleVideoTimestamps.length - 1); + int fromIndex = (int) (p / step); + int toIndex = fromIndex + 1; + float localProgress = (p - fromIndex * step) / step; + if (toIndex < speedScaleVideoTimestamps.length) { + videoSpeedScale = speedScaleVideoTimestamps[fromIndex] * (1f - localProgress) + speedScaleVideoTimestamps[toIndex] * localProgress; + } else { + videoSpeedScale = speedScaleVideoTimestamps[fromIndex]; + } + } + float progressSpeedScale = 0.1f + 0.9f * (1f - Utilities.clamp(progress / 0.1f, 1f, 0)); + speedLinesDrawable.speedScale = 150 * progressSpeedScale * videoSpeedScale; + speedLinesDrawable.onDraw(canvas); + } + canvas.restore(); + invalidate(); + } + int size = (int) (getMeasuredHeight() * 0.9f); + float h = size; + float w = size * 0.671f; + float horizontalPadding = (getMeasuredWidth() - w) / 2f; + roundRadius = size * 0.0671f; + if (fromTop) { + AndroidUtilities.rectTmp.set(horizontalPadding, -roundRadius, getMeasuredWidth() - horizontalPadding, h); + } else { + AndroidUtilities.rectTmp.set(horizontalPadding, getMeasuredHeight() - h, getMeasuredWidth() - horizontalPadding, getMeasuredHeight() + roundRadius); + } + AndroidUtilities.rectTmp.inset(-AndroidUtilities.dp(3), -AndroidUtilities.dp(3)); + AndroidUtilities.rectTmp.inset(-AndroidUtilities.dp(3), -AndroidUtilities.dp(3)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, roundRadius + AndroidUtilities.dp(3), roundRadius + AndroidUtilities.dp(3), phoneFrame2); + AndroidUtilities.rectTmp.inset(AndroidUtilities.dp(3), AndroidUtilities.dp(3)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, roundRadius, roundRadius, phoneFrame1); + + if (fromTop) { + AndroidUtilities.rectTmp.set(horizontalPadding, 0, getMeasuredWidth() - horizontalPadding, h); + } else { + AndroidUtilities.rectTmp.set(horizontalPadding, getMeasuredHeight() - h, getMeasuredWidth() - horizontalPadding, getMeasuredHeight()); + } + + roundRadius -= AndroidUtilities.dp(3); + if (roundedBitmapDrawable != null) { + roundedBitmapDrawable.setCornerRadius(roundRadius); + } + if (cellFlickerDrawable != null) { + cellFlickerDrawable.radius = roundRadius; + } + if (fromTop) { + imageReceiver.setRoundRadius(0, 0, (int) roundRadius, (int) roundRadius); + } else { + imageReceiver.setRoundRadius((int) roundRadius, (int) roundRadius, 0, 0); + } + if (!firstFrameRendered) { + imageReceiver.setImageCoords(AndroidUtilities.rectTmp.left, AndroidUtilities.rectTmp.top, AndroidUtilities.rectTmp.width(), AndroidUtilities.rectTmp.height()); + imageReceiver.draw(canvas); + } + super.dispatchDraw(canvas); + + if (!fromTop) { + canvas.drawCircle(imageReceiver.getCenterX(), imageReceiver.getImageY() + AndroidUtilities.dp(12), AndroidUtilities.dp(6), phoneFrame1); + } + + } + + @Override + public void setOffset(float translationX) { + boolean localVisible; + boolean localAllowPlay; + if (translationX < 0) { + float p = (-translationX / (float) getMeasuredWidth()); + setAlpha(0.5f + Utilities.clamp(1f - p, 1f, 0) * 0.5f); + setRotationY(50 * p); + invalidate(); + if (fromTop) { + setTranslationY(-getMeasuredHeight() * 0.3f * p); + } else { + setTranslationY(getMeasuredHeight() * 0.3f * p); + } + progress = Math.abs(p); + localVisible = p < 1f; + localAllowPlay = p < 0.1f; + } else { + float p = (-translationX / (float) getMeasuredWidth()); + invalidate(); + setRotationY(50 * p); + if (fromTop) { + setTranslationY(getMeasuredHeight() * 0.3f * p); + } else { + setTranslationY(-getMeasuredHeight() * 0.3f * p); + } + localVisible = p > -1f; + localAllowPlay = p > -0.1f; + progress = Math.abs(p); + } + if (localVisible != visible) { + visible = localVisible; + updateAttachState(); + } + if (localAllowPlay != allowPlay) { + allowPlay = localAllowPlay; + imageReceiver.setAllowStartAnimation(allowPlay); + if (allowPlay) { + imageReceiver.startAnimation(); + runVideoPlayer(); + } else { + stopVideoPlayer(); + imageReceiver.stopAnimation(); + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + attached = true; + updateAttachState(); + if (!firstFrameRendered) { + checkVideo(); + } + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.fileLoaded); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + attached = false; + updateAttachState(); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.fileLoaded); + } + + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.fileLoaded) { + final String path = (String) args[0]; + if (attachFileName != null && attachFileName.equals(path)) { + file = (File) args[1]; + checkVideo(); + } + } + } + + private void updateAttachState() { + boolean localPlay = visible && attached; + if (play != localPlay) { + play = localPlay; + if (play) { + imageReceiver.onAttachedToWindow(); + } else { + imageReceiver.onDetachedFromWindow(); + } + } + } + + private void runVideoPlayer() { + if (file != null) { + if (videoPlayer != null) { + return; + } + aspectRatioFrameLayout.setAspectRatio(aspectRatio, 0); + videoPlayer = new VideoPlayer(); + videoPlayer.setTextureView(textureView); + videoPlayer.setDelegate(new VideoPlayer.VideoPlayerDelegate() { + @Override + public void onStateChanged(boolean playWhenReady, int playbackState) { + if (playbackState == ExoPlayer.STATE_ENDED) { + videoPlayer.seekTo(0); + videoPlayer.play(); + } else if (playbackState == ExoPlayer.STATE_IDLE) { + videoPlayer.play(); + } + } + + @Override + public void onError(VideoPlayer player, Exception e) { + + } + + @Override + public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) { + + } + + @Override + public void onRenderedFirstFrame() { + if (!firstFrameRendered) { + textureView.setAlpha(0); + textureView.animate().alpha(1f).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + firstFrameRendered = true; + invalidate(); + } + }).setDuration(200); + } + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + + @Override + public boolean onSurfaceDestroyed(SurfaceTexture surfaceTexture) { + return false; + } + + }); + videoPlayer.preparePlayer(Uri.fromFile(file), "other"); + videoPlayer.setPlayWhenReady(true); + if (!firstFrameRendered) { + imageReceiver.stopAnimation(); + textureView.setAlpha(0); + } + videoPlayer.seekTo(lastFrameTime + 60); + videoPlayer.play(); + } + } + + long lastFrameTime; + + private void stopVideoPlayer() { + if (videoPlayer != null) { + lastFrameTime = videoPlayer.getCurrentPosition(); + videoPlayer.setTextureView(null); + videoPlayer.releasePlayer(true); + videoPlayer = null; + } + } +} 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 c814746d1..997ee13f7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -25,7 +25,6 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLoader; -import org.telegram.messenger.ImageLoader; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; import org.telegram.messenger.MessagesController; @@ -871,7 +870,7 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio needProgress = true; String filter; if (isProfileFragment && videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) { - filter = ImageLoader.AUTOPLAY_FILTER; + filter = "avatar"; } else { filter = null; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressButton.java index 89a21e072..3c48ab79b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProgressButton.java @@ -78,7 +78,11 @@ public class ProgressButton extends Button { } public void setBackgroundRoundRect(int backgroundColor, int pressedBackgroundColor) { - setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), backgroundColor, pressedBackgroundColor)); + setBackgroundRoundRect(backgroundColor, pressedBackgroundColor, 4); + } + + public void setBackgroundRoundRect(int backgroundColor, int pressedBackgroundColor, float radius) { + setBackground(Theme.AdaptiveRipple.filledRect(backgroundColor, radius)); } public void setProgressColor(int progressColor) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java index 00b063618..e01ae52ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProximitySheet.java @@ -251,7 +251,7 @@ public class ProximitySheet extends FrameLayout { buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setMaxLines(2); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackgroundDrawable(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); buttonContainer.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); buttonTextView.setOnClickListener(v -> { if (buttonTextView.getTag() != null) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/QRCodeBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/QRCodeBottomSheet.java index 0ab4514b7..c6f43bcd3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/QRCodeBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/QRCodeBottomSheet.java @@ -50,6 +50,7 @@ public class QRCodeBottomSheet extends BottomSheet { public QRCodeBottomSheet(Context context, String link, String helpMessage) { super(context, false); + fixNavigationBar(); setTitle(LocaleController.getString("InviteByQRCode", R.string.InviteByQRCode), true); ImageView imageView = new ImageView(context) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java index cea4cf734..3cd85efa6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -35,6 +35,7 @@ import java.io.InputStream; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -51,6 +52,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { private static native void replaceColors(long ptr, int[] colorReplacement); public static native int getFrame(long ptr, int frame, Bitmap bitmap, int w, int h, int stride, boolean clear); private static native void createCache(long ptr, int w, int h); + private static native String getCacheFile(long ptr); protected int width; protected int height; @@ -122,6 +124,11 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { private ArrayList> parentViews = new ArrayList<>(); private static DispatchQueuePool loadFrameRunnableQueue = new DispatchQueuePool(4); private static ThreadPoolExecutor lottieCacheGenerateQueue; + private static HashSet generatingCacheFiles = new HashSet<>(); + + File file; + File cacheFile; + boolean precache; private Runnable onAnimationEndListener; private Runnable onFrameReadyRunnable; @@ -137,13 +144,6 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } }; - private Runnable uiRunnableCacheFinished = new Runnable() { - @Override - public void run() { - cacheGenerateTask = null; - decodeFrameFinishedInternal(); - } - }; protected Runnable uiRunnable = new Runnable() { @Override @@ -167,19 +167,26 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } }; + long startTime; + private Runnable uiRunnableGenerateCache = new Runnable() { @Override public void run() { if (!isRecycled && !destroyWhenDone && nativePtr != 0) { + startTime = System.currentTimeMillis(); lottieCacheGenerateQueue.execute(cacheGenerateTask = () -> { - if (cacheGenerateTask == null) { - return; - } - createCache(nativePtr, width, height); uiHandler.post(uiRunnableCacheFinished); }); } + } + }; + + private Runnable uiRunnableCacheFinished = new Runnable() { + @Override + public void run() { + cacheGenerateTask = null; + generatingCacheFiles.remove(cacheFile.getPath()); decodeFrameFinishedInternal(); } }; @@ -220,23 +227,17 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { } protected void recycleResources() { - try { - if (renderingBitmap != null) { - renderingBitmap.recycle(); - renderingBitmap = null; - } - if (backgroundBitmap != null) { - backgroundBitmap.recycle(); - backgroundBitmap = null; - } - } catch (Exception e) { - FileLog.e(e); - renderingBitmap = null; - backgroundBitmap = null; - } + ArrayList bitmapToRecycle = new ArrayList<>(); + bitmapToRecycle.add(renderingBitmap); + bitmapToRecycle.add(nextRenderingBitmap); + renderingBitmap = null; + backgroundBitmap = null; + AndroidUtilities.recycleBitmaps(bitmapToRecycle); + if (onAnimationEndListener != null) { onAnimationEndListener = null; } + invalidateInternal(); } public void setOnFinishCallback(Runnable callback, int frame) { @@ -382,7 +383,6 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { this(file, w, h, precache, limitFps, null, 0); } - File file; public RLottieDrawable(File file, int w, int h, boolean precache, boolean limitFps, int[] colorReplacement, int fitzModifier) { width = w; height = h; @@ -397,6 +397,10 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { if (nativePtr == 0) { file.delete(); } + String cacheFilePath = getCacheFile(nativePtr); + if (cacheFilePath != null) { + cacheFile = new File(cacheFilePath); + } if (shouldLimitFps && metaData[1] < 60) { shouldLimitFps = false; } @@ -1040,7 +1044,7 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { if (isRunning) { if (renderingBitmap == null && nextRenderingBitmap == null) { scheduleNextGetFrame(); - } else if (nextRenderingBitmap != null && (renderingBitmap == null || timeDiff >= timeCheck) && isCurrentParentViewMaster()) { + } else if (nextRenderingBitmap != null && (renderingBitmap == null || timeDiff >= timeCheck)) { if (vibrationPattern != null && currentParentView != null) { Integer force = vibrationPattern.get(currentFrame - 1); if (force != null && !NekoConfig.disableVibration.Bool()) { @@ -1100,4 +1104,8 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable { public void setOnFrameReadyRunnable(Runnable onFrameReadyRunnable) { this.onFrameReadyRunnable = onFrameReadyRunnable; } + + public boolean isLastFrame() { + return currentFrame == getFramesCount() - 1; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java index 4cbd7bc35..259f36fad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedHeaderView.java @@ -209,7 +209,7 @@ public class ReactedHeaderView extends FrameLayout { if (message.messageOwner.reactions != null && message.messageOwner.reactions.results.size() == 1 && !list.reactions.isEmpty()) { for (TLRPC.TL_availableReaction r : MediaDataController.getInstance(currentAccount).getReactionsList()) { if (r.reaction.equals(list.reactions.get(0).reaction)) { - reactView.setImage(ImageLocation.getForDocument(r.static_icon), "50_50", "webp", null, r); + reactView.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_lastframe", "webp", null, r); reactView.setVisibility(VISIBLE); reactView.setAlpha(0); reactView.animate().alpha(1f).start(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java index 90ec9dd18..9438e553c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactedUsersListView.java @@ -6,6 +6,7 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; import android.util.LongSparseArray; @@ -13,7 +14,9 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; +import android.widget.LinearLayout; import android.widget.TextView; import androidx.annotation.NonNull; @@ -23,10 +26,12 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.DocumentObject; import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserObject; import org.telegram.tgnet.ConnectionsManager; @@ -47,7 +52,7 @@ public class ReactedUsersListView extends FrameLayout { private MessageObject message; private String filter; - private RecyclerListView listView; + public RecyclerListView listView; private RecyclerView.Adapter adapter; private FlickerLoadingView loadingView; @@ -55,7 +60,7 @@ public class ReactedUsersListView extends FrameLayout { private List userReactions = new ArrayList<>(); private LongSparseArray peerReactionMap = new LongSparseArray<>(); private String offset; - private boolean isLoading, isLoaded, canLoadMore = true; + public boolean isLoading, isLoaded, canLoadMore = true; private boolean onlySeenNow; private OnHeightChangedListener onHeightChangedListener; @@ -120,7 +125,7 @@ public class ReactedUsersListView extends FrameLayout { loadingView = new FlickerLoadingView(context, resourcesProvider); loadingView.setViewType(FlickerLoadingView.REACTED_TYPE); loadingView.setIsSingleCell(true); - loadingView.setItemsCount(reactionCount == null ? VISIBLE_ITEMS : reactionCount.count); + loadingView.setItemsCount(predictiveCount); addView(loadingView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } @@ -271,6 +276,7 @@ public class ReactedUsersListView extends FrameLayout { titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); titleView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); titleView.setEllipsize(TextUtils.TruncateAt.END); + titleView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); addView(titleView, LayoutHelper.createFrameRelatively(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 58, 0, 44, 0)); reactView = new BackupImageView(context); @@ -288,18 +294,24 @@ public class ReactedUsersListView extends FrameLayout { } avatarDrawable.setInfo(u); titleView.setText(UserObject.getUserName(u)); - avatarView.setImage(ImageLocation.getForUser(u, ImageLocation.TYPE_SMALL), "50_50", avatarDrawable, u); + Drawable thumb = avatarDrawable; + if (u.photo != null && u.photo.strippedBitmap != null) { + thumb = u.photo.strippedBitmap; + } + avatarView.setImage(ImageLocation.getForUser(u, ImageLocation.TYPE_SMALL), "50_50", thumb, u); if (reaction.reaction != null) { TLRPC.TL_availableReaction r = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction.reaction); if (r != null) { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(r.static_icon.thumbs, Theme.key_windowBackgroundGray, 1.0f); - reactView.setImage(ImageLocation.getForDocument(r.static_icon), "50_50", "webp", svgThumb, r); + reactView.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_lastframe", "webp", svgThumb, r); } else { reactView.setImageDrawable(null); } + setContentDescription(LocaleController.formatString("AccDescrReactedWith", R.string.AccDescrReactedWith, UserObject.getUserName(u), reaction.reaction)); } else { reactView.setImageDrawable(null); + setContentDescription(LocaleController.formatString("AccDescrPersonHasSeen", R.string.AccDescrPersonHasSeen, UserObject.getUserName(u))); } } @@ -307,6 +319,12 @@ public class ReactedUsersListView extends FrameLayout { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(ITEM_HEIGHT_DP), MeasureSpec.EXACTLY)); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + } } public ReactedUsersListView setOnProfileSelectedListener(OnProfileSelectedListener onProfileSelectedListener) { @@ -326,4 +344,60 @@ public class ReactedUsersListView extends FrameLayout { public interface OnProfileSelectedListener { void onProfileSelected(ReactedUsersListView view, long userId); } + + public void setPredictiveCount(int predictiveCount) { + this.predictiveCount = predictiveCount; + loadingView.setItemsCount(predictiveCount); + } + + public static class ContainerLinerLayout extends LinearLayout { + + public boolean hasHeader; + + public ContainerLinerLayout(Context context) { + super(context); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int maxWidth = 0; + RecyclerListView listView = null; + if (!hasHeader) { + for (int k = 0; k < getChildCount(); k++) { + if (getChildAt(k) instanceof ReactedUsersListView) { + listView = ((ReactedUsersListView) getChildAt(k)).listView; + if (listView.getAdapter().getItemCount() == listView.getChildCount()) { + int count = listView.getChildCount(); + for (int i = 0; i < count; i++) { + listView.getChildAt(i).measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), MeasureSpec.UNSPECIFIED), heightMeasureSpec); + if (listView.getChildAt(i).getMeasuredWidth() > maxWidth) { + maxWidth = listView.getChildAt(i).getMeasuredWidth(); + } + } + maxWidth += AndroidUtilities.dp(16); + } + } + } + } + int size = MeasureSpec.getSize(widthMeasureSpec); + if (size < AndroidUtilities.dp(240)) { + size = AndroidUtilities.dp(240); + } + if (size > AndroidUtilities.dp(280)) { + size = AndroidUtilities.dp(280); + } + if (size < 0) { + size = 0; + } + if (maxWidth != 0 && maxWidth < size) { + size = maxWidth; + } + if (listView != null) { + for (int i = 0; i < listView.getChildCount(); i++) { + listView.getChildAt(i).measure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), heightMeasureSpec); + } + } + super.onMeasure(MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY), heightMeasureSpec); + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java index 7e94ed393..598979c6f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionTabHolderView.java @@ -11,6 +11,7 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -42,6 +43,10 @@ public class ReactionTabHolderView extends FrameLayout { View overlaySelectorView; private float outlineProgress; Drawable drawable; + + private int count; + private String reaction; + public ReactionTabHolderView(@NonNull Context context) { super(context); @@ -55,7 +60,9 @@ public class ReactionTabHolderView extends FrameLayout { reactView = new BackupImageView(context); addView(reactView, LayoutHelper.createFrameRelatively(24, 24, Gravity.START | Gravity.CENTER_VERTICAL, 8, 0, 8, 0)); + counterView = new TextView(context); + counterView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO); counterView.setTextColor(Theme.getColor(Theme.key_avatar_nameInMessageBlue)); counterView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); addView(counterView, LayoutHelper.createFrameRelatively(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL, 40, 0, 8, 0)); @@ -90,18 +97,22 @@ public class ReactionTabHolderView extends FrameLayout { } public void setCounter(int count) { + this.count = count; counterView.setText(String.format("%s", LocaleController.formatShortNumber(count, null))); iconView.setVisibility(VISIBLE); reactView.setVisibility(GONE); } public void setCounter(int currentAccount, TLRPC.TL_reactionCount counter) { + this.count = counter.count; counterView.setText(String.format("%s", LocaleController.formatShortNumber(counter.count, null))); String e = counter.reaction; + this.reaction = null; for (TLRPC.TL_availableReaction r : MediaDataController.getInstance(currentAccount).getReactionsList()) { if (r.reaction.equals(e)) { SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(r.static_icon, Theme.key_windowBackgroundGray, 1.0f); - reactView.setImage(ImageLocation.getForDocument(r.static_icon), "50_50", "webp", svgThumb, r); + this.reaction = r.reaction; + reactView.setImage(ImageLocation.getForDocument(r.center_icon), "40_40_lastframe", "webp", svgThumb, r); reactView.setVisibility(VISIBLE); iconView.setVisibility(GONE); break; @@ -121,4 +132,19 @@ public class ReactionTabHolderView extends FrameLayout { // rect.set(w, w, getWidth() - w, getHeight() - w); // canvas.drawRoundRect(rect, radius, radius, outlinePaint); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setClassName("android.widget.Button"); + info.setClickable(true); + if (outlineProgress > .5) { + info.setSelected(true); + } + if (reaction != null) { + info.setText(LocaleController.formatPluralString("AccDescrNumberOfPeopleReactions", count, reaction)); + } else { + info.setText(LocaleController.formatPluralString("AccDescrNumberOfReactions", count)); + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java index 9ff13e728..8b26004dd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Reactions/ReactionsEffectOverlay.java @@ -191,14 +191,18 @@ public class ReactionsEffectOverlay { } int size; + int sizeForFilter; if (animationType == ONLY_MOVE_ANIMATION) { size = AndroidUtilities.dp(34); + sizeForFilter = (int) (2f * size / AndroidUtilities.density); } else if (animationType == SHORT_ANIMATION) { size = AndroidUtilities.dp(80); + sizeForFilter = (int) (2f * size / AndroidUtilities.density); } else { size = Math.round(Math.min(AndroidUtilities.dp(350), Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)) * 0.8f); + sizeForFilter = sizeForBigReaction(); } - int sizeForFilter = (int) (2f * size / AndroidUtilities.density); + int emojiSize = size >> 1; int emojiSizeForFilter = sizeForFilter >> 1; @@ -415,6 +419,9 @@ public class ReactionsEffectOverlay { particle.outProgress += 16f / 150f; if (particle.outProgress > 1f) { particle.outProgress = 1f; + avatars.remove(i); + i--; + continue; } } float jumpProgress = progress < 0.5f ? (progress / 0.5f) : (1f - ((progress - 0.5f) / 0.5f)); @@ -534,7 +541,7 @@ public class ReactionsEffectOverlay { ((FrameLayout.LayoutParams) emojiImageView.getLayoutParams()).leftMargin = leftOffset; if (animationType != SHORT_ANIMATION) { - emojiStaticImageView.getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.static_icon), "40_40", null, "webp", availableReaction, 1); + emojiStaticImageView.getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.center_icon), "40_40_lastframe", null, "webp", availableReaction, 1); } container.addView(emojiStaticImageView); emojiStaticImageView.getLayoutParams().width = emojiSize; @@ -709,6 +716,10 @@ public class ReactionsEffectOverlay { } } + public static int sizeForBigReaction() { + return (int) (Math.round(Math.min(AndroidUtilities.dp(350), Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)) * 0.7f) / AndroidUtilities.density); + } + private class AvatarParticle { ImageReceiver imageReceiver; @@ -725,6 +736,5 @@ public class ReactionsEffectOverlay { float currentRotation; boolean incrementRotation; float globalTranslationY; - } } 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 65e95d52c..41617d7f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReactionsContainerLayout.java @@ -24,11 +24,13 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; import androidx.core.util.Consumer; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -44,12 +46,16 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; +import org.telegram.ui.Components.Premium.PremiumLockIconView; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -86,9 +92,12 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private MessageObject messageObject; private int currentAccount; private long waitingLoadingChatId; - ValueAnimator cancelPressedAnimation; - private List reactionsList = Collections.emptyList(); + ValueAnimator cancelPressedAnimation; + FrameLayout premiumLockContainer; + + private List reactionsList = new ArrayList<>(20); + private List premiumLockedReactions = new ArrayList<>(10); private LinearLayoutManager linearLayoutManager; private RecyclerView.Adapter listAdapter; @@ -111,11 +120,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio private float otherViewsScale; private boolean clicked; long lastReactionSentTime; + BaseFragment fragment; + private PremiumLockIconView premiumLockIconView; - public ReactionsContainerLayout(@NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { + public ReactionsContainerLayout(BaseFragment fragment, @NonNull Context context, int currentAccount, Theme.ResourcesProvider resourcesProvider) { super(context); this.resourcesProvider = resourcesProvider; this.currentAccount = currentAccount; + this.fragment = fragment; animationEnabled = MessagesController.getGlobalMainSettings().getBoolean("view_animations", true) && SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW; @@ -126,7 +138,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio recyclerListView = new RecyclerListView(context) { @Override public boolean drawChild(Canvas canvas, View child, long drawingTime) { - if (pressedReaction != null && ((ReactionHolderView) child).currentReaction.reaction.equals(pressedReaction)) { + if (pressedReaction != null && (child instanceof ReactionHolderView) && ((ReactionHolderView) child).currentReaction.reaction.equals(pressedReaction)) { return true; } return super.drawChild(canvas, child, drawingTime); @@ -143,7 +155,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio } outRect.right = AndroidUtilities.dp(4); if (position == listAdapter.getItemCount() - 1) { - outRect.right = AndroidUtilities.dp(6); + if (showUnlockPremiumButton()) { + outRect.right = AndroidUtilities.dp(2); + } else { + outRect.right = AndroidUtilities.dp(6); + } } } }); @@ -153,23 +169,56 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - ReactionHolderView hv = new ReactionHolderView(context); + View view; + switch (viewType) { + default: + case 0: + view = new ReactionHolderView(context); + break; + case 1: + premiumLockContainer = new FrameLayout(context); + premiumLockIconView = new PremiumLockIconView(context, PremiumLockIconView.TYPE_REACTIONS); + premiumLockIconView.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon), Theme.getColor(Theme.key_dialogBackground), 0.7f)); + premiumLockIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + premiumLockIconView.setScaleX(0f); + premiumLockIconView.setScaleY(0f); + premiumLockIconView.setPadding(AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1), AndroidUtilities.dp(1)); + premiumLockContainer.addView(premiumLockIconView, LayoutHelper.createFrame(26, 26, Gravity.CENTER)); + premiumLockIconView.setOnClickListener(v -> { + int[] position = new int[2]; + v.getLocationOnScreen(position); + showUnlockPremium(position[0] + v.getMeasuredWidth() / 2f, position[1] + v.getMeasuredHeight() / 2f); + }); + view = premiumLockContainer; + break; + } + int size = getLayoutParams().height - getPaddingTop() - getPaddingBottom(); - hv.setLayoutParams(new RecyclerView.LayoutParams(size - AndroidUtilities.dp(12), size)); - return new RecyclerListView.Holder(hv); + view.setLayoutParams(new RecyclerView.LayoutParams(size - AndroidUtilities.dp(12), size)); + return new RecyclerListView.Holder(view); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - ReactionHolderView h = (ReactionHolderView) holder.itemView; - h.setScaleX(1); - h.setScaleY(1); - h.setReaction(reactionsList.get(position)); + if (holder.getItemViewType() == 0) { + ReactionHolderView h = (ReactionHolderView) holder.itemView; + h.setScaleX(1); + h.setScaleY(1); + h.setReaction(reactionsList.get(position)); + } } @Override public int getItemCount() { - return reactionsList.size(); + return reactionsList.size() + (showUnlockPremiumButton() ? 1 : 0); + } + + @Override + public int getItemViewType(int position) { + if (position >= 0 && position < reactionsList.size()) { + return 0; + } + return 1; } }); recyclerListView.addOnScrollListener(new LeftRightShadowsListener()); @@ -189,7 +238,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio int dX1 = ch1X - rX; float s1 = SIDE_SCALE + (1f - Math.min(1, -Math.min(dX1, 0f) / ch1.getWidth())) * sideDiff; if (Float.isNaN(s1)) s1 = 1f; - ((ReactionHolderView) ch1).sideScale = s1; + setChildScale(ch1, s1); View ch2 = recyclerView.getChildAt(recyclerView.getChildCount() - 1); ch2.getLocationInWindow(location); @@ -198,11 +247,11 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio int dX2 = rX + recyclerView.getWidth() - (ch2X + ch2.getWidth()); float s2 = SIDE_SCALE + (1f - Math.min(1, -Math.min(dX2, 0f) / ch2.getWidth())) * sideDiff; if (Float.isNaN(s2)) s2 = 1f; - ((ReactionHolderView) ch2).sideScale = s2; + setChildScale(ch2, s2); } for (int i = 1; i < recyclerListView.getChildCount() - 1; i++) { View ch = recyclerListView.getChildAt(i); - ((ReactionHolderView) ch).sideScale = 1f; + setChildScale(ch, 1f); } invalidate(); } @@ -217,19 +266,53 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio outRect.right = AndroidUtilities.dp(8); } }); + recyclerListView.setOnItemClickListener((view, position) -> { + if (delegate != null && view instanceof ReactionHolderView) { + ReactionHolderView reactionHolderView = (ReactionHolderView) view; + delegate.onReactionClicked(this, reactionHolderView.currentReaction, false); + } + }); + recyclerListView.setOnItemLongClickListener((view, position) -> { + if (delegate != null && view instanceof ReactionHolderView) { + ReactionHolderView reactionHolderView = (ReactionHolderView) view; + delegate.onReactionClicked(this, reactionHolderView.currentReaction, true); + return true; + } + return false; + }); addView(recyclerListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); invalidateShaders(); bgPaint.setColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuBackground, resourcesProvider)); } + private boolean showUnlockPremiumButton() { + return !premiumLockedReactions.isEmpty() && !MessagesController.getInstance(currentAccount).premiumLocked; + } + + private void showUnlockPremium(float x, float y) { + PremiumFeatureBottomSheet bottomSheet = new PremiumFeatureBottomSheet(fragment, PremiumPreviewFragment.PREMIUM_FEATURE_REACTIONS, true); + bottomSheet.show(); + } + + private void setChildScale(View child, float scale) { + if (child instanceof ReactionHolderView) { + ((ReactionHolderView) child).sideScale = scale; + } else { + child.setScaleX(scale); + child.setScaleY(scale); + } + } + public void setDelegate(ReactionsContainerDelegate delegate) { this.delegate = delegate; } @SuppressLint("NotifyDataSetChanged") private void setReactionsList(List reactionsList) { - this.reactionsList = reactionsList; + this.reactionsList.clear(); + this.reactionsList.addAll(reactionsList); + checkPremiumReactions(this.reactionsList); int size = getLayoutParams().height - getPaddingTop() - getPaddingBottom(); if (size * reactionsList.size() < AndroidUtilities.dp(200)) { getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT; @@ -303,19 +386,34 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (transitionProgress != 0 && getAlpha() == 1f) { int delay = 0; for (int i = 0; i < recyclerListView.getChildCount(); i++) { - ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i); - checkPressedProgress(canvas, view); - if (view.backupImageView.getImageReceiver().getLottieAnimation() == null) { - continue; - } - if (view.getX() + view.getMeasuredWidth() / 2f > 0 && view.getX() + view.getMeasuredWidth() / 2f < recyclerListView.getWidth()) { - if (!lastVisibleViewsTmp.contains(view)) { - view.play(delay); - delay += 30; + View child = recyclerListView.getChildAt(i); + if (child instanceof ReactionHolderView) { + ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i); + checkPressedProgress(canvas, view); + if (view.backupImageView.getImageReceiver().getLottieAnimation() == null) { + continue; + } + if (view.getX() + view.getMeasuredWidth() / 2f > 0 && view.getX() + view.getMeasuredWidth() / 2f < recyclerListView.getWidth()) { + if (!lastVisibleViewsTmp.contains(view)) { + view.play(delay); + delay += 30; + } + lastVisibleViews.add(view); + } else if (!view.isEnter) { + view.resetAnimation(); + } + } else { + if (child == premiumLockContainer) { + if (child.getX() + child.getMeasuredWidth() / 2f > 0 && child.getX() + child.getMeasuredWidth() / 2f < recyclerListView.getWidth()) { + if (!lastVisibleViewsTmp.contains(child)) { + premiumLockIconView.play(delay); + delay += 30; + } + lastVisibleViews.add(child); + } else { + premiumLockIconView.resetAnimation(); + } } - lastVisibleViews.add(view); - } else if (!view.isEnter) { - view.resetAnimation(); } } } @@ -353,6 +451,22 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio canvas.restore(); } + private void checkPressedProgressForOtherViews(View view) { + int position = recyclerListView.getChildAdapterPosition(view); + float translationX; + translationX = (view.getMeasuredWidth() * (pressedViewScale - 1f)) / 3f - view.getMeasuredWidth() * (1f - otherViewsScale) * (Math.abs(pressedReactionPosition - position) - 1); + + if (position < pressedReactionPosition) { + view.setPivotX(0); + view.setTranslationX(-translationX); + } else { + view.setPivotX(view.getMeasuredWidth()); + view.setTranslationX(translationX); + } + view.setScaleX(otherViewsScale); + view.setScaleY(otherViewsScale); + } + private void checkPressedProgress(Canvas canvas, ReactionHolderView view) { if (view.currentReaction.reaction.equals(pressedReaction)) { @@ -471,6 +585,23 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio setReactionsList(l); } + private void checkPremiumReactions(List reactions) { + premiumLockedReactions.clear(); + if (UserConfig.getInstance(currentAccount).isPremium()) { + return; + } + try { + for (int i = 0; i < reactions.size(); i++) { + if (reactions.get(i).premium) { + premiumLockedReactions.add(reactions.remove(i)); + i--; + } + } + } catch (Exception e) { + return; + } + } + public void startEnterAnimation() { setTransitionProgress(0); setAlpha(1f); @@ -545,10 +676,17 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (backupImageView.getImageReceiver().getLottieAnimation() != null && !backupImageView.getImageReceiver().getLottieAnimation().isRunning() && !backupImageView.getImageReceiver().getLottieAnimation().isGeneratingCache()) { backupImageView.getImageReceiver().getLottieAnimation().start(); } - } }; + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (currentReaction != null) { + info.setText(currentReaction.reaction); + info.setEnabled(true); + } + } ReactionHolderView(Context context) { super(context); @@ -582,6 +720,7 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(currentReaction.activate_animation, Theme.key_windowBackgroundGray, 1.0f); backupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(currentReaction.appear_animation), "60_60_nolimit", null, null, svgThumb, 0, "tgs", react, 0); pressedBackupImageView.getImageReceiver().setImage(ImageLocation.getForDocument(currentReaction.select_animation), "60_60_nolimit", null, null, svgThumb, 0, "tgs", react, 0); + setFocusable(true); } @Override @@ -638,8 +777,10 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio ReactionsContainerLayout.this.invalidate(); } }; + float pressedX, pressedY; boolean pressed; + @Override public boolean onTouchEvent(MotionEvent event) { if (cancelPressedAnimation != null) { @@ -653,14 +794,14 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio AndroidUtilities.runOnUIThread(longPressRunnable, ViewConfiguration.getLongPressTimeout()); } } - float touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop() * 2f; + float touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop() * 2f; boolean cancelByMove = event.getAction() == MotionEvent.ACTION_MOVE && (Math.abs(pressedX - event.getX()) > touchSlop || Math.abs(pressedY - event.getY()) > touchSlop); if (cancelByMove || event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { if (event.getAction() == MotionEvent.ACTION_UP && pressed && (pressedReaction == null || pressedProgress > 0.8f) && delegate != null) { clicked = true; if (System.currentTimeMillis() - lastReactionSentTime > 300) { lastReactionSentTime = System.currentTimeMillis(); - delegate.onReactionClicked(this, currentReaction, pressedProgress > 0.8f); + delegate.onReactionClicked(this, currentReaction, pressedProgress > 0.8f); } } @@ -706,6 +847,8 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio public interface ReactionsContainerDelegate { void onReactionClicked(View v, TLRPC.TL_availableReaction reaction, boolean longpress); + + void hideMenu(); } @Override @@ -737,10 +880,19 @@ public class ReactionsContainerLayout extends FrameLayout implements Notificatio if (getAlpha() != alpha && alpha == 0) { lastVisibleViews.clear(); for (int i = 0; i < recyclerListView.getChildCount(); i++) { - ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i); - view.resetAnimation(); + if (recyclerListView.getChildAt(i) instanceof ReactionHolderView) { + ReactionHolderView view = (ReactionHolderView) recyclerListView.getChildAt(i); + view.resetAnimation(); + } } } super.setAlpha(alpha); } + + @Override + public void setTranslationX(float translationX) { + if (translationX != getTranslationX()) { + super.setTranslationX(translationX); + } + } } \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java index 5fff8b70c..d33a546de 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -1445,6 +1445,10 @@ public class RecyclerListView extends RecyclerView { selectorDrawable.setCallback(this); } + public Drawable getSelectorDrawable() { + return selectorDrawable; + } + public void checkSection(boolean force) { if ((scrollingByUser || force) && fastScroll != null || sectionsType != SECTIONS_TYPE_SIMPLE && sectionsAdapter != null) { LayoutManager layoutManager = getLayoutManager(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java index 2229a669a..b3165e509 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ReportAlert.java @@ -41,7 +41,7 @@ public class ReportAlert extends BottomSheet { super(context); background = new View(context); - background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + background.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 16, 16, 16)); textView = new TextView(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java index a0aaa2438..67ad24472 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java @@ -93,7 +93,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { private int indicatorHeight; private GradientDrawable indicatorDrawable = new GradientDrawable(); - private int scrollOffset = AndroidUtilities.dp(52); + private int scrollOffset = AndroidUtilities.dp(StickerTabView.SMALL_WIDTH); private int underlineHeight = AndroidUtilities.dp(2); private int dividerPadding = AndroidUtilities.dp(12); private int tabPadding = AndroidUtilities.dp(24); @@ -163,6 +163,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } }; tabsContainer.setOrientation(LinearLayout.HORIZONTAL); + tabsContainer.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); addView(tabsContainer); @@ -170,7 +171,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { rectPaint.setAntiAlias(true); rectPaint.setStyle(Style.FILL); - defaultTabLayoutParams = new LinearLayout.LayoutParams(AndroidUtilities.dp(52), LayoutHelper.MATCH_PARENT); + defaultTabLayoutParams = new LinearLayout.LayoutParams(AndroidUtilities.dp(StickerTabView.SMALL_WIDTH), LayoutHelper.MATCH_PARENT); defaultExpandLayoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT, 1.0F); } @@ -448,7 +449,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { float expandProgress; private float stickerTabExpandedWidth = AndroidUtilities.dp(86); - private float stickerTabWidth = AndroidUtilities.dp(52); + private float stickerTabWidth = AndroidUtilities.dp(StickerTabView.SMALL_WIDTH); private float expandOffset; private int scrollByOnNextMeasure = -1; @@ -526,10 +527,10 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { if (child instanceof StickerTabView) { ((StickerTabView) child).setExpanded(false); } - child.getLayoutParams().width = AndroidUtilities.dp(52); + child.getLayoutParams().width = AndroidUtilities.dp(StickerTabView.SMALL_WIDTH); } animateToExpanded = false; - getLayoutParams().height = AndroidUtilities.dp(48); + getLayoutParams().height = AndroidUtilities.dp(StickerTabView.SMALL_HEIGHT); tabsContainer.requestLayout(); } } @@ -547,7 +548,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } tabsContainer.requestLayout(); - getLayoutParams().height = AndroidUtilities.dp(48 + 50); + getLayoutParams().height = AndroidUtilities.dp(StickerTabView.SMALL_HEIGHT + 50); } if (expanded) { @@ -610,9 +611,9 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } public void setImages() { - float tabSize = AndroidUtilities.dp( 52) + AndroidUtilities.dp(34) * expandProgress; + float tabSize = AndroidUtilities.dp(StickerTabView.SMALL_WIDTH) + AndroidUtilities.dp(86 - StickerTabView.SMALL_WIDTH) * expandProgress; float scrollOffset = animateToExpanded ? expandOffset * (1f - expandProgress) : 0; - int start = (int) ((getScrollX() - scrollOffset) / tabSize); + int start = (int) ((getScrollX() - scrollOffset - tabsContainer.getPaddingLeft()) / tabSize); int end = Math.min(tabsContainer.getChildCount(), start + (int) Math.ceil(getMeasuredWidth() / tabSize) + 1); if (animateToExpanded) { start -= 2; @@ -642,8 +643,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { thumbDrawable = (Drawable) thumb; } if (sticker instanceof TLRPC.Document) { - // String.format(Locale.US, "%d_%d_nr_%s" + messageObject.emojiAnimatedStickerColor, w, h, messageObject.toString()); - tabView.imageView.setImage(ImageLocation.getForDocument((TLRPC.Document) sticker), "36_36_nolimit", thumbDrawable, null); + tabView.imageView.setImage(ImageLocation.getForDocument((TLRPC.Document) sticker), "36_36_nolimit", (Drawable) null, null); } else { tabView.imageView.setImageDrawable(thumbDrawable); } @@ -713,7 +713,7 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView { } private int getTabSize() { - return AndroidUtilities.dp(animateToExpanded ? 86 : 52); + return AndroidUtilities.dp(animateToExpanded ? 86 : StickerTabView.SMALL_WIDTH); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java index e09758439..8669fb016 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTextTabStrip.java @@ -44,6 +44,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { private LinearLayout tabsContainer; private ScrollSlidingTabStripDelegate delegate; + private Theme.ResourcesProvider resourcesProvider; private boolean useSameWidth; @@ -119,12 +120,17 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { }; public ScrollSlidingTextTabStrip(Context context) { + this(context, null); + } + + public ScrollSlidingTextTabStrip(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; selectorDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, null); float rad = AndroidUtilities.dpf2(3); selectorDrawable.setCornerRadii(new float[]{rad, rad, rad, rad, 0, 0, 0, 0}); - selectorDrawable.setColor(Theme.getColor(tabLineColorKey)); + selectorDrawable.setColor(Theme.getColor(tabLineColorKey, resourcesProvider)); setFillViewport(true); setWillNotDraw(false); @@ -155,8 +161,8 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { if (newTab == null || prevTab == null) { return; } - int newColor = Theme.getColor(activeTextColorKey); - int prevColor = Theme.getColor(unactiveTextColorKey); + int newColor = Theme.getColor(activeTextColorKey, resourcesProvider); + int prevColor = Theme.getColor(unactiveTextColorKey, resourcesProvider); int r1 = Color.red(newColor); int g1 = Color.green(newColor); @@ -273,7 +279,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { }; tab.setWillNotDraw(false); tab.setGravity(Gravity.CENTER); - tab.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(selectorColorKey), 3)); + tab.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.getColor(selectorColorKey, resourcesProvider), 3)); tab.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); tab.setSingleLine(true); tab.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -331,7 +337,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { for (int a = 0; a < count; a++) { TextView tab = (TextView) tabsContainer.getChildAt(a); tab.setTag(currentPosition == a ? activeTextColorKey : unactiveTextColorKey); - tab.setTextColor(Theme.getColor(currentPosition == a ? activeTextColorKey : unactiveTextColorKey)); + tab.setTextColor(Theme.getColor(currentPosition == a ? activeTextColorKey : unactiveTextColorKey, resourcesProvider)); if (a == 0) { tab.getLayoutParams().width = count == 1 ? LayoutHelper.WRAP_CONTENT : 0; } @@ -343,7 +349,7 @@ public class ScrollSlidingTextTabStrip extends HorizontalScrollView { activeTextColorKey = active; unactiveTextColorKey = unactive; selectorColorKey = selector; - selectorDrawable.setColor(Theme.getColor(tabLineColorKey)); + selectorDrawable.setColor(Theme.getColor(tabLineColorKey, resourcesProvider)); } public int getCurrentTabId() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchDownloadsContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchDownloadsContainer.java index 99b5313b5..bcdb2ecb8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchDownloadsContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchDownloadsContainer.java @@ -3,11 +3,14 @@ package org.telegram.ui.Components; import android.app.Activity; import android.content.Context; import android.graphics.Color; +import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; @@ -197,13 +200,13 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio FileLoader.getInstance(currentAccount).getRecentLoadingFiles(recentLoadingFiles); for (int i = 0; i < currentLoadingFiles.size(); i++) { - if (FileLoader.getPathToMessage(currentLoadingFiles.get(i).messageOwner).exists()) { + if (FileLoader.getInstance(currentAccount).getPathToMessage(currentLoadingFiles.get(i).messageOwner).exists()) { moveToRecent.add(currentLoadingFiles.get(i)); } } for (int i = 0; i < recentLoadingFiles.size(); i++) { - if (!FileLoader.getPathToMessage(recentLoadingFiles.get(i).messageOwner).exists()) { + if (!FileLoader.getInstance(currentAccount).getPathToMessage(recentLoadingFiles.get(i).messageOwner).exists()) { removeFromRecent.add(recentLoadingFiles.get(i)); } } @@ -472,20 +475,25 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio if (type == 0) { GraySectionCell graySectionCell = (GraySectionCell) holder.itemView; if (position == downloadingFilesHeader) { - graySectionCell.setText(LocaleController.getString("Downloading", R.string.Downloading), hasCurrentDownload ? LocaleController.getString("PauseAll", R.string.PauseAll) : LocaleController.getString("ResumeAll", R.string.ResumeAll), new OnClickListener() { - @Override - public void onClick(View view) { - for (int i = 0; i < currentLoadingFiles.size(); i++) { - MessageObject messageObject = currentLoadingFiles.get(i); - if (hasCurrentDownload) { - AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().cancelLoadFile(messageObject.getDocument()); - } else { - AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().loadFile(messageObject.getDocument(), messageObject, 0, 0); + String header = LocaleController.getString("Downloading", R.string.Downloading); + if (graySectionCell.getText().equals(header)) { + graySectionCell.setRightText(hasCurrentDownload ? LocaleController.getString("PauseAll", R.string.PauseAll) : LocaleController.getString("ResumeAll", R.string.ResumeAll), hasCurrentDownload); + } else { + graySectionCell.setText(header, hasCurrentDownload ? LocaleController.getString("PauseAll", R.string.PauseAll) : LocaleController.getString("ResumeAll", R.string.ResumeAll), new OnClickListener() { + @Override + public void onClick(View view) { + for (int i = 0; i < currentLoadingFiles.size(); i++) { + MessageObject messageObject = currentLoadingFiles.get(i); + if (hasCurrentDownload) { + AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().cancelLoadFile(messageObject.getDocument()); + } else { + AccountInstance.getInstance(UserConfig.selectedAccount).getFileLoader().loadFile(messageObject.getDocument(), messageObject, 0, 0); + } } + update(true); } - update(true); - } - }); + }); + } } else if (position == recentFilesHeader) { graySectionCell.setText(LocaleController.getString("RecentlyDownloaded", R.string.RecentlyDownloaded), LocaleController.getString("Settings", R.string.Settings), new OnClickListener() { @Override @@ -607,6 +615,10 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio scrollView.addView(linearLayout); bottomSheet.setCustomView(scrollView); bottomSheet.show(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + AndroidUtilities.setLightStatusBar(bottomSheet.getWindow(), !Theme.isCurrentThemeDark()); + AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), !Theme.isCurrentThemeDark()); + } buttonTextView.setOnClickListener(view -> { bottomSheet.dismiss(); @@ -659,6 +671,12 @@ public class SearchDownloadsContainer extends FrameLayout implements Notificatio sharedDocumentCell.rightDateTextView.setVisibility(View.GONE); addView(sharedDocumentCell); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + sharedDocumentCell.onInitializeAccessibilityNodeInfo(info); + } } public void setUiCallback(FilteredSearchView.UiCallback callback) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java index ec007c366..1d0195d6c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SearchViewPager.java @@ -4,14 +4,18 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.content.DialogInterface; +import android.graphics.Canvas; +import android.graphics.Paint; import android.os.Bundle; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.view.View; +import android.view.animation.OvershootInterpolator; import android.widget.FrameLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -36,6 +40,8 @@ import org.telegram.ui.Adapters.DialogsSearchAdapter; import org.telegram.ui.Adapters.FiltersView; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.DialogCell; +import org.telegram.ui.Cells.HashtagSearchCell; +import org.telegram.ui.Cells.ProfileSearchCell; import org.telegram.ui.Cells.SharedAudioCell; import org.telegram.ui.Cells.SharedDocumentCell; import org.telegram.ui.Cells.SharedLinkCell; @@ -55,6 +61,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie public FrameLayout searchContainer; public RecyclerListView searchListView; public StickerEmptyView emptyView; + private DefaultItemAnimator itemAnimator; public DialogsSearchAdapter dialogsSearchAdapter; private LinearLayoutManager searchLayoutManager; private RecyclerItemsEnterAnimator itemsEnterAnimator; @@ -99,7 +106,16 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie this.folderId = folderId; parent = fragment; this.chatPreviewDelegate = chatPreviewDelegate; - dialogsSearchAdapter = new DialogsSearchAdapter(context, type, initialDialogsType) { + + itemAnimator = new DefaultItemAnimator(); + itemAnimator.setAddDuration(150); + itemAnimator.setMoveDuration(350); + itemAnimator.setChangeDuration(0); + itemAnimator.setRemoveDuration(0); + itemAnimator.setMoveInterpolator(new OvershootInterpolator(1.1f)); + itemAnimator.setTranslationInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + + dialogsSearchAdapter = new DialogsSearchAdapter(context, type, initialDialogsType, itemAnimator) { @Override public void notifyDataSetChanged() { int itemCount = getCurrentItemCount(); @@ -115,7 +131,34 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie }; fragmentView = (SizeNotifierFrameLayout) fragment.getFragmentView(); - searchListView = new BlurredRecyclerView(context); + searchListView = new BlurredRecyclerView(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + if (dialogsSearchAdapter != null && itemAnimator != null && searchLayoutManager != null && dialogsSearchAdapter.showMoreAnimation) { + canvas.save(); + invalidate(); + final int lastItemIndex = dialogsSearchAdapter.getItemCount() - 1; + for (int i = 0; i < getChildCount(); ++i) { + View child = getChildAt(i); + if (getChildAdapterPosition(child) == lastItemIndex) { + canvas.clipRect(0, 0, getWidth(), child.getBottom() + child.getTranslationY()); + break; + } + } + } + super.dispatchDraw(canvas); + if (dialogsSearchAdapter != null && itemAnimator != null && searchLayoutManager != null && dialogsSearchAdapter.showMoreAnimation) { + canvas.restore(); + } + if (dialogsSearchAdapter != null && dialogsSearchAdapter.showMoreHeader != null) { + canvas.save(); + canvas.translate(dialogsSearchAdapter.showMoreHeader.getLeft(), dialogsSearchAdapter.showMoreHeader.getTop() + dialogsSearchAdapter.showMoreHeader.getTranslationY()); + dialogsSearchAdapter.showMoreHeader.draw(canvas); + canvas.restore(); + } + } + }; + searchListView.setItemAnimator(itemAnimator); searchListView.setPivotY(0); searchListView.setAdapter(dialogsSearchAdapter); searchListView.setVerticalScrollBarEnabled(true); @@ -552,7 +595,14 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie } } - public void getThemeDescriptors(ArrayList arrayList) { + public void getThemeDescriptions(ArrayList arrayList) { + for (int i = 0; i < searchListView.getChildCount(); ++i) { + View child = searchListView.getChildAt(i); + if (child instanceof ProfileSearchCell || child instanceof DialogCell || child instanceof HashtagSearchCell) { + arrayList.add(new ThemeDescription(child, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); + } + } + for (int i = 0; i < getChildCount(); i++) { if (getChildAt(i) instanceof FilteredSearchView) { arrayList.addAll(((FilteredSearchView) getChildAt(i)).getThemeDescriptions()); @@ -847,7 +897,7 @@ public class SearchViewPager extends ViewPagerFixed implements FilteredSearchVie } public interface ChatPreviewDelegate { - void startChatPreview(DialogCell cell); + void startChatPreview(RecyclerListView listView, DialogCell cell); void move(float dy); void finish(); } 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 d21620236..1d82fa314 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarView.java @@ -34,6 +34,7 @@ public class SeekBarView extends FrameLayout { private int thumbSize; private int selectorWidth; private int thumbX; + private AnimatedFloat animatedThumbX = new AnimatedFloat(this, 150, CubicBezierInterpolator.DEFAULT); private int thumbDX; private float progressToSet = -100; private boolean pressed; @@ -46,6 +47,7 @@ public class SeekBarView extends FrameLayout { private int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; private float transitionProgress = 1f; private int transitionThumbX; + private int separatorsCount; private boolean twoSided; private final Theme.ResourcesProvider resourcesProvider; @@ -122,6 +124,10 @@ public class SeekBarView extends FrameLayout { }); } + public void setSeparatorsCount(int separatorsCount) { + this.separatorsCount = separatorsCount; + } + public void setColors(int inner, int outer) { innerPaint1.setColor(inner); outerPaint1.setColor(outer); @@ -343,9 +349,24 @@ public class SeekBarView extends FrameLayout { @Override protected void onDraw(Canvas canvas) { + int thumbX = this.thumbX; + if (!twoSided && separatorsCount > 1) { + float step = (getMeasuredWidth() - selectorWidth) / ((float) separatorsCount - 1f); + thumbX = (int) animatedThumbX.set(Math.round((thumbX) / step) * step); + } int y = (getMeasuredHeight() - thumbSize) / 2; innerPaint1.setColor(getThemedColor(Theme.key_player_progressBackground)); canvas.drawRect(selectorWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), getMeasuredWidth() - selectorWidth / 2, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), innerPaint1); + if (!twoSided && separatorsCount > 1) { + for (int i = 0; i < separatorsCount; ++i) { + canvas.drawCircle( + AndroidUtilities.lerp(selectorWidth / 2, getMeasuredWidth() - selectorWidth / 2, i / ((float) separatorsCount - 1f)), + getMeasuredHeight() / 2, + AndroidUtilities.dp(1.6f), + innerPaint1 + ); + } + } if (bufferedProgress > 0) { innerPaint1.setColor(getThemedColor(Theme.key_player_progressCachedBackground)); canvas.drawRect(selectorWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), selectorWidth / 2 + bufferedProgress * (getMeasuredWidth() - selectorWidth), getMeasuredHeight() / 2 + AndroidUtilities.dp(1), innerPaint1); @@ -359,6 +380,20 @@ public class SeekBarView extends FrameLayout { } } else { canvas.drawRect(selectorWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), selectorWidth / 2 + thumbX, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), outerPaint1); + if (separatorsCount > 1) { + for (int i = 0; i < separatorsCount; ++i) { + float cx = AndroidUtilities.lerp(selectorWidth / 2, getMeasuredWidth() - selectorWidth / 2, i / ((float) separatorsCount - 1f)); + if (cx > thumbX + selectorWidth / 2) { + break; + } + canvas.drawCircle( + cx, + getMeasuredHeight() / 2, + AndroidUtilities.dp(1.4f), + outerPaint1 + ); + } + } } if (hoverDrawable != null) { int dx = thumbX + selectorWidth / 2 - AndroidUtilities.dp(16); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java index fc3069e93..5a522d201 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBarWaveform.java @@ -10,12 +10,25 @@ package org.telegram.ui.Components; import android.content.Context; import android.graphics.Canvas; +import android.graphics.LinearGradient; import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Shader; +import android.os.SystemClock; +import android.util.Log; import android.view.MotionEvent; import android.view.View; +import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; + +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.MediaController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; + +import java.util.ArrayList; public class SeekBarWaveform { @@ -23,11 +36,13 @@ public class SeekBarWaveform { private static Paint paintOuter; private int thumbX = 0; private int thumbDX = 0; + private float progress; private float startX; private boolean startDraging = false; private boolean pressed = false; private int width; private int height; + private int fromWidth, toWidth; private SeekBar.SeekBarDelegate delegate; private byte[] waveformBytes; private MessageObject messageObject; @@ -39,21 +54,31 @@ public class SeekBarWaveform { private int selectedColor; private float clearProgress = 1f; - private int clearFromX; private boolean isUnread; + private AnimatedFloat appearFloat = new AnimatedFloat(125, 450, CubicBezierInterpolator.EASE_OUT_QUINT); private float waveScaling = 1f; + private Path path; + private Path alphaPath; + private boolean loading; + private long loadingStart; + private AnimatedFloat loadingFloat = new AnimatedFloat(150, CubicBezierInterpolator.DEFAULT); + private Paint loadingPaint; + private float loadingPaintWidth; + private int loadingPaintColor1, loadingPaintColor2; + + private ArrayList animatedValues; + private float[] heights; + private float[] fromHeights; + private float[] toHeights; + public SeekBarWaveform(Context context) { if (paintInner == null) { paintInner = new Paint(Paint.ANTI_ALIAS_FLAG); paintOuter = new Paint(Paint.ANTI_ALIAS_FLAG); - paintInner.setStyle(Paint.Style.STROKE); - paintOuter.setStyle(Paint.Style.STROKE); - paintInner.setStrokeWidth(AndroidUtilities.dpf2(2)); - paintOuter.setStrokeWidth(AndroidUtilities.dpf2(2)); - paintInner.setStrokeCap(Paint.Cap.ROUND); - paintOuter.setStrokeCap(Paint.Cap.ROUND); + paintInner.setStyle(Paint.Style.FILL); + paintOuter.setStyle(Paint.Style.FILL); } } @@ -69,6 +94,7 @@ public class SeekBarWaveform { public void setWaveform(byte[] waveform) { waveformBytes = waveform; + heights = calculateHeights((int) (width / AndroidUtilities.dpf2(3))); } public void setSelected(boolean value) { @@ -76,11 +102,16 @@ public class SeekBarWaveform { } public void setMessageObject(MessageObject object) { + if (animatedValues != null && messageObject != null && object != null && messageObject.getId() != object.getId()) { + animatedValues.clear(); + } messageObject = object; } public void setParentView(View view) { parentView = view; + loadingFloat.setParent(view); + appearFloat.setParent(view); } public boolean isStartDraging() { @@ -113,6 +144,7 @@ public class SeekBarWaveform { } else if (thumbX > width) { thumbX = width; } + this.progress = thumbX / (float) width; } if (startX != -1 && Math.abs(x - startX) > AndroidUtilities.getPixelsInCM(0.2f, true)) { if (parentView != null && parentView.getParent() != null) { @@ -136,9 +168,9 @@ public class SeekBarWaveform { } public void setProgress(float progress, boolean animated) { + this.progress = isUnread ? 1f : progress; int currentThumbX = isUnread ? width : thumbX; if (animated && currentThumbX != 0 && progress == 0) { - clearFromX = currentThumbX; clearProgress = 0f; } else if (!animated) { clearProgress = 1f; @@ -156,42 +188,46 @@ public class SeekBarWaveform { } public void setSize(int w, int h) { - width = w; - height = h; + setSize(w, h, w, w); } - public void draw(Canvas canvas, View parentView) { - if (waveformBytes == null || width == 0) { - return; + public void setSize(int w, int h, int fromW, int toW) { + width = w; + height = h; + if (heights == null || heights.length != (int) (width / AndroidUtilities.dpf2(3))) { + heights = calculateHeights((int) (width / AndroidUtilities.dpf2(3))); } - float totalBarsCount = width / AndroidUtilities.dp(3); - if (totalBarsCount <= 0.1f) { - return; + if (fromW != toW && (fromWidth != fromW || toWidth != toW)) { + fromWidth = fromW; + toWidth = toW; + fromHeights = calculateHeights((int) (fromWidth / AndroidUtilities.dpf2(3))); + toHeights = calculateHeights((int) (toWidth / AndroidUtilities.dpf2(3))); + } else if (fromW == toW) { + fromHeights = toHeights = null; } + } + + public void setSent() { + appearFloat.set(0, true); + if (parentView != null) { + parentView.invalidate(); + } + } + + private float[] calculateHeights(int count) { + if (waveformBytes == null || count <= 0) { + return null; + } + float[] heights = new float[count]; byte value; int samplesCount = (waveformBytes.length * 8 / 5); - float samplesPerBar = samplesCount / totalBarsCount; + float samplesPerBar = samplesCount / (float) count; float barCounter = 0; int nextBarNum = 0; - isUnread = messageObject != null && !messageObject.isOutOwner() && messageObject.isContentUnread() && thumbX == 0; - paintInner.setColor(isUnread ? outerColor : (selected ? selectedColor : innerColor)); - paintOuter.setColor(outerColor); - - int y = (height - AndroidUtilities.dp(14)) / 2; int barNum = 0; int lastBarNum; int drawBarCount; - - if (clearProgress != 1f) { - clearProgress += 16 / 150f; - if (clearProgress > 1f) { - clearProgress = 1f; - } else { - parentView.invalidate(); - } - } - for (int a = 0; a < samplesCount; a++) { if (a != nextBarNum) { continue; @@ -216,48 +252,162 @@ public class SeekBarWaveform { } for (int b = 0; b < drawBarCount; b++) { - float x = barNum * AndroidUtilities.dpf2(3); - float h = AndroidUtilities.dpf2(Math.max(0, 7 * value / 31.0f)); + if (barNum >= heights.length) { + return heights; + } + heights[barNum++] = Math.max(0, 7 * value / 31.0f); + } + } + return heights; + } - if (x < thumbX && x + AndroidUtilities.dp(2) < thumbX) { - drawLine(canvas,x, y, h, paintOuter); + public void draw(Canvas canvas, View parentView) { + if (waveformBytes == null || width == 0) { + return; + } + float totalBarsCount = width / AndroidUtilities.dpf2(3); + if (totalBarsCount <= 0.1f) { + return; + } + if (clearProgress != 1f) { + clearProgress += 16 / 150f; + if (clearProgress > 1f) { + clearProgress = 1f; + } else { + parentView.invalidate(); + } + } + + float appearProgress = appearFloat.set(1f); + + if (path == null) { + path = new Path(); + } else { + path.reset(); + } + + float alpha = 0; + if (alphaPath == null) { + alphaPath = new Path(); + } else { + alphaPath.reset(); + } + + if (fromHeights != null && toHeights != null) { + float t = (width - fromWidth) / (float) (toWidth - fromWidth); + int maxlen = Math.max(fromHeights.length, toHeights.length); + int minlen = Math.min(fromHeights.length, toHeights.length); + float[] minarr = fromHeights.length < toHeights.length ? fromHeights : toHeights; + float[] maxarr = fromHeights.length < toHeights.length ? toHeights : fromHeights; +// t = CubicBezierInterpolator.EASE_OUT.getInterpolation(t); + float T = fromHeights.length < toHeights.length ? t : 1f - t; + int k = -1; + for (int barNum = 0; barNum < maxlen; ++barNum) { + int l = MathUtils.clamp((int) Math.floor(barNum / (float) maxlen * minlen), 0, minlen - 1); + if (k < l) { + float x = AndroidUtilities.lerp((float) l, (float) barNum, T) * AndroidUtilities.dpf2(3); + float h = AndroidUtilities.dpf2(AndroidUtilities.lerp(minarr[l], maxarr[barNum], T)); + addBar(path, x, h); + k = l; } else { - drawLine(canvas,x, y, h, paintInner); - if (x < thumbX) { - canvas.save(); - canvas.clipRect(x - AndroidUtilities.dpf2(1), y, thumbX, y + AndroidUtilities.dp(14)); - drawLine(canvas,x, y, h, paintOuter); - canvas.restore(); - } + float x = AndroidUtilities.lerp((float) l, (float) barNum, T) * AndroidUtilities.dpf2(3); + float h = AndroidUtilities.dpf2(AndroidUtilities.lerp(minarr[l], maxarr[barNum], T)); + addBar(alphaPath, x, h); + alpha = T; } - if (clearProgress != 1f) { - int alpha = paintOuter.getAlpha(); - paintOuter.setAlpha((int) (alpha * (1f - clearProgress))); - if (x < clearFromX && x + AndroidUtilities.dp(2) < clearFromX) { - drawLine(canvas, x, y, h, paintOuter); - } else if (x < clearFromX) { - canvas.save(); - canvas.clipRect(x - AndroidUtilities.dpf2(1), y, clearFromX, y + AndroidUtilities.dp(14)); - drawLine(canvas, x, y, h, paintOuter); - canvas.restore(); - } - paintOuter.setAlpha(alpha); + } + } else if (heights != null) { + for (int barNum = 0; barNum < totalBarsCount; barNum++) { + if (barNum >= heights.length) { + break; } - barNum++; + float x = barNum * AndroidUtilities.dpf2(3); + float bart = MathUtils.clamp(appearProgress * totalBarsCount - barNum, 0, 1); + float h = AndroidUtilities.dpf2(heights[barNum]) * bart; + addBar(path, x, h); + } + } + + if (alpha > 0) { + canvas.save(); + canvas.clipPath(alphaPath); + drawFill(canvas, alpha); + canvas.restore(); + } + + canvas.save(); + canvas.clipPath(path); + drawFill(canvas, 1f); + canvas.restore(); + } + + private void drawFill(Canvas canvas, float alpha) { + final float strokeWidth = AndroidUtilities.dpf2(2); + + isUnread = messageObject != null && messageObject.isContentUnread() && !messageObject.isOut() && this.progress <= 0; + paintInner.setColor(isUnread ? outerColor : (selected ? selectedColor : innerColor)); + paintOuter.setColor(outerColor); + + loadingFloat.setParent(parentView); + boolean isPlaying = MediaController.getInstance().isPlayingMessage(messageObject); + float loadingT = loadingFloat.set(loading && !isPlaying ? 1f : 0f); + paintInner.setColor(ColorUtils.blendARGB(paintInner.getColor(), innerColor, loadingT)); + paintOuter.setAlpha((int) (paintOuter.getAlpha() * (1f - loadingT) * alpha)); + paintInner.setAlpha((int) (paintInner.getAlpha() * alpha)); + + canvas.drawRect(0, 0, width + strokeWidth, height, paintInner); + if (loadingT < 1f) { + canvas.drawRect(0, 0, (this.progress * (width + strokeWidth)) * (1f - loadingT), height, paintOuter); + } + + if (loadingT > 0f) { + if (loadingPaint == null || Math.abs(loadingPaintWidth - width) > AndroidUtilities.dp(8) || loadingPaintColor1 != innerColor || loadingPaintColor2 != outerColor) { + if (loadingPaint == null) { + loadingPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + } + loadingPaintColor1 = innerColor; + loadingPaintColor2 = outerColor; + loadingPaint.setShader(new LinearGradient(0, 0, loadingPaintWidth = width, 0, new int[]{ loadingPaintColor1, loadingPaintColor2, loadingPaintColor1 }, new float[]{0, 0.2f, 0.4f}, Shader.TileMode.CLAMP)); + } + loadingPaint.setAlpha((int) (255 * loadingT * alpha)); + canvas.save(); + float t = (SystemClock.elapsedRealtime() - loadingStart) / 270f; + t = (float) Math.pow(t, 0.75f); + float dx = (t % 1.6f - .6f) * loadingPaintWidth; + canvas.translate(dx, 0); + canvas.drawRect(-dx, 0, width + 5 - dx, height, loadingPaint); + canvas.restore(); + + if (parentView != null) { + parentView.invalidate(); } } } - private void drawLine(Canvas canvas, float x, int y, float h, Paint paint) { + private void addBar(Path path, float x, float h) { + final float strokeWidth = AndroidUtilities.dpf2(2); + final int y = (height - AndroidUtilities.dp(14)) / 2; h *= waveScaling; - if (h == 0) { - canvas.drawPoint(x + AndroidUtilities.dpf2(1), y + AndroidUtilities.dp(7), paint); - } else { - canvas.drawLine(x + AndroidUtilities.dpf2(1), y + AndroidUtilities.dp(7) - h, x + AndroidUtilities.dpf2(1), y + AndroidUtilities.dp(7) + h, paint); - } + AndroidUtilities.rectTmp.set( + x + AndroidUtilities.dpf2(1) - strokeWidth / 2f, + y + AndroidUtilities.dp(7) + (-h - strokeWidth / 2f), + x + AndroidUtilities.dpf2(1) + strokeWidth / 2f, + y + AndroidUtilities.dp(7) + (h + strokeWidth / 2f) + ); + path.addRoundRect(AndroidUtilities.rectTmp, strokeWidth, strokeWidth, Path.Direction.CW); } public void setWaveScaling(float waveScaling) { this.waveScaling = waveScaling; } + + public void setLoading(boolean loading) { + if (!this.loading && loading && this.loadingFloat.get() <= 0) { + loadingStart = SystemClock.elapsedRealtime(); + } + this.loading = loading; + if (parentView != null) { + parentView.invalidate(); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SenderSelectView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SenderSelectView.java index b6a34f2df..c7e183cc6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SenderSelectView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SenderSelectView.java @@ -9,6 +9,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.Drawable; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -20,7 +21,11 @@ import com.google.android.exoplayer2.util.Log; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageReceiver; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.TLObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; public class SenderSelectView extends View { @@ -49,6 +54,7 @@ public class SenderSelectView extends View { menuPaint.setStrokeCap(Paint.Cap.ROUND); menuPaint.setStyle(Paint.Style.STROKE); updateColors(); + setContentDescription(LocaleController.formatString("AccDescrSendAsPeer", R.string.AccDescrSendAsPeer, "")); } private void updateColors() { @@ -117,6 +123,15 @@ public class SenderSelectView extends View { * @param obj User or chat */ public void setAvatar(TLObject obj) { + String objName = ""; + if (obj instanceof TLRPC.User) { + objName = UserObject.getFirstName((TLRPC.User) obj); + } else if (obj instanceof TLRPC.Chat) { + objName = ((TLRPC.Chat) obj).title; + } else if (obj instanceof TLRPC.ChatInvite) { + objName = ((TLRPC.ChatInvite) obj).title; + } + setContentDescription(LocaleController.formatString("AccDescrSendAsPeer", R.string.AccDescrSendAsPeer, objName)); avatarDrawable.setInfo(obj); avatarImage.setForUserOrChat(obj, avatarDrawable); } 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 d66c0a085..4e7ff73fd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ShareAlert.java @@ -122,15 +122,16 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi private FillLastGridLayoutManager searchLayoutManager; private ShareDialogsAdapter listAdapter; private ShareSearchAdapter searchAdapter; - private ArrayList sendingMessageObjects; + protected ArrayList sendingMessageObjects; private String[] sendingText = new String[2]; private int hasPoll; - private EmptyTextProgressView searchEmptyView; + private StickerEmptyView searchEmptyView; private Drawable shadowDrawable; private View[] shadow = new View[2]; private AnimatorSet[] shadowAnimation = new AnimatorSet[2]; - private LongSparseArray selectedDialogs = new LongSparseArray<>(); + protected LongSparseArray selectedDialogs = new LongSparseArray<>(); private SwitchView switchView; + private int containerViewTop = -1; private ChatActivity parentFragment; private Activity parentActivity; @@ -387,13 +388,13 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi String text = searchEditText.getText().toString(); if (text.length() != 0) { if (searchEmptyView != null) { - searchEmptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + searchEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); } } else { if (gridView.getAdapter() != listAdapter) { int top = getCurrentTop(); - searchEmptyView.setText(LocaleController.getString("NoChats", R.string.NoChats)); - searchEmptyView.showTextView(); + searchEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); + searchEmptyView.showProgress(false, true); checkCurrentList(false); listAdapter.notifyDataSetChanged(); if (top > 0) { @@ -453,7 +454,9 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi parentFragment = fragment; shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); - shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground), PorterDuff.Mode.SRC_IN)); + int backgroundColor = getThemedColor(behindKeyboardColorKey = (darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground)); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(backgroundColor, PorterDuff.Mode.SRC_IN)); + fixNavigationBar(backgroundColor); isFullscreen = fullScreen; linkToCopy[0] = copyLink; @@ -824,13 +827,15 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi super.requestLayout(); } + private boolean lightStatusBar = AndroidUtilities.computePerceivedBrightness(getThemedColor(darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground)) > .721f; + @Override protected void onDraw(Canvas canvas) { canvas.save(); canvas.translate(0, currentPanTranslationY); int y = scrollOffsetY - backgroundPaddingTop + AndroidUtilities.dp(6) + topOffset; - int top = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13) + topOffset; - int height = getMeasuredHeight() + AndroidUtilities.dp(30) + backgroundPaddingTop; + int top = containerViewTop = scrollOffsetY - backgroundPaddingTop - AndroidUtilities.dp(13) + topOffset; + int height = getMeasuredHeight() + AndroidUtilities.dp(30 + 30) + backgroundPaddingTop; int statusBarHeight = 0; float radProgress = 1.0f; if (!isFullscreen && Build.VERSION.SDK_INT >= 21) { @@ -865,12 +870,20 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi Theme.dialogs_onlineCirclePaint.setColor(getThemedColor(darkTheme ? Theme.key_voipgroup_scrollUp : Theme.key_sheet_scrollUp)); canvas.drawRoundRect(rect1, AndroidUtilities.dp(2), AndroidUtilities.dp(2), Theme.dialogs_onlineCirclePaint); - if (statusBarHeight > 0) { - int color1 = getThemedColor(darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground); - int finalColor = Color.argb(0xff, (int) (Color.red(color1) * 0.8f), (int) (Color.green(color1) * 0.8f), (int) (Color.blue(color1) * 0.8f)); - Theme.dialogs_onlineCirclePaint.setColor(finalColor); - canvas.drawRect(backgroundPaddingLeft, AndroidUtilities.statusBarHeight - statusBarHeight, getMeasuredWidth() - backgroundPaddingLeft, AndroidUtilities.statusBarHeight, Theme.dialogs_onlineCirclePaint); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + int flags = getSystemUiVisibility(); + boolean shouldBeLightStatusBar = lightStatusBar && statusBarHeight > AndroidUtilities.statusBarHeight * .5f; + boolean isLightStatusBar = (flags & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) > 0; + if (shouldBeLightStatusBar != isLightStatusBar) { + if (shouldBeLightStatusBar) { + flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } + setSystemUiVisibility(flags); + } } + canvas.restore(); previousTopOffset = topOffset; } @@ -1032,10 +1045,17 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi FlickerLoadingView flickerLoadingView = new FlickerLoadingView(context, resourcesProvider); flickerLoadingView.setViewType(FlickerLoadingView.SHARE_ALERT_TYPE); - searchEmptyView = new EmptyTextProgressView(context, flickerLoadingView, resourcesProvider); - searchEmptyView.setShowAtCenter(true); - searchEmptyView.showTextView(); - searchEmptyView.setText(LocaleController.getString("NoChats", R.string.NoChats)); + if (darkTheme) { + flickerLoadingView.setColors(Theme.key_voipgroup_inviteMembersBackground, Theme.key_voipgroup_searchBackground, null); + } + searchEmptyView = new StickerEmptyView(context, flickerLoadingView, StickerEmptyView.STICKER_TYPE_SEARCH, resourcesProvider); + searchEmptyView.addView(flickerLoadingView, 0); + searchEmptyView.setAnimateLayoutChange(true); + searchEmptyView.showProgress(false, false); + if (darkTheme) { + searchEmptyView.title.setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + } + searchEmptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); searchGridView.setEmptyView(searchEmptyView); searchGridView.setHideIfEmpty(false); searchGridView.setAnimateEmptyView(true, 0); @@ -1152,12 +1172,12 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi float alphaOffset = (frameLayout2.getMeasuredHeight() - AndroidUtilities.dp(48)) * (1f - getAlpha()); shadow[1].setTranslationY(-(frameLayout2.getMeasuredHeight() - AndroidUtilities.dp(48)) + captionEditTextTopOffset + currentPanTranslationY + alphaOffset); - int newColor = getThemedColor(darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground); - if (color != newColor) { - color = newColor; - p.setColor(color); - } - canvas.drawRect(0, captionEditTextTopOffset + alphaOffset, getMeasuredWidth(), getMeasuredHeight(), p); +// int newColor = getThemedColor(darkTheme ? Theme.key_voipgroup_inviteMembersBackground : Theme.key_dialogBackground); +// if (color != newColor) { +// color = newColor; +// p.setColor(color); +// } +// canvas.drawRect(0, captionEditTextTopOffset + alphaOffset, getMeasuredWidth(), getMeasuredHeight(), p); } @Override @@ -1216,14 +1236,40 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi chatActivityEnterViewAnimateFromTop = frameLayout2.getTop() + captionEditTextTopOffset; frameLayout2.invalidate(); } + + @Override + protected void showPopup(int show) { + super.showPopup(show); + if (darkTheme) { + navBarColorKey = null; + AndroidUtilities.setNavigationBarColor(ShareAlert.this.getWindow(), ShareAlert.this.getThemedColor(Theme.key_windowBackgroundGray), true, color -> { + ShareAlert.this.setOverlayNavBarColor(navBarColor = color); + }); + } + } + + @Override + public void hidePopup(boolean byBackButton) { + super.hidePopup(byBackButton); + if (darkTheme) { + navBarColorKey = null; + AndroidUtilities.setNavigationBarColor(ShareAlert.this.getWindow(), ShareAlert.this.getThemedColor(Theme.key_voipgroup_inviteMembersBackground), true, color -> { + ShareAlert.this.setOverlayNavBarColor(navBarColor = color); + }); + } + } }; - if (forCall) { + if (darkTheme) { commentTextView.getEditText().setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + commentTextView.getEditText().setCursorColor(getThemedColor(Theme.key_voipgroup_nameText)); } + commentTextView.setBackgroundColor(backgroundColor); commentTextView.setHint(LocaleController.getString("ShareComment", R.string.ShareComment)); commentTextView.onResume(); - frameLayout2.addView(commentTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 0, 0, 84, 0)); + commentTextView.setPadding(0, 0, AndroidUtilities.dp(84), 0); + frameLayout2.addView(commentTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT)); frameLayout2.setClipChildren(false); + frameLayout2.setClipToPadding(false); commentTextView.setClipChildren(false); writeButtonContainer = new FrameLayout(context) { @@ -1270,8 +1316,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi writeButtonContainer.addView(writeButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.LEFT | Gravity.TOP, Build.VERSION.SDK_INT >= 21 ? 2 : 0, 0, 0, 0)); writeButton.setOnClickListener(v -> sendInternal(true)); writeButton.setOnLongClickListener(v -> { - onSendLongClick(writeButton); - return true; + return onSendLongClick(writeButton); }); textPaint.setTextSize(AndroidUtilities.dp(12)); @@ -1335,13 +1380,12 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } private void selectDialog(ShareDialogCell cell, TLRPC.Dialog dialog) { - if (hasPoll != 0) { - if (DialogObject.isChatDialog(dialog.id)) { - TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialog.id); - boolean isChannel = ChatObject.isChannel(chat) && hasPoll == 2 && !chat.megagroup; - if (isChannel || !ChatObject.canSendPolls(chat)) { - AlertDialog.Builder builder = new AlertDialog.Builder(getContext(), resourcesProvider); - builder.setTitle(LocaleController.getString("SendMessageTitle", R.string.SendMessageTitle)); + if (DialogObject.isChatDialog(dialog.id)) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialog.id); + if (ChatObject.isChannel(chat) && !chat.megagroup && (!ChatObject.isCanWriteToChannel(-dialog.id, currentAccount) || hasPoll == 2)) { + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + builder.setTitle(LocaleController.getString("SendMessageTitle", R.string.SendMessageTitle)); + if (hasPoll == 2) { if (isChannel) { builder.setMessage(LocaleController.getString("PublicPollCantForward", R.string.PublicPollCantForward)); } else if (ChatObject.isActionBannedByDefault(chat, ChatObject.ACTION_SEND_POLLS)) { @@ -1349,11 +1393,24 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } else { builder.setMessage(LocaleController.getString("ErrorSendRestrictedPolls", R.string.ErrorSendRestrictedPolls)); } - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); - builder.show(); - return; + } else { + builder.setMessage(LocaleController.getString("ChannelCantSendMessage", R.string.ChannelCantSendMessage)); } + builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + builder.show(); + return; } + } else if (DialogObject.isEncryptedDialog(dialog.id) && (hasPoll != 0)) { + AlertDialog.Builder builder = new AlertDialog.Builder(parentActivity); + builder.setTitle(LocaleController.getString("SendMessageTitle", R.string.SendMessageTitle)); + if (hasPoll != 0) { + builder.setMessage(LocaleController.getString("PollCantForwardSecretChat", R.string.PollCantForwardSecretChat)); + } else { + builder.setMessage(LocaleController.getString("InvoiceCantForwardSecretChat", R.string.InvoiceCantForwardSecretChat)); + } + builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + builder.show(); + return; } if (selectedDialogs.indexOfKey(dialog.id) >= 0) { selectedDialogs.remove(dialog.id); @@ -1384,21 +1441,29 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi searchView.hideKeyboard(); } } - if (searchAdapter.categoryAdapter != null) { + if (searchAdapter != null && searchAdapter.categoryAdapter != null) { searchAdapter.categoryAdapter.notifyItemRangeChanged(0, searchAdapter.categoryAdapter.getItemCount()); } } + @Override + public int getContainerViewHeight() { + return containerView.getMeasuredHeight() - containerViewTop; + } + private boolean showSendersName = true; private ActionBarPopupWindow sendPopupWindow; private boolean onSendLongClick(View view) { - if (parentFragment == null) { + if (parentActivity == null) { return false; } LinearLayout layout = new LinearLayout(getContext()); layout.setOrientation(LinearLayout.VERTICAL); if (sendingMessageObjects != null) { ActionBarPopupWindow.ActionBarPopupWindowLayout sendPopupLayout1 = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity, resourcesProvider); + if (darkTheme) { + sendPopupLayout1.setBackgroundColor(getThemedColor(Theme.key_voipgroup_inviteMembersBackground)); + } sendPopupLayout1.setAnimationEnabled(false); sendPopupLayout1.setOnTouchListener(new View.OnTouchListener() { private android.graphics.Rect popupRect = new android.graphics.Rect(); @@ -1421,15 +1486,20 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sendPopupWindow.dismiss(); } }); - sendPopupLayout1.setShownFromBotton(false); - sendPopupLayout1.setupRadialSelectors(getThemedColor(Theme.key_dialogButtonSelector)); + sendPopupLayout1.setShownFromBottom(false); ActionBarMenuSubItem showSendersNameView = new ActionBarMenuSubItem(getContext(), true, true, false, resourcesProvider); + if (darkTheme) { + showSendersNameView.setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + } sendPopupLayout1.addView(showSendersNameView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); showSendersNameView.setTextAndIcon(false ? LocaleController.getString("ShowSenderNames", R.string.ShowSenderNames) : LocaleController.getString("ShowSendersName", R.string.ShowSendersName), 0); showSendersNameView.setChecked(showSendersName = true); ActionBarMenuSubItem hideSendersNameView = new ActionBarMenuSubItem(getContext(), true, false, true, resourcesProvider); + if (darkTheme) { + hideSendersNameView.setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + } sendPopupLayout1.addView(hideSendersNameView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); hideSendersNameView.setTextAndIcon(false ? LocaleController.getString("HideSenderNames", R.string.HideSenderNames) : LocaleController.getString("HideSendersName", R.string.HideSendersName), 0); hideSendersNameView.setChecked(!showSendersName); @@ -1441,11 +1511,15 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi showSendersNameView.setChecked(showSendersName = false); hideSendersNameView.setChecked(!showSendersName); }); + sendPopupLayout1.setupRadialSelectors(getThemedColor(darkTheme ? Theme.key_voipgroup_listSelector : Theme.key_dialogButtonSelector)); layout.addView(sendPopupLayout1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, -8)); } ActionBarPopupWindow.ActionBarPopupWindowLayout sendPopupLayout2 = new ActionBarPopupWindow.ActionBarPopupWindowLayout(parentActivity, resourcesProvider); + if (darkTheme) { + sendPopupLayout2.setBackgroundColor(Theme.getColor(Theme.key_voipgroup_inviteMembersBackground)); + } sendPopupLayout2.setAnimationEnabled(false); sendPopupLayout2.setOnTouchListener(new View.OnTouchListener() { private android.graphics.Rect popupRect = new android.graphics.Rect(); @@ -1468,10 +1542,13 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sendPopupWindow.dismiss(); } }); - sendPopupLayout2.setShownFromBotton(false); - sendPopupLayout2.setupRadialSelectors(getThemedColor(Theme.key_dialogButtonSelector)); + sendPopupLayout2.setShownFromBottom(false); ActionBarMenuSubItem sendWithoutSound = new ActionBarMenuSubItem(getContext(), true, true, resourcesProvider); + if (darkTheme) { + sendWithoutSound.setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + sendWithoutSound.setIconColor(getThemedColor(Theme.key_windowBackgroundWhiteHintText)); + } sendWithoutSound.setTextAndIcon(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound), R.drawable.baseline_notifications_off_24); sendWithoutSound.setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout2.addView(sendWithoutSound, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); @@ -1482,7 +1559,11 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sendInternal(false); }); ActionBarMenuSubItem sendMessage = new ActionBarMenuSubItem(getContext(), true, true, resourcesProvider); - sendMessage.setTextAndIcon(LocaleController.getString("SendMessage", R.string.SendMessage), R.drawable.msg_forward_send); + if (darkTheme) { + sendMessage.setTextColor(getThemedColor(Theme.key_voipgroup_nameText)); + sendMessage.setIconColor(getThemedColor(Theme.key_windowBackgroundWhiteHintText)); + } + sendMessage.setTextAndIcon(LocaleController.getString("SendMessage", R.string.SendMessage), R.drawable.msg_send); sendMessage.setMinimumWidth(AndroidUtilities.dp(196)); sendPopupLayout2.addView(sendMessage, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48)); sendMessage.setOnClickListener(v -> { @@ -1491,6 +1572,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } sendInternal(true); }); + sendPopupLayout2.setupRadialSelectors(getThemedColor(darkTheme ? Theme.key_voipgroup_listSelector : Theme.key_dialogButtonSelector)); layout.addView(sendPopupLayout2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -1502,14 +1584,14 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); sendPopupWindow.getContentView().setFocusableInTouchMode(true); - SharedConfig.removeScheduledOrNoSuoundHint(); + SharedConfig.removeScheduledOrNoSoundHint(); layout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); sendPopupWindow.setFocusable(true); int[] location = new int[2]; view.getLocationInWindow(location); int y; - if (keyboardVisible && parentFragment.contentView.getMeasuredHeight() > AndroidUtilities.dp(58)) { + if (keyboardVisible && parentFragment != null && parentFragment.contentView.getMeasuredHeight() > AndroidUtilities.dp(58)) { y = location[1] + view.getMeasuredHeight(); } else { y = location[1] - layout.getMeasuredHeight() - AndroidUtilities.dp(2); @@ -1518,10 +1600,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi sendPopupWindow.dimBehind(); view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - return false; + return true; } - private void sendInternal(boolean withSound) { + protected void sendInternal(boolean withSound) { for (int a = 0; a < selectedDialogs.size(); a++) { long key = selectedDialogs.keyAt(a); if (AlertsCreator.checkSlowMode(getContext(), currentAccount, key, frameLayout2.getTag() != null && commentTextView.length() > 0)) { @@ -1966,6 +2048,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi int itemsCount; DialogsSearchAdapter.CategoryAdapterRecycler categoryAdapter; + RecyclerView categoryListView; public ShareSearchAdapter(Context context) { this.context = context; @@ -1979,7 +2062,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } int oldItemsCount = lastItemCont; if (getItemCount() == 0 && !searchAdapterHelper.isSearchInProgress() && !internalDialogsIsSearching) { - searchEmptyView.showTextView(); + searchEmptyView.showProgress(false, true); } else { recyclerItemsEnterAnimator.showItemsAnimated(oldItemsCount); } @@ -2217,10 +2300,10 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi topBeforeSwitch = getCurrentTop(); } searchResult = result; - searchAdapterHelper.mergeResults(searchResult); + searchAdapterHelper.mergeResults(searchResult, null); int oldItemsCount = lastItemCont; if (getItemCount() == 0 && !searchAdapterHelper.isSearchInProgress() && !internalDialogsIsSearching) { - searchEmptyView.showTextView(); + searchEmptyView.showProgress(false, true); } else { recyclerItemsEnterAnimator.showItemsAnimated(oldItemsCount); } @@ -2256,7 +2339,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } else { internalDialogsIsSearching = true; final int searchId = ++lastSearchId; - searchEmptyView.showProgress(false); + searchEmptyView.showProgress(true, true); Utilities.searchQueue.postRunnable(searchRunnable = () -> { searchRunnable = null; searchDialogsInternal(query, searchId); @@ -2309,7 +2392,11 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi public TLRPC.Dialog getItem(int position) { if (position >= recentDialogsStartRow && recentDialogsStartRow >= 0) { - DialogsSearchAdapter.RecentSearchObject recentSearchObject = recentSearchObjects.get(position - recentDialogsStartRow); + int index = position - recentDialogsStartRow; + if (index < 0 || index >= recentSearchObjects.size()) { + return null; + } + DialogsSearchAdapter.RecentSearchObject recentSearchObject = recentSearchObjects.get(index); TLObject object = recentSearchObject.object; TLRPC.Dialog dialog = new TLRPC.TL_dialog(); if (object instanceof TLRPC.User) { @@ -2376,6 +2463,7 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi return super.onInterceptTouchEvent(e); } }; + categoryListView = horizontalListView; horizontalListView.setItemAnimator(null); horizontalListView.setLayoutAnimation(null); LinearLayoutManager layoutManager = new LinearLayoutManager(context) { @@ -2390,6 +2478,9 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { HintDialogCell cell = (HintDialogCell) holder.itemView; + if (darkTheme) { + cell.setColors(Theme.key_voipgroup_nameText, Theme.key_voipgroup_inviteMembersBackground); + } TLRPC.TL_topPeer peer = MediaDataController.getInstance(currentAccount).hints.get(position); TLRPC.Chat chat = null; @@ -2440,6 +2531,8 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } case 3: { GraySectionCell graySectionCell = new GraySectionCell(context, resourcesProvider); + graySectionCell.setTextColor(darkTheme ? Theme.key_voipgroup_nameText : Theme.key_graySectionText); + graySectionCell.setBackgroundColor(getThemedColor(darkTheme ? Theme.key_voipgroup_searchBackground : Theme.key_graySection)); graySectionCell.setText(LocaleController.getString("Recent", R.string.Recent)); view = graySectionCell; break; @@ -2528,6 +2621,8 @@ public class ShareAlert extends BottomSheet implements NotificationCenter.Notifi } } cell.setDialog(id, selectedDialogs.indexOfKey(id) >= 0, name); + } else if (holder.getItemViewType() == 2) { + ((RecyclerListView) holder.itemView).getAdapter().notifyDataSetChanged(); } } 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 11bd807b8..77b97b6e3 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SharedMediaLayout.java @@ -167,6 +167,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter FlickerLoadingView globalGradientView; private final int viewType; + private UndoView undoView; + public boolean checkPinchToZoom(MotionEvent ev) { if (mediaPages[0].selectedType != 0 || getParent() == null) { return false; @@ -1146,10 +1148,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter final Delegate delegate; private HintView fwdRestrictedHint; + private Theme.ResourcesProvider resourcesProvider; - public SharedMediaLayout(Context context, long did, SharedMediaPreloader preloader, int commonGroupsCount, ArrayList sortedUsers, TLRPC.ChatFull chatInfo, boolean membersFirst, BaseFragment parent, Delegate delegate, int viewType) { + public SharedMediaLayout(Context context, long did, SharedMediaPreloader preloader, int commonGroupsCount, ArrayList sortedUsers, TLRPC.ChatFull chatInfo, boolean membersFirst, BaseFragment parent, Delegate delegate, int viewType, Theme.ResourcesProvider resourcesProvider) { super(context); this.viewType = viewType; + this.resourcesProvider = resourcesProvider; globalGradientView = new FlickerLoadingView(context); globalGradientView.setIsSingleCell(true); @@ -1223,7 +1227,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter searchWas = false; pinnedHeaderShadowDrawable = context.getResources().getDrawable(R.drawable.photos_header_shadow); - pinnedHeaderShadowDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundGrayShadow), PorterDuff.Mode.MULTIPLY)); + pinnedHeaderShadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundGrayShadow), PorterDuff.Mode.MULTIPLY)); if (scrollSlidingTextTabStrip != null) { initialTab = scrollSlidingTextTabStrip.getCurrentTabId(); @@ -1240,6 +1244,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter menu.addOnLayoutChangeListener(new OnLayoutChangeListener() { @Override public void onLayoutChange(View view, int i, int i1, int i2, int i3, int i4, int i5, int i6, int i7) { + if (searchItem == null) { + return; + } View parent = (View) searchItem.getParent(); searchItem.setTranslationX(parent.getMeasuredWidth() - searchItem.getRight()); } @@ -1311,11 +1318,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter searchItem.setVisibility(View.INVISIBLE); photoVideoOptionsItem = new ImageView(context); + photoVideoOptionsItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); photoVideoOptionsItem.setTranslationY(AndroidUtilities.dp(10)); photoVideoOptionsItem.setVisibility(View.INVISIBLE); Drawable calendarDrawable = ContextCompat.getDrawable(context, R.drawable.ic_ab_other).mutate(); - calendarDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), PorterDuff.Mode.MULTIPLY)); + calendarDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), PorterDuff.Mode.MULTIPLY)); photoVideoOptionsItem.setImageDrawable(calendarDrawable); photoVideoOptionsItem.setScaleType(ImageView.ScaleType.CENTER_INSIDE); actionBar.addView(photoVideoOptionsItem, LayoutHelper.createFrame(48, 56, Gravity.RIGHT | Gravity.BOTTOM)); @@ -1466,9 +1474,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter }); EditTextBoldCursor editText = searchItem.getSearchField(); - editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - editText.setHintTextColor(Theme.getColor(Theme.key_player_time)); - editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + editText.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + editText.setHintTextColor(getThemedColor(Theme.key_player_time)); + editText.setCursorColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); searchItemState = 0; SizeNotifierFrameLayout sizeNotifierFrameLayout = null; @@ -1476,7 +1484,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter sizeNotifierFrameLayout = (SizeNotifierFrameLayout) profileActivity.getFragmentView(); } actionModeLayout = new BlurredLinearLayout(context, sizeNotifierFrameLayout); - actionModeLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + actionModeLayout.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); actionModeLayout.setAlpha(0.0f); actionModeLayout.setClickable(true); actionModeLayout.setVisibility(INVISIBLE); @@ -1484,8 +1492,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter closeButton = new ImageView(context); closeButton.setScaleType(ImageView.ScaleType.CENTER); closeButton.setImageDrawable(backDrawable = new BackDrawable(true)); - backDrawable.setColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); - closeButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 1)); + backDrawable.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2)); + closeButton.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 1)); closeButton.setContentDescription(LocaleController.getString("Close", R.string.Close)); actionModeLayout.addView(closeButton, new LinearLayout.LayoutParams(AndroidUtilities.dp(54), ViewGroup.LayoutParams.MATCH_PARENT)); actionModeViews.add(closeButton); @@ -1494,12 +1502,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter selectedMessagesCountTextView = new NumberTextView(context); selectedMessagesCountTextView.setTextSize(18); selectedMessagesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - selectedMessagesCountTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + selectedMessagesCountTextView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText2)); actionModeLayout.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 18, 0, 0, 0)); actionModeViews.add(selectedMessagesCountTextView); if (!DialogObject.isEncryptedDialog(dialog_id)) { - gotoItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + gotoItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false); gotoItem.setIcon(R.drawable.msg_message); gotoItem.setContentDescription(LocaleController.getString("AccDescrGoToMessage", R.string.AccDescrGoToMessage)); gotoItem.setDuplicateParentStateEnabled(false); @@ -1515,7 +1523,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter actionModeViews.add(forwardNoQuoteItem); forwardNoQuoteItem.setOnClickListener(v -> onActionBarItemClick(v, forward_noquote)); - forwardItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + forwardItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false); forwardItem.setIcon(R.drawable.baseline_forward_24); forwardItem.setContentDescription(LocaleController.getString("Forward", R.string.Forward)); forwardItem.setDuplicateParentStateEnabled(false); @@ -1525,7 +1533,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter updateForwardItem(); } - deleteItem = new ActionBarMenuItem(context, null, Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2), false); + deleteItem = new ActionBarMenuItem(context, null, getThemedColor(Theme.key_actionBarActionModeDefaultSelector), getThemedColor(Theme.key_windowBackgroundWhiteGrayText2), false); deleteItem.setIcon(R.drawable.baseline_delete_24); deleteItem.setContentDescription(LocaleController.getString("Delete", R.string.Delete)); deleteItem.setDuplicateParentStateEnabled(false); @@ -2206,7 +2214,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override protected void onDraw(Canvas canvas) { - backgroundPaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + backgroundPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhite)); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), backgroundPaint); super.onDraw(canvas); } @@ -2239,7 +2247,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter floatingDateView.setTranslationY(-AndroidUtilities.dp(48)); addView(floatingDateView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 48 + 4, 0, 0)); - addView(fragmentContextView = new FragmentContextView(context, parent, this, false, null), LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.TOP | Gravity.LEFT, 0, 48, 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(); @@ -2250,7 +2258,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter addView(actionModeLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP)); shadowLine = new View(context); - shadowLine.setBackgroundColor(Theme.getColor(Theme.key_divider)); + shadowLine.setBackgroundColor(getThemedColor(Theme.key_divider)); FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1); layoutParams.topMargin = AndroidUtilities.dp(48) - 1; addView(shadowLine, layoutParams); @@ -2296,7 +2304,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter if (forwardItem.getBackground() != null) forwardItem.setBackground(null); if (forwardNoQuoteItem.getBackground() != null) forwardNoQuoteItem.setBackground(null); } else if (forwardItem.getBackground() == null) { - forwardItem.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 5)); + forwardItem.setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_actionBarActionModeDefaultSelector), 5)); forwardNoQuoteItem.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_actionBarActionModeDefaultSelector), 5)); } } @@ -2664,12 +2672,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } private ScrollSlidingTextTabStripInner createScrollingTextTabStrip(Context context) { - ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip = new ScrollSlidingTextTabStripInner(context); + ScrollSlidingTextTabStripInner scrollSlidingTextTabStrip = new ScrollSlidingTextTabStripInner(context, resourcesProvider); if (initialTab != -1) { scrollSlidingTextTabStrip.setInitialTabId(initialTab); initialTab = -1; } - scrollSlidingTextTabStrip.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + scrollSlidingTextTabStrip.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); scrollSlidingTextTabStrip.setColors(Theme.key_profile_tabSelectedLine, Theme.key_profile_tabSelectedText, Theme.key_profile_tabText, Theme.key_profile_tabSelector); scrollSlidingTextTabStrip.setDelegate(new ScrollSlidingTextTabStrip.ScrollSlidingTabStripDelegate() { @Override @@ -3181,7 +3189,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter showActionMode(false); actionBar.closeSearchField(); cantDeleteMessagesCount = 0; - }, null, null); + }, null, resourcesProvider); } else if (id == forward || id == forward_noquote) { if (info != null) { TLRPC.Chat chat = profileActivity.getMessagesController().getChat(info.id); @@ -3239,6 +3247,17 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } fragment1.finishFragment(); + UndoView undoView = null; + if (profileActivity instanceof ProfileActivity) { + undoView = ((ProfileActivity) profileActivity).getUndoView(); + } + if (undoView != null) { + if (dids.size() == 1) { + undoView.showWithAction(dids.get(0), UndoView.ACTION_FWD_MESSAGES, fmessages.size()); + } else { + undoView.showWithAction(0, UndoView.ACTION_FWD_MESSAGES, fmessages.size(), dids.size(), null, null); + } + } } else { long did = dids.get(0); Bundle args1 = new Bundle(); @@ -4921,7 +4940,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public View getSectionHeaderView(int section, View view) { if (view == null) { view = new GraySectionCell(mContext); - view.setBackgroundColor(Theme.getColor(Theme.key_graySection) & 0xf2ffffff); + view.setBackgroundColor(getThemedColor(Theme.key_graySection) & 0xf2ffffff); } if (section == 0) { view.setAlpha(0.0f); @@ -4940,19 +4959,19 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter View view; switch (viewType) { case 0: - view = new GraySectionCell(mContext); + view = new GraySectionCell(mContext, resourcesProvider); break; case 1: - view = new SharedLinkCell(mContext); + view = new SharedLinkCell(mContext, SharedLinkCell.VIEW_TYPE_DEFAULT, resourcesProvider); ((SharedLinkCell) view).setDelegate(sharedLinkCellDelegate); break; case 3: - View emptyStubView = createEmptyStubView(mContext, 3, dialog_id); + View emptyStubView = createEmptyStubView(mContext, 3, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); case 2: default: - FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext, resourcesProvider); flickerLoadingView.setIsSingleCell(true); flickerLoadingView.showDate(false); flickerLoadingView.setViewType(FlickerLoadingView.LINKS_TYPE); @@ -5066,12 +5085,12 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter View view; switch (viewType) { case 1: - SharedDocumentCell cell = new SharedDocumentCell(mContext); + SharedDocumentCell cell = new SharedDocumentCell(mContext, SharedDocumentCell.VIEW_TYPE_DEFAULT, resourcesProvider); cell.setGlobalGradientView(globalGradientView); view = cell; break; case 2: - FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext, resourcesProvider); view = flickerLoadingView; if (currentType == 2) { flickerLoadingView.setViewType(FlickerLoadingView.AUDIO_TYPE); @@ -5083,7 +5102,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter flickerLoadingView.setGlobalGradientView(globalGradientView); break; case 4: - View emptyStubView = createEmptyStubView(mContext, currentType, dialog_id); + View emptyStubView = createEmptyStubView(mContext, currentType, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); case 3: @@ -5096,7 +5115,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter p.removeView(view); } } else { - view = new SharedAudioCell(mContext) { + view = new SharedAudioCell(mContext, SharedAudioCell.VIEW_TYPE_DEFAULT, resourcesProvider) { @Override public boolean needPlayMessage(MessageObject messageObject) { if (messageObject.isVoice() || messageObject.isRoundVideo()) { @@ -5228,45 +5247,39 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } - public static View createEmptyStubView(Context context, int currentType, long dialog_id) { - EmptyStubView emptyStubView = new EmptyStubView(context); + public static View createEmptyStubView(Context context, int currentType, long dialog_id, Theme.ResourcesProvider resourcesProvider) { + EmptyStubView emptyStubView = new EmptyStubView(context, resourcesProvider); if (currentType == 0) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip1); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoMediaSecret", R.string.NoMediaSecret)); } else { emptyStubView.emptyTextView.setText(LocaleController.getString("NoMedia", R.string.NoMedia)); } } else if (currentType == 1) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip2); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedFilesSecret", R.string.NoSharedFilesSecret)); } else { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedFiles", R.string.NoSharedFiles)); } } else if (currentType == 2) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip5); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedVoiceSecret", R.string.NoSharedVoiceSecret)); } else { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedVoice", R.string.NoSharedVoice)); } } else if (currentType == 3) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip3); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedLinksSecret", R.string.NoSharedLinksSecret)); } else { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedLinks", R.string.NoSharedLinks)); } } else if (currentType == 4) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip4); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedAudioSecret", R.string.NoSharedAudioSecret)); } else { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedAudio", R.string.NoSharedAudio)); } } else if (currentType == 5) { - emptyStubView.emptyImageView.setImageResource(R.drawable.tip1); if (DialogObject.isEncryptedDialog(dialog_id)) { emptyStubView.emptyTextView.setText(LocaleController.getString("NoSharedGifSecret", R.string.NoSharedGifSecret)); } else { @@ -5289,7 +5302,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter boolean ignoreRequestLayout; - public EmptyStubView(Context context) { + public EmptyStubView(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); emptyTextView = new TextView(context); emptyImageView = new ImageView(context); @@ -5299,7 +5312,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - emptyTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); + emptyTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2, resourcesProvider)); emptyTextView.setGravity(Gravity.CENTER); emptyTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); emptyTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), AndroidUtilities.dp(128)); @@ -5397,7 +5410,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter switch (viewType) { case 0: if (sharedResources == null) { - sharedResources = new SharedPhotoVideoCell2.SharedResources(parent.getContext()); + sharedResources = new SharedPhotoVideoCell2.SharedResources(parent.getContext(), resourcesProvider); } view = new SharedPhotoVideoCell2(mContext, sharedResources, profileActivity.getCurrentAccount()); SharedPhotoVideoCell2 cell = (SharedPhotoVideoCell2) view; @@ -5405,7 +5418,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter break; default: case 2: - View emptyStubView = createEmptyStubView(mContext, 0, dialog_id); + View emptyStubView = createEmptyStubView(mContext, 0, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); } @@ -5676,6 +5689,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == currentType) { if (searchesInProgress == 0 && count == 0) { + mediaPages[a].emptyView.title.setText(LocaleController.formatString(R.string.NoResultFoundFor, "NoResultFoundFor", query)); mediaPages[a].emptyView.showProgress(false, true); } else if (oldItemCounts == 0) { animateItemsEnter(mediaPages[a].listView, 0, null); @@ -5814,6 +5828,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter for (int a = 0; a < mediaPages.length; a++) { if (mediaPages[a].selectedType == currentType) { if (searchesInProgress == 0 && count == 0) { + mediaPages[a].emptyView.title.setText(LocaleController.getString("NoResult", R.string.NoResult)); mediaPages[a].emptyView.showProgress(false, true); } else if (oldItemCount == 0) { animateItemsEnter(mediaPages[a].listView, 0, null); @@ -5864,9 +5879,9 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; if (currentType == 1) { - view = new SharedDocumentCell(mContext); + view = new SharedDocumentCell(mContext, SharedDocumentCell.VIEW_TYPE_DEFAULT, resourcesProvider); } else if (currentType == 4) { - view = new SharedAudioCell(mContext) { + view = new SharedAudioCell(mContext, SharedAudioCell.VIEW_TYPE_DEFAULT, resourcesProvider) { @Override public boolean needPlayMessage(MessageObject messageObject) { if (messageObject.isVoice() || messageObject.isRoundVideo()) { @@ -5883,7 +5898,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } }; } else { - view = new SharedLinkCell(mContext); + view = new SharedLinkCell(mContext, SharedLinkCell.VIEW_TYPE_DEFAULT, resourcesProvider); ((SharedLinkCell) view).setDelegate(sharedLinkCellDelegate); } view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -5968,11 +5983,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 1) { - View emptyStubView = createEmptyStubView(mContext, 5, dialog_id); + View emptyStubView = createEmptyStubView(mContext, 5, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); } - ContextLinkCell cell = new ContextLinkCell(mContext, true); + ContextLinkCell cell = new ContextLinkCell(mContext, true, resourcesProvider); cell.setCanPreviewGif(true); return new RecyclerListView.Holder(cell); } @@ -6094,15 +6109,15 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter View view; switch (viewType) { case 0: - view = new ProfileSearchCell(mContext); + view = new ProfileSearchCell(mContext, resourcesProvider); break; case 2: - View emptyStubView = createEmptyStubView(mContext, 6, dialog_id); + View emptyStubView = createEmptyStubView(mContext, 6, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); case 1: default: - FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext); + FlickerLoadingView flickerLoadingView = new FlickerLoadingView(mContext, resourcesProvider); flickerLoadingView.setIsSingleCell(true); flickerLoadingView.showDate(false); flickerLoadingView.setViewType(FlickerLoadingView.DIALOG_TYPE); @@ -6162,11 +6177,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == 1) { - View emptyStubView = createEmptyStubView(mContext, 7, dialog_id); + View emptyStubView = createEmptyStubView(mContext, 7, dialog_id, resourcesProvider); emptyStubView.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); return new RecyclerListView.Holder(emptyStubView); } - View view = new UserCell(mContext, 9, 0, true); + View view = new UserCell(mContext, 9, 0, true, false, resourcesProvider); view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); return new RecyclerListView.Holder(view); } @@ -6425,8 +6440,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - ManageChatUserCell view = new ManageChatUserCell(mContext, 9, 5, true); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + ManageChatUserCell view = new ManageChatUserCell(mContext, 9, 5, true, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); view.setDelegate((cell, click) -> { TLObject object = getItem((Integer) cell.getTag()); if (object instanceof TLRPC.ChannelParticipant) { @@ -6462,7 +6477,7 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter name = new SpannableStringBuilder(u); int idx = AndroidUtilities.indexOfIgnoreCase(u, nameSearch); if (idx != -1) { - name.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), idx, idx + nameSearch.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + name.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_windowBackgroundWhiteBlueText4)), idx, idx + nameSearch.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } @@ -6671,8 +6686,8 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter public int backgroundColor = Color.TRANSPARENT; - public ScrollSlidingTextTabStripInner(Context context) { - super(context); + public ScrollSlidingTextTabStripInner(Context context, Theme.ResourcesProvider resourcesProvider) { + super(context, resourcesProvider); } protected void drawBackground(Canvas canvas) { @@ -6693,6 +6708,11 @@ public class SharedMediaLayout extends FrameLayout implements NotificationCenter } } + private int getThemedColor(String key) { + Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; + return color != null ? color : Theme.getColor(key); + } + public interface Delegate { void scrollToSharedMedia(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SideMenultItemAnimator.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SideMenultItemAnimator.java index d1658cf6b..bc072a9fb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SideMenultItemAnimator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SideMenultItemAnimator.java @@ -311,7 +311,7 @@ public class SideMenultItemAnimator extends SimpleItemAnimator { final RecyclerView.ViewHolder newHolder = changeInfo.newHolder; final View newView = newHolder != null ? newHolder.itemView : null; if (view != null) { - final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(getChangeDuration()); + final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(getChangeRemoveDuration()); mChangeAnimations.add(changeInfo.oldHolder); oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX); oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY); @@ -336,7 +336,8 @@ public class SideMenultItemAnimator extends SimpleItemAnimator { if (newView != null) { final ViewPropertyAnimator newViewAnimation = newView.animate(); mChangeAnimations.add(changeInfo.newHolder); - newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration()).alpha(1).setListener(new AnimatorListenerAdapter() { + newViewAnimation.translationX(0).translationY(0).setDuration(getChangeAddDuration()) + .setStartDelay(getChangeDuration() - getChangeAddDuration()).alpha(1).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animator) { dispatchChangeStarting(changeInfo.newHolder, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleThemeDescription.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleThemeDescription.java index fe675b154..39efa4c62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleThemeDescription.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SimpleThemeDescription.java @@ -7,10 +7,14 @@ import java.util.ArrayList; public class SimpleThemeDescription { private SimpleThemeDescription() {} + public static ThemeDescription createThemeDescription(ThemeDescription.ThemeDescriptionDelegate del, String key) { + return new ThemeDescription(null, 0, null, null, null, del, key); + } + public static ArrayList createThemeDescriptions(ThemeDescription.ThemeDescriptionDelegate del, String... keys) { ArrayList l = new ArrayList<>(keys.length); for (String k : keys) { - l.add(new ThemeDescription(null, 0, null, null, null, del, k)); + l.add(createThemeDescription(del, k)); } return l; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java index c6bf352de..d0bfeb7ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlideChooseView.java @@ -1,15 +1,27 @@ package org.telegram.ui.Components; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; +import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; import android.graphics.DashPathEffect; +import android.graphics.Interpolator; import android.graphics.Paint; import android.os.Bundle; +import android.os.SystemClock; import android.text.TextPaint; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; +import android.view.animation.LinearInterpolator; +import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; + +import org.checkerframework.checker.units.qual.A; import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; @@ -31,7 +43,6 @@ public class SlideChooseView extends View { private boolean moving; private boolean startMoving; - private float startX; private float xTouchDown; private float yTouchDown; @@ -41,10 +52,15 @@ public class SlideChooseView extends View { private int[] optionsSizes; private int selectedIndex; + private float selectedIndexTouch; + private AnimatedFloat selectedIndexAnimatedHolder = new AnimatedFloat(this, 120, CubicBezierInterpolator.DEFAULT); + private AnimatedFloat movingAnimatedHolder = new AnimatedFloat(this, 150, CubicBezierInterpolator.DEFAULT); private Callback callback; private final Theme.ResourcesProvider resourcesProvider; + private boolean touchWasClose = false; + public SlideChooseView(Context context) { this(context, null); } @@ -105,18 +121,18 @@ public class SlideChooseView extends View { public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); + float indexTouch = MathUtils.clamp((x - sideSide + circleSize / 2f) / (lineSize + gapSize * 2 + circleSize), 0, optionsStr.length - 1); + boolean isClose = Math.abs(indexTouch - Math.round(indexTouch)) < .35f; + if (isClose) { + indexTouch = Math.round(indexTouch); + } if (event.getAction() == MotionEvent.ACTION_DOWN) { xTouchDown = x; yTouchDown = y; - for (int a = 0; a < optionsStr.length; a++) { - int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; - if (x > cx - AndroidUtilities.dp(15) && x < cx + AndroidUtilities.dp(15)) { - startMoving = a == selectedIndex; - startX = x; - startMovingPreset = selectedIndex; - break; - } - } + selectedIndexTouch = indexTouch; + startMovingPreset = selectedIndex; + startMoving = true; + invalidate(); } else if (event.getAction() == MotionEvent.ACTION_MOVE) { if (!moving) { if (Math.abs(xTouchDown - x) > Math.abs(yTouchDown - y)) { @@ -124,32 +140,24 @@ public class SlideChooseView extends View { } } if (startMoving) { - if (Math.abs(startX - x) >= AndroidUtilities.getPixelsInCM(0.5f, true)) { + if (Math.abs(xTouchDown - x) >= AndroidUtilities.dp(2)) { moving = true; startMoving = false; } - } else if (moving) { - for (int a = 0; a < optionsStr.length; a++) { - int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; - int diff = lineSize / 2 + circleSize / 2 + gapSize; - if (x > cx - diff && x < cx + diff) { - if (selectedIndex != a) { - setOption(a); - } - break; - } + } + if (moving) { + selectedIndexTouch = indexTouch; + invalidate(); + if (Math.round(selectedIndexTouch) != selectedIndex && isClose) { + setOption(Math.round(selectedIndexTouch)); } } + invalidate(); } else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) { if (!moving) { - for (int a = 0; a < 5; a++) { - int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; - if (x > cx - AndroidUtilities.dp(15) && x < cx + AndroidUtilities.dp(15)) { - if (selectedIndex != a) { - setOption(a); - } - break; - } + selectedIndexTouch = indexTouch; + if (Math.round(selectedIndexTouch) != selectedIndex) { + setOption(Math.round(selectedIndexTouch)); } } else { if (selectedIndex != startMovingPreset) { @@ -161,12 +169,18 @@ public class SlideChooseView extends View { } startMoving = false; moving = false; + invalidate(); getParent().requestDisallowInterceptTouchEvent(false); } return true; } private void setOption(int index) { + if (selectedIndex != index) { + try { + performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } selectedIndex = index; if (callback != null) { callback.onOptionSelected(index); @@ -185,15 +199,18 @@ public class SlideChooseView extends View { @Override protected void onDraw(Canvas canvas) { - textPaint.setColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + float selectedIndexAnimated = selectedIndexAnimatedHolder.set(selectedIndex); + float movingAnimated = movingAnimatedHolder.set(moving ? 1 : 0); int cy = getMeasuredHeight() / 2 + AndroidUtilities.dp(11); for (int a = 0; a < optionsStr.length; a++) { int cx = sideSide + (lineSize + gapSize * 2 + circleSize) * a + circleSize / 2; - int color = a <= selectedIndex ? getThemedColor(Theme.key_switchTrackChecked) : getThemedColor(Theme.key_switchTrack); + float t = Math.max(0, 1f - Math.abs(a - selectedIndexAnimated)); + float ut = MathUtils.clamp(selectedIndexAnimated - a + 1f, 0, 1); + int color = ColorUtils.blendARGB(getThemedColor(Theme.key_switchTrack), getThemedColor(Theme.key_switchTrackChecked), ut); paint.setColor(color); linePaint.setColor(color); - canvas.drawCircle(cx, cy, a == selectedIndex ? AndroidUtilities.dp(6) : circleSize / 2, paint); + canvas.drawCircle(cx, cy, AndroidUtilities.lerp(circleSize / 2, AndroidUtilities.dp(6), t), paint); if (a != 0) { int x = cx - circleSize / 2 - gapSize - lineSize; int width = lineSize; @@ -208,18 +225,16 @@ public class SlideChooseView extends View { } canvas.drawLine(x + AndroidUtilities.dp(1), cy, x + width - AndroidUtilities.dp(1), cy, linePaint); } else { - if (a == selectedIndex || a == selectedIndex + 1) { - width -= AndroidUtilities.dp(3); - } - if (a == selectedIndex + 1) { - x += AndroidUtilities.dp(3); - } + float nt = MathUtils.clamp(1f - Math.abs(a - selectedIndexAnimated - 1), 0, 1); + float nct = MathUtils.clamp(1f - Math.min(Math.abs(a - selectedIndexAnimated), Math.abs(a - selectedIndexAnimated - 1)), 0, 1); + width -= AndroidUtilities.dp(3) * nct; + x += AndroidUtilities.dp(3) * nt; canvas.drawRect(x, cy - AndroidUtilities.dp(1), x + width, cy + AndroidUtilities.dp(1), paint); } } int size = optionsSizes[a]; String text = optionsStr[a]; - + textPaint.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_windowBackgroundWhiteGrayText), getThemedColor(Theme.key_windowBackgroundWhiteBlueText), t)); if (a == 0) { canvas.drawText(text, AndroidUtilities.dp(22), AndroidUtilities.dp(28), textPaint); } else if (a == optionsStr.length - 1) { @@ -228,6 +243,12 @@ public class SlideChooseView extends View { canvas.drawText(text, cx - size / 2, AndroidUtilities.dp(28), textPaint); } } + + float cx = sideSide + (lineSize + gapSize * 2 + circleSize) * selectedIndexAnimated + circleSize / 2; + paint.setColor(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_switchTrackChecked), 80)); + canvas.drawCircle(cx, cy, AndroidUtilities.dp(12 * movingAnimated), paint); + paint.setColor(getThemedColor(Theme.key_switchTrackChecked)); + canvas.drawCircle(cx, cy, AndroidUtilities.dp(6), paint); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java index cdfdbce66..f26bb057b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SlotsDrawable.java @@ -8,6 +8,7 @@ import org.telegram.messenger.DownloadController; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.Cells.ChatMessageCell; @@ -218,7 +219,7 @@ public class SlotsDrawable extends RLottieDrawable { num = 2; } TLRPC.Document document = stickerSet.documents.get(num); - File path = FileLoader.getPathToAttach(document, true); + File path = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); String json = readRes(path, 0); if (TextUtils.isEmpty(json)) { loading = true; @@ -328,7 +329,7 @@ public class SlotsDrawable extends RLottieDrawable { } } TLRPC.Document document = stickerSet.documents.get(num); - File path = FileLoader.getPathToAttach(document, true); + File path = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(document, true); String json = readRes(path, 0); if (TextUtils.isEmpty(json)) { loading = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java index ed56122c1..5c33d5134 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerEmptyView.java @@ -20,6 +20,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.Theme; public class StickerEmptyView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -103,7 +104,7 @@ public class StickerEmptyView extends FrameLayout implements NotificationCenter. subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitle.setGravity(Gravity.CENTER); - linearLayout.addView(stickerView, LayoutHelper.createLinear(130, 130, Gravity.CENTER_HORIZONTAL)); + linearLayout.addView(stickerView, LayoutHelper.createLinear(117, 117, Gravity.CENTER_HORIZONTAL)); linearLayout.addView(title, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 12, 0, 0)); linearLayout.addView(subtitle, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 0, 8, 0, 0)); addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 56, 0, 56, 30)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java index b0fc6ea07..4e96bbbb2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerMasksAlert.java @@ -288,6 +288,7 @@ public class StickerMasksAlert extends BottomSheet implements NotificationCenter behindKeyboardColorKey = null; behindKeyboardColor = 0xff252525; useLightStatusBar = false; + fixNavigationBar(0xff252525); currentType = MediaDataController.TYPE_IMAGE; 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 fb477b9f6..74e2b6b96 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerSetBulletinLayout.java @@ -1,20 +1,27 @@ package org.telegram.ui.Components; import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import androidx.annotation.IntDef; import androidx.annotation.NonNull; +import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.FileLoader; import org.telegram.messenger.ImageLocation; 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.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; +import org.telegram.ui.LaunchActivity; +import org.telegram.ui.PremiumPreviewFragment; import java.util.ArrayList; @@ -28,8 +35,10 @@ public class StickerSetBulletinLayout extends Bulletin.TwoLineLayout { public static final int TYPE_REMOVED_FROM_RECENT = 3; public static final int TYPE_REMOVED_FROM_FAVORITES = 4; public static final int TYPE_ADDED_TO_FAVORITES = 5; + public static final int TYPE_REPLACED_TO_FAVORITES = 6; + public static final int TYPE_REPLACED_TO_FAVORITES_GIFS = 7; - @IntDef(value = {TYPE_EMPTY, TYPE_REMOVED, TYPE_ARCHIVED, TYPE_ADDED, TYPE_REMOVED_FROM_RECENT, TYPE_REMOVED_FROM_FAVORITES, TYPE_ADDED_TO_FAVORITES}) + @IntDef(value = {TYPE_EMPTY, TYPE_REMOVED, TYPE_ARCHIVED, TYPE_ADDED, TYPE_REMOVED_FROM_RECENT, TYPE_REMOVED_FROM_FAVORITES, TYPE_ADDED_TO_FAVORITES, TYPE_REPLACED_TO_FAVORITES}) public @interface Type { } @@ -90,7 +99,7 @@ public class StickerSetBulletinLayout extends Bulletin.TwoLineLayout { imageLocation = ImageLocation.getForSticker(thumb, sticker, thumbVersion); } - if (object instanceof TLRPC.Document && MessageObject.isAnimatedStickerDocument(sticker, true) || MessageObject.isVideoSticker(sticker)) { + if (object instanceof TLRPC.Document && MessageObject.isAnimatedStickerDocument(sticker, true) || MessageObject.isVideoSticker(sticker) || MessageObject.isGifDocument(sticker)) { imageView.setImage(ImageLocation.getForDocument(sticker), "50_50", imageLocation, null, 0, setObject); } else if (imageLocation != null && imageLocation.imageType == FileLoader.IMAGE_TYPE_LOTTIE) { imageView.setImage(imageLocation, "50_50", "tgs", null, setObject); @@ -137,6 +146,36 @@ public class StickerSetBulletinLayout extends Bulletin.TwoLineLayout { titleTextView.setText(LocaleController.getString("AddedToFavorites", R.string.AddedToFavorites)); subtitleTextView.setVisibility(ViewPagerFixed.GONE); break; + 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), () -> { + Activity activity = AndroidUtilities.findActivity(context); + if (activity instanceof LaunchActivity) { + ((LaunchActivity) activity).presentFragment(new PremiumPreviewFragment(LimitReachedBottomSheet.limitTypeToServerString(LimitReachedBottomSheet.TYPE_STICKERS))); + } + }); + subtitleTextView.setText(str); + } else { + titleTextView.setText(LocaleController.formatString("LimitReachedFavoriteStickers", R.string.LimitReachedFavoriteStickers, MessagesController.getInstance(UserConfig.selectedAccount).stickersFavedLimitPremium)); + subtitleTextView.setText(LocaleController.formatString("LimitReachedFavoriteStickersSubtitlePremium", R.string.LimitReachedFavoriteStickersSubtitlePremium)); + } + break; + 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), () -> { + Activity activity = AndroidUtilities.findActivity(context); + if (activity instanceof LaunchActivity) { + ((LaunchActivity) activity).presentFragment(new PremiumPreviewFragment(LimitReachedBottomSheet.limitTypeToServerString(LimitReachedBottomSheet.TYPE_GIFS))); + } + }); + subtitleTextView.setText(str); + } else { + titleTextView.setText(LocaleController.formatString("LimitReachedFavoriteGifs", R.string.LimitReachedFavoriteGifs, MessagesController.getInstance(UserConfig.selectedAccount).savedGifsLimitPremium)); + subtitleTextView.setText(LocaleController.formatString("LimitReachedFavoriteGifsSubtitlePremium", R.string.LimitReachedFavoriteGifsSubtitlePremium)); + } + break; case TYPE_REMOVED_FROM_RECENT: titleTextView.setText(LocaleController.getString("RemovedFromRecent", R.string.RemovedFromRecent)); subtitleTextView.setVisibility(ViewPagerFixed.GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerTabView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerTabView.java index 314d9f4db..68aafa711 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerTabView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickerTabView.java @@ -4,7 +4,6 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.content.Context; -import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.TypedValue; import android.view.Gravity; @@ -24,6 +23,11 @@ public class StickerTabView extends FrameLayout { public final static int ICON_TYPE = 1; public final static int EMOJI_TYPE = 2; + public final static int SMALL_WIDTH = 38; + public final static int SMALL_HEIGHT = 36; + + private final static int IMAGE_SMALL_SIZE = 26; + public int type; public float dragOffset; public boolean inited; @@ -51,7 +55,7 @@ public class StickerTabView extends FrameLayout { imageView = new BackupImageView(getContext()); imageView.setLayerNum(1); imageView.setAspectFit(false); - addView(imageView, LayoutHelper.createFrame(36, 36, Gravity.CENTER)); + addView(imageView, LayoutHelper.createFrame(IMAGE_SMALL_SIZE, IMAGE_SMALL_SIZE, Gravity.CENTER)); visibleView = imageView; } else if (type == ICON_TYPE) { iconView = new ImageView(context); @@ -62,7 +66,7 @@ public class StickerTabView extends FrameLayout { imageView = new BackupImageView(getContext()); imageView.setLayerNum(1); imageView.setAspectFit(true); - addView(imageView, LayoutHelper.createFrame(30, 30, Gravity.CENTER)); + addView(imageView, LayoutHelper.createFrame(IMAGE_SMALL_SIZE, IMAGE_SMALL_SIZE, Gravity.CENTER)); visibleView = imageView; } @@ -82,7 +86,7 @@ public class StickerTabView extends FrameLayout { return; } this.expanded = expanded; - float size = type == ICON_TYPE ? 24 : 30; + float size = type == ICON_TYPE ? 24 : IMAGE_SMALL_SIZE; float sizeExpanded = type == ICON_TYPE ? 38 : 56; visibleView.getLayoutParams().width = AndroidUtilities.dp(expanded ? sizeExpanded : size); @@ -100,12 +104,12 @@ public class StickerTabView extends FrameLayout { return; } if (expanded) { - float size = type == ICON_TYPE ? 24 : 30; + float size = type == ICON_TYPE ? 24 : IMAGE_SMALL_SIZE; float sizeExpanded = type == ICON_TYPE ? 38 : 56; - float fromX = AndroidUtilities.dp(52 - size) / 2f; - float fromY = AndroidUtilities.dp(48 - size) / 2f; + float fromX = AndroidUtilities.dp(SMALL_WIDTH - size) / 2f; + float fromY = AndroidUtilities.dp(SMALL_HEIGHT - size) / 2f; float toX = AndroidUtilities.dp(86 - sizeExpanded) / 2f; - float toY = AndroidUtilities.dp(48 + 50 - sizeExpanded) / 2f; + float toY = AndroidUtilities.dp(SMALL_HEIGHT + 50 - sizeExpanded) / 2f; visibleView.setTranslationY((fromY - toY) * (1 - expandProgress) - AndroidUtilities.dp(8) * expandProgress); visibleView.setTranslationX((fromX - toX) * (1 - expandProgress)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java index fadfdcf2e..a94983be7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -20,6 +20,9 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; @@ -66,6 +69,8 @@ import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MediaController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessageObject; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; @@ -113,6 +118,14 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not void onStickerSetUninstalled(); } + public interface StickersAlertCustomButtonDelegate { + String getCustomButtonTextColorKey(); + String getCustomButtonRippleColorKey(); + String getCustomButtonColorKey(); + String getCustomButtonText(); + boolean onCustomButtonPressed(); + } + private static class LinkMovementMethodMy extends LinkMovementMethod { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { @@ -135,6 +148,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private TextView titleTextView; private ActionBarMenuItem optionsButton; private TextView pickerBottomLayout; + private FrameLayout pickerBottomFrameLayout; private FrameLayout stickerPreviewLayout; private TextView previewSendButton; private View previewSendButtonShadow; @@ -163,6 +177,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not private StickersAlertDelegate delegate; private StickersAlertInstallDelegate installDelegate; + private StickersAlertCustomButtonDelegate customButtonDelegate; private int scrollOffsetY; private int reqId; @@ -211,7 +226,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not @Override public boolean needSend() { - return previewSendButton.getVisibility() == View.VISIBLE && importingStickers == null; + return delegate != null; } @Override @@ -230,6 +245,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not public StickersAlert(Context context, Object parentObject, TLObject object, Theme.ResourcesProvider resourcesProvider) { super(context, false, resourcesProvider); + fixNavigationBar(); this.resourcesProvider = resourcesProvider; parentActivity = (Activity) context; final TLRPC.TL_messages_getAttachedStickers req = new TLRPC.TL_messages_getAttachedStickers(); @@ -295,6 +311,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not public StickersAlert(Context context, String software, ArrayList uris, ArrayList emoji, Theme.ResourcesProvider resourcesProvider) { super(context, false, resourcesProvider); + fixNavigationBar(); parentActivity = (Activity) context; importingStickers = uris; importingSoftware = software; @@ -375,6 +392,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not public StickersAlert(Context context, BaseFragment baseFragment, TLRPC.InputStickerSet set, TLRPC.TL_messages_stickerSet loadedSet, StickersAlertDelegate stickersAlertDelegate, Theme.ResourcesProvider resourcesProvider) { super(context, false, resourcesProvider); + fixNavigationBar(); delegate = stickersAlertDelegate; inputStickerSet = set; stickerSet = loadedSet; @@ -446,6 +464,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not optionsButton.setVisibility(View.VISIBLE); stickerSet = (TLRPC.TL_messages_stickerSet) response; showEmoji = !stickerSet.set.masks; + checkPremiumStickers(); mediaDataController.preloadStickerSetThumb(stickerSet); updateSendButton(); updateFields(); @@ -462,11 +481,22 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not adapter.notifyDataSetChanged(); } mediaDataController.preloadStickerSetThumb(stickerSet); + checkPremiumStickers(); } } if (stickerSet != null) { showEmoji = !stickerSet.set.masks; } + checkPremiumStickers(); + } + + private void checkPremiumStickers() { + if (stickerSet != null) { + stickerSet = MessagesController.getInstance(currentAccount).filterPremiumStickers(stickerSet); + if (stickerSet == null) { + dismiss(); + } + } } private void init(Context context) { @@ -500,12 +530,13 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } itemSize = (MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(36)) / 5; int contentSize; + MarginLayoutParams params = (MarginLayoutParams) gridView.getLayoutParams(); if (importingStickers != null) { - contentSize = AndroidUtilities.dp(48 + 48) + Math.max(3, (int) Math.ceil(importingStickers.size() / 5.0f)) * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.statusBarHeight; + contentSize = AndroidUtilities.dp(48) + params.bottomMargin + Math.max(3, (int) Math.ceil(importingStickers.size() / 5.0f)) * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.statusBarHeight; } else if (stickerSetCovereds != null) { - contentSize = AndroidUtilities.dp(48 + 8) + AndroidUtilities.dp(60) * stickerSetCovereds.size() + adapter.stickersRowCount * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.dp(24); + contentSize = AndroidUtilities.dp(8) + params.bottomMargin + AndroidUtilities.dp(60) * stickerSetCovereds.size() + adapter.stickersRowCount * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.dp(24); } else { - contentSize = AndroidUtilities.dp(48 + 48) + Math.max(3, (stickerSet != null ? (int) Math.ceil(stickerSet.documents.size() / 5.0f) : 0)) * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.statusBarHeight; + contentSize = AndroidUtilities.dp(48) + params.bottomMargin + Math.max(3, (stickerSet != null ? (int) Math.ceil(stickerSet.documents.size() / 5.0f) : 0)) * AndroidUtilities.dp(82) + backgroundPaddingTop + AndroidUtilities.statusBarHeight; } int padding = contentSize < (height / 5 * 3.2) ? 0 : (height / 5 * 2); if (padding != 0 && contentSize < height) { @@ -519,7 +550,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } if (gridView.getPaddingTop() != padding) { ignoreLayout = true; - gridView.setPadding(AndroidUtilities.dp(10), padding, AndroidUtilities.dp(10), 0); + gridView.setPadding(AndroidUtilities.dp(10), padding, AndroidUtilities.dp(10), AndroidUtilities.dp(8)); emptyView.setPadding(0, padding, 0, 0); ignoreLayout = false; } @@ -709,16 +740,18 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not stickerEmojiTextView.setText(MediaDataController.getInstance(currentAccount).getEmojiForSticker(selectedSticker.id)); } - TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(selectedSticker.thumbs, 90); - stickerImageView.getImageReceiver().setImage(ImageLocation.getForDocument(selectedSticker), null, ImageLocation.getForDocument(thumb, selectedSticker), null, "webp", stickerSet, 1); - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) stickerPreviewLayout.getLayoutParams(); - layoutParams.topMargin = scrollOffsetY; - stickerPreviewLayout.setLayoutParams(layoutParams); - stickerPreviewLayout.setVisibility(View.VISIBLE); - AnimatorSet animatorSet = new AnimatorSet(); - animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, View.ALPHA, 0.0f, 1.0f)); - animatorSet.setDuration(200); - animatorSet.start(); + if (!ContentPreviewViewer.getInstance().showMenuFor(view)) { + TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(selectedSticker.thumbs, 90); + stickerImageView.getImageReceiver().setImage(ImageLocation.getForDocument(selectedSticker), null, ImageLocation.getForDocument(thumb, selectedSticker), null, "webp", stickerSet, 1); + FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) stickerPreviewLayout.getLayoutParams(); + layoutParams.topMargin = scrollOffsetY; + stickerPreviewLayout.setLayoutParams(layoutParams); + stickerPreviewLayout.setVisibility(View.VISIBLE); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playTogether(ObjectAnimator.ofFloat(stickerPreviewLayout, View.ALPHA, 0.0f, 1.0f)); + animatorSet.setDuration(200); + animatorSet.start(); + } } }; gridView.setOnItemClickListener(stickersOnItemClickListener); @@ -775,13 +808,16 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not containerView.addView(shadow[1], frameLayoutParams); pickerBottomLayout = new TextView(context); - pickerBottomLayout.setBackgroundDrawable(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), getThemedColor(Theme.key_listSelector))); + pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), getThemedColor(Theme.key_listSelector))); pickerBottomLayout.setTextColor(getThemedColor(buttonTextColorKey = Theme.key_dialogTextBlue2)); pickerBottomLayout.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); pickerBottomLayout.setPadding(AndroidUtilities.dp(18), 0, AndroidUtilities.dp(18), 0); - pickerBottomLayout.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + pickerBottomLayout.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); pickerBottomLayout.setGravity(Gravity.CENTER); - containerView.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); + + pickerBottomFrameLayout = new FrameLayout(context); + pickerBottomFrameLayout.addView(pickerBottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48)); + containerView.addView(pickerBottomFrameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.BOTTOM)); stickerPreviewLayout = new FrameLayout(context); stickerPreviewLayout.setVisibility(View.GONE); @@ -805,7 +841,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not previewSendButton.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), getThemedColor(Theme.key_listSelector))); previewSendButton.setGravity(Gravity.CENTER); previewSendButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0); - previewSendButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + previewSendButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); stickerPreviewLayout.addView(previewSendButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT)); previewSendButton.setOnClickListener(v -> { if (importingStickersPaths != null) { @@ -877,6 +913,11 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not installDelegate = stickersAlertInstallDelegate; } + public void setCustomButtonDelegate(StickersAlertCustomButtonDelegate customButtonDelegate) { + this.customButtonDelegate = customButtonDelegate; + updateFields(); + } + private void onSubItemClick(int id) { if (stickerSet == null) { return; @@ -956,7 +997,13 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } titleTextView.setText(stringBuilder != null ? stringBuilder : stickerSet.set.title); - if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id)) { + if (customButtonDelegate != null) { + setButton(v -> { + if (customButtonDelegate.onCustomButtonPressed()) { + dismiss(); + } + }, customButtonDelegate.getCustomButtonText(), customButtonDelegate.getCustomButtonTextColorKey(), customButtonDelegate.getCustomButtonColorKey(), customButtonDelegate.getCustomButtonRippleColorKey()); + } else if (!MediaDataController.getInstance(currentAccount).isStickerPackInstalled(stickerSet.set.id)) { optionsButton.hideSubItem(menu_archive); String text; if (stickerSet.set != null && stickerSet.set.masks) { @@ -979,7 +1026,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not try { if (error == null) { if (showTooltipWhenToggle) { - Bulletin.make(parentFragment, new StickerSetBulletinLayout(pickerBottomLayout.getContext(), stickerSet, StickerSetBulletinLayout.TYPE_ADDED, null, resourcesProvider), Bulletin.DURATION_SHORT).show(); + Bulletin.make(parentFragment, new StickerSetBulletinLayout(pickerBottomFrameLayout.getContext(), stickerSet, StickerSetBulletinLayout.TYPE_ADDED, null, resourcesProvider), Bulletin.DURATION_SHORT).show(); } if (response instanceof TLRPC.TL_messages_stickerSetInstallResultArchive) { MediaDataController.getInstance(currentAccount).processStickerSetInstallResultArchive(parentFragment, true, type, (TLRPC.TL_messages_stickerSetInstallResultArchive) response); @@ -992,7 +1039,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } MediaDataController.getInstance(currentAccount).loadStickers(type, false, true); })); - }, text, Theme.key_dialogTextBlue2); + }, text, Theme.key_featuredStickers_buttonText, Theme.key_featuredStickers_addButton, Theme.key_featuredStickers_addButtonPressed); } else { optionsButton.showSubItem(menu_archive); String text; @@ -1384,7 +1431,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not Bulletin.addDelegate((FrameLayout) containerView, new Bulletin.Delegate() { @Override public int getBottomOffset(int tag) { - return pickerBottomLayout != null ? pickerBottomLayout.getHeight() : 0; + return pickerBottomFrameLayout != null ? pickerBottomFrameLayout.getHeight() : 0; } }); } @@ -1404,10 +1451,6 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not gridView.getChildAt(a).invalidate(); } } - if (ContentPreviewViewer.getInstance().isVisible()) { - ContentPreviewViewer.getInstance().close(); - } - ContentPreviewViewer.getInstance().reset(); } else if (id == NotificationCenter.fileUploaded) { if (uploadImportStickers == null) { return; @@ -1455,9 +1498,30 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } private void setButton(View.OnClickListener onClickListener, String title, String colorKey) { + setButton(onClickListener, title, colorKey, null, null); + } + + private void setButton(View.OnClickListener onClickListener, String title, String colorKey, String backgroundColorKey, String backgroundSelectorColorKey) { pickerBottomLayout.setTextColor(getThemedColor(buttonTextColorKey = colorKey)); - pickerBottomLayout.setText(title.toUpperCase()); + pickerBottomLayout.setText(customButtonDelegate == null ? title.toUpperCase() : title); pickerBottomLayout.setOnClickListener(onClickListener); + + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) pickerBottomLayout.getLayoutParams(); + ViewGroup.MarginLayoutParams shadowParams = (ViewGroup.MarginLayoutParams) shadow[1].getLayoutParams(); + ViewGroup.MarginLayoutParams gridParams = (ViewGroup.MarginLayoutParams) gridView.getLayoutParams(); + ViewGroup.MarginLayoutParams emptyParams = (ViewGroup.MarginLayoutParams) emptyView.getLayoutParams(); + if (backgroundColorKey != null && backgroundSelectorColorKey != null) { + pickerBottomLayout.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), getThemedColor(backgroundColorKey), getThemedColor(backgroundSelectorColorKey))); + pickerBottomFrameLayout.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = AndroidUtilities.dp(8); + emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(64); + } else { + pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), getThemedColor(Theme.key_listSelector))); + pickerBottomFrameLayout.setBackgroundColor(Color.TRANSPARENT); + params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0; + emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(48); + } + containerView.requestLayout(); } public boolean isShowTooltipWhenToggle() { @@ -1697,4 +1761,13 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not } } } + + @Override + public void onBackPressed() { + if (ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().closeWithMenu(); + return; + } + super.onBackPressed(); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/StroageUsageView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/StroageUsageView.java index b36e36e5b..1316ff288 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StroageUsageView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StroageUsageView.java @@ -191,7 +191,6 @@ public class StroageUsageView extends FrameLayout { this.totalDeviceFreeSize = totalDeviceFreeSize; this.totalDeviceSize = totalDeviceSize; - freeSizeTextView.setText(LocaleController.formatString("TotalDeviceFreeSize", R.string.TotalDeviceFreeSize, AndroidUtilities.formatFileSize(totalDeviceFreeSize))); totlaSizeTextView.setText(LocaleController.formatString("TotalDeviceSize", R.string.TotalDeviceSize, AndroidUtilities.formatFileSize(totalDeviceSize - totalDeviceFreeSize))); @@ -342,7 +341,7 @@ public class StroageUsageView extends FrameLayout { // canvas.drawLine(AndroidUtilities.dp(24), AndroidUtilities.dp(20), getMeasuredWidth() - AndroidUtilities.dp(24), AndroidUtilities.dp(20), paintCalculcating); AndroidUtilities.rectTmp.set(AndroidUtilities.dp(24), AndroidUtilities.dp(17), getMeasuredWidth() - AndroidUtilities.dp(24), AndroidUtilities.dp(23)); cellFlickerDrawable.setParentWidth(getMeasuredWidth()); - cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(3)); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(3), null); } int currentP = AndroidUtilities.dp(24); if (!calculating) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SwipeGestureSettingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SwipeGestureSettingsView.java index 556e86df3..64d3e36b9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SwipeGestureSettingsView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SwipeGestureSettingsView.java @@ -6,9 +6,13 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.os.Build; +import android.os.Bundle; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.View; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import androidx.core.graphics.ColorUtils; @@ -104,7 +108,7 @@ public class SwipeGestureSettingsView extends FrameLayout { invalidate(); picker.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); }); - + picker.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); picker.setValue(SharedConfig.getChatSwipeAction(currentAccount)); addView(picker, LayoutHelper.createFrame(132, LayoutHelper.MATCH_PARENT, Gravity.RIGHT, 21, 0, 21, 0)); @@ -327,4 +331,27 @@ public class SwipeGestureSettingsView extends FrameLayout { picker.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); picker.invalidate(); } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + info.setContentDescription(strings[picker.getValue()]); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, null)); + } + } + + @Override + public void onInitializeAccessibilityEvent(AccessibilityEvent event) { + super.onInitializeAccessibilityEvent(event); + if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED) { + int newValue = picker.getValue() + 1; + if (newValue > picker.getMaxValue() || newValue < 0) { + newValue = 0; + } + setContentDescription(strings[newValue]); + picker.changeValueByOne(true); + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java index 20c7ccef1..acb1ae009 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java @@ -25,14 +25,19 @@ import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; +import android.media.AudioManager; import android.os.Build; import androidx.annotation.Keep; + +import android.os.VibrationEffect; +import android.os.Vibrator; import android.util.StateSet; import android.view.HapticFeedbackConstants; import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.OneUIUtilities; import org.telegram.ui.ActionBar.Theme; import java.lang.reflect.Method; @@ -80,6 +85,8 @@ public class Switch extends View { private Paint overlayEraserPaint; private Paint overlayMaskPaint; + private Theme.ResourcesProvider resourcesProvider; + private int overrideColorProgress; public interface OnCheckedChangeListener { @@ -87,7 +94,12 @@ public class Switch extends View { } public Switch(Context context) { + this(context, null); + } + + public Switch(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); + this.resourcesProvider = resourcesProvider; rectF = new RectF(); paint = new Paint(Paint.ANTI_ALIAS_FLAG); @@ -95,6 +107,8 @@ public class Switch extends View { paint2.setStyle(Paint.Style.STROKE); paint2.setStrokeCap(Paint.Cap.ROUND); paint2.setStrokeWidth(AndroidUtilities.dp(2)); + + setHapticFeedbackEnabled(true); } @Keep @@ -190,7 +204,7 @@ public class Switch extends View { rippleDrawable.setCallback(this); } if (isChecked && colorSet != 2 || !isChecked && colorSet != 1) { - int color = isChecked ? Theme.getColor(Theme.key_switchTrackBlueSelectorChecked) : Theme.getColor(Theme.key_switchTrackBlueSelector); + int color = isChecked ? Theme.getColor(Theme.key_switchTrackBlueSelectorChecked, resourcesProvider) : Theme.getColor(Theme.key_switchTrackBlueSelector, resourcesProvider); /*if (Build.VERSION.SDK_INT < 28) { color = Color.argb(Color.alpha(color) * 2, Color.red(color), Color.green(color), Color.blue(color)); }*/ @@ -268,7 +282,7 @@ public class Switch extends View { if (checked != isChecked) { isChecked = checked; if (attachedToWindow && animated) { - vibrateChecked(); + vibrateChecked(checked); animateToCheckedState(checked); } else { cancelCheckAnimator(); @@ -293,7 +307,7 @@ public class Switch extends View { if (icon != 0) { iconDrawable = getResources().getDrawable(icon).mutate(); if (iconDrawable != null) { - iconDrawable.setColorFilter(new PorterDuffColorFilter(lastIconColor = Theme.getColor(isChecked ? trackCheckedColorKey : trackColorKey), PorterDuff.Mode.SRC_IN)); + iconDrawable.setColorFilter(new PorterDuffColorFilter(lastIconColor = Theme.getColor(isChecked ? trackCheckedColorKey : trackColorKey, resourcesProvider), PorterDuff.Mode.SRC_IN)); } } else { iconDrawable = null; @@ -401,8 +415,8 @@ public class Switch extends View { colorProgress = progress; } - color1 = Theme.getColor(trackColorKey); - color2 = Theme.getColor(trackCheckedColorKey); + color1 = Theme.getColor(trackColorKey, resourcesProvider); + color2 = Theme.getColor(trackCheckedColorKey, resourcesProvider); if (a == 0 && iconDrawable != null && lastIconColor != (isChecked ? color2 : color1)) { iconDrawable.setColorFilter(new PorterDuffColorFilter(lastIconColor = (isChecked ? color2 : color1), PorterDuff.Mode.SRC_IN)); } @@ -456,8 +470,8 @@ public class Switch extends View { colorProgress = progress; } - color1 = Theme.getColor(thumbColorKey); - color2 = Theme.getColor(thumbCheckedColorKey); + color1 = Theme.getColor(thumbColorKey, resourcesProvider); + color2 = Theme.getColor(thumbCheckedColorKey, resourcesProvider); r1 = Color.red(color1); r2 = Color.red(color2); g1 = Color.green(color1); @@ -532,21 +546,18 @@ public class Switch extends View { private boolean semHaptics = false; - private void vibrateChecked() { + private void vibrateChecked(boolean toCheck) { try { - Integer hapticIndex = null; - Method method = null; - if (Build.VERSION.SDK_INT >= 29) { - method = HapticFeedbackConstants.class.getDeclaredMethod("hidden_semGetVibrationIndex", Integer.TYPE); - } else if (Build.VERSION.SDK_INT >= 28) { - method = HapticFeedbackConstants.class.getMethod("semGetVibrationIndex", Integer.TYPE); - } - if (method != null) { - method.setAccessible(true); - hapticIndex = (Integer) method.invoke(null, 27); - } - if (hapticIndex != null) { - performHapticFeedback(hapticIndex); + if (isHapticFeedbackEnabled() && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { + final Vibrator vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE); + int slightAmplitude = OneUIUtilities.isOneUI() ? 5 : 15; + VibrationEffect vibrationEffect = VibrationEffect.createWaveform( + toCheck ? new long[] { 80, 25, 15 } : new long[] { 25, 80, 10 }, + toCheck ? new int[] { slightAmplitude, 0, 255 } : new int[] { 0, slightAmplitude, 140 }, + -1 + ); + vibrator.cancel(); + vibrator.vibrate(vibrationEffect); semHaptics = true; } } catch (Exception ignore) {} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemePreviewDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemePreviewDrawable.java index dfe165374..2848c9fcd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemePreviewDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemePreviewDrawable.java @@ -116,8 +116,9 @@ public class ThemePreviewDrawable extends BitmapDrawable { Bitmap patternBitmap = null; if (pattern != null) { + int W = 560, H = 678; if ("application/x-tgwallpattern".equals(themeDocument.mime_type)) { - patternBitmap = SvgHelper.getBitmap(pattern, 560, 678, false); + patternBitmap = SvgHelper.getBitmap(pattern, W, H, false); } else { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inSampleSize = 1; @@ -126,8 +127,8 @@ public class ThemePreviewDrawable extends BitmapDrawable { float photoW = opts.outWidth; float photoH = opts.outHeight; float scaleFactor; - int w_filter = 560; - int h_filter = 678; + int w_filter = W; + int h_filter = H; if (w_filter >= h_filter && photoW > photoH) { scaleFactor = Math.max(photoW / w_filter, photoH / h_filter); } else { @@ -159,11 +160,11 @@ public class ThemePreviewDrawable extends BitmapDrawable { backgroundPaint.setColorFilter(new PorterDuffColorFilter(patternColor, PorterDuff.Mode.SRC_IN)); } backgroundPaint.setAlpha(255); - float scale = Math.max(560.0f / patternBitmap.getWidth(), 678.0f / patternBitmap.getHeight()); + float scale = Math.max((float) W / patternBitmap.getWidth(), (float) H / patternBitmap.getHeight()); int w = (int) (patternBitmap.getWidth() * scale); int h = (int) (patternBitmap.getHeight() * scale); - int x = (560 - w) / 2; - int y = (678 - h) / 2; + int x = (W - w) / 2; + int y = (H - h) / 2; canvas.save(); canvas.translate(x, y); canvas.scale(scale, scale); 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 a75e53198..b0f35b442 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java @@ -21,6 +21,7 @@ import android.text.TextPaint; import android.text.TextUtils; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import org.telegram.messenger.AndroidUtilities; @@ -44,6 +45,9 @@ import java.util.List; public class ThemeSmallPreviewView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { + private final static int PATTERN_BITMAP_MAXWIDTH = 120; + private final static int PATTERN_BITMAP_MAXHEIGHT = 140; + public final static int TYPE_DEFAULT = 0; public final static int TYPE_GRID = 1; public final static int TYPE_QR = 2; @@ -95,7 +99,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe outlineBackgroundPaint.setStrokeWidth(AndroidUtilities.dp(2)); outlineBackgroundPaint.setStyle(Paint.Style.STROKE); - outlineBackgroundPaint.setColor(0xFFE3E3E3); + outlineBackgroundPaint.setColor(0x20E3E3E3); } @Override @@ -211,7 +215,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe if (result != null && result.first == themeId) { if (item.previewDrawable instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) item.previewDrawable; - motionBackgroundDrawable.setPatternBitmap(intensity >= 0 ? 100 : -100, result.second); + motionBackgroundDrawable.setPatternBitmap(intensity >= 0 ? 100 : -100, prescaleBitmap(result.second), true); motionBackgroundDrawable.setPatternColorFilter(patternColor); } invalidate(); @@ -231,10 +235,10 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe if (wallPaper != null && wallPaper.document != null) { TLRPC.Document wallpaperDocument = wallPaper.document; - final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaperDocument.thumbs, 120); + final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaperDocument.thumbs, PATTERN_BITMAP_MAXWIDTH); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaperDocument); ImageReceiver imageReceiver = new ImageReceiver(); - imageReceiver.setImage(imageLocation, "120_80", null, null, null, 1); + imageReceiver.setImage(imageLocation, PATTERN_BITMAP_MAXWIDTH + "_" + PATTERN_BITMAP_MAXHEIGHT, null, null, null, 1); imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); if (!set || holder == null) { @@ -244,9 +248,8 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe if (resultBitmap != null) { if (item.previewDrawable instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) item.previewDrawable; - motionBackgroundDrawable.setPatternBitmap(wallPaper.settings == null || wallPaper.settings.intensity >= 0 ? 100 : -100, resultBitmap); + motionBackgroundDrawable.setPatternBitmap(wallPaper.settings == null || wallPaper.settings.intensity >= 0 ? 100 : -100, prescaleBitmap(resultBitmap), true); motionBackgroundDrawable.setPatternColorFilter(patternColor); - invalidate(); } } @@ -255,11 +258,11 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe } } else if (accent != null && accent.info == null) { ChatThemeController.chatThemeQueue.postRunnable(() -> { - Bitmap bitmap = SvgHelper.getBitmap(R.raw.default_pattern, AndroidUtilities.dp(80), AndroidUtilities.dp(120), Color.BLACK, 3f); + Bitmap bitmap = SvgHelper.getBitmap(R.raw.default_pattern, AndroidUtilities.dp(PATTERN_BITMAP_MAXWIDTH), AndroidUtilities.dp(PATTERN_BITMAP_MAXHEIGHT), Color.BLACK, AndroidUtilities.density); AndroidUtilities.runOnUIThread(() -> { if (item.previewDrawable instanceof MotionBackgroundDrawable) { MotionBackgroundDrawable motionBackgroundDrawable = (MotionBackgroundDrawable) item.previewDrawable; - motionBackgroundDrawable.setPatternBitmap(100, bitmap); + motionBackgroundDrawable.setPatternBitmap(100, prescaleBitmap(bitmap), true); motionBackgroundDrawable.setPatternColorFilter(patternColor); invalidate(); } @@ -279,11 +282,16 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe backupImageView.getImageReceiver().getLottieAnimation().setCurrentFrame(0, false); } } + + if (chatThemeItem.chatTheme == null || chatThemeItem.chatTheme.showAsDefaultStub) { + setContentDescription(LocaleController.getString("ChatNoTheme", R.string.ChatNoTheme)); + } else { + setContentDescription(chatThemeItem.chatTheme.getEmoticon()); + } } boolean isSelected; - public void setSelected(boolean selected, boolean animated) { if (!animated) { if (strokeAlphaAnimator != null) { @@ -318,6 +326,22 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe isSelected = selected; } + private Bitmap prescaleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return null; + } + float scale = Math.max(AndroidUtilities.dp(PATTERN_BITMAP_MAXWIDTH) / bitmap.getWidth(), AndroidUtilities.dp(PATTERN_BITMAP_MAXHEIGHT) / bitmap.getHeight()); + if (bitmap.getWidth() <= 0 || bitmap.getHeight() <= 0 || Math.abs(scale - 1f) < .0125f) { + return bitmap; + } + int w = (int) (bitmap.getWidth() * scale); + int h = (int) (bitmap.getHeight() * scale); + if (h <= 0 || w <= 0) { + return bitmap; + } + return Bitmap.createScaledBitmap(bitmap, w, h, true); + } + @Override public void setBackgroundColor(int color) { backgroundFillPaint.setColor(getThemedColor(Theme.key_dialogBackgroundGray)); @@ -434,9 +458,11 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe } else if (color1 != 0) { drawable = new ColorDrawable(color1); } else if (item.themeInfo != null && (item.themeInfo.previewWallpaperOffset > 0 || item.themeInfo.pathToWallpaper != null)) { - Bitmap wallpaper = AndroidUtilities.getScaledBitmap(AndroidUtilities.dp(76), AndroidUtilities.dp(97), item.themeInfo.pathToWallpaper, item.themeInfo.pathToFile, item.themeInfo.previewWallpaperOffset); + Bitmap wallpaper = AndroidUtilities.getScaledBitmap(AndroidUtilities.dp(112), AndroidUtilities.dp(134), item.themeInfo.pathToWallpaper, item.themeInfo.pathToFile, item.themeInfo.previewWallpaperOffset); if (wallpaper != null) { - drawable = new BitmapDrawable(wallpaper); + BitmapDrawable bitmapDrawable = new BitmapDrawable(wallpaper); + bitmapDrawable.setFilterBitmap(true); + drawable = bitmapDrawable; } } else { drawable = new MotionBackgroundDrawable(0xffdbddbb, 0xff6ba587, 0xffd5d88d, 0xff88b884, true); @@ -531,10 +557,12 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe previewDrawable.setAlpha((int) (255 * alpha)); previewDrawable.draw(canvas); if (previewDrawable instanceof ColorDrawable || (previewDrawable instanceof MotionBackgroundDrawable && ((MotionBackgroundDrawable) previewDrawable).isOneColor())) { - outlineBackgroundPaint.setAlpha((int) (255 * alpha)); + int wasAlpha = outlineBackgroundPaint.getAlpha(); + outlineBackgroundPaint.setAlpha((int) (wasAlpha * alpha)); float padding = INNER_RECT_SPACE; AndroidUtilities.rectTmp.set(padding, padding, getWidth() - padding, getHeight() - padding); canvas.drawRoundRect(AndroidUtilities.rectTmp, INNER_RADIUS, INNER_RADIUS, outlineBackgroundPaint); + outlineBackgroundPaint.setAlpha(wasAlpha); } canvas.restore(); } else { @@ -635,4 +663,11 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe invalidate(); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + info.setSelected(isSelected); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java index e866b7f63..74b6d1531 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java @@ -91,11 +91,16 @@ public class TimerDrawable extends Drawable { } else if (timeString.length() > 2) { timeString = "c"; } - } else { + } else if (time < 60 * 60 * 24 * 364){ timeString = "" + value / 60 / 60 / 24 / 30; if (timeString.length() < 2) { timeString += LocaleController.getString("SecretChatTimerMonths", R.string.SecretChatTimerMonths); } + } else { + timeString = "" + value / 60 / 60 / 24 / 364; + if (timeString.length() < 2) { + timeString += LocaleController.getString("SecretChatTimerYears", R.string.SecretChatTimerYears); + } } timePaint.setTextSize(AndroidUtilities.dp(11)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranscribeButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranscribeButton.java new file mode 100644 index 000000000..9457c0ec7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranscribeButton.java @@ -0,0 +1,498 @@ +package org.telegram.ui.Components; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PixelFormat; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.RippleDrawable; +import android.os.Build; +import android.os.SystemClock; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.style.ImageSpan; +import android.util.StateSet; +import android.view.MotionEvent; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.ColorUtils; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; + +import org.telegram.messenger.AccountInstance; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.DialogObject; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.MessagesStorage; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Cells.ChatMessageCell; +import org.telegram.ui.PremiumPreviewFragment; + +import java.util.HashMap; +import java.util.Objects; + +public class TranscribeButton { + + private final static int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; + + private int backgroundColor, color, iconColor, rippleColor; + private Paint backgroundPaint, strokePaint; + private Path progressClipPath; + + private boolean loading; + private AnimatedFloat loadingFloat; + + private RLottieDrawable inIconDrawable; + private RLottieDrawable outIconDrawable; + + private Drawable selectorDrawable; + private ChatMessageCell parent; + private SeekBarWaveform seekBar; + + private long start; + private Rect bounds, pressBounds; + + private boolean premium; + private boolean isOpen, shouldBeOpen; + + public TranscribeButton(ChatMessageCell parent, SeekBarWaveform seekBar) { + start = SystemClock.elapsedRealtime(); + this.parent = parent; + this.seekBar = seekBar; + this.bounds = new Rect(0, 0, AndroidUtilities.dp(30), AndroidUtilities.dp(30)); + this.pressBounds = new Rect(this.bounds); + this.pressBounds.inset(AndroidUtilities.dp(8), AndroidUtilities.dp(8)); + + outIconDrawable = new RLottieDrawable(R.raw.transcribe_out, "transcribe_out", AndroidUtilities.dp(26), AndroidUtilities.dp(26)); + outIconDrawable.setCurrentFrame(0); + outIconDrawable.setCallback(parent); + outIconDrawable.addParentView(parent); + outIconDrawable.setOnFinishCallback(() -> { + outIconDrawable.stop(); + inIconDrawable.stop(); + isOpen = shouldBeOpen = true; + inIconDrawable.setCurrentFrame(0); + }, 19); + outIconDrawable.setAllowDecodeSingleFrame(true); + + inIconDrawable = new RLottieDrawable(R.raw.transcribe_in, "transcribe_in", AndroidUtilities.dp(26), AndroidUtilities.dp(26)); + inIconDrawable.setCurrentFrame(0); + inIconDrawable.setCallback(parent); + inIconDrawable.addParentView(parent); + inIconDrawable.setOnFinishCallback(() -> { + inIconDrawable.stop(); + outIconDrawable.stop(); + isOpen = shouldBeOpen = false; + outIconDrawable.setCurrentFrame(0); + }, 19); + inIconDrawable.setAllowDecodeSingleFrame(true); + + this.isOpen = false; + this.shouldBeOpen = false; + premium = AccountInstance.getInstance(parent.getMessageObject().currentAccount).getUserConfig().isPremium(); + + loadingFloat = new AnimatedFloat(parent, 250, CubicBezierInterpolator.EASE_OUT_QUINT); + } + + public void setLoading(boolean loading, boolean animated) { + this.loading = loading; + seekBar.setLoading(loading); + if (!animated) { + loadingFloat.set(this.loading ? 1 : 0, true); + } else { + if (loadingFloat.get() <= 0f) { + start = SystemClock.elapsedRealtime(); + } + } + if (parent != null) { + parent.invalidate(); + } + } + + public void setOpen(boolean open, boolean animated) { + boolean wasShouldBeOpen = shouldBeOpen; + shouldBeOpen = open; + if (animated) { + if (open && !wasShouldBeOpen) { + isOpen = false; + inIconDrawable.setCurrentFrame(0); + outIconDrawable.setCurrentFrame(0); + outIconDrawable.start(); + } else if (!open && wasShouldBeOpen) { + isOpen = true; + outIconDrawable.setCurrentFrame(0); + inIconDrawable.setCurrentFrame(0); + inIconDrawable.start(); + } + } else { + isOpen = open; + inIconDrawable.stop(); + outIconDrawable.stop(); + inIconDrawable.setCurrentFrame(0); + outIconDrawable.setCurrentFrame(0); + } + if (parent != null) { + parent.invalidate(); + } + } + + private boolean pressed = false; + private long pressId = 0; + public boolean onTouch(int action, float x, float y) { + if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { + if (pressed && action == MotionEvent.ACTION_UP) { + onTap(); + return true; + } + pressed = false; + return false; + } + if (!pressBounds.contains((int) x, (int) y)) { + return false; + } + if (action == MotionEvent.ACTION_DOWN) { + pressed = true; + } + if (pressed && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && selectorDrawable instanceof RippleDrawable) { + selectorDrawable.setHotspot(x, y); + selectorDrawable.setState(pressedState); + parent.invalidate(); + } + return true; + } + + public void onTap() { + boolean processClick, toOpen = !shouldBeOpen; + if (!shouldBeOpen) { + processClick = !loading; + if (premium && parent.getMessageObject().isSent()) { + setLoading(true, true); + } + } else { + processClick = true; + setOpen(false, true); + setLoading(false, true); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && selectorDrawable instanceof RippleDrawable) { + selectorDrawable.setState(StateSet.NOTHING); + parent.invalidate(); + } + pressed = false; + if (processClick) { + if (!premium && toOpen) { + if (parent.getDelegate() != null) { + parent.getDelegate().needShowPremiumFeatures(PremiumPreviewFragment.featureTypeToServerString(PremiumPreviewFragment.PREMIUM_FEATURE_VOICE_TO_TEXT)); + } + } else { + transcribePressed(parent.getMessageObject(), toOpen); + } + } + } + + public void setColor(boolean isOut, int color, int grayColor) { + boolean disabled = !premium; +// if (disabled) { +// color = ColorUtils.blendARGB(color, grayColor, isOut ? .6f : .8f); +// color = ColorUtils.setAlphaComponent(color, (int) (Color.alpha(color) * .8f)); +// } + boolean newColor = this.color != color; + this.iconColor = this.color = color; + this.backgroundColor = ColorUtils.setAlphaComponent(color, (int) (Color.alpha(color) * 0.156f)); + this.rippleColor = Theme.blendOver(this.backgroundColor, ColorUtils.setAlphaComponent(color, (int) (Color.alpha(color) * (Theme.isCurrentThemeDark() ? .3f : .2f)))); + if (backgroundPaint == null) { + backgroundPaint = new Paint(); + } + backgroundPaint.setColor(this.backgroundColor); + if (newColor || selectorDrawable == null) { + selectorDrawable = Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(8), 0, this.rippleColor); + selectorDrawable.setCallback(parent); + } + if (newColor) { + inIconDrawable.beginApplyLayerColors(); + inIconDrawable.setLayerColor("Artboard Outlines.**", this.iconColor); + inIconDrawable.commitApplyLayerColors(); + inIconDrawable.setAllowDecodeSingleFrame(true); + inIconDrawable.updateCurrentFrame(); + outIconDrawable.beginApplyLayerColors(); + outIconDrawable.setLayerColor("Artboard Outlines.**", this.iconColor); + outIconDrawable.commitApplyLayerColors(); + outIconDrawable.setAllowDecodeSingleFrame(true); + outIconDrawable.updateCurrentFrame(); + } +// inIconDrawable.setAlpha(disabled ? 125 : 255); +// outIconDrawable.setAlpha(disabled ? 125 : 255); + if (strokePaint == null) { + strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); + strokePaint.setStyle(Paint.Style.STROKE); + } + strokePaint.setColor(color); + } + + private final FastOutSlowInInterpolator interpolator = new FastOutSlowInInterpolator(); + private Path boundsPath; + + public void draw(Canvas canvas) { + this.bounds.set(0, AndroidUtilities.dp(3), AndroidUtilities.dp(30), AndroidUtilities.dp(3 + 24)); + this.pressBounds.set(this.bounds.left - AndroidUtilities.dp(8), this.bounds.top - AndroidUtilities.dp(8), this.bounds.right + AndroidUtilities.dp(8), this.bounds.bottom + AndroidUtilities.dp(8)); + if (boundsPath == null) { + boundsPath = new Path(); + AndroidUtilities.rectTmp.set(this.bounds); + boundsPath.addRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), Path.Direction.CW); + } + canvas.save(); + canvas.clipPath(boundsPath); + if (backgroundPaint != null) { + canvas.drawRect(this.bounds, backgroundPaint); + } + if (selectorDrawable != null && premium) { + selectorDrawable.setBounds(bounds); + selectorDrawable.draw(canvas); + } + canvas.restore(); + + float loadingT = loadingFloat.set(loading ? 1f : 0f); + if (loadingT > 0f) { + float[] segments = getSegments((long) ((SystemClock.elapsedRealtime() - start) * .75f)); + + canvas.save(); + if (progressClipPath == null) { + progressClipPath = new Path(); + } + progressClipPath.reset(); + AndroidUtilities.rectTmp.set(pressBounds); + float segmentLength = Math.max(40 * loadingT, segments[1] - segments[0]); + progressClipPath.addArc(AndroidUtilities.rectTmp, segments[0] + segmentLength * (1f - loadingT) * (loading ? 0f : 1f), segmentLength * loadingT); + progressClipPath.lineTo(AndroidUtilities.rectTmp.centerX(), AndroidUtilities.rectTmp.centerY()); + progressClipPath.close(); + canvas.clipPath(progressClipPath); + AndroidUtilities.rectTmp.set(bounds); + strokePaint.setStrokeWidth(AndroidUtilities.dp(1.5f)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), strokePaint); + canvas.restore(); + + parent.invalidate(); + } + + canvas.save(); + canvas.translate(AndroidUtilities.dp(2), AndroidUtilities.dp(2)); + if (isOpen) { + inIconDrawable.draw(canvas); + } else { + outIconDrawable.draw(canvas); + } + canvas.restore(); + } + + private float[] segments; + private float[] getSegments(long d) { + if (segments == null) { + segments = new float[2]; + } + final long t = d % 5400L; + segments[0] = 1520 * t / 5400f - 20; + segments[1] = 1520 * t / 5400f; + float fraction; + for (int i = 0; i < 4; ++i) { + fraction = (t - i * 1350) / 667f; + segments[1] += interpolator.getInterpolation(fraction) * 250; + fraction = (t - (667 + i * 1350)) / 667f; + segments[0] += interpolator.getInterpolation(fraction) * 250; + } + return segments; + } + + + public static class LoadingPointsSpan extends ImageSpan { + private static LoadingPointsDrawable drawable; + + public LoadingPointsSpan() { + super(drawable == null ? drawable = new LoadingPointsDrawable(Theme.chat_msgTextPaint) : drawable, ImageSpan.ALIGN_BOTTOM); + float fontSize = Theme.chat_msgTextPaint.getTextSize() * 0.89f; + int yoff = (int) (fontSize * 0.02f); + getDrawable().setBounds(0, yoff, (int) fontSize, yoff + (int) (fontSize * 1.25f)); + } + + @Override + public void updateDrawState(TextPaint textPaint) { + float fontSize = textPaint.getTextSize() * 0.89f; + int yoff = (int) (fontSize * 0.02f); + getDrawable().setBounds(0, yoff, (int) fontSize, yoff + (int) (fontSize * 1.25f)); + super.updateDrawState(textPaint); + } + } + + private static class LoadingPointsDrawable extends Drawable { + private RLottieDrawable lottie; + private int lastColor; + private Paint paint; + public LoadingPointsDrawable(TextPaint textPaint) { + this.paint = textPaint; + float fontSize = textPaint.getTextSize() * 0.89f; + lottie = new RLottieDrawable(R.raw.dots_loading, "dots_loading", (int) fontSize, (int) (fontSize * 1.25f)) { + @Override + protected boolean hasParentView() { + return true; + } + }; + lottie.setAutoRepeat(1); + lottie.setCurrentFrame((int) (SystemClock.elapsedRealtime() / 16f % 60f)); + lottie.setAllowDecodeSingleFrame(true); + lottie.start(); + } + + public void setColor(int color) { + lottie.beginApplyLayerColors(); + lottie.setLayerColor("Comp 1.**", color); + lottie.commitApplyLayerColors(); + lottie.setAllowDecodeSingleFrame(true); + lottie.updateCurrentFrame(); + } + + @Override + public void draw(@NonNull Canvas canvas) { + int color = this.paint.getColor(); + if (color != lastColor) { + setColor(color); + lastColor = color; + } + lottie.draw(canvas); + } + + @Override + public void setAlpha(int i) {} + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) {} + @Override + public int getOpacity() { + return PixelFormat.TRANSPARENT; + } + } + + + // requests logic + + private static int reqInfoHash(MessageObject messageObject) { + if (messageObject == null) { + return 0; + } + return Objects.hash(messageObject.currentAccount, messageObject.getDialogId(), messageObject.getId()); + } + + private static HashMap transcribeOperationsById; + private static HashMap transcribeOperationsByDialogPosition; + + public static boolean isTranscribing(MessageObject messageObject) { + return ( + (transcribeOperationsByDialogPosition != null && (transcribeOperationsByDialogPosition.containsValue(messageObject) || transcribeOperationsByDialogPosition.containsKey((Integer) reqInfoHash(messageObject)))) || + (transcribeOperationsById != null && messageObject != null && messageObject.messageOwner != null && transcribeOperationsById.containsKey(messageObject.messageOwner.voiceTranscriptionId)) + ); + } + + private static void transcribePressed(MessageObject messageObject, boolean open) { + if (messageObject == null || messageObject.messageOwner == null || !messageObject.isSent()) { + return; + } + int account = messageObject.currentAccount; + final long start = SystemClock.elapsedRealtime(), minDuration = 350; + TLRPC.InputPeer peer = MessagesController.getInstance(account).getInputPeer(messageObject.messageOwner.peer_id); + long dialogId = DialogObject.getPeerDialogId(peer); + int messageId = messageObject.messageOwner.id; + if (open) { + if (messageObject.messageOwner.voiceTranscription != null && messageObject.messageOwner.voiceTranscriptionFinal) { + messageObject.messageOwner.voiceTranscriptionOpen = true; + MessagesStorage.getInstance(account).updateMessageVoiceTranscriptionOpen(dialogId, messageId, messageObject.messageOwner); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(account).postNotificationName(NotificationCenter.voiceTranscriptionUpdate, messageObject, null, null, (Boolean) true, (Boolean) true); + }); + } else { + TLRPC.TL_messages_transcribeAudio req = new TLRPC.TL_messages_transcribeAudio(); + req.peer = peer; + req.msg_id = messageId; + if (transcribeOperationsByDialogPosition == null) { + transcribeOperationsByDialogPosition = new HashMap<>(); + } + transcribeOperationsByDialogPosition.put((Integer) reqInfoHash(messageObject), messageObject); + ConnectionsManager.getInstance(account).sendRequest(req, (res, err) -> { + String text; + long id = 0; + boolean isFinal = false; + if (res instanceof TLRPC.TL_messages_transcribedAudio) { + TLRPC.TL_messages_transcribedAudio r = (TLRPC.TL_messages_transcribedAudio) res; + text = r.text; + id = r.transcription_id; + isFinal = !r.pending; + if (TextUtils.isEmpty(text)) { + text = !isFinal ? null : ""; + } + if (transcribeOperationsById == null) { + transcribeOperationsById = new HashMap<>(); + } + transcribeOperationsById.put(id, messageObject); + messageObject.messageOwner.voiceTranscriptionId = id; + } else { + text = ""; + isFinal = true; + } + final String finalText = text; + final long finalId = id; + final long duration = SystemClock.elapsedRealtime() - start; + messageObject.messageOwner.voiceTranscriptionOpen = true; + messageObject.messageOwner.voiceTranscriptionFinal = isFinal; + if (BuildVars.LOGS_ENABLED) { + FileLog.e("Transcription request sent, received final=" + isFinal + " id=" + finalId + " text=" + finalText); + } + + MessagesStorage.getInstance(account).updateMessageVoiceTranscription(dialogId, messageId, finalText, messageObject.messageOwner); + if (isFinal) { + AndroidUtilities.runOnUIThread(() -> finishTranscription(messageObject, finalId, finalText), Math.max(0, minDuration - duration)); + } + }); + } + } else { + if (transcribeOperationsByDialogPosition != null) { + transcribeOperationsByDialogPosition.remove((Integer) reqInfoHash(messageObject)); + } + messageObject.messageOwner.voiceTranscriptionOpen = false; + MessagesStorage.getInstance(account).updateMessageVoiceTranscriptionOpen(dialogId, messageId, messageObject.messageOwner); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(account).postNotificationName(NotificationCenter.voiceTranscriptionUpdate, messageObject, null, null, (Boolean) false, null); + }); + } + } + + public static boolean finishTranscription(MessageObject messageObject, long transcription_id, String text) { + try { + MessageObject messageObjectByTranscriptionId = null; + if (transcribeOperationsById != null && transcribeOperationsById.containsKey(transcription_id)) { + messageObjectByTranscriptionId = transcribeOperationsById.remove(transcription_id); + } + if (messageObject == null) { + messageObject = messageObjectByTranscriptionId; + } + if (messageObject == null || messageObject.messageOwner == null) { + return false; + } + final MessageObject finalMessageObject = messageObject; + if (transcribeOperationsByDialogPosition != null) { + transcribeOperationsByDialogPosition.remove((Integer) reqInfoHash(messageObject)); + } + messageObject.messageOwner.voiceTranscriptionFinal = true; + MessagesStorage.getInstance(messageObject.currentAccount).updateMessageVoiceTranscription(messageObject.getDialogId(), messageObject.getId(), text, messageObject.messageOwner); + AndroidUtilities.runOnUIThread(() -> { + NotificationCenter.getInstance(finalMessageObject.currentAccount).postNotificationName(NotificationCenter.voiceTranscriptionUpdate, finalMessageObject, (Long) transcription_id, (String) text, (Boolean) true, (Boolean) true); + }); + return true; + } catch (Exception ignore) {} + return false; + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java new file mode 100644 index 000000000..403f65fd2 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TranslateAlert2.java @@ -0,0 +1,1813 @@ +package org.telegram.ui.Components; + +import static org.telegram.messenger.AndroidUtilities.dp; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +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.graphics.Region; +import android.graphics.Shader; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.os.SystemClock; +import android.text.Layout; +import android.text.Spannable; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.text.style.ClickableSpan; +import android.text.style.URLSpan; +import android.text.util.Linkify; +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.view.ViewParent; +import android.view.WindowManager; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import org.json.JSONArray; +import org.json.JSONTokener; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.DispatchQueue; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.R; +import org.telegram.messenger.XiaomiUtilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.net.URI; +import java.nio.charset.Charset; +import java.util.ArrayList; + +public class TranslateAlert2 extends BottomSheet { + + public static volatile DispatchQueue translateQueue = new DispatchQueue("translateQueue", false); + + public RecyclerListView listView; + private LinearLayoutManager layoutManager; + private View paddingView; +// private FrameLayout container; + private TextView titleView; + private LinearLayout subtitleView; + private InlineLoadingTextView subtitleFromView; + private ImageView subtitleArrowView; + private TextView subtitleToView; + private ImageView backButton; + private HeaderView header; + private FrameLayout headerShadowView; +// private NestedScrollView scrollView; + private TextBlocksLayout textsView; + private TextView buttonTextView; + private FrameLayout buttonContainerView; + private FrameLayout buttonView; + private FrameLayout buttonShadowView; + private TextView allTextsView; +// private FrameLayout textsContainerView; + private FrameLayout bulletinContainer; + +// private FrameLayout.LayoutParams titleLayout; +// private FrameLayout.LayoutParams subtitleLayout; +// private FrameLayout.LayoutParams headerLayout; +// private FrameLayout.LayoutParams scrollViewLayout; + + private int blockIndex = 0; + private ArrayList textBlocks; +// +// private boolean canExpand() { +// return ( +// textsView.getBlocksCount() < textBlocks.size() || +// minHeight(true) >= (AndroidUtilities.displayMetrics.heightPixels * heightMaxPercent) +// ); +// } +// private void updateCanExpand() { +// boolean canExpand = canExpand(); +// if (containerOpenAnimationT > 0f && !canExpand) { +// openAnimationTo(0f, false); +// } +// +// buttonShadowView.animate().alpha(canExpand ? 1f : 0f).setDuration((long) (Math.abs(buttonShadowView.getAlpha() - (canExpand ? 1f : 0f)) * 220)).start(); +// } + + public interface OnLinkPress { + public boolean run(URLSpan urlSpan); + } + + @Override + public void onBackPressed() { + dismiss(); + } + + private class HeaderView extends FrameLayout { + + public HeaderView(Context context) { + super(context); + } + + private float expandedT = 0f; + public void setExpandedT(float value) { + backButton.setAlpha(value); + headerShadowView.setAlpha(value); + if (Math.abs(expandedT - value) > 0.01f) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && expandedT > .5f != value > .5f) { + int flags = containerView.getSystemUiVisibility(); + if (value > .5f) { + flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } else { + flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; + } + containerView.setSystemUiVisibility(flags); + } + expandedT = value; + invalidate(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + titleView.layout( + dp(22), + dp(22), + right - left - dp(22), + dp(22) + titleView.getMeasuredHeight() + ); + subtitleView.layout( + dp(22) - LoadingTextView2.paddingHorizontal, + dp(47) - LoadingTextView2.paddingVertical, + right - left - dp(22) - LoadingTextView2.paddingHorizontal, + dp(47) - LoadingTextView2.paddingVertical + subtitleView.getMeasuredHeight() + ); + backButton.layout(0, 0, dp(56), dp(56)); + headerShadowView.layout(0, dp(55), right - left, dp(56)); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == titleView) { + canvas.save(); + canvas.translate(dp(50 * expandedT), dp(-14 * expandedT)); + canvas.scale(1f - expandedT * 0.111f, 1f - expandedT * 0.111f, child.getX(), child.getY() + child.getMeasuredHeight() / 2); + boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return result; + } else if (child == subtitleView) { + canvas.save(); + canvas.translate(dp(50 * expandedT), dp(-17 * expandedT)); + boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return result; + } else { + return super.drawChild(canvas, child, drawingTime); + } + } + + @Override + protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) { + if (child == backButton) { + backButton.measure( + MeasureSpec.makeMeasureSpec(dp(56), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(dp(56), MeasureSpec.EXACTLY) + ); + } else { + super.measureChild(child, parentWidthMeasureSpec, parentHeightMeasureSpec); + } + } + } + + private boolean allowScroll = true; + private String fromLanguage, toLanguage; + private CharSequence text; + private BaseFragment fragment; + private boolean noforwards; + private OnLinkPress onLinkPress; + private Runnable onDismiss; + + public void updateCanExpand() { + boolean canExpand = listView.canScrollVertically(1) || listView.canScrollVertically(-1); + float canExpandAlpha = canExpand ? 1f : 0f; + buttonShadowView.animate().alpha(canExpandAlpha).setDuration(200).start(); + allowScroll = canExpand; + } + + public TranslateAlert2(BaseFragment fragment, Context context, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress, Runnable onDismiss) { + super(context, false); + fixNavigationBar(); + + this.onLinkPress = onLinkPress; + this.noforwards = noforwards; + this.fragment = fragment; + this.fromLanguage = fromLanguage != null && fromLanguage.equals("und") ? "auto" : fromLanguage; + this.toLanguage = toLanguage; + this.text = text; + this.textBlocks = cutInBlocks(text, 1024); + this.onDismiss = onDismiss; + + if (noforwards) { + getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE); + } + + allTextsView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MOST_SPEC); + } + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + if (links != null && links.draw(canvas)) { + invalidate(); + } + canvas.restore(); + } + @Override + public boolean onTextContextMenuItem(int id) { + if (id == android.R.id.copy && isFocused()) { + android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); + android.content.ClipData clip = android.content.ClipData.newPlainText( + "label", + getText().subSequence( + Math.max(0, Math.min(getSelectionStart(), getSelectionEnd())), + Math.max(0, Math.max(getSelectionStart(), getSelectionEnd())) + ) + ); + clipboard.setPrimaryClip(clip); + BulletinFactory.of(bulletinContainer, null).createCopyBulletin(LocaleController.getString("TextCopied", R.string.TextCopied)).show(); + clearFocus(); + return true; + } else { + return super.onTextContextMenuItem(id); + } + } + }; + links = new LinkSpanDrawable.LinkCollector(allTextsView); + allTextsView.setTextColor(0x00000000); + allTextsView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + allTextsView.setTextIsSelectable(!noforwards); + allTextsView.setHighlightColor(Theme.getColor(Theme.key_chat_inTextSelectionHighlight)); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !XiaomiUtilities.isMIUI()) { + final int handleColor = Theme.getColor(Theme.key_chat_TextSelectionCursor); + + Drawable left = allTextsView.getTextSelectHandleLeft(); + left.setColorFilter(handleColor, PorterDuff.Mode.SRC_IN); + allTextsView.setTextSelectHandleLeft(left); + + Drawable right = allTextsView.getTextSelectHandleRight(); + right.setColorFilter(handleColor, PorterDuff.Mode.SRC_IN); + allTextsView.setTextSelectHandleRight(right); + } + } catch (Exception ignore) {} + allTextsView.setMovementMethod(new LinkMovementMethod()); + + textsView = new TextBlocksLayout(context, dp(16), Theme.getColor(Theme.key_dialogTextBlack), allTextsView) { + @Override + protected void onHeightUpdated(int height, int dy) { +// if (dy != 0 && listView != null && listView.canScrollVertically(-dy)) { +// try { +// listView.scrollBy(0, -dy); +// } catch (Exception ignore) {} +// } + paddingView.requestFocus(); + paddingView.requestLayout(); + } + }; + textsView.setPadding( + dp(22) - LoadingTextView2.paddingHorizontal, + dp(12 + 8) - LoadingTextView2.paddingVertical, + dp(22) - LoadingTextView2.paddingHorizontal, + dp(12) - LoadingTextView2.paddingVertical + ); + for (CharSequence blockText : textBlocks) { + textsView.addBlock(blockText); + } + + final Paint backgroundPaint = new Paint(); + backgroundPaint.setColor(Theme.getColor(Theme.key_dialogBackground)); + backgroundPaint.setShadowLayer(dp(2), 0, dp(-0.66f), 0x1e000000); + final Paint navigationBarPaint = new Paint(); + navigationBarPaint.setColor(Theme.getColor(Theme.key_dialogBackgroundGray)); + + containerView = new FrameLayout(context) { + @Override + public boolean hasOverlappingRendering() { + return false; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + float top = getCurrentItemTop(); + float expandedT = 1f - Math.max(0, Math.min(top / dp(48), 1)); + header.setTranslationY(top); + header.setExpandedT(expandedT); + updateCanExpand(); + float r = dp(12) * (1f - expandedT); + AndroidUtilities.rectTmp.set(backgroundPaddingLeft, getPaddingTop() + top - (AndroidUtilities.statusBarHeight + dp(8)) * expandedT + dp(8), getWidth() - backgroundPaddingLeft, getPaddingTop() + top + dp(20)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, navigationBarPaint); + AndroidUtilities.rectTmp.set(backgroundPaddingLeft, getPaddingTop() + top, getWidth() - backgroundPaddingLeft, getPaddingTop() + getHeight() + dp(12)); + canvas.drawRoundRect(AndroidUtilities.rectTmp, r, r, backgroundPaint); + + super.dispatchDraw(canvas); + } + + @Override + public void setTranslationY(float translationY) { + super.setTranslationY(translationY); + onContainerTranslationYChanged(translationY); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == listView) { + canvas.save(); + canvas.clipRect(0, getPaddingTop() + listView.getPaddingTop(), getWidth(), getHeight() - listView.getPaddingBottom()); + boolean result = super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return result; + } else { + return super.drawChild(canvas, child, drawingTime); + } + } + }; + containerView.setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0); + containerView.setClipChildren(false); + containerView.setClipToPadding(false); + containerView.setWillNotDraw(false); + + listView = new RecyclerListView(context) { + + @Override + public View getFocusedChild() { + return textsView; + } + + @Override + public void onScrolled(int dx, int dy) { + checkForNextLoading(); + super.onScrolled(dx, dy); + containerView.invalidate(); + } + + @Override + public void onScrollStateChanged(int state) { + super.onScrollStateChanged(state); + + if (state == SCROLL_STATE_IDLE && header.expandedT > 0 && header.expandedT < 1) { + smoothScrollBy(0, (int) header.getTranslationY()); + } + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + if (!allowScroll) { + return false; + } + return super.onTouchEvent(e); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent e) { + if (!allowScroll) { + return false; + } + return super.onInterceptTouchEvent(e); + } + }; + listView.setClipChildren(true); + listView.setClipToPadding(true); + listView.setPadding(0, dp(56), 0, dp(80)); + listView.setLayoutManager(layoutManager = new LinearLayoutManager(context) { + @Override + public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { + super.onLayoutChildren(recycler, state); + + } + }); + layoutManager.setOrientation(RecyclerView.VERTICAL); + layoutManager.setReverseLayout(true); + listView.setAdapter(new RecyclerView.Adapter() { + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == 0) { + return new RecyclerListView.Holder(textsView); + } + return new RecyclerListView.Holder(paddingView); + } + + @Override + public int getItemViewType(int position) { + return position; + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {} + + @Override + public int getItemCount() { + return 2; + } + }); + + View redDot = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(32), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(32), MeasureSpec.EXACTLY)); + } + }; + redDot.setBackgroundColor(0xffff0000); + containerView.addView(redDot); + + containerView.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + header = new HeaderView(context); + header.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); + containerView.addView(header, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.FILL_HORIZONTAL)); + + titleView = new TextView(context); + titleView.setPivotX(LocaleController.isRTL ? titleView.getWidth() : 0); + titleView.setPivotY(0); + titleView.setLines(1); + titleView.setText(LocaleController.getString("AutomaticTranslation", R.string.AutomaticTranslation)); + titleView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); + header.addView(titleView, LayoutHelper.createFrame( + LayoutHelper.MATCH_PARENT, + LayoutHelper.WRAP_CONTENT, + Gravity.FILL_HORIZONTAL | Gravity.TOP, + 22, 22,22, 0 + )); + titleView.post(() -> { + titleView.setPivotX(LocaleController.isRTL ? titleView.getWidth() : 0); + }); + + subtitleView = new LinearLayout(context); + subtitleView.setOrientation(LinearLayout.HORIZONTAL); + if (Build.VERSION.SDK_INT >= 17) { + subtitleView.setLayoutDirection(LocaleController.isRTL ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); + } + subtitleView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT); + + String fromLanguageName = languageName(fromLanguage); + subtitleFromView = new InlineLoadingTextView(context, fromLanguageName == null ? languageName(toLanguage) : fromLanguageName, dp(14), Theme.getColor(Theme.key_player_actionBarSubtitle)) { + @Override + protected void onLoadAnimation(float t) { + MarginLayoutParams lp = (MarginLayoutParams) subtitleFromView.getLayoutParams(); + if (lp != null) { + if (LocaleController.isRTL) { + lp.leftMargin = dp(2f - t * 6f); + } else { + lp.rightMargin = dp(2f - t * 6f); + } + subtitleFromView.setLayoutParams(lp); + } + } + }; + subtitleFromView.showLoadingText = false; + subtitleArrowView = new ImageView(context); + subtitleArrowView.setImageResource(R.drawable.search_arrow); + subtitleArrowView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_player_actionBarSubtitle), PorterDuff.Mode.MULTIPLY)); + if (LocaleController.isRTL) { + subtitleArrowView.setScaleX(-1f); + } + + subtitleToView = new TextView(context); + subtitleToView.setLines(1); + subtitleToView.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + subtitleToView.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp(14)); + subtitleToView.setText(languageName(toLanguage)); + + if (LocaleController.isRTL) { + subtitleView.setPadding(InlineLoadingTextView.paddingHorizontal, 0, 0, 0); + subtitleView.addView(subtitleToView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + subtitleView.addView(subtitleArrowView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 3, 1, 3, 0)); + subtitleView.addView(subtitleFromView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 0, 0)); + } else { + subtitleView.setPadding(0, 0, InlineLoadingTextView.paddingHorizontal, 0); + subtitleView.addView(subtitleFromView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 0, 0, 0, 0)); + subtitleView.addView(subtitleArrowView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 3, 1, 3, 0)); + subtitleView.addView(subtitleToView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); + } + if (fromLanguageName != null) { + subtitleFromView.set(fromLanguageName); + } + + header.addView(subtitleView, LayoutHelper.createFrame( + LayoutHelper.MATCH_PARENT, + LayoutHelper.WRAP_CONTENT, + Gravity.TOP | (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT), + 22 - LoadingTextView2.paddingHorizontal / AndroidUtilities.density, + 47 - LoadingTextView2.paddingVertical / AndroidUtilities.density, + 22 - LoadingTextView2.paddingHorizontal / AndroidUtilities.density, + 0 + )); + + backButton = new ImageView(context); + backButton.setImageResource(R.drawable.ic_ab_back); + backButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_dialogTextBlack), PorterDuff.Mode.MULTIPLY)); + backButton.setScaleType(ImageView.ScaleType.FIT_CENTER); + backButton.setPadding(AndroidUtilities.dp(16), 0, AndroidUtilities.dp(16), 0); + backButton.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector))); + backButton.setClickable(false); + backButton.setAlpha(0f); + backButton.setOnClickListener(e -> { + if (backButton.getAlpha() > .5f) { + dismiss(); + } + }); + header.addView(backButton, LayoutHelper.createFrame(56, 56, Gravity.LEFT | Gravity.CENTER_HORIZONTAL)); + + headerShadowView = new FrameLayout(context); + headerShadowView.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + headerShadowView.setAlpha(0); + header.addView(headerShadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + + paddingView = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int padding = (int) Math.max(AndroidUtilities.displaySize.y * .5f, listView.getMeasuredHeight() - listView.getPaddingTop() - listView.getPaddingBottom() - textsView.height()); + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(padding, MeasureSpec.EXACTLY)); + } + }; + +// +// header.setClipChildren(false); +// container.addView(header, headerLayout = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 70, Gravity.FILL_HORIZONTAL | Gravity.TOP)); + +// textsContainerView = new FrameLayout(context); +// textsContainerView.addView(textsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + +// scrollView.addView(textsContainerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 1f)); + +// container.addView(scrollView, scrollViewLayout = LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.FILL, 0, 70, 0, 81)); + + fetchNext(); + + +// container.addView(buttonShadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL, 0, 0, 0, 80)); + + buttonTextView = new TextView(context); + buttonTextView.setLines(1); + buttonTextView.setSingleLine(true); + buttonTextView.setGravity(Gravity.CENTER_HORIZONTAL); + buttonTextView.setEllipsize(TextUtils.TruncateAt.END); + buttonTextView.setGravity(Gravity.CENTER); + buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); + buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + buttonTextView.setText(LocaleController.getString("CloseTranslation", R.string.CloseTranslation)); + + buttonView = new FrameLayout(context); + buttonView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonView.addView(buttonTextView); + buttonView.setOnClickListener(e -> dismiss()); + + buttonContainerView = new FrameLayout(context); + buttonContainerView.addView(buttonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 16, 16, 16, 16)); + + buttonShadowView = new FrameLayout(context); + buttonShadowView.setBackgroundColor(Theme.getColor(Theme.key_dialogShadowLine)); + buttonShadowView.setAlpha(0); + buttonContainerView.addView(buttonShadowView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1, Gravity.TOP | Gravity.FILL_HORIZONTAL)); + + containerView.addView(buttonContainerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80, Gravity.BOTTOM | Gravity.FILL_HORIZONTAL)); + + bulletinContainer = new FrameLayout(context); + containerView.addView(bulletinContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.FILL, 0, 0, 0, 81)); + } + + private float getCurrentItemTop() { + View child = listView.getChildAt(0); + if (child == null) { + return 0; + } + RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findContainingViewHolder(child); + if (holder != null && holder.getAdapterPosition() == 0) { + return Math.max(0, child.getY() - header.getMeasuredHeight()); + } + return 0; + } + + @Override + protected boolean canDismissWithSwipe() { + return !listView.canScrollVertically(-1); + } + + // private boolean scrollAtBottom() { +// View view = (View) scrollView.getChildAt(scrollView.getChildCount() - 1); +// int bottom = view.getBottom(); +// LoadingTextView2 lastUnloadedBlock = textsView.getFirstUnloadedBlock(); +// if (lastUnloadedBlock != null) { +// bottom = lastUnloadedBlock.getTop(); +// } +// int diff = (bottom - (scrollView.getHeight() + scrollView.getScrollY())); +// return diff <= textsContainerView.getPaddingBottom(); +// } + + private boolean hasSelection() { + return allTextsView.hasSelection(); + } + + private Rect containerRect = new Rect(); + private Rect textRect = new Rect(); + private Rect translateMoreRect = new Rect(); + private Rect buttonRect = new Rect(); + private Rect backRect = new Rect(); + private Rect scrollRect = new Rect(); + private float fromY = 0; + private boolean pressedOutside = false; + private boolean maybeScrolling = false; + private boolean scrolling = false; + private boolean fromScrollRect = false; + private boolean fromTranslateMoreView = false; + private float fromScrollViewY = 0; + private Spannable allTexts = null; + private LinkSpanDrawable pressedLink; + private LinkSpanDrawable.LinkCollector links; + +// @Override +// public boolean dispatchTouchEvent(@NonNull MotionEvent event) { +// try { +// float x = event.getX(); +// float y = event.getY(); +// +// container.getGlobalVisibleRect(containerRect); +// if (!containerRect.contains((int) x, (int) y)) { +// if (event.getAction() == MotionEvent.ACTION_DOWN) { +// pressedOutside = true; +// return true; +// } else if (event.getAction() == MotionEvent.ACTION_UP) { +// if (pressedOutside) { +// pressedOutside = false; +// dismiss(); +// return true; +// } +// } +// } +// +// try { +// allTextsView.getGlobalVisibleRect(textRect); +// if (textRect.contains((int) x, (int) y) && !maybeScrolling) { +// Layout allTextsLayout = allTextsView.getLayout(); +// int tx = (int) (x - allTextsView.getLeft() - container.getLeft()), +// ty = (int) (y - allTextsView.getTop() - container.getTop() - scrollView.getTop() + scrollView.getScrollY()); +// final int line = allTextsLayout.getLineForVertical(ty); +// final int off = allTextsLayout.getOffsetForHorizontal(line, tx); +// +// final float left = allTextsLayout.getLineLeft(line); +// if (allTexts instanceof Spannable && left <= tx && left + allTextsLayout.getLineWidth(line) >= tx) { +// ClickableSpan[] linkSpans = allTexts.getSpans(off, off, ClickableSpan.class); +// if (linkSpans != null && linkSpans.length >= 1) { +// if (event.getAction() == MotionEvent.ACTION_UP && pressedLink.getSpan() == linkSpans[0]) { +// ((ClickableSpan) pressedLink.getSpan()).onClick(allTextsView); +// if (links != null) { +// links.removeLink(pressedLink); +// } +// pressedLink = null; +// allTextsView.setTextIsSelectable(!noforwards); +// } else if (event.getAction() == MotionEvent.ACTION_DOWN) { +// pressedLink = new LinkSpanDrawable(linkSpans[0], fragment.getResourceProvider(), tx, ty, false); +// if (links != null) { +// links.addLink(pressedLink); +// } +// LinkPath path = pressedLink.obtainNewPath(); +// int start = allTexts.getSpanStart(pressedLink.getSpan()); +// int end = allTexts.getSpanEnd(pressedLink.getSpan()); +// path.setCurrentLayout(allTextsLayout, start, 0); +// allTextsLayout.getSelectionPath(start, end, path); +// } +// allTextsView.invalidate(); +// return true; +// } +// } +// } +// if (pressedLink != null) { +// if (links != null) { +// links.clear(); +// } +// pressedLink = null; +// } +// } catch (Exception e2) { +// e2.printStackTrace(); +// } +// +// scrollView.getGlobalVisibleRect(scrollRect); +// backButton.getGlobalVisibleRect(backRect); +// buttonView.getGlobalVisibleRect(buttonRect); +// if (pressedLink == null && /*!(scrollRect.contains((int) x, (int) y) && !canExpand() && containerOpenAnimationT < .5f && !scrolling) &&*/ !hasSelection()) { +// if ( +// !backRect.contains((int) x, (int) y) && +// !buttonRect.contains((int) x, (int) y) && +// event.getAction() == MotionEvent.ACTION_DOWN +// ) { +// fromScrollRect = scrollRect.contains((int) x, (int) y) && (containerOpenAnimationT > 0 || !canExpand()); +// maybeScrolling = true; +// scrolling = scrollRect.contains((int) x, (int) y) && textsView.getBlocksCount() > 0 && !((LoadingTextView2) textsView.getBlockAt(0)).loaded; +// fromY = y; +// fromScrollY = getScrollY(); +// fromScrollViewY = scrollView.getScrollY(); +// return super.dispatchTouchEvent(event) || true; +// } else if (maybeScrolling && (event.getAction() == MotionEvent.ACTION_MOVE || event.getAction() == MotionEvent.ACTION_UP)) { +// float dy = fromY - y; +// if (fromScrollRect) { +// dy = -Math.max(0, -(fromScrollViewY + dp(48)) - dy); +// if (dy < 0) { +// scrolling = true; +// allTextsView.setTextIsSelectable(false); +// } +// } else if (Math.abs(dy) > dp(4) && !fromScrollRect) { +// scrolling = true; +// allTextsView.setTextIsSelectable(false); +// scrollView.stopNestedScroll(); +// allowScroll = false; +// } +// float fullHeight = AndroidUtilities.displayMetrics.heightPixels, +// minHeight = Math.min(minHeight(), fullHeight * heightMaxPercent); +// float scrollYPx = minHeight * (1f - -Math.min(Math.max(fromScrollY, -1), 0)) + (fullHeight - minHeight) * Math.min(1, Math.max(fromScrollY, 0)) + dy; +// float scrollY = scrollYPx > minHeight ? (scrollYPx - minHeight) / (fullHeight - minHeight) : -(1f - scrollYPx / minHeight); +// if (!canExpand()) { +// scrollY = Math.min(scrollY, 0); +// } +// updateCanExpand(); +// +// if (scrolling) { +// setScrollY(scrollY); +// if (event.getAction() == MotionEvent.ACTION_UP) { +// scrolling = false; +// allTextsView.setTextIsSelectable(!noforwards); +// maybeScrolling = false; +// allowScroll = true; +// scrollYTo( +// Math.abs(dy) > dp(16) ? +// Math.round(fromScrollY) + (scrollY > fromScrollY ? 1f : -1f) * (float) Math.ceil(Math.abs(fromScrollY - scrollY)) : +// Math.round(fromScrollY), +// () -> { +// contentView.post(this::checkForNextLoading); +// } +// ); +// } +// return true; +// } +// } +// } +// if (hasSelection() && maybeScrolling) { +// scrolling = false; +// allTextsView.setTextIsSelectable(!noforwards); +// maybeScrolling = false; +// allowScroll = true; +// scrollYTo(Math.round(fromScrollY)); +// } +// return super.dispatchTouchEvent(event); +// } catch (Exception e) { +// e.printStackTrace(); +// return super.dispatchTouchEvent(event); +// } +// return super.dispatchTouchEvent(event); +// } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + containerView.setPadding(backgroundPaddingLeft, AndroidUtilities.statusBarHeight, backgroundPaddingLeft, 0); + } +// +// contentView.setPadding(0, AndroidUtilities.statusBarHeight, 0, 0); +// contentView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); +// setContentView(contentView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); +// +// Window window = getWindow(); +// window.setWindowAnimations(R.style.DialogNoAnimation); +// WindowManager.LayoutParams params = window.getAttributes(); +// params.width = ViewGroup.LayoutParams.MATCH_PARENT; +// params.gravity = Gravity.TOP | Gravity.LEFT; +// params.dimAmount = 0; +// params.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND; +// if (Build.VERSION.SDK_INT >= 21) { +// params.flags |= +// WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | +// WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | +// WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | +// WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; +// } +// params.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; +// params.height = ViewGroup.LayoutParams.MATCH_PARENT; +// if (Build.VERSION.SDK_INT >= 28) { +// params.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES; +// } +// window.setAttributes(params); +// } + + protected ColorDrawable backDrawable = new ColorDrawable(0xff000000) { + @Override + public void setAlpha(int alpha) { + super.setAlpha(alpha); +// contentView.invalidate(); + } + }; + + public String languageName(String locale) { + // sorry, no more vodka + if (locale == null || locale.equals("und") || locale.equals("auto")) { + return null; + } + LocaleController.LocaleInfo thisLanguageInfo = LocaleController.getInstance().getBuiltinLanguageByPlural(locale); + if (thisLanguageInfo == null) { + return null; + } + LocaleController.LocaleInfo currentLanguageInfo = LocaleController.getInstance().getCurrentLocaleInfo(); + boolean isCurrentLanguageEnglish = currentLanguageInfo != null && "en".equals(currentLanguageInfo.pluralLangCode); + if (isCurrentLanguageEnglish) { + // trying to show this language in a language of the interface, but there are only names in english and its own + return thisLanguageInfo.nameEnglish; + } else { + return thisLanguageInfo.name; + } + } + + public void updateSourceLanguage() { + String fromLanguageName = languageName(fromLanguage); + if (fromLanguageName != null) { + subtitleView.setAlpha(1); + if (!subtitleFromView.loaded) { + subtitleFromView.loaded(fromLanguageName); + } + } else if (loaded) { + subtitleView.animate().alpha(0).setDuration(150).start(); + titleView.animate().scaleX(1.2f).scaleY(1.2f).translationY(dp(5)).setDuration(150).start(); + } + } + + private ArrayList cutInBlocks(CharSequence full, int maxBlockSize) { + ArrayList blocks = new ArrayList<>(); + if (full == null) { + return blocks; + } + while (full.length() > maxBlockSize) { + String maxBlockStr = full.subSequence(0, maxBlockSize).toString(); + int n = maxBlockStr.lastIndexOf("\n\n"); + if (n == -1) n = maxBlockStr.lastIndexOf("\n"); + if (n == -1) n = maxBlockStr.lastIndexOf(". "); + if (n == -1) n = maxBlockStr.length(); + blocks.add(full.subSequence(0, n + 1)); + full = full.subSequence(n + 1, full.length()); + } + if (full.length() > 0) { + blocks.add(full); + } + return blocks; + } + + private boolean loading = false; + private boolean loaded = false; + private boolean fetchNext() { + if (loading) { + return false; + } + loading = true; + + if (blockIndex >= textBlocks.size()) { + return false; + } + + fetchTranslation( + textBlocks.get(blockIndex), + Math.min((blockIndex + 1) * 1000, 3500), + (String translatedText, String sourceLanguage) -> { + loaded = true; + Spannable spannable = new SpannableStringBuilder(translatedText); + try { + MessageObject.addUrlsByPattern(false, spannable, false, 0, 0, true); + URLSpan[] urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class); + for (int i = 0; i < urlSpans.length; ++i) { + URLSpan urlSpan = urlSpans[i]; + int start = spannable.getSpanStart(urlSpan), + end = spannable.getSpanEnd(urlSpan); + if (start == -1 || end == -1) { + continue; + } + spannable.removeSpan(urlSpan); + spannable.setSpan( + new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + if (onLinkPress != null) { + onLinkPress.run(urlSpan); + dismiss(); + } else { + AlertsCreator.showOpenUrlAlert(fragment, urlSpan.getURL(), false, false); + } + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + int alpha = Math.min(ds.getAlpha(), ds.getColor() >> 24 & 0xff); + if (!(urlSpan instanceof URLSpanNoUnderline)) { + ds.setUnderlineText(true); + } + ds.setColor(Theme.getColor(Theme.key_dialogTextLink)); + ds.setAlpha(alpha); + } + }, + start, end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ); + } + + AndroidUtilities.addLinks(spannable, Linkify.WEB_URLS); + urlSpans = spannable.getSpans(0, spannable.length(), URLSpan.class); + for (int i = 0; i < urlSpans.length; ++i) { + URLSpan urlSpan = urlSpans[i]; + int start = spannable.getSpanStart(urlSpan), + end = spannable.getSpanEnd(urlSpan); + if (start == -1 || end == -1) { + continue; + } + spannable.removeSpan(urlSpan); + spannable.setSpan( + new ClickableSpan() { + @Override + public void onClick(@NonNull View view) { + AlertsCreator.showOpenUrlAlert(fragment, urlSpan.getURL(), false, false); + } + + @Override + public void updateDrawState(@NonNull TextPaint ds) { + int alpha = Math.min(ds.getAlpha(), ds.getColor() >> 24 & 0xff); + if (!(urlSpan instanceof URLSpanNoUnderline)) + ds.setUnderlineText(true); + ds.setColor(Theme.getColor(Theme.key_dialogTextLink)); + ds.setAlpha(alpha); + } + }, + start, end, + Spanned.SPAN_EXCLUSIVE_EXCLUSIVE + ); + } + + spannable = (Spannable) Emoji.replaceEmoji(spannable, allTextsView.getPaint().getFontMetricsInt(), dp(14), false); + } catch (Exception e) { + e.printStackTrace(); + } + + SpannableStringBuilder allTextsBuilder = new SpannableStringBuilder(allTexts == null ? "" : allTexts); + if (blockIndex != 0) { + allTextsBuilder.append("\n"); + } + allTextsBuilder.append(spannable); + allTexts = allTextsBuilder; + textsView.setWholeText(allTexts); + + LoadingTextView2 block = textsView.getBlockAt(blockIndex); + if (block != null) { + block.loaded(spannable, () -> AndroidUtilities.runOnUIThread(this::checkForNextLoading)); + } + + if (sourceLanguage != null) { + fromLanguage = sourceLanguage; + updateSourceLanguage(); + } + + blockIndex++; + loading = false; + }, + (boolean rateLimit) -> { + Toast.makeText( + getContext(), + rateLimit ? + LocaleController.getString("TranslationFailedAlert1", R.string.TranslationFailedAlert1) : + LocaleController.getString("TranslationFailedAlert2", R.string.TranslationFailedAlert2), + Toast.LENGTH_SHORT + ).show(); + + if (blockIndex == 0) { + dismiss(); + } + } + ); + return true; + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + if (onDismiss != null) { + onDismiss.run(); + } + } + +// @Override +// public boolean dispatchTouchEvent(@NonNull MotionEvent event) { +// if (event.getAction() == MotionEvent.ACTION_DOWN && event.getY() < contentView.getPaddingTop() + header.getTranslationY()) { +// dismiss(); +// return true; +// } +// return super.dispatchTouchEvent(event); +// } + + private void checkForNextLoading() { + if (!listView.canScrollVertically(-1)) { + fetchNext(); + } + } + + public interface OnTranslationSuccess { + public void run(String translated, String sourceLanguage); + } + public interface OnTranslationFail { + public void run(boolean rateLimit); + } + private void fetchTranslation(CharSequence text, long minDuration, OnTranslationSuccess onSuccess, OnTranslationFail onFail) { + if (!translateQueue.isAlive()) { + translateQueue.start(); + } + translateQueue.postRunnable(() -> { + String uri = ""; + HttpURLConnection connection = null; + long start = SystemClock.elapsedRealtime(); + try { + uri = "https://translate.googleapis.com/translate_a/single?client=gtx&sl="; + uri += Uri.encode(fromLanguage); + uri += "&tl="; + uri += Uri.encode(toLanguage); + uri += "&dt=t&ie=UTF-8&oe=UTF-8&otf=1&ssel=0&tsel=0&kc=7&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&q="; + uri += Uri.encode(text.toString()); + connection = (HttpURLConnection) new URI(uri).toURL().openConnection(); + connection.setRequestMethod("GET"); + connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36"); + connection.setRequestProperty("Content-Type", "application/json"); + + StringBuilder textBuilder = new StringBuilder(); + try (Reader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")))) { + int c; + while ((c = reader.read()) != -1) { + textBuilder.append((char) c); + } + } + String jsonString = textBuilder.toString(); + + JSONTokener tokener = new JSONTokener(jsonString); + JSONArray array = new JSONArray(tokener); + JSONArray array1 = array.getJSONArray(0); + String sourceLanguage = null; + try { + sourceLanguage = array.getString(2); + } catch (Exception e2) {} + if (sourceLanguage != null && sourceLanguage.contains("-")) { + sourceLanguage = sourceLanguage.substring(0, sourceLanguage.indexOf("-")); + } + StringBuilder result = new StringBuilder(); + for (int i = 0; i < array1.length(); ++i) { + String blockText = array1.getJSONArray(i).getString(0); + if (blockText != null && !blockText.equals("null")) { + result.append(blockText); + } + } + if (text.length() > 0 && text.charAt(0) == '\n') { + result.insert(0, "\n"); + } + final String finalResult = result.toString(); + final String finalSourceLanguage = sourceLanguage; + + long elapsed = SystemClock.elapsedRealtime() - start; + AndroidUtilities.runOnUIThread(() -> { + if (onSuccess != null) { + onSuccess.run(finalResult, finalSourceLanguage); + } + }, Math.max(0, minDuration - elapsed)); + } catch (Exception e) { + try { + Log.e("translate", "failed to translate a text " + (connection != null ? connection.getResponseCode() : null) + " " + (connection != null ? connection.getResponseMessage() : null)); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + e.printStackTrace(); + + if (onFail != null) { + try { + final boolean rateLimit = connection != null && connection.getResponseCode() == 429; + AndroidUtilities.runOnUIThread(() -> { + onFail.run(rateLimit); + }); + } catch (Exception e2) { + AndroidUtilities.runOnUIThread(() -> { + onFail.run(false); + }); + } + } + } + }); + } + private static void translateText(int currentAccount, TLRPC.InputPeer peer, int msg_id, String from_lang, String to_lang) { + TLRPC.TL_messages_translateText req = new TLRPC.TL_messages_translateText(); + + req.peer = peer; + req.msg_id = msg_id; + req.flags |= 1; + + if (from_lang != null) { + req.from_lang = from_lang; + req.flags |= 4; + } + + req.to_lang = to_lang; + + try { + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (error, res) -> {}); + } catch (Exception e) { + FileLog.e(e); + } + } + + public static TranslateAlert2 showAlert(Context context, BaseFragment fragment, int currentAccount, TLRPC.InputPeer peer, int msgId, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress, Runnable onDismiss) { + if (peer != null) { + translateText(currentAccount, peer, msgId, fromLanguage != null && fromLanguage.equals("und") ? null : fromLanguage, toLanguage); + } + TranslateAlert2 alert = new TranslateAlert2(fragment, context, fromLanguage, toLanguage, text, noforwards, onLinkPress, onDismiss); + if (fragment != null) { + if (fragment.getParentActivity() != null) { + fragment.showDialog(alert); + } + } else { + alert.show(); + } + return alert; + } + public static TranslateAlert2 showAlert(Context context, BaseFragment fragment, String fromLanguage, String toLanguage, CharSequence text, boolean noforwards, OnLinkPress onLinkPress, Runnable onDismiss) { + TranslateAlert2 alert = new TranslateAlert2(fragment, context, fromLanguage, toLanguage, text, noforwards, onLinkPress, onDismiss); + if (fragment != null) { + if (fragment.getParentActivity() != null) { + fragment.showDialog(alert); + } + } else { + alert.show(); + } + return alert; + } + + private static final int MOST_SPEC = View.MeasureSpec.makeMeasureSpec(999999, View.MeasureSpec.AT_MOST); + public static class TextBlocksLayout extends ViewGroup { + + private TextView wholeTextView; + private final int fontSize; + private final int textColor; + + public TextBlocksLayout(Context context, int fontSize, int textColor, TextView wholeTextView) { + super(context); + + this.fontSize = fontSize; + this.textColor = textColor; + + if (wholeTextView != null) { + wholeTextView.setPadding(LoadingTextView2.paddingHorizontal, LoadingTextView2.paddingVertical, LoadingTextView2.paddingHorizontal, LoadingTextView2.paddingVertical); + addView(this.wholeTextView = wholeTextView); + } + } + + public void setWholeText(CharSequence wholeText) { + // having focus on that text view can cause jumping scroll to the top after loading a new block + // TODO(dkaraush): preserve selection after setting a new text + wholeTextView.clearFocus(); + wholeTextView.setText(wholeText); + } + + public LoadingTextView2 addBlock(CharSequence fromText) { + LoadingTextView2 textView = new LoadingTextView2(getContext(), fromText, getBlocksCount() > 0, fontSize, textColor); + addView(textView); + if (wholeTextView != null) { + wholeTextView.bringToFront(); + } + return textView; + } + + public int getBlocksCount() { + return getChildCount() - (wholeTextView != null ? 1 : 0); + } + public LoadingTextView2 getBlockAt(int i) { + View child = getChildAt(i); + if (child instanceof LoadingTextView2) { + return (LoadingTextView2) child; + } + return null; + } + + public LoadingTextView2 getFirstUnloadedBlock() { + final int count = getBlocksCount(); + for (int i = 0; i < count; ++i) { + LoadingTextView2 block = getBlockAt(i); + if (block != null && !block.loaded) + return block; + } + return null; + } + + private static final int gap = -LoadingTextView2.paddingVertical * 4 + dp(.48f); + public int height() { + int height = 0; + final int count = getBlocksCount(); + for (int i = 0; i < count; ++i) { + height += getBlockAt(i).height(); + } + return getPaddingTop() + height + getPaddingBottom(); + } + + protected void onHeightUpdated(int height, int dy) {} + + public void updateHeight() { + boolean updated; + int newHeight = height(); + int dy = 0; + RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) getLayoutParams(); + if (lp == null) { + lp = new RecyclerView.LayoutParams(LayoutParams.MATCH_PARENT, newHeight); + updated = true; + } else { + updated = lp.height != newHeight; + dy = newHeight - lp.height; + lp.height = newHeight; + } + + if (updated) { + this.setLayoutParams(lp); + onHeightUpdated(newHeight, dy); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int count = getBlocksCount(); + final int innerWidthMeasureSpec = MeasureSpec.makeMeasureSpec( + MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(), + MeasureSpec.getMode(widthMeasureSpec) + ); + for (int i = 0; i < count; ++i) { + LoadingTextView2 block = getBlockAt(i); + block.measure(innerWidthMeasureSpec, MOST_SPEC); + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height(), MeasureSpec.EXACTLY)); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int y = 0; + final int count = getBlocksCount(); + for (int i = 0; i < count; ++i) { + LoadingTextView2 block = getBlockAt(i); + final int blockHeight = block.height(); + final int translationY = i > 0 ? gap : 0; + block.layout(getPaddingLeft(), getPaddingTop() + y + translationY, r - l - getPaddingRight(), getPaddingTop() + y + blockHeight + translationY); + y += blockHeight; + if (i > 0 && i < count - 1) { + y += gap; + } + } + + wholeTextView.measure( + MeasureSpec.makeMeasureSpec(r - l - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(b - t - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY) + ); + wholeTextView.layout( + getPaddingLeft(), + getPaddingTop(), + (r - l) - getPaddingRight(), + getPaddingTop() + wholeTextView.getMeasuredHeight() + ); + } + } + + public static class InlineLoadingTextView extends ViewGroup { + + public static final int paddingHorizontal = dp(4), + paddingVertical = 0; + + + public boolean showLoadingText = true; + + private final TextView fromTextView; + private final TextView toTextView; + + private final ValueAnimator loadingAnimator; + + private final long start = SystemClock.elapsedRealtime(); + public InlineLoadingTextView(Context context, CharSequence fromText, int fontSize, int textColor) { + super(context); + + setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); + setClipChildren(false); + setWillNotDraw(false); + + fromTextView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MOST_SPEC, MOST_SPEC); + } + }; + fromTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); + fromTextView.setTextColor(textColor); + fromTextView.setText(fromText); + fromTextView.setLines(1); + fromTextView.setMaxLines(1); + fromTextView.setSingleLine(true); + fromTextView.setEllipsize(null); + addView(fromTextView); + + toTextView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(MOST_SPEC, MOST_SPEC); + } + }; + toTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); + toTextView.setTextColor(textColor); + toTextView.setLines(1); + toTextView.setMaxLines(1); + toTextView.setSingleLine(true); + toTextView.setEllipsize(null); + addView(toTextView); + + int c1 = Theme.getColor(Theme.key_dialogBackground), + c2 = Theme.getColor(Theme.key_dialogBackgroundGray); + LinearGradient gradient = new LinearGradient(0, 0, gradientWidth, 0, new int[]{ c1, c2, c1 }, new float[] { 0, 0.67f, 1f }, Shader.TileMode.REPEAT); + loadingPaint.setShader(gradient); + + loadingAnimator = ValueAnimator.ofFloat(0f, 1f); + loadingAnimator.addUpdateListener(a -> invalidate()); + loadingAnimator.setDuration(Long.MAX_VALUE); + loadingAnimator.start(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + fromTextView.measure(0, 0); + toTextView.measure(0, 0); + super.onMeasure( + MeasureSpec.makeMeasureSpec( + (int) AndroidUtilities.lerp(fromTextView.getMeasuredWidth(), toTextView.getMeasuredWidth(), loadingT) + getPaddingLeft() + getPaddingRight(), + MeasureSpec.EXACTLY + ), + MeasureSpec.makeMeasureSpec( + Math.max(fromTextView.getMeasuredHeight(), toTextView.getMeasuredHeight()), + MeasureSpec.EXACTLY + ) + ); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + fromTextView.layout(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + fromTextView.getMeasuredWidth(), getPaddingTop() + fromTextView.getMeasuredHeight()); + toTextView.layout(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + toTextView.getMeasuredWidth(), getPaddingTop() + toTextView.getMeasuredHeight()); + updateWidth(); + } + + private void updateWidth() { + boolean updated; + + int newWidth = (int) AndroidUtilities.lerp(fromTextView.getMeasuredWidth(), toTextView.getMeasuredWidth(), loadingT) + getPaddingLeft() + getPaddingRight(); + int newHeight = Math.max(fromTextView.getMeasuredHeight(), toTextView.getMeasuredHeight()); + LayoutParams lp = getLayoutParams(); + if (lp == null) { + lp = new LinearLayout.LayoutParams(newWidth, newHeight); + updated = true; + } else { + updated = lp.width != newWidth || lp.height != newHeight; + lp.width = newWidth; + lp.height = newHeight; + } + + if (updated) + setLayoutParams(lp); + } + + protected void onLoadAnimation(float t) {} + + public boolean loaded = false; + public float loadingT = 0f; + private ValueAnimator loadedAnimator = null; + public void loaded(CharSequence loadedText) { + loaded(loadedText, 350,null); + } + public void loaded(CharSequence loadedText, Runnable onLoadEnd) { + loaded(loadedText, 350, onLoadEnd); + } + public void loaded(CharSequence loadedText, long duration, Runnable onLoadEnd) { + loaded = true; + toTextView.setText(loadedText); + + if (loadingAnimator.isRunning()) { + loadingAnimator.cancel(); + } + if (loadedAnimator == null) { + loadedAnimator = ValueAnimator.ofFloat(0f, 1f); + loadedAnimator.addUpdateListener(a -> { + loadingT = (float) a.getAnimatedValue(); + updateWidth(); + invalidate(); + onLoadAnimation(loadingT); + }); + loadedAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (onLoadEnd != null) + onLoadEnd.run(); + } + }); + loadedAnimator.setDuration(duration); + loadedAnimator.setInterpolator(CubicBezierInterpolator.EASE_BOTH); + loadedAnimator.start(); + } + } + public void set(CharSequence loadedText) { + loaded = true; + toTextView.setText(loadedText); + + if (loadingAnimator.isRunning()) { + loadingAnimator.cancel(); + } + if (loadedAnimator != null) { + loadedAnimator.cancel(); + loadedAnimator = null; + } + loadingT = 1f; + requestLayout(); + updateWidth(); + invalidate(); + onLoadAnimation(1f); + } + + private final RectF rect = new RectF(); + private final Path inPath = new Path(), + tempPath = new Path(), + loadingPath = new Path(), + shadePath = new Path(); + private final Paint loadingPaint = new Paint(); + private final float gradientWidth = dp(350f); + @Override + protected void onDraw(Canvas canvas) { + float w = getWidth(), h = getHeight(); + + float cx = LocaleController.isRTL ? Math.max(w / 2f, w - 8f) : Math.min(w / 2f, 8f), + cy = Math.min(h / 2f, 8f), + R = (float) Math.sqrt(Math.max( + Math.max(cx*cx + cy*cy, (w-cx)*(w-cx) + cy*cy), + Math.max(cx*cx + (h-cy)*(h-cy), (w-cx)*(w-cx) + (h-cy)*(h-cy)) + )), + r = loadingT * R; + inPath.reset(); + inPath.addCircle(cx, cy, r, Path.Direction.CW); + + canvas.save(); + canvas.clipPath(inPath, Region.Op.DIFFERENCE); + + loadingPaint.setAlpha((int) ((1f - loadingT) * 255)); + float dx = gradientWidth - (((SystemClock.elapsedRealtime() - start) / 1000f * gradientWidth) % gradientWidth); + shadePath.reset(); + shadePath.addRect(0, 0, w, h, Path.Direction.CW); + + loadingPath.reset(); + rect.set(0, 0, w, h); + loadingPath.addRoundRect(rect, dp(4), dp(4), Path.Direction.CW); + canvas.clipPath(loadingPath); + canvas.translate(-dx, 0); + shadePath.offset(dx, 0f, tempPath); + canvas.drawPath(tempPath, loadingPaint); + canvas.translate(dx, 0); + canvas.restore(); + + if (showLoadingText && fromTextView != null) { + canvas.save(); + rect.set(0, 0, w, h); + canvas.clipPath(inPath, Region.Op.DIFFERENCE); + canvas.translate(paddingHorizontal, paddingVertical); + canvas.saveLayerAlpha(rect, (int) (255 * .08f), Canvas.ALL_SAVE_FLAG); + fromTextView.draw(canvas); + canvas.restore(); + canvas.restore(); + } + + if (toTextView != null) { + canvas.save(); + canvas.clipPath(inPath); + canvas.translate(paddingHorizontal, paddingVertical); + canvas.saveLayerAlpha(rect, (int) (255 * loadingT), Canvas.ALL_SAVE_FLAG); + toTextView.draw(canvas); + if (loadingT < 1f) { + canvas.restore(); + } + canvas.restore(); + } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + return false; + } + } + + public static class LoadingTextView2 extends ViewGroup { + + public static final int paddingHorizontal = dp(4), + paddingVertical = dp(1.5f); + + public boolean showLoadingText = true; + + private final TextView fromTextView; + private final TextView toTextView; + + private final boolean scaleFromZero; + private final ValueAnimator loadingAnimator; + + private final long start = SystemClock.elapsedRealtime(); + private float scaleT = 1f; + public LoadingTextView2(Context context, CharSequence fromText, boolean scaleFromZero, int fontSize, int textColor) { + super(context); + + setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical); + setClipChildren(false); + setWillNotDraw(false); + + fromTextView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MOST_SPEC); + } + }; + fromTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); + fromTextView.setTextColor(textColor); + fromTextView.setText(fromText); + fromTextView.setLines(0); + fromTextView.setMaxLines(0); + fromTextView.setSingleLine(false); + fromTextView.setEllipsize(null); + addView(fromTextView); + + toTextView = new TextView(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MOST_SPEC); + } + }; + toTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, fontSize); + toTextView.setTextColor(textColor); + toTextView.setLines(0); + toTextView.setMaxLines(0); + toTextView.setSingleLine(false); + toTextView.setEllipsize(null); + addView(toTextView); + + int c1 = Theme.getColor(Theme.key_dialogBackground), + c2 = Theme.getColor(Theme.key_dialogBackgroundGray); + LinearGradient gradient = new LinearGradient(0, 0, gradientWidth, 0, new int[]{ c1, c2, c1 }, new float[] { 0, 0.67f, 1f }, Shader.TileMode.REPEAT); + loadingPaint.setShader(gradient); + + this.scaleFromZero = scaleFromZero; + loadingAnimator = ValueAnimator.ofFloat(0f, 1f); + if (scaleFromZero) + scaleT = 0; + loadingAnimator.addUpdateListener(a -> { + invalidate(); + if (scaleFromZero) { + boolean scaleTWasNoFull = scaleT < 1f; + scaleT = Math.min(1, (SystemClock.elapsedRealtime() - start) / 400f); + if (scaleTWasNoFull) { + updateHeight(); + } + } + }); + loadingAnimator.setDuration(Long.MAX_VALUE); + loadingAnimator.start(); + } + + public int innerHeight() { + return (int) (AndroidUtilities.lerp(fromTextView.getMeasuredHeight(), toTextView.getMeasuredHeight(), loadingT) * scaleT); + } + public int height() { + return getPaddingTop() + innerHeight() + getPaddingBottom(); + } + + private void updateHeight() { + ViewParent parent = getParent(); + if (parent instanceof TextBlocksLayout) { + ((TextBlocksLayout) parent).updateHeight(); + } + } + + public boolean loaded = false; + private float loadingT = 0f; + private ValueAnimator loadedAnimator = null; + public void loaded(CharSequence loadedText, Runnable onLoadEnd) { + loaded = true; + toTextView.setText(loadedText); + layout(); + + if (loadingAnimator.isRunning()) { + loadingAnimator.cancel(); + } + if (loadedAnimator == null) { + loadedAnimator = ValueAnimator.ofFloat(0f, 1f); + loadedAnimator.addUpdateListener(a -> { + loadingT = (float) a.getAnimatedValue(); + updateHeight(); + invalidate(); + }); + loadedAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (onLoadEnd != null) + onLoadEnd.run(); + } + }); + loadedAnimator.setDuration(350); + loadedAnimator.setInterpolator(CubicBezierInterpolator.EASE_BOTH); + loadedAnimator.start(); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int width = MeasureSpec.getSize(widthMeasureSpec), + innerWidth = width - getPaddingLeft() - getPaddingRight(); + if (fromTextView.getMeasuredWidth() <= 0 || lastWidth != innerWidth) { + measureChild(fromTextView, innerWidth); + updateLoadingPath(); + } + if (toTextView.getMeasuredWidth() <= 0 || lastWidth != innerWidth) { + measureChild(toTextView, innerWidth); + } + lastWidth = innerWidth; + super.onMeasure( + MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(height(), MeasureSpec.EXACTLY) + ); + } + + int lastWidth = 0; + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + layout(r - l - getPaddingLeft() - getPaddingRight(), true); + } + private void layout(int width, boolean force) { + if (lastWidth != width || force) { + layout(lastWidth = width); + } + } + private void layout(int width) { + measureChild(fromTextView, width); + layoutChild(fromTextView, width); + updateLoadingPath(); + measureChild(toTextView, width); + layoutChild(toTextView, width); + updateHeight(); + } + private void layout() { + layout(lastWidth); + } + private void measureChild(View view, int width) { + view.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MOST_SPEC); + } + private void layoutChild(View view, int width) { + view.layout(getPaddingLeft(), getPaddingTop(), getPaddingLeft() + width, getPaddingTop() + view.getMeasuredHeight()); + } + + private RectF fetchedPathRect = new RectF(); + private void updateLoadingPath() { + if (fromTextView != null && fromTextView.getMeasuredWidth() > 0) { + loadingPath.reset(); + Layout loadingLayout = fromTextView.getLayout(); + if (loadingLayout != null) { + CharSequence text = loadingLayout.getText(); + final int lineCount = loadingLayout.getLineCount(); + for (int i = 0; i < lineCount; ++i) { + float s = loadingLayout.getLineLeft(i), + e = loadingLayout.getLineRight(i), + l = Math.min(s, e), + r = Math.max(s, e); + int start = loadingLayout.getLineStart(i), + end = loadingLayout.getLineEnd(i); + boolean hasNonEmptyChar = false; + for (int j = start; j < end; ++j) { + char c = text.charAt(j); + if (c != '\n' && c != '\t' && c != ' ') { + hasNonEmptyChar = true; + break; + } + } + if (!hasNonEmptyChar) + continue; + fetchedPathRect.set( + l - paddingHorizontal, + loadingLayout.getLineTop(i) - paddingVertical, + r + paddingHorizontal, + loadingLayout.getLineBottom(i) + paddingVertical + ); + loadingPath.addRoundRect(fetchedPathRect, dp(4), dp(4), Path.Direction.CW); + } + } + } + } + + private final RectF rect = new RectF(); + private final Path inPath = new Path(), + tempPath = new Path(), + loadingPath = new Path(), + shadePath = new Path(); + private final Paint loadingPaint = new Paint(); + private final float gradientWidth = dp(350f); + @Override + protected void onDraw(Canvas canvas) { + float w = getWidth(), h = getHeight(); + + float cx = LocaleController.isRTL ? Math.max(w / 2f, w - 8f) : Math.min(w / 2f, 8f), + cy = Math.min(h / 2f, 8f), + R = (float) Math.sqrt(Math.max( + Math.max(cx*cx + cy*cy, (w-cx)*(w-cx) + cy*cy), + Math.max(cx*cx + (h-cy)*(h-cy), (w-cx)*(w-cx) + (h-cy)*(h-cy)) + )), + r = loadingT * R; + inPath.reset(); + inPath.addCircle(cx, cy, r, Path.Direction.CW); + + canvas.save(); + canvas.clipPath(inPath, Region.Op.DIFFERENCE); + + loadingPaint.setAlpha((int) ((1f - loadingT) * 255)); + float dx = gradientWidth - (((SystemClock.elapsedRealtime() - start) / 1000f * gradientWidth) % gradientWidth); + shadePath.reset(); + shadePath.addRect(0, 0, w, h, Path.Direction.CW); + + canvas.translate(paddingHorizontal, paddingVertical); + canvas.clipPath(loadingPath); + canvas.translate(-paddingHorizontal, -paddingVertical); + canvas.translate(-dx, 0); + shadePath.offset(dx, 0f, tempPath); + canvas.drawPath(tempPath, loadingPaint); + canvas.translate(dx, 0); + canvas.restore(); + + if (showLoadingText && fromTextView != null) { + canvas.save(); + rect.set(0, 0, w, h); + canvas.clipPath(inPath, Region.Op.DIFFERENCE); + canvas.translate(paddingHorizontal, paddingVertical); + canvas.saveLayerAlpha(rect, (int) (255 * .08f), Canvas.ALL_SAVE_FLAG); + fromTextView.draw(canvas); + canvas.restore(); + canvas.restore(); + } + + if (toTextView != null) { + canvas.save(); + canvas.clipPath(inPath); + canvas.translate(paddingHorizontal, paddingVertical); + canvas.saveLayerAlpha(rect, (int) (255 * loadingT), Canvas.ALL_SAVE_FLAG); + toTextView.draw(canvas); + if (loadingT < 1f) { + canvas.restore(); + } + canvas.restore(); + } + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + return false; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java index 0bd1c0d0a..bf8009118 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanNoUnderline.java @@ -22,6 +22,9 @@ public class URLSpanNoUnderline extends URLSpan { private TextStyleSpan.TextStyleRun style; private TLObject object; + // Used to label video timestamps + public String label; + public URLSpanNoUnderline(String url) { this(url, null); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java index 590a633b5..54227f1d7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/URLSpanReplacement.java @@ -14,10 +14,12 @@ import android.text.style.URLSpan; import android.view.View; import org.telegram.messenger.browser.Browser; +import org.telegram.ui.LaunchActivity; public class URLSpanReplacement extends URLSpan { private TextStyleSpan.TextStyleRun style; + private boolean navigateToPremiumBot; public URLSpanReplacement(String url) { this(url, null); @@ -28,12 +30,19 @@ public class URLSpanReplacement extends URLSpan { style = run; } + public void setNavigateToPremiumBot(boolean navigateToPremiumBot) { + this.navigateToPremiumBot = navigateToPremiumBot; + } + public TextStyleSpan.TextStyleRun getTextStyleRun() { return style; } @Override public void onClick(View widget) { + if (navigateToPremiumBot && widget.getContext() instanceof LaunchActivity) { + ((LaunchActivity) widget.getContext()).setNavigateToPremiumBot(true); + } Uri uri = Uri.parse(getURL()); Browser.openUrl(widget.getContext(), uri); } 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 d0aedbe1b..3a1c14f9e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UndoView.java @@ -36,6 +36,7 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import android.widget.Toast; import com.jakewharton.processphoenix.ProcessPhoenix; @@ -89,7 +90,7 @@ public class UndoView extends FrameLayout { private String timeLeftString; private int textWidth; - private int currentAction; + private int currentAction = -1; private ArrayList currentDialogIds; private Runnable currentActionRunnable; private Runnable currentCancelRunnable; @@ -443,7 +444,7 @@ public class UndoView extends FrameLayout { } public void showWithAction(ArrayList dialogIds, int action, Object infoObject, Object infoObject2, Runnable actionRunnable, Runnable cancelRunnable) { - if (!AndroidUtilities.shouldShowClipboardToast() && currentAction == ACTION_MESSAGE_COPIED || currentAction == ACTION_USERNAME_COPIED || currentAction == ACTION_HASHTAG_COPIED || currentAction == ACTION_TEXT_COPIED || currentAction == ACTION_LINK_COPIED || currentAction == ACTION_PHONE_COPIED || currentAction == ACTION_EMAIL_COPIED || currentAction == ACTION_VOIP_LINK_COPIED) { + if (!AndroidUtilities.shouldShowClipboardToast() && (currentAction == ACTION_MESSAGE_COPIED || currentAction == ACTION_USERNAME_COPIED || currentAction == ACTION_HASHTAG_COPIED || currentAction == ACTION_TEXT_COPIED || currentAction == ACTION_LINK_COPIED || currentAction == ACTION_PHONE_COPIED || currentAction == ACTION_EMAIL_COPIED || currentAction == ACTION_VOIP_LINK_COPIED)) { return; } if (currentActionRunnable != null) { @@ -611,6 +612,7 @@ public class UndoView extends FrameLayout { icon = R.raw.voip_invite; timeLeft = 3000; } else if (action == ACTION_PAYMENT_SUCCESS) { + Toast.makeText(getContext(), LocaleController.getString("nekoXPaymentRemovedToast", R.string.nekoXPaymentRemovedToast), Toast.LENGTH_LONG).show(); /* infoText = (CharSequence) infoObject; subInfoText = null; icon = R.raw.payment_success; @@ -868,6 +870,9 @@ public class UndoView extends FrameLayout { } subInfoText = null; icon = currentAction == ACTION_PIN_DIALOGS ? R.raw.ic_pin : R.raw.ic_unpin; + if (infoObject2 instanceof Integer) { + timeLeft = (int) infoObject2; + } } else { if (action == ACTION_ARCHIVE_HINT) { infoText = LocaleController.getString("ChatArchived", R.string.ChatArchived); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java index 246e2ad2c..fac382f76 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/UpdateAppAlertDialog.java @@ -75,7 +75,7 @@ public class UpdateAppAlertDialog extends BottomSheet { background = new View(context); if (hasBackground) { - background.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + background.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); } addView(background, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, withoutBackground ? 0 : 16, 16, 16)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java index 64a94f001..402c95907 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoForwardDrawable.java @@ -34,6 +34,7 @@ public class VideoForwardDrawable extends Drawable { private long time; private String timeStr; + private float playScaleFactor = 1f; public void setTime(long dt) { time = dt; @@ -67,6 +68,11 @@ public class VideoForwardDrawable extends Drawable { path1.close(); } + public void setPlayScaleFactor(float playScaleFactor) { + this.playScaleFactor = playScaleFactor; + invalidate(); + } + public boolean isAnimating() { return animating; } @@ -170,6 +176,7 @@ public class VideoForwardDrawable extends Drawable { } canvas.save(); + canvas.scale(playScaleFactor, playScaleFactor, x, y + getIntrinsicHeight() / 2f); if (leftSide) { canvas.rotate(180, x, y + getIntrinsicHeight() / 2); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java index 6f893a021..6016a832c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoPlayerSeekBar.java @@ -13,15 +13,30 @@ import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; +import android.os.Build; import android.os.SystemClock; +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.util.Log; +import android.util.Pair; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; import androidx.core.graphics.ColorUtils; -import com.google.android.exoplayer2.util.Log; - import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.Emoji; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.MessageObject; +import org.telegram.messenger.Utilities; + +import java.util.ArrayList; +import java.util.Collections; public class VideoPlayerSeekBar { @@ -31,13 +46,16 @@ public class VideoPlayerSeekBar { } } + private float progress; private static Paint paint; private static Paint strokePaint; private static int thumbWidth; private int thumbX = 0; + private float animatedThumbX = 0; private int draggingThumbX = 0; private int thumbDX = 0; private boolean pressed = false; + private boolean pressedDelayed = false; private int width; private int height; private SeekBarDelegate delegate; @@ -65,6 +83,8 @@ public class VideoPlayerSeekBar { private int fromThumbX = 0; private float animateThumbProgress = 1f; + private AnimatedFloat animateThumbLoopBackProgress; + private float loopBackWasThumbX; public VideoPlayerSeekBar(View parent) { if (paint == null) { @@ -77,6 +97,7 @@ public class VideoPlayerSeekBar { parentView = parent; thumbWidth = AndroidUtilities.dp(24); currentRadius = AndroidUtilities.dp(6); + animateThumbLoopBackProgress = new AnimatedFloat(0f, parent, 0, 300, CubicBezierInterpolator.EASE_OUT_QUINT); } public void setDelegate(SeekBarDelegate seekBarDelegate) { @@ -97,19 +118,21 @@ public class VideoPlayerSeekBar { } else if (thumbX > width - thumbWidth) { thumbX = thumbWidth - width; } + animatedThumbX = thumbX; } - pressed = true; + pressed = pressedDelayed = true; draggingThumbX = thumbX; thumbDX = (int) (x - thumbX); return true; } } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { if (pressed) { - thumbX = draggingThumbX; + animatedThumbX = thumbX = draggingThumbX; if (action == MotionEvent.ACTION_UP && delegate != null) { delegate.onSeekBarDrag((float) thumbX / (float) (width - thumbWidth)); } pressed = false; + AndroidUtilities.runOnUIThread(() -> pressedDelayed = false, 50); return true; } } else if (action == MotionEvent.ACTION_MOVE) { @@ -139,6 +162,11 @@ public class VideoPlayerSeekBar { } public void setProgress(float progress, boolean animated) { + if (Math.abs(this.progress - 1f) < 0.04f && Math.abs(progress) < 0.04f) { + animateThumbLoopBackProgress.set(1, true); + loopBackWasThumbX = thumbX; + } + this.progress = progress; int newThumb = (int) Math.ceil((width - thumbWidth) * progress); if (animated) { @@ -158,6 +186,9 @@ public class VideoPlayerSeekBar { } else if (thumbX > width - thumbWidth) { thumbX = width - thumbWidth; } + if (Math.abs(animatedThumbX - thumbX) > AndroidUtilities.dp(8)) { + animatedThumbX = thumbX; + } } public void setProgress(float progress) { @@ -218,12 +249,95 @@ public class VideoPlayerSeekBar { this.horizontalPadding = horizontalPadding; } + private ArrayList> timestamps; + private CharSequence lastCaption; + private long lastVideoDuration; + + public void updateTimestamps(MessageObject messageObject, long videoDuration) { + if (messageObject == null || videoDuration < 0) { + timestamps = null; + currentTimestamp = -1; + timestampsAppearing = 0; + if (timestampLabel != null) { + timestampLabel[0] = timestampLabel[1] = null; + } + lastCaption = null; + lastVideoDuration = -1; + return; + } + CharSequence text = messageObject.caption; + if (text == lastCaption && lastVideoDuration == videoDuration) { + return; + } + lastCaption = text; + lastVideoDuration = videoDuration; + if (!(text instanceof Spanned)) { + timestamps = null; + currentTimestamp = -1; + timestampsAppearing = 0; + if (timestampLabel != null) { + timestampLabel[0] = timestampLabel[1] = null; + } + return; + } + Spanned spanned = (Spanned) text; + URLSpanNoUnderline[] links; + try { + links = spanned.getSpans(0, spanned.length(), URLSpanNoUnderline.class); + } catch (Exception e) { + FileLog.e(e); + timestamps = null; + currentTimestamp = -1; + timestampsAppearing = 0; + if (timestampLabel != null) { + timestampLabel[0] = timestampLabel[1] = null; + } + return; + } + timestamps = new ArrayList<>(); + timestampsAppearing = 0; + if (timestampLabelPaint == null) { + timestampLabelPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + timestampLabelPaint.setTextSize(AndroidUtilities.dp(12)); + timestampLabelPaint.setColor(0xffffffff); + } + for (int i = 0; i < links.length; ++i) { + URLSpanNoUnderline link = links[i]; + if (link != null && link.getURL().startsWith("video?")) { + Integer seconds = Utilities.parseInt(link.getURL().substring(6)); + if (seconds != null && seconds >= 0) { + float position = seconds * 1000L / (float) videoDuration; + String label = link.label; + SpannableStringBuilder builder = new SpannableStringBuilder(label); + Emoji.replaceEmoji(builder, timestampLabelPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false); + timestamps.add(new Pair<>(position, builder)); + } + } + } + Collections.sort(timestamps, (a, b) -> { + if (a.first > b.first) { + return 1; + } else if (b.first > a.first) { + return -1; + } else { + return 0; + } + }); + } + public void draw(Canvas canvas, View view) { - final float radius = AndroidUtilities.lerp(thumbWidth / 2f, smallLineHeight / 2f, transitionProgress); rect.left = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f, 0, transitionProgress); rect.top = AndroidUtilities.lerp((height - lineHeight) / 2f, height - AndroidUtilities.dp(3) - smallLineHeight, transitionProgress); rect.bottom = AndroidUtilities.lerp((height + lineHeight) / 2f, height - AndroidUtilities.dp(3), transitionProgress); + float thumbX = this.thumbX; + animatedThumbX = Math.min(animatedThumbX, thumbX); + animatedThumbX = AndroidUtilities.lerp(animatedThumbX, thumbX, .5f); + if (Math.abs(thumbX - animatedThumbX) > 0.005f) { + parentView.invalidate(); + } + thumbX = animatedThumbX; + float currentThumbX = thumbX; if (animateThumbProgress != 1f) { animateThumbProgress += 16 / 220f; @@ -235,10 +349,16 @@ public class VideoPlayerSeekBar { currentThumbX = fromThumbX * (1f - progressInterpolated) + thumbX * progressInterpolated; } } + + float loopBack = animateThumbLoopBackProgress.set(0); + if (pressed) { + loopBack = 0; + } + // background rect.right = horizontalPadding + AndroidUtilities.lerp(width - thumbWidth / 2f, parentView.getWidth() - horizontalPadding * 2f, transitionProgress); setPaintColor(selected ? backgroundSelectedColor : backgroundColor, 1f - transitionProgress); - canvas.drawRoundRect(rect, radius, radius, paint); + drawProgressBar(canvas, rect, paint); if (bufferedAnimationValue != 1f) { bufferedAnimationValue += 16 / 100f; @@ -254,34 +374,22 @@ public class VideoPlayerSeekBar { if (animateFromBufferedProgress > 0) { rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + animateFromBufferedProgress * (width - thumbWidth), parentView.getWidth() - horizontalPadding * 2f, transitionProgress); setPaintColor(selected ? backgroundSelectedColor : cacheColor, (1f - transitionProgress) * (1f - bufferedAnimationValue)); - canvas.drawRoundRect(rect, radius, radius, paint); + drawProgressBar(canvas, rect, paint); } if (bufferedProgress > 0) { rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + bufferedProgress * (width - thumbWidth), parentView.getWidth() - horizontalPadding * 2f, transitionProgress); setPaintColor(selected ? backgroundSelectedColor : cacheColor, 1f - transitionProgress); - canvas.drawRoundRect(rect, radius, radius, paint); + drawProgressBar(canvas, rect, paint); } } else { float currentBufferedProgress = animateFromBufferedProgress * (1f - bufferedAnimationValue) + bufferedProgress * bufferedAnimationValue; if (currentBufferedProgress > 0) { rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + currentBufferedProgress * (width - thumbWidth), parentView.getWidth() - horizontalPadding * 2f, transitionProgress); setPaintColor(selected ? backgroundSelectedColor : cacheColor, 1f - transitionProgress); - canvas.drawRoundRect(rect, radius, radius, paint); + drawProgressBar(canvas, rect, paint); } } - // progress - rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + (pressed ? draggingThumbX : currentThumbX), (parentView.getWidth() - horizontalPadding * 2f) * getProgress(), transitionProgress); - if (transitionProgress > 0f && rect.width() > 0) { - // progress stroke - strokePaint.setAlpha((int) (transitionProgress * 255 * 0.2f)); - canvas.drawRoundRect(rect, radius, radius, strokePaint); - } - setPaintColor(ColorUtils.blendARGB(progressColor, smallLineColor, transitionProgress), 1f); - canvas.drawRoundRect(rect, radius, radius, paint); - - // circle - setPaintColor(ColorUtils.blendARGB(circleColor, getProgress() == 0 ? Color.TRANSPARENT : smallLineColor, transitionProgress), 1f - transitionProgress); int newRad = AndroidUtilities.dp(pressed ? 8 : 6); if (currentRadius != newRad) { long newUpdateTime = SystemClock.elapsedRealtime(); @@ -306,7 +414,267 @@ public class VideoPlayerSeekBar { } } final float circleRadius = AndroidUtilities.lerp(currentRadius, 0, transitionProgress); - canvas.drawCircle(rect.right, rect.centerY(), circleRadius, paint); + + if (loopBack > 0) { + float wasLeft = rect.left; + rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + (width - thumbWidth), parentView.getWidth() - horizontalPadding * 2f, transitionProgress); + rect.left = AndroidUtilities.lerp(wasLeft, rect.right, 1f - loopBack); + if (transitionProgress > 0f && rect.width() > 0) { + // progress stroke + strokePaint.setAlpha((int) (transitionProgress * 255 * 0.2f)); + drawProgressBar(canvas, rect, strokePaint); + } + setPaintColor(ColorUtils.blendARGB(progressColor, smallLineColor, transitionProgress), 1f); + drawProgressBar(canvas, rect, paint); + + rect.left = wasLeft; + + setPaintColor(ColorUtils.blendARGB(circleColor, getProgress() == 0 ? Color.TRANSPARENT : smallLineColor, transitionProgress), 1f - transitionProgress); + float wasRight = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + loopBackWasThumbX, (parentView.getWidth() - horizontalPadding * 2f) * (loopBackWasThumbX / (float) (width - thumbWidth)), transitionProgress); + canvas.drawCircle(wasRight, rect.centerY(), circleRadius * loopBack, paint); + } + + // progress + rect.right = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f + (pressed ? draggingThumbX : currentThumbX), (parentView.getWidth() - horizontalPadding * 2f) * getProgress(), transitionProgress); + if (transitionProgress > 0f && rect.width() > 0) { + // progress stroke + strokePaint.setAlpha((int) (transitionProgress * 255 * 0.2f)); + drawProgressBar(canvas, rect, strokePaint); + } + setPaintColor(ColorUtils.blendARGB(progressColor, smallLineColor, transitionProgress), 1f); + drawProgressBar(canvas, rect, paint); + + // circle + setPaintColor(ColorUtils.blendARGB(circleColor, getProgress() == 0 ? Color.TRANSPARENT : smallLineColor, transitionProgress), 1f - transitionProgress); + canvas.drawCircle(rect.right, rect.centerY(), circleRadius * (1f - loopBack), paint); + + drawTimestampLabel(canvas); + } + + private float timestampsAppearing = 0; + private long lastTimestampsAppearingUpdate; + private final float TIMESTAMP_GAP = 1f; + private static float[] tmpRadii; + private static Path tmpPath; + + private void drawProgressBar(Canvas canvas, RectF rect, Paint paint) { + float radius = AndroidUtilities.dp(AndroidUtilities.lerp(2, 1, transitionProgress)); + if (timestamps == null || timestamps.isEmpty()) { + canvas.drawRoundRect(rect, radius, radius, paint); + } else { + float lineWidth = rect.bottom - rect.top; + float left = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f, 0, transitionProgress); + float right = horizontalPadding + AndroidUtilities.lerp(width - thumbWidth / 2f, parentView.getWidth() - horizontalPadding * 2f, transitionProgress); + AndroidUtilities.rectTmp.set(rect); + float halfGap = AndroidUtilities.dp(TIMESTAMP_GAP * timestampsAppearing) / 2f; + if (tmpPath == null) { + tmpPath = new Path(); + } + tmpPath.reset(); + float minDur = AndroidUtilities.dp(4) / (right - left); + int start = -1, end = -1; + for (int i = 0; i < timestamps.size(); ++i) { + if (timestamps.get(i).first >= minDur) { + start = i; + break; + } + } + if (start < 0) { + start = 0; + } + for (int i = timestamps.size() - 1; i >= 0; --i) { + if (1f - timestamps.get(i).first >= minDur) { + end = i + 1; + break; + } + } + if (end < 0) { + end = timestamps.size(); + } + boolean first = true; + for (int i = start; i <= end; ++i) { + float from = i == start ? 0 : timestamps.get(i - 1).first; + float to = i == end ? 1 : timestamps.get(i).first; + + AndroidUtilities.rectTmp.left = AndroidUtilities.lerp(left, right, from) + (i > 0 ? halfGap : 0); + AndroidUtilities.rectTmp.right = AndroidUtilities.lerp(left, right, to) - (i < end ? halfGap : 0); + + boolean last; + if (last = AndroidUtilities.rectTmp.right > rect.right) { + AndroidUtilities.rectTmp.right = rect.right; + } + if (AndroidUtilities.rectTmp.right < rect.left) { + continue; + } + if (AndroidUtilities.rectTmp.left < rect.left) { + AndroidUtilities.rectTmp.left = rect.left; + } + + if (tmpRadii == null) { + tmpRadii = new float[8]; + } + if (i == start || last && AndroidUtilities.rectTmp.left >= rect.left) { + tmpRadii[0] = tmpRadii[1] = tmpRadii[6] = tmpRadii[7] = radius; + tmpRadii[2] = tmpRadii[3] = tmpRadii[4] = tmpRadii[5] = radius * 0.7f * timestampsAppearing; + } else if (i >= end) { + tmpRadii[0] = tmpRadii[1] = tmpRadii[6] = tmpRadii[7] = radius * 0.7f * timestampsAppearing; + tmpRadii[2] = tmpRadii[3] = tmpRadii[4] = tmpRadii[5] = radius; + } else { + tmpRadii[0] = tmpRadii[1] = tmpRadii[6] = tmpRadii[7] = + tmpRadii[2] = tmpRadii[3] = tmpRadii[4] = tmpRadii[5] = radius * 0.7f * timestampsAppearing; + } + tmpPath.addRoundRect(AndroidUtilities.rectTmp, tmpRadii, Path.Direction.CW); + + if (last) { + break; + } + } + canvas.drawPath(tmpPath, paint); + } + } + + + private int currentTimestamp = -1, lastTimestamp = -1; + private StaticLayout[] timestampLabel; + private TextPaint timestampLabelPaint; + private float timestampChangeT = 1; + private int timestampChangeDirection; + private long lastTimestampUpdate; + private float lastWidth = -1; + + private void drawTimestampLabel(Canvas canvas) { + if (timestamps == null || timestamps.isEmpty()) { + return; + } + + float progress = pressed || pressedDelayed ? (draggingThumbX / (float) (width - thumbWidth)) : (animatedThumbX / (float) (width - thumbWidth)); + + int timestampIndex = -1; + for (int i = timestamps.size() - 1; i >= 0; --i) { + if (timestamps.get(i).first - 0.001f <= progress) { + timestampIndex = i; + break; + } + } + + if (timestampLabel == null) { + timestampLabel = new StaticLayout[2]; + } + + float left = horizontalPadding + AndroidUtilities.lerp(thumbWidth / 2f, 0, transitionProgress); + float right = horizontalPadding + AndroidUtilities.lerp(width - thumbWidth / 2f, parentView.getWidth() - horizontalPadding * 2f, transitionProgress); + float rightPadded = horizontalPadding + (width - thumbWidth / 2f); + float width = Math.abs(left - rightPadded) - AndroidUtilities.dp(16); + + if (lastWidth > 0 && Math.abs(lastWidth - width) > 0.01f) { + if (timestampLabel[0] != null) { + timestampLabel[0] = makeStaticLayout(timestampLabel[0].getText(), (int) width); + } + if (timestampLabel[1] != null) { + timestampLabel[1] = makeStaticLayout(timestampLabel[1].getText(), (int) width); + } + } + lastWidth = width; + + if (timestampIndex != currentTimestamp) { + timestampLabel[1] = timestampLabel[0]; + if (pressed) { + try { + parentView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); + } catch (Exception ignore) {} + } + if (timestampIndex >= 0 && timestampIndex < timestamps.size()) { + CharSequence label = timestamps.get(timestampIndex).second; + if (label == null) { + timestampLabel[0] = null; + } else { + timestampLabel[0] = makeStaticLayout(label, (int) width); + } + } else { + timestampLabel[0] = null; + } + timestampChangeT = 0; + if (timestampIndex == -1) { + timestampChangeDirection = -1; + } else if (currentTimestamp == -1) { + timestampChangeDirection = 1; + } else if (timestampIndex < currentTimestamp) { + timestampChangeDirection = -1; + } else if (timestampIndex > currentTimestamp) { + timestampChangeDirection = 1; + } + lastTimestamp = currentTimestamp; + currentTimestamp = timestampIndex; + } + if (timestampChangeT < 1f) { + long tx = Math.min(17, Math.abs(SystemClock.elapsedRealtime() - lastTimestampUpdate)); + float duration = timestamps.size() > 8 ? 160f : 220f; + timestampChangeT = Math.min(timestampChangeT + tx / duration, 1); + parentView.invalidate(); + lastTimestampUpdate = SystemClock.elapsedRealtime(); + } + if (timestampsAppearing < 1f) { + long tx = Math.min(17, Math.abs(SystemClock.elapsedRealtime() - lastTimestampUpdate)); + timestampsAppearing = Math.min(timestampsAppearing + tx / 200f, 1); + parentView.invalidate(); + lastTimestampsAppearingUpdate = SystemClock.elapsedRealtime(); + } + float changeT = CubicBezierInterpolator.DEFAULT.getInterpolation(timestampChangeT); + + canvas.save(); + float bottom = AndroidUtilities.lerp((height + lineHeight) / 2f, height - AndroidUtilities.dp(3), transitionProgress); + canvas.translate(left + (right - rightPadded) * (transitionProgress), bottom + AndroidUtilities.dp(12)); + if (timestampLabel[1] != null) { + canvas.save(); + if (timestampChangeDirection != 0) { + canvas.translate(AndroidUtilities.dp(8) + AndroidUtilities.dp(16) * -timestampChangeDirection * changeT, 0); + } + canvas.translate(0, -timestampLabel[1].getHeight() / 2f); + timestampLabelPaint.setAlpha((int) (255 * (1f - transitionProgress) * (1f - changeT) * timestampsAppearing)); + timestampLabel[1].draw(canvas); + canvas.restore(); + } + if (timestampLabel[0] != null) { + canvas.save(); + if (timestampChangeDirection != 0) { + canvas.translate(AndroidUtilities.dp(8) + AndroidUtilities.dp(16) * timestampChangeDirection * (1f - changeT), 0); + } + canvas.translate(0, -timestampLabel[0].getHeight() / 2f); + timestampLabelPaint.setAlpha((int) (255 * (1f - transitionProgress) * changeT * timestampsAppearing)); + timestampLabel[0].draw(canvas); + canvas.restore(); + } + canvas.restore(); + } + + private StaticLayout makeStaticLayout(CharSequence text, int width) { + if (timestampLabelPaint == null) { + timestampLabelPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); + timestampLabelPaint.setTextSize(AndroidUtilities.dp(12)); + timestampLabelPaint.setColor(0xffffffff); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + return StaticLayout.Builder.obtain(text, 0, text.length(), timestampLabelPaint, width) + .setMaxLines(1) + .setAlignment(Layout.Alignment.ALIGN_CENTER) + .setEllipsize(TextUtils.TruncateAt.END) + .setEllipsizedWidth(Math.min(AndroidUtilities.dp(400), width)) + .build(); + } else { + return new StaticLayout( + text, + 0, + text.length(), + timestampLabelPaint, + width, + Layout.Alignment.ALIGN_CENTER, + 1, + 0, + false, + TextUtils.TruncateAt.END, + Math.min(AndroidUtilities.dp(400), (int) width) + ); + } } private void setPaintColor(int color, float alpha) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java index a6509f710..5c5d1974d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoSeekPreviewImage.java @@ -184,7 +184,7 @@ public class VideoSeekPreviewImage extends View { if (FileLoader.getInstance(currentAccount).isLoadingFile(name)) { path = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), document.dc_id + "_" + document.id + ".temp").getAbsolutePath(); } else { - path = FileLoader.getPathToAttach(document, false).getAbsolutePath(); + path = FileLoader.getInstance(currentAccount).getPathToAttach(document, false).getAbsolutePath(); } fileDrawable = new AnimatedFileDrawable(new File(path), true, document.size, document, null, parentObject, 0, currentAccount, true); } else { 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 8359204b3..8fec663d0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ViewPagerFixed.java @@ -930,7 +930,8 @@ public class ViewPagerFixed extends FrameLayout { } }; ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); - listView.setSelectorType(7); + listView.setSelectorType(8); + listView.setSelectorRadius(6); listView.setSelectorDrawableColor(Theme.getColor(selectorColorKey)); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) { @Override 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 abd9754ca..1c027e149 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 @@ -701,8 +701,7 @@ public class SpoilerEffect extends Drawable { /** * Optimized version of text layout double-render - * - * @param v View to use as a parent view + * @param v View to use as a parent view * @param invalidateSpoilersParent Set to invalidate parent or not * @param spoilersColor Spoilers' color * @param verticalOffset Additional vertical offset @@ -710,10 +709,11 @@ public class SpoilerEffect extends Drawable { * @param textLayout Layout to render * @param spoilers Spoilers list to render * @param canvas Canvas to render + * @param useParentWidth */ @SuppressLint("WrongConstant") @MainThread - public static void renderWithRipple(View v, boolean invalidateSpoilersParent, int spoilersColor, int verticalOffset, AtomicReference patchedLayoutRef, Layout textLayout, List spoilers, Canvas canvas) { + 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); return; @@ -792,7 +792,11 @@ public class SpoilerEffect extends Drawable { boolean useAlphaLayer = spoilers.get(0).rippleProgress != -1; if (useAlphaLayer) { - canvas.saveLayer(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight(), null, canvas.ALL_SAVE_FLAG); + int w = v.getMeasuredWidth(); + if (useParentWidth && v.getParent() instanceof View) { + w = ((View) v.getParent()).getMeasuredWidth(); + } + canvas.saveLayer(0, 0, w, v.getMeasuredHeight(), null, canvas.ALL_SAVE_FLAG); } else { canvas.save(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java index 9779e2108..1e3d2530e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/AcceptDeclineView.java @@ -500,13 +500,16 @@ public class AcceptDeclineView extends View { this.screenWasWakeup = screenWasWakeup; } - private abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider { + public static abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider { private final View hostView; private final int virtualViewsCount; private final Rect rect = new Rect(); private final AccessibilityManager accessibilityManager; - private AcceptDeclineAccessibilityNodeProvider(View hostView, int virtualViewsCount) { + + private int currentFocusedVirtualViewId = View.NO_ID; + + protected AcceptDeclineAccessibilityNodeProvider(View hostView, int virtualViewsCount) { this.hostView = hostView; this.virtualViewsCount = virtualViewsCount; this.accessibilityManager = ContextCompat.getSystemService(hostView.getContext(), AccessibilityManager.class); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CellFlickerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CellFlickerDrawable.java index 7fca1f3fe..4292c2d12 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CellFlickerDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/CellFlickerDrawable.java @@ -2,15 +2,23 @@ package org.telegram.ui.Components.voip; 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.RectF; import android.graphics.Shader; +import android.graphics.drawable.Drawable; +import android.view.View; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.SvgHelper; public class CellFlickerDrawable { @@ -22,19 +30,23 @@ public class CellFlickerDrawable { int size; int parentWidth; - float progress; + public float progress; long lastUpdateTime; Matrix matrix = new Matrix(); public boolean repeatEnabled = true; public boolean drawFrame = true; + public boolean frameInside = false; public float repeatProgress = 1.2f; public float animationSpeedScale = 1f; + View parentView; + Runnable onRestartCallback; public CellFlickerDrawable() { this(64, 204); } + public CellFlickerDrawable(int a1, int a2) { size = AndroidUtilities.dp(160); gradientShader = new LinearGradient(0, 0, size, 0, new int[]{Color.TRANSPARENT, ColorUtils.setAlphaComponent(Color.WHITE, a1), Color.TRANSPARENT}, null, Shader.TileMode.CLAMP); @@ -64,10 +76,32 @@ public class CellFlickerDrawable { this.progress = progress; } - public void draw(Canvas canvas, RectF rectF, float rad) { + public void draw(Canvas canvas, RectF rectF, float rad, View view) { + update(view); + canvas.drawRoundRect(rectF, rad, rad, paint); + if (drawFrame) { + if (frameInside) { + rectF.inset(paintOutline.getStrokeWidth() / 2f, paintOutline.getStrokeWidth() / 2f); + } + canvas.drawRoundRect(rectF, rad, rad, paintOutline); + } + } + + public void draw(Canvas canvas, Path path, View view) { + update(view); + canvas.drawPath(path, paint); + if (drawFrame) { + canvas.drawPath(path, paintOutline); + } + } + + private void update(View view) { if (progress > 1f && !repeatEnabled) { return; } + if (view != null) { + view.invalidate(); + } long currentTime = System.currentTimeMillis(); if (lastUpdateTime != 0) { long dt = currentTime - lastUpdateTime; @@ -75,6 +109,9 @@ public class CellFlickerDrawable { progress += (dt / 1200f) * animationSpeedScale; if (progress > repeatProgress) { progress = 0; + if (onRestartCallback != null) { + onRestartCallback.run(); + } } lastUpdateTime = currentTime; } @@ -82,22 +119,17 @@ public class CellFlickerDrawable { lastUpdateTime = currentTime; } - if (progress > 1f) { - return; - } +// if (progress > 1f) { +// return; +// } float x = (parentWidth + size * 2) * progress - size; + matrix.reset(); matrix.setTranslate(x, 0); gradientShader.setLocalMatrix(matrix); gradientShader2.setLocalMatrix(matrix); - - canvas.drawRoundRect(rectF, rad, rad, paint); - if (drawFrame) { - canvas.drawRoundRect(rectF, rad, rad, paintOutline); - } } - public void draw(Canvas canvas, GroupCallMiniTextureView view) { long currentTime = System.currentTimeMillis(); if (lastUpdateTime != 0) { @@ -106,6 +138,9 @@ public class CellFlickerDrawable { progress += dt / 500f; if (progress > 4f) { progress = 0; + if (onRestartCallback != null) { + onRestartCallback.run(); + } } lastUpdateTime = currentTime; } @@ -125,6 +160,9 @@ public class CellFlickerDrawable { AndroidUtilities.rectTmp.set(view.textureView.currentClipHorizontal, view.textureView.currentClipVertical, view.textureView.getMeasuredWidth() - view.textureView.currentClipHorizontal, view.textureView.getMeasuredHeight() - view.textureView.currentClipVertical); canvas.drawRect(AndroidUtilities.rectTmp, paint); if (drawFrame) { + if (frameInside) { + AndroidUtilities.rectTmp.inset(paintOutline.getStrokeWidth() / 2f, paintOutline.getStrokeWidth() / 2f); + } canvas.drawRoundRect(AndroidUtilities.rectTmp, view.textureView.roundRadius, view.textureView.roundRadius, paintOutline); } } @@ -132,4 +170,64 @@ public class CellFlickerDrawable { public void setParentWidth(int parentWidth) { this.parentWidth = parentWidth; } + + public DrawableInterface getDrawableInterface(View parentView, SvgHelper.SvgDrawable drawable) { + this.parentView = parentView; + return new DrawableInterface(drawable); + } + + + public void setOnRestartCallback(Runnable runnable) { + onRestartCallback = runnable; + } + + public class DrawableInterface extends Drawable { + + public float radius; + SvgHelper.SvgDrawable svgDrawable; + + public DrawableInterface(SvgHelper.SvgDrawable drawable) { + svgDrawable = drawable; + } + + @Override + public void draw(@NonNull Canvas canvas) { + setParentWidth(getBounds().width()); + AndroidUtilities.rectTmp.set(getBounds()); + CellFlickerDrawable.this.draw(canvas, AndroidUtilities.rectTmp, radius, null); + if (svgDrawable != null) { + svgDrawable.setPaint(paint); + float x = (parentWidth + size * 2) * progress - size; + int drawableSize = (int) (parentWidth * 0.5f); + float s = svgDrawable.getScale(); + matrix.reset(); + matrix.setScale(1f / s, 0, size / 2f, 0); + matrix.setTranslate(x - svgDrawable.getBounds().left - size / s, 0); + + gradientShader.setLocalMatrix(matrix); + svgDrawable.setBounds( + getBounds().centerX() - drawableSize / 2, getBounds().centerY() - drawableSize / 2, + getBounds().centerX() + drawableSize / 2, getBounds().centerY() + drawableSize / 2 + ); + svgDrawable.draw(canvas); + } + parentView.invalidate(); + } + + @Override + public void setAlpha(int alpha) { + paint.setAlpha(alpha); + paintOutline.setAlpha(alpha); + } + + @Override + public void setColorFilter(@Nullable ColorFilter colorFilter) { + + } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/RTMPStreamPipOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/RTMPStreamPipOverlay.java index 5ef37d138..13c23a592 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/RTMPStreamPipOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/voip/RTMPStreamPipOverlay.java @@ -543,7 +543,7 @@ public class RTMPStreamPipOverlay implements NotificationCenter.NotificationCent if (getAlpha() == 0f) return; AndroidUtilities.rectTmp.set(0, 0, getWidth(), getHeight()); - cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(ROUNDED_CORNERS_DP)); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(ROUNDED_CORNERS_DP), null); invalidate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java index 785d703c2..5026cfe99 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java @@ -56,6 +56,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent private AvatarDrawable avatarDrawable; private TextView infoTextView; private CheckBoxCell checkBoxCell; + private Theme.ResourcesProvider resourcesProvider; private long user_id; private boolean addContact; @@ -74,6 +75,16 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent super(args); } + public ContactAddActivity(Bundle args, Theme.ResourcesProvider resourcesProvider) { + super(args); + this.resourcesProvider = resourcesProvider; + } + + @Override + public Theme.ResourcesProvider getResourceProvider() { + return resourcesProvider; + } + @Override public boolean onFragmentCreate() { getNotificationCenter().addObserver(this, NotificationCenter.updateInterfaces); @@ -96,6 +107,8 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent @Override public View createView(Context context) { + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_avatar_actionBarSelectorBlue, resourcesProvider), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider), false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setAllowOverlayTitle(true); if (addContact) { @@ -145,7 +158,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent frameLayout.addView(avatarImage, LayoutHelper.createFrame(60, 60, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP)); nameTextView = new TextView(context); - nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + nameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20); nameTextView.setLines(1); nameTextView.setMaxLines(1); @@ -156,7 +169,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent frameLayout.addView(nameTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 80, 3, LocaleController.isRTL ? 80 : 0, 0)); onlineTextView = new TextView(context); - onlineTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); + onlineTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3, resourcesProvider)); onlineTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); onlineTextView.setLines(1); onlineTextView.setMaxLines(1); @@ -165,10 +178,15 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent onlineTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT)); frameLayout.addView(onlineTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 0 : 80, 32, LocaleController.isRTL ? 80 : 0, 0)); - firstNameField = new EditTextBoldCursor(context); + firstNameField = new EditTextBoldCursor(context) { + @Override + protected Theme.ResourcesProvider getResourcesProvider() { + return resourcesProvider; + } + }; firstNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - firstNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - firstNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + firstNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourcesProvider)); + firstNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); firstNameField.setBackgroundDrawable(null); firstNameField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); firstNameField.setMaxLines(1); @@ -178,7 +196,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent firstNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); firstNameField.setImeOptions(EditorInfo.IME_ACTION_NEXT); firstNameField.setHint(LocaleController.getString("FirstName", R.string.FirstName)); - firstNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + firstNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); firstNameField.setCursorSize(AndroidUtilities.dp(20)); firstNameField.setCursorWidth(1.5f); linearLayout.addView(firstNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 24, 24, 0)); @@ -201,10 +219,15 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent } }); - lastNameField = new EditTextBoldCursor(context); + lastNameField = new EditTextBoldCursor(context) { + @Override + protected Theme.ResourcesProvider getResourcesProvider() { + return resourcesProvider; + } + }; lastNameField.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); - lastNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - lastNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + lastNameField.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText, resourcesProvider)); + lastNameField.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); lastNameField.setBackgroundDrawable(null); lastNameField.setLineColors(getThemedColor(Theme.key_windowBackgroundWhiteInputField), getThemedColor(Theme.key_windowBackgroundWhiteInputFieldActivated), getThemedColor(Theme.key_windowBackgroundWhiteRedText3)); lastNameField.setMaxLines(1); @@ -214,7 +237,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent lastNameField.setInputType(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); lastNameField.setImeOptions(EditorInfo.IME_ACTION_DONE); lastNameField.setHint(LocaleController.getString("LastName", R.string.LastName)); - lastNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + lastNameField.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); lastNameField.setCursorSize(AndroidUtilities.dp(20)); lastNameField.setCursorWidth(1.5f); linearLayout.addView(lastNameField, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 36, 24, 16, 24, 0)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java index c106af5b0..763abb9fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java @@ -251,7 +251,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter SharedConfig.toggleSortContactsByName(); sortByName = SharedConfig.sortContactsByName; listViewAdapter.setSortType(sortByName ? 1 : 2, false); - sortItem.setIcon(sortByName ? R.drawable.contacts_sort_time : R.drawable.contacts_sort_name); + sortItem.setIcon(sortByName ? R.drawable.msg_contacts_time : R.drawable.msg_contacts_name); } } }); @@ -319,7 +319,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter item.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); item.setContentDescription(LocaleController.getString("Search", R.string.Search)); if (!createSecretChat && !returnAsResult) { - sortItem = menu.addItem(sort_button, sortByName ? R.drawable.contacts_sort_time : R.drawable.contacts_sort_name); + sortItem = menu.addItem(sort_button, sortByName ? R.drawable.msg_contacts_time : R.drawable.msg_contacts_name); sortItem.setContentDescription(LocaleController.getString("AccDescrContactSorting", R.string.AccDescrContactSorting)); } @@ -1263,7 +1263,6 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{GraySectionCell.class}, new String[]{"textView"}, null, null, null, Theme.key_graySectionText)); themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_CELLBACKGROUNDCOLOR, new Class[]{GraySectionCell.class}, null, null, null, Theme.key_graySection)); - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedCheckDrawable}, null, Theme.key_chats_verifiedCheck)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_verifiedDrawable}, null, Theme.key_chats_verifiedBackground)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{ProfileSearchCell.class}, Theme.dialogs_offlinePaint, null, null, Theme.key_windowBackgroundWhiteGrayText3)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index 2412a3680..2e35fdd3a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -8,9 +8,11 @@ package org.telegram.ui; +import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; +import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -29,35 +31,41 @@ import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.View; -import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.FrameLayout; +import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ImageLoader; import org.telegram.messenger.MediaController; import org.telegram.messenger.MediaDataController; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; +import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLocation; import org.telegram.messenger.ImageReceiver; -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; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; import org.telegram.messenger.WebFile; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.Cells.ContextLinkCell; import org.telegram.ui.Cells.StickerCell; import org.telegram.ui.Cells.StickerEmojiCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -83,10 +91,15 @@ public class ContentPreviewViewer { public interface ContentPreviewViewerDelegate { void sendSticker(TLRPC.Document sticker, String query, Object parent, boolean notify, int scheduleDate); + void openSet(TLRPC.InputStickerSet set, boolean clearInputField); + boolean needSend(); + boolean canSchedule(); + boolean isInScheduleMode(); + long getDialogId(); default boolean needRemove() { @@ -133,12 +146,12 @@ public class ContentPreviewViewer { private float moveY = 0; private float finalMoveY; private float startMoveY; - private boolean animateY; private float currentMoveYProgress; private View currentPreviewCell; private boolean clearsInputField; private Runnable openPreviewRunnable; - private BottomSheet visibleDialog; + ActionBarPopupWindow popupWindow; + private ActionBarPopupWindow visibleMenu; private ContentPreviewViewerDelegate delegate; private boolean isRecentSticker; @@ -148,17 +161,25 @@ public class ContentPreviewViewer { private int currentAccount; private ColorDrawable backgroundDrawable = new ColorDrawable(0x71000000); + private Bitmap blurrBitmap; private Activity parentActivity; private WindowManager.LayoutParams windowLayoutParams; private FrameLayout windowView; private FrameLayoutDrawer containerView; private ImageReceiver centerImage = new ImageReceiver(); + private ImageReceiver effectImage = new ImageReceiver(); private boolean isVisible = false; private float showProgress; private StaticLayout stickerEmojiLayout; private long lastUpdateTime; private int keyboardHeight = AndroidUtilities.dp(200); private Drawable slideUpDrawable; + private boolean menuVisible; + private float blurProgress; + private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); + private UnlockPremiumView unlockPremiumView; + private boolean closeOnDismiss; + private boolean drawEffect; private Runnable showSheetRunnable = new Runnable() { @Override @@ -166,12 +187,22 @@ public class ContentPreviewViewer { if (parentActivity == null) { return; } + closeOnDismiss = true; if (currentContentType == CONTENT_TYPE_STICKER) { + if (MessageObject.isPremiumSticker(currentDocument) && !AccountInstance.getInstance(currentAccount).getUserConfig().isPremium()) { + showUnlockPremiumView(); + menuVisible = true; + containerView.invalidate(); + if (!NekoConfig.disableVibration.Bool()) + containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + return; + } final boolean inFavs = MediaDataController.getInstance(currentAccount).isStickerInFavorites(currentDocument); - BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity, true, resourcesProvider); ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); + menuVisible = true; + containerView.invalidate(); if (delegate != null) { if (delegate.needSend() && !delegate.isInScheduleMode()) { items.add(LocaleController.getString("SendStickerPreview", R.string.SendStickerPreview)); @@ -190,7 +221,7 @@ public class ContentPreviewViewer { } if (currentStickerSet != null && delegate.needOpen()) { items.add(LocaleController.formatString("ViewPackPreview", R.string.ViewPackPreview)); - icons.add(R.drawable.outline_pack); + icons.add(R.drawable.msg_media); actions.add(1); } if (delegate.needRemove()) { @@ -204,7 +235,7 @@ public class ContentPreviewViewer { } if (!MessageObject.isMaskDocument(currentDocument) && (inFavs || MediaDataController.getInstance(currentAccount).canAddStickerToFavorites() && MessageObject.isStickerHasSet(currentDocument))) { items.add(inFavs ? LocaleController.getString("DeleteFromFavorites", R.string.DeleteFromFavorites) : LocaleController.getString("AddToFavorites", R.string.AddToFavorites)); - icons.add(inFavs ? R.drawable.outline_unfave : R.drawable.outline_fave); + icons.add(inFavs ? R.drawable.msg_unfave : R.drawable.msg_fave); actions.add(2); } if (isRecentSticker) { @@ -219,70 +250,101 @@ public class ContentPreviewViewer { for (int a = 0; a < icons.size(); a++) { ic[a] = icons.get(a); } - builder.setItems(items.toArray(new CharSequence[0]), ic, (dialog, which) -> { - if (parentActivity == null) { - return; - } - if (actions.get(which) == 0 || actions.get(which) == 6 || actions.get(which) == 100) { - if (delegate != null) { - delegate.sendSticker(currentDocument, currentQuery, parentObject, actions.get(which) == 0, 0); - } - } else if (actions.get(which) == 1) { - if (delegate != null) { - delegate.openSet(currentStickerSet, clearsInputField); - } - } else if (actions.get(which) == 2) { - MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_FAVE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); - } else if (actions.get(which) == 3) { - TLRPC.Document sticker = currentDocument; - Object parent = parentObject; - String query = currentQuery; - ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; - AlertsCreator.createScheduleDatePickerDialog(parentActivity, stickerPreviewViewerDelegate.getDialogId(), (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendSticker(sticker, query, parent, notify, scheduleDate)); - } else if (actions.get(which) == 4) { - MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_IMAGE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), true); - } else if (actions.get(which) == 5) { - delegate.remove(importingSticker); - } else if (actions.get(which) == nkbtn_stickerdl) { - // save to gallery - MessageHelper.getInstance(currentAccount).saveStickerToGallery(parentActivity, currentDocument); - } - }); - builder.setDimBehind(false); - visibleDialog = builder.create(); - visibleDialog.setOnDismissListener(dialog -> { - visibleDialog = null; - close(); - }); - visibleDialog.show(); - if (!NekoConfig.disableVibration.Bool()) { - containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - } - if (delegate != null && delegate.needRemove()) { - BottomSheet.BottomSheetCell cell = visibleDialog.getItemViews().get(0); - cell.setTextColor(getThemedColor(Theme.key_dialogTextRed)); - cell.setIconColor(getThemedColor(Theme.key_dialogRedIcon)); - } - } else if (delegate != null) { - animateY = true; - visibleDialog = new BottomSheet(parentActivity, false) { + + + View.OnClickListener onItemClickListener = new View.OnClickListener() { @Override - protected void onContainerTranslationYChanged(float translationY) { - if (animateY) { - ViewGroup container = getSheetContainer(); - if (finalMoveY == 0) { - finalMoveY = 0;//-container.getMeasuredHeight() / 2; - startMoveY = moveY; + public void onClick(View v) { + if (parentActivity == null) { + return; + } + int which = (int) v.getTag(); + if (actions.get(which) == 0 || actions.get(which) == 6) { + if (delegate != null) { + delegate.sendSticker(currentDocument, currentQuery, parentObject, actions.get(which) == 0, 0); } - currentMoveYProgress = 1.0f - Math.min(1.0f, translationY / containerView.getMeasuredHeight()); - moveY = startMoveY + (finalMoveY - startMoveY) * currentMoveYProgress; - ContentPreviewViewer.this.containerView.invalidate(); - if (currentMoveYProgress == 1.0f) { - animateY = false; + } else if (actions.get(which) == 1) { + if (delegate != null) { + delegate.openSet(currentStickerSet, clearsInputField); } + } else if (actions.get(which) == 2) { + MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_FAVE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), inFavs); + } else if (actions.get(which) == 3) { + TLRPC.Document sticker = currentDocument; + Object parent = parentObject; + String query = currentQuery; + ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; + AlertsCreator.createScheduleDatePickerDialog(parentActivity, stickerPreviewViewerDelegate.getDialogId(), (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendSticker(sticker, query, parent, notify, scheduleDate)); + } else if (actions.get(which) == 4) { + MediaDataController.getInstance(currentAccount).addRecentSticker(MediaDataController.TYPE_IMAGE, parentObject, currentDocument, (int) (System.currentTimeMillis() / 1000), true); + } else if (actions.get(which) == 5) { + delegate.remove(importingSticker); + } + if (popupWindow != null) { + popupWindow.dismiss(); } } }; + ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(containerView.getContext(), R.drawable.popup_fixed_alert2, resourcesProvider); + + for (int i = 0; i < items.size(); i++) { + View item = ActionBarMenuItem.addItem(previewMenu, icons.get(i), items.get(i), false, resourcesProvider); + item.setTag(i); + item.setOnClickListener(onItemClickListener); + } + popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + popupWindow = null; + menuVisible = false; + if (closeOnDismiss) { + close(); + } + } + }; + popupWindow.setPauseNotifications(true); + popupWindow.setDismissAnimationDuration(100); + popupWindow.setScaleOut(true); + popupWindow.setOutsideTouchable(true); + popupWindow.setClippingEnabled(true); + popupWindow.setAnimationStyle(R.style.PopupContextAnimation); + popupWindow.setFocusable(true); + previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + popupWindow.getContentView().setFocusableInTouchMode(true); + + int insets = 0; + int top; + if (Build.VERSION.SDK_INT >= 21 && lastInsets != null) { + insets = lastInsets.getStableInsetBottom() + lastInsets.getStableInsetTop(); + top = lastInsets.getStableInsetTop(); + } else { + top = AndroidUtilities.statusBarHeight; + } + int size; + if (currentContentType == CONTENT_TYPE_GIF) { + size = Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dp(40f); + } else { + if (drawEffect) { + size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dpf2(40f)); + } else { + size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); + } + } + + int y = (int) (moveY + Math.max(size / 2 + top + (stickerEmojiLayout != null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - insets - keyboardHeight) / 2) + size / 2); + y += AndroidUtilities.dp(24); + if (drawEffect) { + y += AndroidUtilities.dp(24); + } + popupWindow.showAtLocation(containerView, 0, (int) ((containerView.getMeasuredWidth() - previewMenu.getMeasuredWidth()) / 2f), y); + + if (!NekoConfig.disableVibration.Bool()) + containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + + } else if (delegate != null) { + menuVisible = true; ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); ArrayList icons = new ArrayList<>(); @@ -322,17 +384,21 @@ public class ContentPreviewViewer { for (int a = 0; a < icons.size(); a++) { ic[a] = icons.get(a); } - visibleDialog.setItems(items.toArray(new CharSequence[0]), ic, (dialog, which) -> { + + ActionBarPopupWindow.ActionBarPopupWindowLayout previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout(containerView.getContext(), R.drawable.popup_fixed_alert2, resourcesProvider); + + View.OnClickListener onItemClickListener = v -> { if (parentActivity == null) { return; } + int which = (int) v.getTag(); if (actions.get(which) == 0 || actions.get(which) == 100) { delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, actions.get(which) == 0, 0); } else if (actions.get(which) == 1) { MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument); delegate.gifAddedOrDeleted(); } else if (actions.get(which) == 2) { - MediaDataController.getInstance(currentAccount).addRecentGif(currentDocument, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(currentDocument, (int) (System.currentTimeMillis() / 1000), true); MessagesController.getInstance(currentAccount).saveGif("gif", currentDocument); delegate.gifAddedOrDeleted(); } else if (actions.get(which) == 3) { @@ -342,23 +408,106 @@ public class ContentPreviewViewer { ContentPreviewViewerDelegate stickerPreviewViewerDelegate = delegate; AlertsCreator.createScheduleDatePickerDialog(parentActivity, stickerPreviewViewerDelegate.getDialogId(), (notify, scheduleDate) -> stickerPreviewViewerDelegate.sendGif(document != null ? document : result, parent, notify, scheduleDate), resourcesProvider); } - }); - visibleDialog.setDimBehind(false); - visibleDialog.setOnDismissListener(dialog -> { - visibleDialog = null; - close(); - }); - visibleDialog.show(); - if (!NekoConfig.disableVibration.Bool()) { - containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + if (popupWindow != null) { + popupWindow.dismiss(); + } + }; + + for (int i = 0; i < items.size(); i++) { + ActionBarMenuSubItem item = ActionBarMenuItem.addItem(previewMenu, icons.get(i), items.get(i), false, resourcesProvider); + item.setTag(i); + item.setOnClickListener(onItemClickListener); + + if (canDelete && i == items.size() - 1) { + item.setColors(getThemedColor(Theme.key_dialogTextRed2), getThemedColor(Theme.key_dialogRedIcon)); + } } - if (canDelete) { - visibleDialog.setItemColor(items.size() - 1, getThemedColor(Theme.key_dialogTextRed2), getThemedColor(Theme.key_dialogRedIcon)); + popupWindow = new ActionBarPopupWindow(previewMenu, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT) { + @Override + public void dismiss() { + super.dismiss(); + popupWindow = null; + menuVisible = false; + if (closeOnDismiss) { + close(); + } + } + }; + popupWindow.setPauseNotifications(true); + popupWindow.setDismissAnimationDuration(150); + popupWindow.setScaleOut(true); + popupWindow.setOutsideTouchable(true); + popupWindow.setClippingEnabled(true); + popupWindow.setAnimationStyle(R.style.PopupContextAnimation); + popupWindow.setFocusable(true); + previewMenu.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); + popupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); + popupWindow.getContentView().setFocusableInTouchMode(true); + + int insets = 0; + int top; + if (Build.VERSION.SDK_INT >= 21 && lastInsets != null) { + insets = lastInsets.getStableInsetBottom() + lastInsets.getStableInsetTop(); + top = lastInsets.getStableInsetTop(); + } else { + top = AndroidUtilities.statusBarHeight; + } + int size = Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dp(40f); + + + int y = (int) (moveY + Math.max(size / 2 + top + (stickerEmojiLayout != null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - insets - keyboardHeight) / 2) + size / 2); + y += AndroidUtilities.dp(24) - moveY; + popupWindow.showAtLocation(containerView, 0, (int) ((containerView.getMeasuredWidth() - previewMenu.getMeasuredWidth()) / 2f), y); + + if (!NekoConfig.disableVibration.Bool()) + containerView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); + + if (moveY != 0) { + if (finalMoveY == 0) { + finalMoveY = 0; + startMoveY = moveY; + } + ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1f); + valueAnimator.addUpdateListener(animation -> { + currentMoveYProgress = (float) animation.getAnimatedValue(); + moveY = startMoveY + (finalMoveY - startMoveY) * currentMoveYProgress; + ContentPreviewViewer.this.containerView.invalidate(); + }); + valueAnimator.setDuration(350); + valueAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + valueAnimator.start(); } } } }; + private void showUnlockPremiumView() { + if (unlockPremiumView == null) { + unlockPremiumView = new UnlockPremiumView(containerView.getContext(), UnlockPremiumView.TYPE_STICKERS, resourcesProvider); + containerView.addView(unlockPremiumView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + unlockPremiumView.setOnClickListener(v -> { + menuVisible = false; + containerView.invalidate(); + close(); + }); + unlockPremiumView.premiumButtonView.buttonLayout.setOnClickListener(v -> { + if (parentActivity instanceof LaunchActivity) { + LaunchActivity activity = (LaunchActivity) parentActivity; + if (activity.getActionBarLayout() != null && activity.getActionBarLayout().getLastFragment() != null) { + activity.getActionBarLayout().getLastFragment().dismissCurrentDialog(); + } + activity.presentFragment(new PremiumPreviewFragment(PremiumPreviewFragment.featureTypeToServerString(PremiumPreviewFragment.PREMIUM_FEATURE_STICKERS))); + } + menuVisible = false; + containerView.invalidate(); + close(); + }); + } + AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, false, 1f, false); + AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, true); + unlockPremiumView.setTranslationY(0); + } + private int currentContentType; private TLRPC.Document currentDocument; private SendMessagesHelper.ImportingSticker importingSticker; @@ -370,6 +519,7 @@ public class ContentPreviewViewer { @SuppressLint("StaticFieldLeak") private static volatile ContentPreviewViewer Instance = null; + public static ContentPreviewViewer getInstance() { ContentPreviewViewer localInstance = Instance; if (localInstance == null) { @@ -434,7 +584,7 @@ public class ContentPreviewViewer { if (isVisible) { if (event.getAction() == MotionEvent.ACTION_MOVE) { if (currentContentType == CONTENT_TYPE_GIF) { - if (visibleDialog == null && showProgress == 1.0f) { + if (!menuVisible && showProgress == 1.0f) { if (lastTouchY == -10000) { lastTouchY = event.getY(); currentMoveY = 0; @@ -505,8 +655,13 @@ public class ContentPreviewViewer { ((ContextLinkCell) currentPreviewCell).setScaled(false); } currentPreviewCell = view; - setKeyboardHeight(height); clearsInputField = false; + menuVisible = false; + closeOnDismiss = false; + if (popupWindow != null) { + popupWindow.dismiss(); + } + AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, false); if (currentPreviewCell instanceof StickerEmojiCell) { StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; open(stickerEmojiCell.getSticker(), stickerEmojiCell.getStickerPath(), stickerEmojiCell.getEmoji(), delegate != null ? delegate.getQuery(false) : null, null, contentType, stickerEmojiCell.isRecent(), stickerEmojiCell.getParentObject(), resourcesProvider); @@ -619,7 +774,7 @@ public class ContentPreviewViewer { listView.requestDisallowInterceptTouchEvent(true); openPreviewRunnable = null; setParentActivity((Activity) listView.getContext()); - setKeyboardHeight(height); + //setKeyboardHeight(height); clearsInputField = false; if (currentPreviewCell instanceof StickerEmojiCell) { StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) currentPreviewCell; @@ -637,7 +792,8 @@ public class ContentPreviewViewer { contextLinkCell.setScaled(true); } } - currentPreviewCell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + if (!NekoConfig.disableVibration.Bool()) + currentPreviewCell.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); }; AndroidUtilities.runOnUIThread(openPreviewRunnable, 200); return true; @@ -654,6 +810,8 @@ public class ContentPreviewViewer { currentAccount = UserConfig.selectedAccount; centerImage.setCurrentAccount(currentAccount); centerImage.setLayerNum(Integer.MAX_VALUE); + effectImage.setCurrentAccount(currentAccount); + effectImage.setLayerNum(Integer.MAX_VALUE); if (parentActivity == activity) { return; } @@ -677,12 +835,14 @@ public class ContentPreviewViewer { protected void onAttachedToWindow() { super.onAttachedToWindow(); centerImage.onAttachedToWindow(); + effectImage.onAttachedToWindow(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); centerImage.onDetachedFromWindow(); + effectImage.onDetachedFromWindow(); } }; containerView.setFocusable(false); @@ -694,6 +854,10 @@ public class ContentPreviewViewer { return true; }); + + SharedPreferences sharedPreferences = MessagesController.getInstance(currentAccount).getGlobalEmojiSettings(); + keyboardHeight = sharedPreferences.getInt("kbd_height", AndroidUtilities.dp(200)); + windowLayoutParams = new WindowManager.LayoutParams(); windowLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT; windowLayoutParams.format = PixelFormat.TRANSLUCENT; @@ -708,6 +872,10 @@ public class ContentPreviewViewer { centerImage.setAspectFit(true); centerImage.setInvalidateAll(true); centerImage.setParentView(containerView); + + effectImage.setAspectFit(true); + effectImage.setInvalidateAll(true); + effectImage.setParentView(containerView); } public void setKeyboardHeight(int height) { @@ -721,6 +889,8 @@ public class ContentPreviewViewer { this.resourcesProvider = resourcesProvider; isRecentSticker = isRecent; stickerEmojiLayout = null; + backgroundDrawable.setColor(Theme.getActiveTheme().isDark() ? 0x71000000 : 0x64E6E6E6); + drawEffect = false; if (contentType == CONTENT_TYPE_STICKER) { if (document == null && sticker == null) { return; @@ -730,6 +900,8 @@ public class ContentPreviewViewer { textPaint.setTextSize(AndroidUtilities.dp(24)); } + effectImage.clearImage(); + drawEffect = false; if (document != null) { TLRPC.InputStickerSet newSet = null; for (int a = 0; a < document.attributes.size(); a++) { @@ -740,24 +912,19 @@ public class ContentPreviewViewer { } } if (newSet != null && (delegate == null || delegate.needMenu())) { - try { - if (visibleDialog != null) { - visibleDialog.setOnDismissListener(null); - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); } currentStickerSet = newSet; TLRPC.PhotoSize thumb = FileLoader.getClosestPhotoSizeWithSize(document.thumbs, 90); if (MessageObject.isVideoStickerDocument(document)) { - centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, null, 0, "webp", currentStickerSet, 1); + centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, null, 0, "webp", currentStickerSet, 1); } else { centerImage.setImage(ImageLocation.getForDocument(document), null, ImageLocation.getForDocument(thumb, document), null, "webp", currentStickerSet, 1); + if (MessageObject.isPremiumSticker(document)) { + drawEffect = true; + effectImage.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", currentStickerSet, 1); + } } for (int a = 0; a < document.attributes.size(); a++) { TLRPC.DocumentAttribute attribute = document.attributes.get(a); @@ -776,15 +943,6 @@ public class ContentPreviewViewer { stickerEmojiLayout = new StaticLayout(emoji, textPaint, AndroidUtilities.dp(100), Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); } if (delegate.needMenu()) { - try { - if (visibleDialog != null) { - visibleDialog.setOnDismissListener(null); - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); AndroidUtilities.runOnUIThread(showSheetRunnable, 1300); } @@ -816,6 +974,13 @@ public class ContentPreviewViewer { AndroidUtilities.runOnUIThread(showSheetRunnable, 2000); } + if (centerImage.getLottieAnimation() != null) { + centerImage.getLottieAnimation().setCurrentFrame(0); + } + if (drawEffect && effectImage.getLottieAnimation() != null) { + effectImage.getLottieAnimation().setCurrentFrame(0); + } + currentContentType = contentType; currentDocument = document; importingSticker = sticker; @@ -853,27 +1018,31 @@ public class ContentPreviewViewer { return isVisible; } + public void closeWithMenu() { + menuVisible = false; + if (popupWindow != null) { + popupWindow.dismiss(); + popupWindow = null; + } + close(); + } + public void close() { - if (parentActivity == null || visibleDialog != null) { + if (parentActivity == null || menuVisible) { return; } AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); showProgress = 1.0f; lastUpdateTime = System.currentTimeMillis(); containerView.invalidate(); - try { - if (visibleDialog != null) { - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } currentDocument = null; currentStickerSet = null; currentQuery = null; delegate = null; isVisible = false; + if (unlockPremiumView != null) { + unlockPremiumView.animate().alpha(0).translationY(AndroidUtilities.dp(56)).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); + } NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 8); } @@ -883,17 +1052,15 @@ public class ContentPreviewViewer { currentDocument = null; currentQuery = null; currentStickerSet = null; - try { - if (visibleDialog != null) { - visibleDialog.dismiss(); - visibleDialog = null; - } - } catch (Exception e) { - FileLog.e(e); - } if (parentActivity == null || windowView == null) { return; } + if (blurrBitmap != null) { + blurrBitmap.recycle(); + blurrBitmap = null; + } + blurProgress = 0f; + menuVisible = false; try { if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); @@ -917,6 +1084,35 @@ public class ContentPreviewViewer { if (containerView == null || backgroundDrawable == null) { return; } + + if (menuVisible && blurrBitmap == null) { + prepareBlurBitmap(); + } + + if (blurrBitmap != null) { + if (menuVisible && blurProgress != 1f) { + blurProgress += 16 / 120f; + if (blurProgress > 1f) { + blurProgress = 1f; + } + containerView.invalidate(); + } else if (!menuVisible && blurProgress != 0f) { + blurProgress -= 16 / 120f; + if (blurProgress < 0f) { + blurProgress = 0f; + } + containerView.invalidate(); + } + + if (blurProgress != 0 && blurrBitmap != null) { + paint.setAlpha((int) (blurProgress * 255)); + canvas.save(); + canvas.scale(12f, 12f); + canvas.drawBitmap(blurrBitmap, 0, 0, paint); + canvas.restore(); + } + } + backgroundDrawable.setAlpha((int) (180 * showProgress)); backgroundDrawable.setBounds(0, 0, containerView.getWidth(), containerView.getHeight()); backgroundDrawable.draw(canvas); @@ -935,15 +1131,35 @@ public class ContentPreviewViewer { if (currentContentType == CONTENT_TYPE_GIF) { size = Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dp(40f); } else { - size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); + if (drawEffect) { + size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) - AndroidUtilities.dpf2(40f)); + } else { + size = (int) (Math.min(containerView.getWidth(), containerView.getHeight() - insets) / 1.8f); + } } - - canvas.translate(containerView.getWidth() / 2, moveY + Math.max(size / 2 + top + (stickerEmojiLayout != null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - insets - keyboardHeight) / 2)); + float topOffset = Math.max(size / 2 + top + (stickerEmojiLayout != null ? AndroidUtilities.dp(40) : 0), (containerView.getHeight() - insets - keyboardHeight) / 2); + if (drawEffect) { + topOffset += AndroidUtilities.dp(40); + } + canvas.translate(containerView.getWidth() / 2, moveY + topOffset); float scale = 0.8f * showProgress / 0.8f; size = (int) (size * scale); - centerImage.setAlpha(showProgress); - centerImage.setImageCoords(-size / 2, -size / 2, size, size); - centerImage.draw(canvas); + + if (drawEffect) { + float smallImageSize = size * 0.6669f; + float padding = size * 0.0546875f; + centerImage.setAlpha(showProgress); + centerImage.setImageCoords(size - smallImageSize - size / 2f - padding, (size - smallImageSize) / 2f - size / 2f, smallImageSize, smallImageSize); + centerImage.draw(canvas); + + effectImage.setAlpha(showProgress); + effectImage.setImageCoords(-size / 2f, -size / 2f, size, size); + effectImage.draw(canvas); + } else { + centerImage.setAlpha(showProgress); + centerImage.setImageCoords(-size / 2f, -size / 2f, size, size); + centerImage.draw(canvas); + } if (currentContentType == CONTENT_TYPE_GIF && slideUpDrawable != null) { int w = slideUpDrawable.getIntrinsicWidth(); @@ -954,7 +1170,11 @@ public class ContentPreviewViewer { slideUpDrawable.draw(canvas); } if (stickerEmojiLayout != null) { - canvas.translate(-AndroidUtilities.dp(50), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + if (drawEffect) { + canvas.translate(-AndroidUtilities.dp(50), -effectImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + } else { + canvas.translate(-AndroidUtilities.dp(50), -centerImage.getImageHeight() / 2 - AndroidUtilities.dp(30)); + } stickerEmojiLayout.draw(canvas); } canvas.restore(); @@ -982,6 +1202,12 @@ public class ContentPreviewViewer { centerImage.setImageBitmap((Drawable) null); AndroidUtilities.unlockOrientation(parentActivity); AndroidUtilities.runOnUIThread(() -> centerImage.setImageBitmap((Bitmap) null)); + if (blurrBitmap != null) { + blurrBitmap.recycle(); + blurrBitmap = null; + } + AndroidUtilities.updateViewVisibilityAnimated(unlockPremiumView, false, 1f, false); + blurProgress = 0f; try { if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); @@ -998,4 +1224,40 @@ public class ContentPreviewViewer { Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null; return color != null ? color : Theme.getColor(key); } + + private void prepareBlurBitmap() { + if (parentActivity == null) { + return; + } + View parentView = parentActivity.getWindow().getDecorView(); + int w = (int) (parentView.getMeasuredWidth() / 12.0f); + int h = (int) (parentView.getMeasuredHeight() / 12.0f); + Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + canvas.scale(1.0f / 12.0f, 1.0f / 12.0f); + canvas.drawColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + parentView.draw(canvas); + if (parentActivity instanceof LaunchActivity && ((LaunchActivity) parentActivity).getActionBarLayout().getLastFragment().getVisibleDialog() != null) { + ((LaunchActivity) parentActivity).getActionBarLayout().getLastFragment().getVisibleDialog().getWindow().getDecorView().draw(canvas); + } + Utilities.stackBlurBitmap(bitmap, Math.max(10, Math.max(w, h) / 180)); + blurrBitmap = bitmap; + } + + public boolean showMenuFor(View view) { + if (view instanceof StickerEmojiCell) { + Activity activity = AndroidUtilities.findActivity(view.getContext()); + if (activity == null) { + return true; + } + setParentActivity(activity); + StickerEmojiCell stickerEmojiCell = (StickerEmojiCell) view; + open(stickerEmojiCell.getSticker(), stickerEmojiCell.getStickerPath(), stickerEmojiCell.getEmoji(), delegate != null ? delegate.getQuery(false) : null, null, CONTENT_TYPE_STICKER, stickerEmojiCell.isRecent(), stickerEmojiCell.getParentObject(), resourcesProvider); + AndroidUtilities.cancelRunOnUIThread(showSheetRunnable); + AndroidUtilities.runOnUIThread(showSheetRunnable, 16); + stickerEmojiCell.setScaled(true); + return true; + } + return false; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java index 2658d00c0..4a6160713 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataAutoDownloadActivity.java @@ -582,8 +582,8 @@ public class DataAutoDownloadActivity extends BaseFragment { break; } } - int size1 = (video1 ? o1.sizes[index1] : 0) + (doc1 ? o1.sizes[index2] : 0); - int size2 = (video2 ? o2.sizes[index1] : 0) + (doc2 ? o2.sizes[index2] : 0); + long size1 = (video1 ? o1.sizes[index1] : 0) + (doc1 ? o1.sizes[index2] : 0); + long size2 = (video2 ? o2.sizes[index1] : 0) + (doc2 ? o2.sizes[index2] : 0); if (size1 > size2) { return 1; } else if (size1 < size2) { @@ -697,7 +697,7 @@ public class DataAutoDownloadActivity extends BaseFragment { } else { preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset(); } - int maxSize = preset.sizes[DownloadController.typeToIndex(type)]; + long maxSize = preset.sizes[DownloadController.typeToIndex(type)]; int count = 0; StringBuilder builder = new StringBuilder(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java index f9851fee6..4cb6c580c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java @@ -18,6 +18,9 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildVars; import org.telegram.messenger.DownloadController; @@ -48,9 +51,6 @@ import java.io.File; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - import kotlin.Unit; import tw.nekomimi.nekogram.ui.BottomBuilder; import tw.nekomimi.nekogram.NekoConfig; @@ -95,6 +95,12 @@ public class DataSettingsActivity extends BaseFragment { private int proxySection2Row; private int clearDraftsRow; private int clearDraftsSectionRow; + private int saveToGallerySectionRow; + private int saveToGalleryPeerRow; + private int saveToGalleryChannelsRow; + private int saveToGalleryGroupsRow; + private int saveToGalleryDividerRow; + private int rowCount; @Override @@ -115,6 +121,13 @@ public class DataSettingsActivity extends BaseFragment { roamingRow = rowCount++; resetDownloadRow = rowCount++; mediaDownloadSection2Row = rowCount++; + + saveToGallerySectionRow = rowCount++; + saveToGalleryPeerRow = rowCount++; + saveToGalleryGroupsRow = rowCount++; + saveToGalleryChannelsRow = rowCount++; + saveToGalleryDividerRow = rowCount++; + autoplayHeaderRow = rowCount++; autoplayGifsRow = rowCount++; autoplayVideoRow = rowCount++; @@ -129,6 +142,7 @@ public class DataSettingsActivity extends BaseFragment { enableMkvRow = -1; } enableAllStreamInfoRow = rowCount++; + enableCacheStreamRow = -1;//rowCount++; callsSectionRow = rowCount++; useLessDataForCallsRow = rowCount++; @@ -172,7 +186,19 @@ public class DataSettingsActivity extends BaseFragment { frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position, x, y) -> { - if (position == mobileRow || position == roamingRow || position == wifiRow) { + if (position == saveToGalleryGroupsRow || position == saveToGalleryChannelsRow || position == saveToGalleryPeerRow) { + int flag; + if (position == saveToGalleryGroupsRow) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_GROUP; + } else if (position == saveToGalleryChannelsRow) { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_CHANNELS; + } else { + flag = SharedConfig.SAVE_TO_GALLERY_FLAG_PEER; + } + SharedConfig.toggleSaveToGalleryFlag(flag); + TextCheckCell textCheckCell = (TextCheckCell) view; + textCheckCell.setChecked((SharedConfig.saveToGalleryFlags & flag) != 0); + } else if (position == mobileRow || position == roamingRow || position == wifiRow) { if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { boolean wasEnabled = listAdapter.isRowEnabled(resetDownloadRow); @@ -509,6 +535,8 @@ public class DataSettingsActivity extends BaseFragment { headerCell.setText(LocaleController.getString("Streaming", R.string.Streaming)); } else if (position == autoplayHeaderRow) { headerCell.setText(LocaleController.getString("AutoplayMedia", R.string.AutoplayMedia)); + } else if (position == saveToGallerySectionRow) { + headerCell.setText(LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); } break; } @@ -526,6 +554,12 @@ public class DataSettingsActivity extends BaseFragment { checkCell.setTextAndCheck(LocaleController.getString("AutoplayGIF", R.string.AutoplayGIF), SharedConfig.autoplayGifs, true); } else if (position == autoplayVideoRow) { checkCell.setTextAndCheck(LocaleController.getString("AutoplayVideo", R.string.AutoplayVideo), SharedConfig.autoplayVideo, false); + } else if (position == saveToGalleryPeerRow) { + checkCell.setTextAndCheck(LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate), (SharedConfig.saveToGalleryFlags & SharedConfig.SAVE_TO_GALLERY_FLAG_PEER) != 0, true); + } else if (position == saveToGalleryGroupsRow) { + checkCell.setTextAndCheck(LocaleController.getString("SaveToGalleryGroups", R.string.SaveToGalleryGroups), (SharedConfig.saveToGalleryFlags & SharedConfig.SAVE_TO_GALLERY_FLAG_GROUP) != 0, true); + } else if (position == saveToGalleryChannelsRow) { + checkCell.setTextAndCheck(LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels), (SharedConfig.saveToGalleryFlags & SharedConfig.SAVE_TO_GALLERY_FLAG_CHANNELS) != 0, false); } break; } @@ -633,7 +667,7 @@ public class DataSettingsActivity extends BaseFragment { } return position == mobileRow || position == roamingRow || position == wifiRow || position == storageUsageRow || position == useLessDataForCallsRow || position == dataUsageRow || position == proxyRow || position == clearDraftsRow || position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == quickRepliesRow || position == autoplayVideoRow || position == autoplayGifsRow || - position == storageNumRow; + position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow; } @Override @@ -676,11 +710,11 @@ public class DataSettingsActivity extends BaseFragment { @Override public int getItemViewType(int position) { - if (position == mediaDownloadSection2Row || position == usageSection2Row || position == callsSection2Row || position == proxySection2Row || position == autoplaySectionRow || position == clearDraftsSectionRow) { + if (position == mediaDownloadSection2Row || position == usageSection2Row || position == callsSection2Row || position == proxySection2Row || position == autoplaySectionRow || position == clearDraftsSectionRow || position == saveToGalleryDividerRow) { return 0; - } else if (position == mediaDownloadSectionRow || position == streamSectionRow || position == callsSectionRow || position == usageSectionRow || position == proxySectionRow || position == autoplayHeaderRow) { + } else if (position == mediaDownloadSectionRow || position == streamSectionRow || position == callsSectionRow || position == usageSectionRow || position == proxySectionRow || position == autoplayHeaderRow || position == saveToGallerySectionRow) { return 2; - } else if (position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == autoplayGifsRow || position == autoplayVideoRow) { + } else if (position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == autoplayGifsRow || position == autoplayVideoRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow) { return 3; } else if (position == enableAllStreamInfoRow) { return 4; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java b/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java index ca6c22aea..1a5360069 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DefaultThemesPreviewCell.java @@ -9,9 +9,11 @@ import android.content.Context; import android.content.SharedPreferences; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.drawable.RippleDrawable; import android.text.TextUtils; import android.view.Gravity; import android.view.View; +import android.view.Window; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -22,6 +24,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.tgnet.TLRPC; @@ -43,18 +46,22 @@ import java.util.ArrayList; public class DefaultThemesPreviewCell extends LinearLayout { private final RecyclerListView recyclerView; - private final LinearLayoutManager layoutManager; + private LinearLayoutManager layoutManager = null; private final FlickerLoadingView progressView; private final ChatThemeBottomSheet.Adapter adapter; RLottieDrawable darkThemeDrawable; TextCell dayNightCell; TextCell browseThemesCell; + private ValueAnimator navBarAnimator; + private int navBarColor; private int selectedPosition = -1; BaseFragment parentFragment; int currentType; int themeIndex; + private Boolean wasPortrait = null; + public DefaultThemesPreviewCell(Context context, BaseFragment parentFragment, int type) { super(context); this.currentType = type; @@ -67,24 +74,13 @@ public class DefaultThemesPreviewCell extends LinearLayout { adapter = new ChatThemeBottomSheet.Adapter(parentFragment.getCurrentAccount(), null, currentType == ThemeActivity.THEME_TYPE_BASIC ? ThemeSmallPreviewView.TYPE_DEFAULT : ThemeSmallPreviewView.TYPE_GRID); recyclerView = new RecyclerListView(getContext()); recyclerView.setAdapter(adapter); + recyclerView.setSelectorDrawableColor(0); recyclerView.setClipChildren(false); recyclerView.setClipToPadding(false); recyclerView.setHasFixedSize(true); recyclerView.setItemAnimator(null); recyclerView.setNestedScrollingEnabled(false); - if (currentType == ThemeActivity.THEME_TYPE_BASIC) { - recyclerView.setLayoutManager(layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); - } else { - recyclerView.setHasFixedSize(false); - GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), 3); - gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { - @Override - public int getSpanSize(int position) { - return 1; - } - }); - recyclerView.setLayoutManager(layoutManager = gridLayoutManager); - } + updateLayoutManager(); recyclerView.setFocusable(false); recyclerView.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0); @@ -159,6 +155,7 @@ public class DefaultThemesPreviewCell extends LinearLayout { darkThemeDrawable.commitApplyLayerColors(); dayNightCell = new TextCell(context); + dayNightCell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_listSelector), Theme.RIPPLE_MASK_ALL)); dayNightCell.imageLeft = 21; addView(dayNightCell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); @@ -175,6 +172,7 @@ public class DefaultThemesPreviewCell extends LinearLayout { return; } int iconOldColor = Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4); + int navBarOldColor = Theme.getColor(Theme.key_windowBackgroundGray); DrawerProfileCell.switchingTheme = true; SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("themeconfig", Activity.MODE_PRIVATE); String dayThemeName = preferences.getString("lastDayTheme", "Blue"); @@ -208,7 +206,7 @@ public class DefaultThemesPreviewCell extends LinearLayout { dayNightCell.getImageView().getLocationInWindow(pos); pos[0] += dayNightCell.getImageView().getMeasuredWidth() / 2; pos[1] += dayNightCell.getImageView().getMeasuredHeight() / 2 + AndroidUtilities.dp(3); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, pos, -1, toDark, dayNightCell.getImageView()); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, themeInfo, false, pos, -1, toDark, dayNightCell.getImageView(), dayNightCell); updateDayNightMode(); updateSelectedPosition(); @@ -219,8 +217,8 @@ public class DefaultThemesPreviewCell extends LinearLayout { valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { - int color = ColorUtils.blendARGB(iconOldColor, iconNewColor, (Float) valueAnimator.getAnimatedValue()); - darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN)); + int iconColor = ColorUtils.blendARGB(iconOldColor, iconNewColor, (float) valueAnimator.getAnimatedValue()); + darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(iconColor, PorterDuff.Mode.SRC_IN)); } }); valueAnimator.addListener(new AnimatorListenerAdapter() { @@ -233,6 +231,36 @@ public class DefaultThemesPreviewCell extends LinearLayout { valueAnimator.setDuration(350); valueAnimator.start(); + int navBarNewColor = Theme.getColor(Theme.key_windowBackgroundGray); + final Window window = context instanceof Activity ? ((Activity) context).getWindow() : null; + if (window != null) { + if (navBarAnimator != null && navBarAnimator.isRunning()) { + navBarOldColor = navBarColor; + navBarAnimator.cancel(); + } + final int navBarFromColor = navBarOldColor; + navBarAnimator = ValueAnimator.ofFloat(0, 1); + final float startDelay = toDark ? 50 : 200, duration = 150, fullDuration = 350; + navBarAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + float t = Math.max(0, Math.min(1, ((float) valueAnimator.getAnimatedValue() * fullDuration - startDelay) / duration)); + navBarColor = ColorUtils.blendARGB(navBarFromColor, navBarNewColor, t); + AndroidUtilities.setNavigationBarColor(window, navBarColor, false); + AndroidUtilities.setLightNavigationBar(window, AndroidUtilities.computePerceivedBrightness(navBarColor) >= 0.721f); + } + }); + navBarAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + AndroidUtilities.setNavigationBarColor(window, navBarNewColor, false); + AndroidUtilities.setLightNavigationBar(window, AndroidUtilities.computePerceivedBrightness(navBarNewColor) >= 0.721f); + } + }); + navBarAnimator.setDuration((long) fullDuration); + navBarAnimator.start(); + } + if (Theme.isCurrentThemeDay()) { dayNightCell.setTextAndIcon(LocaleController.getString("SettingsSwitchToNightMode", R.string.SettingsSwitchToNightMode), darkThemeDrawable, true); } else { @@ -254,8 +282,8 @@ public class DefaultThemesPreviewCell extends LinearLayout { } } - if (!Theme.defaultEmojiThemes.isEmpty()) { - ArrayList themes = new ArrayList<>(Theme.defaultEmojiThemes); + if (!MediaDataController.getInstance(parentFragment.getCurrentAccount()).defaultEmojiThemes.isEmpty()) { + ArrayList themes = new ArrayList<>(MediaDataController.getInstance(parentFragment.getCurrentAccount()).defaultEmojiThemes); if (currentType == ThemeActivity.THEME_TYPE_BASIC) { EmojiThemes chatTheme = EmojiThemes.createPreviewCustom(); @@ -270,11 +298,45 @@ public class DefaultThemesPreviewCell extends LinearLayout { updateDayNightMode(); updateSelectedPosition(); updateColors(); - if (selectedPosition >= 0) { + if (selectedPosition >= 0 && layoutManager != null) { layoutManager.scrollToPositionWithOffset(selectedPosition, AndroidUtilities.dp(16)); } } + public void updateLayoutManager() { + final boolean isPortrait = AndroidUtilities.displaySize.y > AndroidUtilities.displaySize.x; + if (wasPortrait != null && wasPortrait == isPortrait) { + return; + } + if (currentType == ThemeActivity.THEME_TYPE_BASIC) { + if (layoutManager == null) { + recyclerView.setLayoutManager(layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); + } + } else { + int spanCount = isPortrait ? 3 : 9; + if (layoutManager instanceof GridLayoutManager) { + ((GridLayoutManager) layoutManager).setSpanCount(spanCount); + } else { + recyclerView.setHasFixedSize(false); + GridLayoutManager gridLayoutManager = new GridLayoutManager(getContext(), spanCount); + gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override + public int getSpanSize(int position) { + return 1; + } + }); + recyclerView.setLayoutManager(layoutManager = gridLayoutManager); + } + } + wasPortrait = isPortrait; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + updateLayoutManager(); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + public void updateDayNightMode() { if (currentType == ThemeActivity.THEME_TYPE_BASIC) { themeIndex = !Theme.isCurrentThemeDay() ? 2 : 0; @@ -386,7 +448,7 @@ public class DefaultThemesPreviewCell extends LinearLayout { if (currentType == ThemeActivity.THEME_TYPE_BASIC) { darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4), PorterDuff.Mode.SRC_IN)); - dayNightCell.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector))); + Theme.setSelectorDrawableColor(dayNightCell.getBackground(), Theme.getColor(Theme.key_listSelector), true); browseThemesCell.setBackground(Theme.createSelectorWithBackgroundDrawable(Theme.getColor(Theme.key_windowBackgroundWhite), Theme.getColor(Theme.key_listSelector))); dayNightCell.setColors(null, Theme.key_windowBackgroundWhiteBlueText4); browseThemesCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); 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 5829fb6d8..9e506864c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Delegates/MemberRequestsDelegate.java @@ -709,7 +709,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener ActionBarMenuSubItem addCell = new ActionBarMenuSubItem(context, true, false); addCell.setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem, resourcesProvider), Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon, resourcesProvider)); addCell.setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector, resourcesProvider)); - addCell.setTextAndIcon(isChannel ? LocaleController.getString("AddToChannel", R.string.AddToChannel) : LocaleController.getString("AddToGroup", R.string.AddToGroup), R.drawable.actions_requests); + addCell.setTextAndIcon(isChannel ? LocaleController.getString("AddToChannel", R.string.AddToChannel) : LocaleController.getString("AddToGroup", R.string.AddToGroup), R.drawable.msg_requests); addCell.setOnClickListener((v) -> { if (importer != null) { onAddClicked(importer); @@ -738,7 +738,7 @@ public class MemberRequestsDelegate implements MemberRequestCell.OnClickListener ActionBarMenuSubItem dismissCell = new ActionBarMenuSubItem(context, false, true); dismissCell.setColors(Theme.getColor(Theme.key_dialogTextRed2, resourcesProvider), Theme.getColor(Theme.key_dialogRedIcon, resourcesProvider)); dismissCell.setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector, resourcesProvider)); - dismissCell.setTextAndIcon(LocaleController.getString("DismissRequest", R.string.DismissRequest), R.drawable.actions_remove_user); + dismissCell.setTextAndIcon(LocaleController.getString("DismissRequest", R.string.DismissRequest), R.drawable.msg_remove); dismissCell.setOnClickListener((v) -> { if (importer != null) { onDismissClicked(importer); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index 554414e67..dd142d6a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -43,7 +43,6 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.Vibrator; import android.text.TextPaint; import android.text.TextUtils; import android.util.Property; @@ -119,6 +118,7 @@ import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.BottomSheet; import org.telegram.ui.ActionBar.MenuDrawable; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -167,6 +167,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.MediaActionDrawable; import org.telegram.ui.Components.NumberTextView; import org.telegram.ui.Components.PacmanAnimation; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.ProxyDrawable; import org.telegram.ui.Components.PullForegroundDrawable; import org.telegram.ui.Components.RLottieDrawable; @@ -199,6 +200,7 @@ import tw.nekomimi.nekogram.utils.UpdateUtil; import tw.nekomimi.nekogram.utils.VibrateUtil; public class DialogsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + public final static int DIALOGS_TYPE_START_ATTACH_BOT = 14; private boolean canShowFilterTabsView; private boolean filterTabsViewIsVisible; @@ -221,6 +223,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private int lastItemsCount; private DialogsItemAnimator dialogsItemAnimator; private RecyclerItemsEnterAnimator recyclerItemsEnterAnimator; + private boolean isLocked; public ViewPage(Context context) { super(context); @@ -259,9 +262,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private View blurredView; private Paint scrimPaint; + private Drawable scrimViewBackground; private View scrimView; private boolean scrimViewSelected; private int[] scrimViewLocation = new int[2]; + private boolean scrimViewAppearing; private AnimatorSet scrimAnimatorSet; private ActionBarPopupWindow scrimPopupWindow; private ActionBarMenuSubItem[] scrimPopupWindowItems; @@ -376,6 +381,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private boolean afterSignup; private boolean showSetPasswordConfirm; private int otherwiseReloginDays; + private boolean allowGroups; + private boolean allowChannels; + private boolean allowUsers; + private boolean allowBots; private boolean closeFragment; // private FrameLayout updateLayout; @@ -452,6 +461,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. private float scrollAdditionalOffset; private int debugLastUpdateAction = -1; + private boolean slowedReloadAfterDialogClick; public final Property SCROLL_Y = new AnimationProperties.FloatProperty("animationValue") { @Override @@ -725,6 +735,19 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. canvas.save(); getLocationInWindow(pos); canvas.translate(scrimViewLocation[0] - pos[0], scrimViewLocation[1] - (Build.VERSION.SDK_INT < 21 ? AndroidUtilities.statusBarHeight : 0)); + if (scrimViewBackground != null) { + scrimViewBackground.setAlpha(scrimViewAppearing ? 255 : (int) (scrimPaint.getAlpha() / 50f * 255f)); + scrimViewBackground.setBounds(0, 0, scrimView.getWidth(), scrimView.getHeight()); + scrimViewBackground.draw(canvas); + } + Drawable selectorDrawable = filterTabsView.getListView().getSelectorDrawable(); + if (scrimViewAppearing && selectorDrawable != null) { + canvas.save(); + Rect selectorBounds = selectorDrawable.getBounds(); + canvas.translate(-selectorBounds.left, -selectorBounds.top); + selectorDrawable.draw(canvas); + canvas.restore(); + } scrimView.draw(canvas); if (scrimViewSelected) { Drawable drawable = filterTabsView.getSelectorDrawable(); @@ -804,7 +827,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { child.setTranslationY(0); } - int transitionPadding = (isSlideBackTransition || isDrawerTransition) ? (int) (h * 0.05f) : 0; + int transitionPadding = ((isSlideBackTransition || isDrawerTransition) ? (int) (h * 0.05f) : 0); h += transitionPadding; child.setPadding(child.getPaddingLeft(), child.getPaddingTop(), child.getPaddingRight(), transitionPadding); child.measure(contentWidthSpec, View.MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), h), View.MeasureSpec.EXACTLY)); @@ -844,6 +867,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { paddingBottom = 0; } + setBottomClip(paddingBottom); lastMeasuredTopPadding = topPadding; @@ -1031,7 +1055,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPages[1].setTranslationX(dx - viewPages[0].getMeasuredWidth()); } float scrollProgress = Math.abs(dx) / (float) viewPages[0].getMeasuredWidth(); - filterTabsView.selectTabWithId(viewPages[1].selectedType, scrollProgress); + if (viewPages[1].isLocked && scrollProgress > 0.3f) { + dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0)); + filterTabsView.shakeLock(viewPages[1].selectedType); + AndroidUtilities.runOnUIThread(() -> { + showDialog(new LimitReachedBottomSheet(DialogsActivity.this, getContext(), LimitReachedBottomSheet.TYPE_FOLDERS, currentAccount)); + }, 200); + return false; + } else { + filterTabsView.selectTabWithId(viewPages[1].selectedType, scrollProgress); + } } } else if (ev == null || ev.getPointerId(0) == startedTrackingPointerId && (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_POINTER_UP)) { velocityTracker.computeCurrentVelocity(1000, maximumVelocity); @@ -1052,20 +1085,23 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (startedTracking) { float x = viewPages[0].getX(); tabsAnimation = new AnimatorSet(); - if (additionalOffset != 0) { - if (Math.abs(velX) > 1500) { - backAnimation = animatingForward ? velX > 0 : velX < 0; - } else { - if (animatingForward) { - backAnimation = (viewPages[1].getX() > (viewPages[0].getMeasuredWidth() >> 1)); - } else { - backAnimation = (viewPages[0].getX() < (viewPages[0].getMeasuredWidth() >> 1)); - } - } + if (viewPages[1].isLocked) { + backAnimation = true; } else { - backAnimation = Math.abs(x) < viewPages[0].getMeasuredWidth() / 3.0f && (Math.abs(velX) < 3500 || Math.abs(velX) < Math.abs(velY)); + if (additionalOffset != 0) { + if (Math.abs(velX) > 1500) { + backAnimation = animatingForward ? velX > 0 : velX < 0; + } else { + if (animatingForward) { + backAnimation = (viewPages[1].getX() > (viewPages[0].getMeasuredWidth() >> 1)); + } else { + backAnimation = (viewPages[0].getX() < (viewPages[0].getMeasuredWidth() >> 1)); + } + } + } else { + backAnimation = Math.abs(x) < viewPages[0].getMeasuredWidth() / 3.0f && (Math.abs(velX) < 3500 || Math.abs(velX) < Math.abs(velY)); + } } - float distToMove; float dx; if (backAnimation) { dx = Math.abs(x); @@ -1889,6 +1925,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. hasInvoice = arguments.getBoolean("hasInvoice", false); showSetPasswordConfirm = arguments.getBoolean("showSetPasswordConfirm", showSetPasswordConfirm); otherwiseReloginDays = arguments.getInt("otherwiseRelogin"); + allowGroups = arguments.getBoolean("allowGroups", true); + allowChannels = arguments.getBoolean("allowChannels", true); + allowUsers = arguments.getBoolean("allowUsers", true); + allowBots = arguments.getBoolean("allowBots", true); closeFragment = arguments.getBoolean("closeFragment", true); } @@ -1961,11 +2001,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. messagesController.loadHintDialogs(); messagesController.loadUserInfo(accountInstance.getUserConfig().getCurrentUser(), false, 0); accountInstance.getContactsController().checkInviteText(); - accountInstance.getMediaDataController().loadRecents(MediaDataController.TYPE_FAVE, false, true, false); - accountInstance.getMediaDataController().loadRecents(MediaDataController.TYPE_GREETINGS, false, true, false); - accountInstance.getMediaDataController().checkFeaturedStickers(); - accountInstance.getMediaDataController().checkReactions(); - accountInstance.getMediaDataController().checkMenuBots(); + accountInstance.getMediaDataController().chekAllMedia(false); AndroidUtilities.runOnUIThread(() -> accountInstance.getDownloadController().loadDownloadingFiles(), 200); for (String emoji : messagesController.diceEmojies) { accountInstance.getMediaDataController().loadStickersByEmojiOrName(emoji, true, true); @@ -2099,7 +2135,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. downloadsItem = menu.addItem(3, new ColorDrawable(Color.TRANSPARENT)); downloadsItem.addView(new DownloadProgressIcon(currentAccount, context)); - downloadsItem.setContentDescription(LocaleController.getString("AccDescrPasscodeLock", R.string.AccDescrPasscodeLock)); + downloadsItem.setContentDescription(LocaleController.getString("DownloadsTabs", R.string.DownloadsTabs)); downloadsItem.setVisibility(View.GONE); updatePasscodeButton(); @@ -2190,7 +2226,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } actionBar.setBackButtonContentDescription(LocaleController.getString("AccDescrOpenMenu", R.string.AccDescrOpenMenu)); } - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); ((SizeNotifierFrameLayout) fragmentView).invalidateBlur(); } @@ -2222,6 +2258,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return !actionBar.isActionModeShowed() && databaseMigrationHint == null; } }); + if (initialDialogsType == 2 || initialDialogsType == DIALOGS_TYPE_START_ATTACH_BOT) { + searchItem.setVisibility(View.GONE); + } searchItem.setSearchFieldHint(LocaleController.getString("Search", R.string.Search)); searchItem.setContentDescription(LocaleController.getString("Search", R.string.Search)); if (onlySelect) { @@ -2331,12 +2370,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { })); -// if (getMessagesController().dialogFilters.size() > 1) { -// filterTabsView.beginCrossfade(); -// } getMessagesController().removeFilter(dialogFilter); getMessagesStorage().deleteDialogFilter(dialogFilter); - // filterTabsView.commitCrossfade(); }); AlertDialog alertDialog = builder.create(); showDialog(alertDialog); @@ -2363,18 +2398,24 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } @Override - public void onPageSelected(int id, boolean forward) { - if (viewPages[0].selectedType == id) { + public void onPageSelected(FilterTabsView.Tab tab, boolean forward) { + if (viewPages[0].selectedType == tab.id) { return; } + if (tab.isLocked) { + filterTabsView.shakeLock(tab.id); + showDialog(new LimitReachedBottomSheet(DialogsActivity.this, context, LimitReachedBottomSheet.TYPE_FOLDERS, currentAccount)); + return; + } + ArrayList dialogFilters = getMessagesController().dialogFilters; - if (id != Integer.MAX_VALUE && (id < 0 || id >= dialogFilters.size())) { + if (!tab.isDefault && (tab.id < 0 || tab.id >= dialogFilters.size())) { return; } if (parentLayout != null) { - parentLayout.getDrawerLayoutContainer().setAllowOpenDrawerBySwipe(id == filterTabsView.getFirstTabId() || SharedConfig.getChatSwipeAction(currentAccount) != SwipeGestureSettingsView.SWIPE_GESTURE_FOLDERS); + parentLayout.getDrawerLayoutContainer().setAllowOpenDrawerBySwipe(tab.id == filterTabsView.getFirstTabId() || SharedConfig.getChatSwipeAction(currentAccount) != SwipeGestureSettingsView.SWIPE_GESTURE_FOLDERS); } - viewPages[1].selectedType = id; + viewPages[1].selectedType = tab.id; viewPages[1].setVisibility(View.VISIBLE); viewPages[1].setTranslationX(viewPages[0].getMeasuredWidth()); showScrollbars(false); @@ -2414,7 +2455,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public int getTabCounter(int tabId) { - if (tabId == Integer.MAX_VALUE) { + if (tabId == filterTabsView.getDefaultTabId()) { return getMessagesStorage().getMainUnreadCount(); } ArrayList dialogFilters = getMessagesController().dialogFilters; @@ -2438,7 +2479,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. Rect rect = new Rect(); MessagesController.DialogFilter dialogFilter; - if (tabView.getId() == Integer.MAX_VALUE) { + if (tabView.getId() == filterTabsView.getDefaultTabId()) { dialogFilter = null; } else { dialogFilter = getMessagesController().dialogFilters.get(tabView.getId()); @@ -2498,7 +2539,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. linearLayout.setMinimumWidth(AndroidUtilities.dp(200)); linearLayout.setOrientation(LinearLayout.VERTICAL); scrimPopupWindowItems = new ActionBarMenuSubItem[4]; - for (int a = 0, N = (tabView.getId() == Integer.MAX_VALUE ? 3 : 4); a < 4; a++) { + for (int a = 0, N = (tabView.getId() == filterTabsView.getDefaultTabId() ? 3 : 4); a < 4; a++) { ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getParentActivity(), a == 0, a == N - 1); if (a == 0) { if (getMessagesController().dialogFilters.size() <= 1) continue; @@ -2568,6 +2609,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. scrimAnimatorSet = null; } scrimAnimatorSet = new AnimatorSet(); + scrimViewAppearing = false; ArrayList animators = new ArrayList<>(); animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0)); scrimAnimatorSet.playTogether(animators); @@ -2590,7 +2632,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } }; - tabView.setBackground(Theme.createRoundRectDrawable(AndroidUtilities.dp(6), 0, Theme.getColor(Theme.key_actionBarDefault))); + scrimViewBackground = Theme.createRoundRectDrawable(AndroidUtilities.dp(6), 0, Theme.getColor(Theme.key_actionBarDefault)); scrimPopupWindow.setDismissAnimationDuration(220); scrimPopupWindow.setOutsideTouchable(true); scrimPopupWindow.setClippingEnabled(true); @@ -2617,6 +2659,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. scrimAnimatorSet.cancel(); } scrimAnimatorSet = new AnimatorSet(); + scrimViewAppearing = true; ArrayList animators = new ArrayList<>(); animators.add(ObjectAnimator.ofInt(scrimPaint, AnimationProperties.PAINT_ALPHA, 0, 50)); scrimAnimatorSet.playTogether(animators); @@ -2650,7 +2693,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. TLRPC.User user = getUserConfig().getCurrentUser(); avatarDrawable.setInfo(user); imageView.getImageReceiver().setCurrentAccount(currentAccount); - imageView.setImage(ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_STRIPPED), "50_50", avatarDrawable, user); + Drawable thumb = user != null && user.photo != null && user.photo.strippedBitmap != null ? user.photo.strippedBitmap : avatarDrawable; + imageView.setImage(ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL), "50_50", ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_STRIPPED), "50_50", thumb, user); int accounts = 0; for (int a : SharedConfig.activeAccounts) { @@ -2691,7 +2735,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. filterTabsView.selectTabWithId(viewPages[1].selectedType, scrollProgress); } } - ((SizeNotifierFrameLayout) contentView).invalidateBlur(); + contentView.invalidateBlur(); } } }; @@ -2934,7 +2978,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPage.addView(viewPage.listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); viewPage.listView.setOnItemClickListener((view, position) -> { if (initialDialogsType == 10) { - onItemLongClick(view, position, 0, 0, viewPage.dialogsType, viewPage.dialogsAdapter); + onItemLongClick(viewPage.listView, view, position, 0, 0, viewPage.dialogsType, viewPage.dialogsAdapter); return; } else if ((initialDialogsType == 11 || initialDialogsType == 13) && position == 1) { Bundle args = new Bundle(); @@ -2980,17 +3024,21 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE && filterTabsView.isEditing()) { return false; } - return onItemLongClick(view, position, x, y, viewPage.dialogsType, viewPage.dialogsAdapter); - } - - @Override - public void onLongClickRelease() { - finishPreviewFragment(); + return onItemLongClick(viewPage.listView, view, position, x, y, viewPage.dialogsType, viewPage.dialogsAdapter); } @Override public void onMove(float dx, float dy) { - movePreviewFragment(dy); + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + movePreviewFragment(dy); + } + } + + @Override + public void onLongClickRelease() { + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + finishPreviewFragment(); + } } }); viewPage.swipeController = new SwipeController(viewPage); @@ -3153,18 +3201,22 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } searchViewPager = new SearchViewPager(context, this, type, initialDialogsType, folderId, new SearchViewPager.ChatPreviewDelegate() { @Override - public void startChatPreview(DialogCell cell) { + public void startChatPreview(RecyclerListView listView, DialogCell cell) { showChatPreview(cell); } @Override public void move(float dy) { - movePreviewFragment(dy); + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + movePreviewFragment(dy); + } } @Override public void finish() { - finishPreviewFragment(); + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + finishPreviewFragment(); + } } }); contentView.addView(searchViewPager); @@ -3253,15 +3305,23 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. @Override public void needClearList() { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("ClearSearchAlertTitle", R.string.ClearSearchAlertTitle)); - builder.setMessage(LocaleController.getString("ClearSearchAlert", R.string.ClearSearchAlert)); - builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> { - if (searchViewPager.dialogsSearchAdapter.isRecentSearchDisplayed()) { + if (searchViewPager.dialogsSearchAdapter.isSearchWas() && searchViewPager.dialogsSearchAdapter.isRecentSearchDisplayed()) { + builder.setTitle(LocaleController.getString("ClearSearchAlertPartialTitle", R.string.ClearSearchAlertPartialTitle)); + builder.setMessage(LocaleController.formatPluralString("ClearSearchAlertPartial", searchViewPager.dialogsSearchAdapter.getRecentResultsCount())); + builder.setPositiveButton(LocaleController.getString("Clear", R.string.Clear).toUpperCase(), (dialogInterface, i) -> { searchViewPager.dialogsSearchAdapter.clearRecentSearch(); - } else { - searchViewPager.dialogsSearchAdapter.clearRecentHashtags(); - } - }); + }); + } else { + builder.setTitle(LocaleController.getString("ClearSearchAlertTitle", R.string.ClearSearchAlertTitle)); + builder.setMessage(LocaleController.getString("ClearSearchAlert", R.string.ClearSearchAlert)); + builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> { + if (searchViewPager.dialogsSearchAdapter.isRecentSearchDisplayed()) { + searchViewPager.dialogsSearchAdapter.clearRecentSearch(); + } else { + searchViewPager.dialogsSearchAdapter.clearRecentHashtags(); + } + }); + } builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); AlertDialog dialog = builder.create(); showDialog(dialog); @@ -3286,7 +3346,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searchViewPager.searchListView.setOnItemClickListener((view, position) -> { if (initialDialogsType == 10) { - onItemLongClick(view, position, 0, 0, -1, searchViewPager.dialogsSearchAdapter); + onItemLongClick(searchViewPager.searchListView, view, position, 0, 0, -1, searchViewPager.dialogsSearchAdapter); return; } onItemClick(view, position, searchViewPager.dialogsSearchAdapter); @@ -3294,17 +3354,21 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searchViewPager.searchListView.setOnItemLongClickListener(new RecyclerListView.OnItemLongClickListenerExtended() { @Override public boolean onItemClick(View view, int position, float x, float y) { - return onItemLongClick(view, position, x, y, -1, searchViewPager.dialogsSearchAdapter); - } - - @Override - public void onLongClickRelease() { - finishPreviewFragment(); + return onItemLongClick(searchViewPager.searchListView, view, position, x, y, -1, searchViewPager.dialogsSearchAdapter); } @Override public void onMove(float dx, float dy) { - movePreviewFragment(dy); + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + movePreviewFragment(dy); + } + } + + @Override + public void onLongClickRelease() { + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + finishPreviewFragment(); + } } }); @@ -3323,6 +3387,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. floatingButtonContainer.setVisibility(onlySelect && initialDialogsType != 10 || folderId != 0 ? View.GONE : View.VISIBLE); contentView.addView(floatingButtonContainer, LayoutHelper.createFrame((Build.VERSION.SDK_INT >= 21 ? 56 : 60), (Build.VERSION.SDK_INT >= 21 ? 56 : 60), (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.BOTTOM, LocaleController.isRTL ? 14 : 0, 0, LocaleController.isRTL ? 0 : 14, 14)); floatingButtonContainer.setOnClickListener(v -> { + if (parentLayout != null && parentLayout.isInPreviewMode()) { + finishPreviewFragment(); + return; + } if (initialDialogsType == 10) { if (delegate == null || selectedDialogs.isEmpty()) { return; @@ -3414,7 +3482,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } return super.dispatchTouchEvent(ev); } - @Override + @Override public void setTranslationY(float translationY) { super.setTranslationY(translationY); if (!commentViewAnimated) { @@ -3434,8 +3502,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. contentView.setClipChildren(false); contentView.setClipToPadding(false); commentView.allowBlur = false; + commentView.forceSmoothKeyboard(true); commentView.setAllowStickersAndGifs(false, false); commentView.setForceShowSendButton(true, false); + commentView.setPadding(0, 0, AndroidUtilities.dp(20), 0); commentView.setVisibility(View.GONE); commentView.getSendButton().setAlpha(0); commentViewBg = new View(getParentActivity()); @@ -3650,7 +3720,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. writeButton = new ImageView[2]; for (int a = 0; a < 2; ++a) { writeButton[a] = new ImageView(context); - writeButton[a].setImageResource(a == 1 ? R.drawable.actionbtn_next : R.drawable.attach_send); + writeButton[a].setImageResource(a == 1 ? R.drawable.msg_arrow_forward : R.drawable.attach_send); writeButton[a].setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingIcon), PorterDuff.Mode.MULTIPLY)); writeButton[a].setScaleType(ImageView.ScaleType.CENTER); writeButtonBackground.addView(writeButton[a], LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 56 : 60, Build.VERSION.SDK_INT >= 21 ? 56 : 60, Gravity.CENTER)); @@ -3755,7 +3825,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } }; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + blurredView.setForeground(new ColorDrawable(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundWhite), 100))); + } + blurredView.setFocusable(false); + blurredView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); + blurredView.setOnClickListener(e -> { + finishPreviewFragment(); + }); blurredView.setVisibility(View.GONE); + blurredView.setFitsSystemWindows(true); contentView.addView(blurredView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); } @@ -4052,8 +4131,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { currentCount = 0; } - if (currentCount + alwaysShow.size() > 100) { - showDialog(AlertsCreator.createSimpleAlert(getParentActivity(), LocaleController.getString("FilterAddToAlertFullTitle", R.string.FilterAddToAlertFullTitle), LocaleController.getString("FilterRemoveFromAlertFullText", R.string.FilterRemoveFromAlertFullText)).create()); + int totalCount = currentCount + alwaysShow.size(); + if ((totalCount > getMessagesController().dialogFiltersChatsLimitDefault && !getUserConfig().isPremium()) || totalCount > getMessagesController().dialogFiltersChatsLimitPremium) { + showDialog(new LimitReachedBottomSheet(DialogsActivity.this, fragmentView.getContext(), LimitReachedBottomSheet.TYPE_CHATS_IN_FOLDER, currentAccount)); return; } if (filter != null) { @@ -4123,11 +4203,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. int a = animated ? 1 : 0; RecyclerView.Adapter currentAdapter = viewPages[a].listView.getAdapter(); - if (viewPages[a].selectedType == Integer.MAX_VALUE) { + MessagesController.DialogFilter filter = getMessagesController().dialogFilters.get(viewPages[a].selectedType); + if (filter.isDefault()) { viewPages[a].dialogsType = initialDialogsType; viewPages[a].listView.updatePullState(); } else { - MessagesController.DialogFilter filter = getMessagesController().dialogFilters.get(viewPages[a].selectedType); if (viewPages[a == 0 ? 1 : 0].dialogsType == 7) { viewPages[a].dialogsType = 8; } else { @@ -4136,6 +4216,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPages[a].listView.setScrollEnabled(true); getMessagesController().selectDialogFilter(filter, viewPages[a].dialogsType == 8 ? 1 : 0); } + viewPages[1].isLocked = filter.locked; + viewPages[a].dialogsAdapter.setDialogsType(viewPages[a].dialogsType); viewPages[a].layoutManager.scrollToPositionWithOffset(viewPages[a].dialogsType == 0 && hasHiddenArchive() ? 1 : 0, (int) actionBar.getTranslationY()); checkListLoad(viewPages[a]); @@ -4182,7 +4264,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } ArrayList filters = getMessagesController().dialogFilters; SharedPreferences preferences = MessagesController.getMainSettings(currentAccount); - if (!filters.isEmpty()) { + if (filters.size() > 1) { if (force || filterTabsView.getVisibility() != View.VISIBLE) { boolean animatedUpdateItems = animated; if (filterTabsView.getVisibility() != View.VISIBLE) { @@ -4191,7 +4273,8 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. canShowFilterTabsView = true; updateFilterTabsVisibility(animated); int id = filterTabsView.getCurrentTabId(); - if (id != Integer.MAX_VALUE && id >= filters.size()) { + int stableId = filterTabsView.getCurrentTabStableId(); + if (id != filterTabsView.getDefaultTabId() && id >= filters.size()) { filterTabsView.resetTabId(); } filterTabsView.removeTabs(); @@ -4199,28 +4282,30 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. filterTabsView.addTab(Integer.MAX_VALUE, 0, LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); for (int a = 0, N = filters.size(); a < N; a++) { MessagesController.DialogFilter dialogFilter = filters.get(a); - switch (NekoConfig.tabsTitleType.Int()) { - case NekoXConfig.TITLE_TYPE_TEXT: - filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.name); - break; - case NekoXConfig.TITLE_TYPE_ICON: - filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.emoticon != null ? dialogFilter.emoticon : "📂"); - break; - case NekoXConfig.TITLE_TYPE_MIX: - filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.emoticon != null ? dialogFilter.emoticon + " " + dialogFilter.name : "📂 " + dialogFilter.name); - break; - } + if (filters.get(a).isDefault()) { + filterTabsView.addTab(a, 0, LocaleController.getString("FilterAllChats", R.string.FilterAllChats), true, filters.get(a).locked); + } else { + switch (NekoConfig.tabsTitleType.Int()) { + case NekoXConfig.TITLE_TYPE_TEXT: + filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.name); + break; + case NekoXConfig.TITLE_TYPE_ICON: + filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.emoticon != null ? dialogFilter.emoticon : "📂"); + break; + case NekoXConfig.TITLE_TYPE_MIX: + filterTabsView.addTab(a, filters.get(a).localId, dialogFilter.emoticon != null ? dialogFilter.emoticon + " " + dialogFilter.name : "📂 " + dialogFilter.name); + break; + } } } - id = filterTabsView.getCurrentTabId(); boolean updateCurrentTab = NekoConfig.hideAllTab.Bool(); - if (id >= 0) { - if (viewPages[0].selectedType != id) { + if (stableId >= 0) { + if (filterTabsView.getStableId(viewPages[0].selectedType) != stableId) { updateCurrentTab = true; viewPages[0].selectedType = id; } } for (int a = 0; a < viewPages.length; a++) { - if (viewPages[a].selectedType != Integer.MAX_VALUE && viewPages[a].selectedType >= filters.size()) { + if (viewPages[a].selectedType >= filters.size()) { viewPages[a].selectedType = filters.size(); } viewPages[a].listView.setScrollingTouchSlop(RecyclerView.TOUCH_SLOP_PAGING); @@ -4232,6 +4317,9 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (parentLayout != null) { parentLayout.getDrawerLayoutContainer().setAllowOpenDrawerBySwipe(id == filterTabsView.getFirstTabId() || SharedConfig.getChatSwipeAction(currentAccount) != SwipeGestureSettingsView.SWIPE_GESTURE_FOLDERS); } + if (filterTabsView.isLocked(filterTabsView.getCurrentTabId())) { + filterTabsView.selectFirstTab(); + } } } else { if (filterTabsView.getVisibility() != View.GONE) { @@ -4244,14 +4332,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPages[0].setTranslationX(0); viewPages[1].setTranslationX(viewPages[0].getMeasuredWidth()); } - if (viewPages[0].selectedType != Integer.MAX_VALUE) { - viewPages[0].selectedType = Integer.MAX_VALUE; + if (viewPages[0].selectedType != filterTabsView.getDefaultTabId()) { + viewPages[0].selectedType = filterTabsView.getDefaultTabId(); viewPages[0].dialogsAdapter.setDialogsType(initialDialogsType); viewPages[0].dialogsType = initialDialogsType; viewPages[0].dialogsAdapter.notifyDataSetChanged(); } viewPages[1].setVisibility(View.GONE); - viewPages[1].selectedType = Integer.MAX_VALUE; + viewPages[1].selectedType = 0; viewPages[1].dialogsAdapter.setDialogsType(initialDialogsType); viewPages[1].dialogsType = initialDialogsType; viewPages[1].dialogsAdapter.notifyDataSetChanged(); @@ -4492,7 +4580,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } return false; } else if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE && !tabsAnimationInProgress && !filterTabsView.isAnimatingIndicator() - && filterTabsView.getCurrentTabId() != Integer.MAX_VALUE && !startedTracking) { + && !startedTracking && !filterTabsView.isFirstTabSelected()) { if(!NekoConfig.hideAllTab.Bool()){ filterTabsView.selectFirstTab(); return false; @@ -4649,7 +4737,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. searchViewPager.clear(); if (folderId != 0) { - FiltersView.MediaFilterData filterData = new FiltersView.MediaFilterData(R.drawable.chats_archive, R.drawable.chats_archive, LocaleController.getString("ArchiveSearchFilter", R.string.ArchiveSearchFilter), null, FiltersView.FILTER_TYPE_ARCHIVE); + FiltersView.MediaFilterData filterData = new FiltersView.MediaFilterData(R.drawable.chats_archive, LocaleController.getString("ArchiveSearchFilter", R.string.ArchiveSearchFilter), null, FiltersView.FILTER_TYPE_ARCHIVE); addSearchFilter(filterData); } } else { @@ -5071,7 +5159,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (index > 0) { hash = hash.substring(index + 1); } - showDialog(new JoinGroupAlert(getParentActivity(), invite, hash, DialogsActivity.this)); + showDialog(new JoinGroupAlert(getParentActivity(), invite, hash, DialogsActivity.this, null)); return; } else { if (invite.chat != null) { @@ -5218,6 +5306,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. presentFragment(new ChatActivity(args)); } } else { + slowedReloadAfterDialogClick = true; if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { ChatActivity chatActivity = new ChatActivity(args); if (adapter instanceof DialogsAdapter && DialogObject.isUserDialog(dialogId) && (getMessagesController().dialogs_dict.get(dialogId) == null)) { @@ -5232,7 +5321,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } - private boolean onItemLongClick(View view, int position, float x, float y, int dialogsType, RecyclerListView.Adapter adapter) { + private boolean onItemLongClick(RecyclerListView listView, View view, int position, float x, float y, int dialogsType, RecyclerListView.Adapter adapter) { if (getParentActivity() == null) { return false; } @@ -5244,7 +5333,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } if (adapter == searchViewPager.dialogsSearchAdapter) { Object item = searchViewPager.dialogsSearchAdapter.getItem(position); - if (searchViewPager.dialogsSearchAdapter.isRecentSearchDisplayed()) { + if (!searchViewPager.dialogsSearchAdapter.isSearchWas()) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("ClearSearchSingleAlertTitle", R.string.ClearSearchSingleAlertTitle)); long did; @@ -5320,39 +5409,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return true; } else { if (dialog instanceof TLRPC.TL_dialogFolder) { - if (!NekoConfig.disableVibration.Bool()) { - view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); - } - BottomBuilder builder = new BottomBuilder(getParentActivity()); - final boolean hasUnread = getMessagesStorage().getArchiveUnreadCount() != 0; - - int[] icons = new int[]{ - hasUnread ? R.drawable.baseline_done_all_24 : 0, - SharedConfig.archiveHidden ? R.drawable.deproko_baseline_pin_24 : R.drawable.deproko_baseline_pin_undo_24, - }; - String[] items = new String[]{ - hasUnread ? LocaleController.getString("MarkAllAsRead", R.string.MarkAllAsRead) : null, - SharedConfig.archiveHidden ? LocaleController.getString("PinInTheList", R.string.PinInTheList) : LocaleController.getString("HideAboveTheList", R.string.HideAboveTheList) - }; - builder.addItems(items, icons, (which, t, c) -> { - if (which == 0) { - getMessagesStorage().readAllDialogs(1); - } else if (which == 1 && viewPages != null) { - for (int a = 0; a < viewPages.length; a++) { - if (viewPages[a].dialogsType != 0 || viewPages[a].getVisibility() != View.VISIBLE) { - continue; - } - View child = viewPages[a].listView.getChildAt(0); - DialogCell dialogCell = null; - if (child instanceof DialogCell && ((DialogCell) child).isFolderCell()) { - dialogCell = (DialogCell) child; - } - viewPages[a].listView.toggleArchiveHidden(true, dialogCell); - } - } - return Unit.INSTANCE; - }); - showDialog(builder.create()); + onArchiveLongPress(view); return false; } if (actionBar.isActionModeShowed() && isDialogPinned(dialog)) { @@ -5363,6 +5420,41 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } + private void onArchiveLongPress(View view) { + if (!NekoConfig.disableVibration.Bool()) { + view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity()); + final boolean hasUnread = getMessagesStorage().getArchiveUnreadCount() != 0; + + int[] icons = new int[]{ + hasUnread ? R.drawable.baseline_done_all_24 : 0, + SharedConfig.archiveHidden ? R.drawable.deproko_baseline_pin_24 : R.drawable.deproko_baseline_pin_undo_24, + }; + CharSequence[] items = new CharSequence[]{ + hasUnread ? LocaleController.getString("MarkAllAsRead", R.string.MarkAllAsRead) : null, + SharedConfig.archiveHidden ? LocaleController.getString("PinInTheList", R.string.PinInTheList) : LocaleController.getString("HideAboveTheList", R.string.HideAboveTheList) + }; + builder.setItems(items, icons, (d, which) -> { + if (which == 0) { + getMessagesStorage().readAllDialogs(1); + } else if (which == 1 && viewPages != null) { + for (int a = 0; a < viewPages.length; a++) { + if (viewPages[a].dialogsType != 0 || viewPages[a].getVisibility() != View.VISIBLE) { + continue; + } + View child = viewPages[a].listView.getChildAt(0); + DialogCell dialogCell = null; + if (child instanceof DialogCell && ((DialogCell) child).isFolderCell()) { + dialogCell = (DialogCell) child; + } + viewPages[a].listView.toggleArchiveHidden(true, dialogCell); + } + } + }); + showDialog(builder.create()); + } + + private boolean showChatPreview(DialogCell cell) { long dialogId = cell.getDialogId(); Bundle args = new Bundle(); @@ -5387,19 +5479,305 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (message_id != 0) { args.putInt("message_id", message_id); } - if (searchString != null) { - if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { - getNotificationCenter().postNotificationName(NotificationCenter.closeChats); - prepareBlurBitmap(); - presentFragmentAsPreview(new ChatActivity(args)); - } + + final ArrayList dialogIdArray = new ArrayList<>(); + dialogIdArray.add(dialogId); + +// boolean hasFolders = getMessagesController().filtersEnabled && getMessagesController().dialogFiltersLoaded && getMessagesController().dialogFilters != null && getMessagesController().dialogFilters.size() > 0; + final ActionBarPopupWindow.ActionBarPopupWindowLayout[] previewMenu = new ActionBarPopupWindow.ActionBarPopupWindowLayout[1]; +// +// LinearLayout foldersMenuView = null; +// int[] foldersMenu = new int[1]; +// if (hasFolders) { +// foldersMenuView = new LinearLayout(getParentActivity()); +// foldersMenuView.setOrientation(LinearLayout.VERTICAL); +// +// ScrollView scrollView = new ScrollView(getParentActivity()) { +// @Override +// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { +// super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec( +// (int) Math.min( +// MeasureSpec.getSize(heightMeasureSpec), +// Math.min(AndroidUtilities.displaySize.y * 0.35f, AndroidUtilities.dp(400)) +// ), +// MeasureSpec.getMode(heightMeasureSpec) +// )); +// } +// }; +// LinearLayout linearLayout = new LinearLayout(getParentActivity()); +// linearLayout.setOrientation(LinearLayout.VERTICAL); +// scrollView.addView(linearLayout); +// final boolean backButtonAtTop = true; +// +// final int foldersCount = getMessagesController().dialogFilters.size(); +// ActionBarMenuSubItem lastItem = null; +// for (int i = 0; i < foldersCount; ++i) { +// MessagesController.DialogFilter folder = getMessagesController().dialogFilters.get(i); +// if (folder.includesDialog(AccountInstance.getInstance(currentAccount), dialogId)) { +// continue; +// } +// final ArrayList alwaysShow = FiltersListBottomSheet.getDialogsCount(DialogsActivity.this, folder, dialogIdArray, true, false); +// int currentCount = folder.alwaysShow.size(); +// if (currentCount + alwaysShow.size() > 100) { +// continue; +// } +// ActionBarMenuSubItem folderItem = lastItem = new ActionBarMenuSubItem(getParentActivity(), !backButtonAtTop && linearLayout.getChildCount() == 0, false); +// folderItem.setTextAndIcon(folder.name, R.drawable.msg_folders); +// folderItem.setMinimumWidth(160); +// folderItem.setOnClickListener(e -> { +// if (!alwaysShow.isEmpty()) { +// for (int a = 0; a < alwaysShow.size(); a++) { +// folder.neverShow.remove(alwaysShow.get(a)); +// } +// folder.alwaysShow.addAll(alwaysShow); +// FilterCreateActivity.saveFilterToServer(folder, folder.flags, folder.name, folder.alwaysShow, folder.neverShow, folder.pinnedDialogs, false, false, true, true, false, DialogsActivity.this, null); +// } +// long did; +// if (alwaysShow.size() == 1) { +// did = alwaysShow.get(0); +// } else { +// did = 0; +// } +// getUndoView().showWithAction(did, UndoView.ACTION_ADDED_TO_FOLDER, alwaysShow.size(), folder, null, null); +// hideActionMode(true); +// finishPreviewFragment(); +// }); +// linearLayout.addView(folderItem); +// } +// if (lastItem != null && backButtonAtTop) { +// lastItem.updateSelectorBackground(false, true); +// } +// if (linearLayout.getChildCount() <= 0) { +// hasFolders = false; +// } else { +// ActionBarPopupWindow.GapView gap = new ActionBarPopupWindow.GapView(getParentActivity(), getResourceProvider(), Theme.key_actionBarDefaultSubmenuSeparator); +// gap.setTag(R.id.fit_width_tag, 1); +// ActionBarMenuSubItem backItem = new ActionBarMenuSubItem(getParentActivity(), backButtonAtTop, !backButtonAtTop); +// backItem.setTextAndIcon(LocaleController.getString("Back", R.string.Back), R.drawable.ic_ab_back); +// backItem.setMinimumWidth(160); +// backItem.setOnClickListener(e -> { +// if (previewMenu[0] != null) { +// previewMenu[0].getSwipeBack().closeForeground(); +// } +// }); +// if (backButtonAtTop) { +// foldersMenuView.addView(backItem); +// foldersMenuView.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); +// foldersMenuView.addView(scrollView); +// } else { +// foldersMenuView.addView(scrollView); +// foldersMenuView.addView(gap, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 8)); +// foldersMenuView.addView(backItem); +// } +// } +// } + + int flags = ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_SHOWN_FROM_BOTTOM; +// if (hasFolders) { +// flags |= ActionBarPopupWindow.ActionBarPopupWindowLayout.FLAG_USE_SWIPEBACK; +// } + + final ChatActivity[] chatActivity = new ChatActivity[1]; + previewMenu[0] = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getParentActivity(), R.drawable.popup_fixed_alert, getResourceProvider(), flags); + +// if (hasFolders) { +// foldersMenu[0] = previewMenu[0].addViewToSwipeBack(foldersMenuView); +// ActionBarMenuSubItem addToFolderItem = new ActionBarMenuSubItem(getParentActivity(), true, false); +// addToFolderItem.setTextAndIcon(LocaleController.getString("FilterAddTo", R.string.FilterAddTo), R.drawable.msg_addfolder); +// addToFolderItem.setMinimumWidth(160); +// addToFolderItem.setOnClickListener(e -> +// previewMenu[0].getSwipeBack().openForeground(foldersMenu[0]) +// ); +// previewMenu[0].addView(addToFolderItem); +// previewMenu[0].getSwipeBack().setOnHeightUpdateListener(height -> { +// if (chatActivity[0] == null || chatActivity[0].getFragmentView() == null) { +// return; +// } +// ViewGroup.LayoutParams lp = chatActivity[0].getFragmentView().getLayoutParams(); +// if (lp instanceof ViewGroup.MarginLayoutParams) { +// ((ViewGroup.MarginLayoutParams) lp).bottomMargin = AndroidUtilities.dp(24 + 16 + 8) + height; +// chatActivity[0].getFragmentView().setLayoutParams(lp); +// } +// }); +// } + + ActionBarMenuSubItem markAsUnreadItem = new ActionBarMenuSubItem(getParentActivity(), true, false); + if (cell.getHasUnread()) { + markAsUnreadItem.setTextAndIcon(LocaleController.getString("MarkAsRead", R.string.MarkAsRead), R.drawable.msg_markread); } else { - if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { - prepareBlurBitmap(); - presentFragmentAsPreview(new ChatActivity(args)); - } + markAsUnreadItem.setTextAndIcon(LocaleController.getString("MarkAsUnread", R.string.MarkAsUnread), R.drawable.msg_markunread); } - return true; + markAsUnreadItem.setMinimumWidth(160); + markAsUnreadItem.setOnClickListener(e -> { + if (cell.getHasUnread()) { + markAsRead(dialogId); + } else { + markAsUnread(dialogId); + } + finishPreviewFragment(); + }); + previewMenu[0].addView(markAsUnreadItem); + + final boolean[] hasPinAction = new boolean[1]; + hasPinAction[0] = true; + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(dialogId); + boolean containsFilter; + final MessagesController.DialogFilter filter = ( + (containsFilter = (viewPages[0].dialogsType == 7 || viewPages[0].dialogsType == 8) && (!actionBar.isActionModeShowed() || actionBar.isActionModeShowed(null))) ? + getMessagesController().selectedDialogFilter[viewPages[0].dialogsType == 8 ? 1 : 0] : null + ); + if (!isDialogPinned(dialog)) { + int pinnedCount = 0; + int pinnedSecretCount = 0; + int newPinnedCount = 0; + int newPinnedSecretCount = 0; + ArrayList dialogs = getMessagesController().getDialogs(folderId); + for (int a = 0, N = dialogs.size(); a < N; a++) { + TLRPC.Dialog dialog1 = dialogs.get(a); + if (dialog1 instanceof TLRPC.TL_dialogFolder) { + continue; + } + if (isDialogPinned(dialog1)) { + if (DialogObject.isEncryptedDialog(dialog1.id)) { + pinnedSecretCount++; + } else { + pinnedCount++; + } + } else if (!getMessagesController().isPromoDialog(dialog1.id, false)) { + break; + } + } + int alreadyAdded = 0; + if (dialog != null && !isDialogPinned(dialog)) { + if (DialogObject.isEncryptedDialog(dialogId)) { + newPinnedSecretCount++; + } else { + newPinnedCount++; + } + if (filter != null && filter.alwaysShow.contains(dialogId)) { + alreadyAdded++; + } + } + int maxPinnedCount; + if (containsFilter && filter != null) { + maxPinnedCount = 100 - filter.alwaysShow.size(); + } else if (folderId != 0 || filter != null) { + maxPinnedCount = getMessagesController().maxFolderPinnedDialogsCount; + } else { + maxPinnedCount = getMessagesController().maxPinnedDialogsCount; + } + hasPinAction[0] = !(newPinnedSecretCount + pinnedSecretCount > maxPinnedCount || newPinnedCount + pinnedCount - alreadyAdded > maxPinnedCount); + } + + if (hasPinAction[0]) { + ActionBarMenuSubItem unpinItem = new ActionBarMenuSubItem(getParentActivity(), false, false); + if (isDialogPinned(dialog)) { + unpinItem.setTextAndIcon(LocaleController.getString("UnpinMessage", R.string.UnpinMessage), R.drawable.msg_unpin); + } else { + unpinItem.setTextAndIcon(LocaleController.getString("PinMessage", R.string.PinMessage), R.drawable.msg_pin); + } + unpinItem.setMinimumWidth(160); + unpinItem.setOnClickListener(e -> { + finishPreviewFragment(); + AndroidUtilities.runOnUIThread(() -> { + int minPinnedNum = Integer.MAX_VALUE; + if (filter != null && isDialogPinned(dialog)) { + for (int c = 0, N = filter.pinnedDialogs.size(); c < N; c++) { + minPinnedNum = Math.min(minPinnedNum, filter.pinnedDialogs.valueAt(c)); + } + minPinnedNum -= canPinCount; + } + TLRPC.EncryptedChat encryptedChat = null; + if (DialogObject.isEncryptedDialog(dialogId)) { + encryptedChat = getMessagesController().getEncryptedChat(DialogObject.getEncryptedChatId(dialogId)); + } + if (!isDialogPinned(dialog)) { + pinDialog(dialogId, true, filter, minPinnedNum, true); + getUndoView().showWithAction(0, UndoView.ACTION_PIN_DIALOGS, 1, 1600, null, null); + if (filter != null) { + if (encryptedChat != null) { + if (!filter.alwaysShow.contains(encryptedChat.user_id)) { + filter.alwaysShow.add(encryptedChat.user_id); + } + } else { + if (!filter.alwaysShow.contains(dialogId)) { + filter.alwaysShow.add(dialogId); + } + } + } + } else { + pinDialog(dialogId, false, filter, minPinnedNum, true); + getUndoView().showWithAction(0, UndoView.ACTION_UNPIN_DIALOGS, 1, 1600, null, null); + } + if (filter != null) { + FilterCreateActivity.saveFilterToServer(filter, filter.flags, filter.name, filter.alwaysShow, filter.neverShow, filter.pinnedDialogs, false, false, true, true, false, DialogsActivity.this, null); + } + getMessagesController().reorderPinnedDialogs(folderId, null, 0); + updateCounters(true); + if (viewPages != null) { + for (int a = 0; a < viewPages.length; a++) { + viewPages[a].dialogsAdapter.onReorderStateChanged(false); + } + } + updateVisibleRows(MessagesController.UPDATE_MASK_REORDER | MessagesController.UPDATE_MASK_CHECK); + + }, 100); + }); + previewMenu[0].addView(unpinItem); + } + + if (!DialogObject.isUserDialog(dialogId) || !UserObject.isUserSelf(getMessagesController().getUser(dialogId))) { + ActionBarMenuSubItem muteItem = new ActionBarMenuSubItem(getParentActivity(), false, false); + if (!getMessagesController().isDialogMuted(dialogId)) { + muteItem.setTextAndIcon(LocaleController.getString("Mute", R.string.Mute), R.drawable.msg_mute); + } else { + muteItem.setTextAndIcon(LocaleController.getString("Unmute", R.string.Unmute), R.drawable.msg_unmute); + } + muteItem.setMinimumWidth(160); + muteItem.setOnClickListener(e -> { + boolean isMuted = getMessagesController().isDialogMuted(dialogId); + if (!isMuted) { + getNotificationsController().setDialogNotificationsSettings(dialogId, NotificationsController.SETTING_MUTE_FOREVER); + } else { + getNotificationsController().setDialogNotificationsSettings(dialogId, NotificationsController.SETTING_MUTE_UNMUTE); + } + BulletinFactory.createMuteBulletin(this, !isMuted, null).show(); + finishPreviewFragment(); + }); + previewMenu[0].addView(muteItem); + } + + ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true); + deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon)); + deleteItem.setTextColor(getThemedColor(Theme.key_dialogTextRed)); + deleteItem.setTextAndIcon(LocaleController.getString("Delete", R.string.Delete), R.drawable.msg_delete); + deleteItem.setMinimumWidth(160); + deleteItem.setOnClickListener(e -> { + performSelectedDialogsAction(dialogIdArray, delete, false); + finishPreviewFragment(); + }); + previewMenu[0].addView(deleteItem); + + if (getMessagesController().checkCanOpenChat(args, DialogsActivity.this)) { + if (searchString != null) { + getNotificationCenter().postNotificationName(NotificationCenter.closeChats); + } + prepareBlurBitmap(); + parentLayout.highlightActionButtons = true; + if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y) { + presentFragmentAsPreview(chatActivity[0] = new ChatActivity(args)); + } else { + presentFragmentAsPreviewWithMenu(chatActivity[0] = new ChatActivity(args), previewMenu[0]); + if (chatActivity[0] != null) { + chatActivity[0].allowExpandPreviewByClick = true; + try { + chatActivity[0].getAvatarContainer().getAvatarImageView().performAccessibilityAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); + } catch (Exception ignore) {} + } + } + return true; + } + return false; } private void updateFloatingButtonOffset() { @@ -5604,7 +5982,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. filter = null; } int count = selectedDialogs.size(); - int pinedActionCount = 0; + int pinnedActionCount = 0; if (action == archive || action == archive2) { ArrayList copy = new ArrayList<>(selectedDialogs); getMessagesController().addDialogToFolder(copy, canUnarchiveCount == 0 ? 1 : 0, -1, null, 0); @@ -5674,21 +6052,15 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else if (NekoConfig.unlimitedPinnedDialogs.Bool() || folderId != 0 || filter != null) { maxPinnedCount = getMessagesController().maxFolderPinnedDialogsCount; } else { - maxPinnedCount = getMessagesController().maxPinnedDialogsCount; + maxPinnedCount = getUserConfig().isPremium() ? getMessagesController().dialogFiltersPinnedLimitPremium : getMessagesController().dialogFiltersPinnedLimitDefault; } if (newPinnedSecretCount + pinnedSecretCount > maxPinnedCount || newPinnedCount + pinnedCount - alreadyAdded > maxPinnedCount) { if (folderId != 0 || filter != null) { AlertsCreator.showSimpleAlert(DialogsActivity.this, LocaleController.formatString("PinFolderLimitReached", R.string.PinFolderLimitReached, LocaleController.formatPluralString("Chats", maxPinnedCount))); } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); - builder.setMessage(LocaleController.formatString("PinToTopLimitReached2", R.string.PinToTopLimitReached2, LocaleController.formatPluralString("Chats", maxPinnedCount))); - builder.setNegativeButton(LocaleController.getString("FiltersSetupPinAlert", R.string.FiltersSetupPinAlert), (dialog, which) -> presentFragment(new FiltersSetupActivity())); - builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, getParentActivity(), LimitReachedBottomSheet.TYPE_PIN_DIALOGS, currentAccount); + showDialog(limitReachedBottomSheet); } - AndroidUtilities.shakeView(pinItem, 2, 0); - VibrateUtil.vibrate(); return; } } else if ((action == delete || action == clear) && count > 1 && alert) { @@ -5802,7 +6174,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (isDialogPinned(dialog)) { continue; } - pinedActionCount++; + pinnedActionCount++; pinDialog(selectedDialog, true, filter, minPinnedNum, count == 1); if (filter != null) { minPinnedNum++; @@ -5820,39 +6192,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (!isDialogPinned(dialog)) { continue; } - pinedActionCount++; + pinnedActionCount++; pinDialog(selectedDialog, false, filter, minPinnedNum, count == 1); - } } else if (action == read) { if (canReadCount != 0) { - debugLastUpdateAction = 2; - int selectedDialogIndex = -1; - if (filter != null && (filter.flags & MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0 && !filter.alwaysShow(currentAccount, dialog)) { - setDialogsListFrozen(true); - if (frozenDialogsList != null) { - for (int i = 0; i < frozenDialogsList.size(); i++) { - if (frozenDialogsList.get(i).id == selectedDialog) { - selectedDialogIndex = i; - break; - } - } - if (selectedDialogIndex < 0) { - setDialogsListFrozen(false, false); - } - } - } - getMessagesController().markMentionsAsRead(selectedDialog); - getMessagesController().markDialogAsRead(selectedDialog, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, 0, true, 0); - - if (selectedDialogIndex >= 0) { - frozenDialogsList.remove(selectedDialogIndex); - viewPages[0].dialogsItemAnimator.prepareForRemove(); - viewPages[0].dialogsAdapter.notifyItemRemoved(selectedDialogIndex); - dialogRemoveFinished = 2; - } + markAsRead(selectedDialog); } else { - getMessagesController().markDialogAsUnread(selectedDialog, null, 0); + markAsUnread(selectedDialog); } } else if (action == delete || action == clear) { if (count == 1) { @@ -5955,7 +6302,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getMessagesController().reorderPinnedDialogs(folderId, null, 0); } if (searchIsShowed) { - getUndoView().showWithAction(0, canPinCount != 0 ? UndoView.ACTION_PIN_DIALOGS : UndoView.ACTION_UNPIN_DIALOGS, pinedActionCount); + getUndoView().showWithAction(0, canPinCount != 0 ? UndoView.ACTION_PIN_DIALOGS : UndoView.ACTION_UNPIN_DIALOGS, pinnedActionCount); } } if (scrollToTop) { @@ -5967,6 +6314,46 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. hideActionMode(action != pin2 && action != pin && action != delete); } + private void markAsRead(long did) { + TLRPC.Dialog dialog = getMessagesController().dialogs_dict.get(did); + MessagesController.DialogFilter filter; + boolean containsFilter = (viewPages[0].dialogsType == 7 || viewPages[0].dialogsType == 8) && (!actionBar.isActionModeShowed() || actionBar.isActionModeShowed(null)); + if (containsFilter) { + filter = getMessagesController().selectedDialogFilter[viewPages[0].dialogsType == 8 ? 1 : 0]; + } else { + filter = null; + } + debugLastUpdateAction = 2; + int selectedDialogIndex = -1; + if (filter != null && (filter.flags & MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0 && !filter.alwaysShow(currentAccount, dialog)) { + setDialogsListFrozen(true); + if (frozenDialogsList != null) { + for (int i = 0; i < frozenDialogsList.size(); i++) { + if (frozenDialogsList.get(i).id == did) { + selectedDialogIndex = i; + break; + } + } + if (selectedDialogIndex < 0) { + setDialogsListFrozen(false, false); + } + } + } + getMessagesController().markMentionsAsRead(did); + getMessagesController().markDialogAsRead(did, dialog.top_message, dialog.top_message, dialog.last_message_date, false, 0, 0, true, 0); + + if (selectedDialogIndex >= 0) { + frozenDialogsList.remove(selectedDialogIndex); + viewPages[0].dialogsItemAnimator.prepareForRemove(); + viewPages[0].dialogsAdapter.notifyItemRemoved(selectedDialogIndex); + dialogRemoveFinished = 2; + } + } + + private void markAsUnread(long did) { + getMessagesController().markDialogAsUnread(did, null, 0); + } + private void performDeleteOrClearDialogAction(int action, long selectedDialog, TLRPC.Chat chat, boolean isBot, boolean revoke) { if (action == clear) { getMessagesController().deleteDialog(selectedDialog, 1, revoke); @@ -6299,12 +6686,12 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else { blockItem.setVisibility(View.VISIBLE); } - if (filterTabsView == null || filterTabsView.getVisibility() != View.VISIBLE || filterTabsView.getCurrentTabId() == Integer.MAX_VALUE) { + if (filterTabsView == null || filterTabsView.getVisibility() != View.VISIBLE || filterTabsView.currentTabIsDefault()) { removeFromFolderItem.setVisibility(View.GONE); } else { removeFromFolderItem.setVisibility(View.VISIBLE); } - if (filterTabsView != null && ((searchTabsView != null && searchTabsView.getVisibility() == View.VISIBLE) || (filterTabsView.getVisibility() == View.VISIBLE && filterTabsView.getCurrentTabId() == Integer.MAX_VALUE)) && !FiltersListBottomSheet.getCanAddDialogFilters(this, selectedDialogs).isEmpty()) { + if (filterTabsView != null && ((searchTabsView != null && searchTabsView.getVisibility() == View.VISIBLE) || (filterTabsView.getVisibility() == View.VISIBLE && filterTabsView.currentTabIsDefault())) && !FiltersListBottomSheet.getCanAddDialogFilters(this, selectedDialogs).isEmpty()) { addToFolderItem.setVisibility(View.VISIBLE); } else { addToFolderItem.setVisibility(View.GONE); @@ -6761,29 +7148,18 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } - @SuppressWarnings("unchecked") - @Override - public void didReceivedNotification(int id, int account, Object... args) { - if (id == NotificationCenter.dialogsNeedReload) { - if (viewPages == null || dialogsListFrozen) { - return; - } + private void reloadViewPageDialogs(ViewPage viewPage, boolean newMessage) { + if (viewPage.getVisibility() != View.VISIBLE) { + return; + } + int oldItemCount = viewPage.dialogsAdapter.getCurrentCount(); - MessagesController messagesController = AccountInstance.getInstance(currentAccount).getMessagesController(); - ArrayList dialogs = messagesController.getDialogs(folderId); + if (viewPage.dialogsType == 0 && hasHiddenArchive() && viewPage.listView.getChildCount() == 0) { + LinearLayoutManager layoutManager = (LinearLayoutManager) viewPage.listView.getLayoutManager(); + layoutManager.scrollToPositionWithOffset(1, 0); + } - for (int a = 0; a < viewPages.length; a++) { - if (viewPages[a].getVisibility() != View.VISIBLE) { - continue; - } - int oldItemCount = viewPages[a].dialogsAdapter.getCurrentCount(); - - if (viewPages[a].dialogsType == 0 && hasHiddenArchive() && viewPages[a].listView.getChildCount() == 0) { - LinearLayoutManager layoutManager = (LinearLayoutManager) viewPages[a].listView.getLayoutManager(); - layoutManager.scrollToPositionWithOffset(1, 0); - } - - if (viewPages[a].selectedType >= 0 && + if (viewPages[a].selectedType >= 0 && viewPages[a].selectedType < getMessagesController().dialogFilters.size() && getMessagesController().dialogFilters.get(viewPages[a].selectedType) != null && getMessagesController().selectedDialogFilter[viewPages[a].dialogsType == 8 ? 1 : 0] != null && @@ -6791,39 +7167,67 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. getMessagesController().selectedDialogFilter[viewPages[a].dialogsType == 8 ? 1 : 0].id) { getMessagesController().selectDialogFilter(getMessagesController().dialogFilters.get(viewPages[a].selectedType), viewPages[a].dialogsType == 8 ? 1 : 0); viewPages[a].dialogsAdapter.notifyDataSetChanged(); - } else if (viewPages[a].dialogsAdapter.isDataSetChanged() || args.length > 0) { - viewPages[a].dialogsAdapter.updateHasHints(); - int newItemCount = viewPages[a].dialogsAdapter.getItemCount(); - if (newItemCount == 1 && oldItemCount == 1 && viewPages[a].dialogsAdapter.getItemViewType(0) == 5) { - if (viewPages[a].dialogsAdapter.lastDialogsEmptyType != viewPages[a].dialogsAdapter.dialogsEmptyType()) { - viewPages[a].dialogsAdapter.notifyItemChanged(0); + } else if (viewPage.dialogsAdapter.isDataSetChanged() || newMessage) { + viewPage.dialogsAdapter.updateHasHints(); + int newItemCount = viewPage.dialogsAdapter.getItemCount(); + if (newItemCount == 1 && oldItemCount == 1 && viewPage.dialogsAdapter.getItemViewType(0) == 5) { + if (viewPage.dialogsAdapter.lastDialogsEmptyType != viewPage.dialogsAdapter.dialogsEmptyType()) { + viewPage.dialogsAdapter.notifyItemChanged(0); + } + } else { + viewPage.dialogsAdapter.notifyDataSetChanged(); + if (newItemCount > oldItemCount && initialDialogsType != 11 && initialDialogsType != 12 && initialDialogsType != 13) { + viewPage.recyclerItemsEnterAnimator.showItemsAnimated(oldItemCount); + } + } + } else { + updateVisibleRows(MessagesController.UPDATE_MASK_NEW_MESSAGE); + int newItemCount = viewPage.dialogsAdapter.getItemCount(); + if (newItemCount > oldItemCount && initialDialogsType != 11 && initialDialogsType != 12 && initialDialogsType != 13) { + viewPage.recyclerItemsEnterAnimator.showItemsAnimated(oldItemCount); + } + } + try { + viewPage.listView.setEmptyView(folderId == 0 ? viewPage.progressView : null); + } catch (Exception e) { + FileLog.e(e); + } + checkListLoad(viewPage); + } + + @SuppressWarnings("unchecked") + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.dialogsNeedReload) { + if (viewPages == null || dialogsListFrozen) { + return; + } + for (int a = 0; a < viewPages.length; a++) { + final ViewPage viewPage = viewPages[a]; + MessagesController.DialogFilter filter = null; + if (viewPages[0].dialogsType == 7 || viewPages[0].dialogsType == 8) { + filter = getMessagesController().selectedDialogFilter[viewPages[0].dialogsType == 8 ? 1 : 0]; + } + boolean isUnread = filter != null && (filter.flags & MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ) != 0; + if (slowedReloadAfterDialogClick && isUnread) { + // in unread tab dialogs reload too instantly removes dialog from folder after clicking on it + AndroidUtilities.runOnUIThread(() -> { + reloadViewPageDialogs(viewPage, args.length > 0); + if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE) { + filterTabsView.checkTabsCounter(); } - } else { - viewPages[a].dialogsAdapter.notifyDataSetChanged(); - if (newItemCount > oldItemCount && initialDialogsType != 11 && initialDialogsType != 12 && initialDialogsType != 13) { - viewPages[a].recyclerItemsEnterAnimator.showItemsAnimated(oldItemCount); - } - } + }, 160); } else { - updateVisibleRows(MessagesController.UPDATE_MASK_NEW_MESSAGE); - int newItemCount = viewPages[a].dialogsAdapter.getItemCount(); - if (newItemCount > oldItemCount && initialDialogsType != 11 && initialDialogsType != 12 && initialDialogsType != 13) { - viewPages[a].recyclerItemsEnterAnimator.showItemsAnimated(oldItemCount); - } + reloadViewPageDialogs(viewPage, args.length > 0); } - try { - viewPages[a].listView.setEmptyView(folderId == 0 ? viewPages[a].progressView : null); - } catch (Exception e) { - FileLog.e(e); - } - checkListLoad(viewPages[a]); } if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE) { filterTabsView.checkTabsCounter(); } + slowedReloadAfterDialogClick = false; } else if (id == NotificationCenter.dialogsUnreadCounterChanged) { if (filterTabsView != null && filterTabsView.getVisibility() == View.VISIBLE) { - filterTabsView.notifyTabCounterChanged(Integer.MAX_VALUE); + filterTabsView.notifyTabCounterChanged(filterTabsView.getDefaultTabId()); } } else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) { updateVisibleRows(0); @@ -7130,6 +7534,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. setDialogsListFrozen(frozen, true); } + public class DialogsHeader extends TLRPC.Dialog { + public static final int HEADER_TYPE_MY_CHANNELS = 0; + public static final int HEADER_TYPE_MY_GROUPS = 1; + public static final int HEADER_TYPE_GROUPS = 2; + public int headerType; + public DialogsHeader(int type) { + this.headerType = type; + } + } + @NonNull public ArrayList getDialogsArray(int currentAccount, int dialogsType, int folderId, boolean frozen) { if (frozen && frozenDialogsList != null) { @@ -7142,17 +7556,28 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. return messagesController.dialogsServerOnly; } else if (dialogsType == 2) { ArrayList dialogs = new ArrayList<>(messagesController.dialogsCanAddUsers.size() + messagesController.dialogsMyChannels.size() + messagesController.dialogsMyGroups.size() + 2); - if (messagesController.dialogsMyChannels.size() > 0) { - dialogs.add(null); + if (messagesController.dialogsMyChannels.size() > 0 && allowChannels) { + dialogs.add(new DialogsHeader(DialogsHeader.HEADER_TYPE_MY_CHANNELS)); dialogs.addAll(messagesController.dialogsMyChannels); } - if (messagesController.dialogsMyGroups.size() > 0) { - dialogs.add(null); + if (messagesController.dialogsMyGroups.size() > 0 && allowGroups) { + dialogs.add(new DialogsHeader(DialogsHeader.HEADER_TYPE_MY_GROUPS)); dialogs.addAll(messagesController.dialogsMyGroups); } if (messagesController.dialogsCanAddUsers.size() > 0) { - dialogs.add(null); - dialogs.addAll(messagesController.dialogsCanAddUsers); + final int count = messagesController.dialogsCanAddUsers.size(); + boolean first = true; + for (int i = 0; i < count; ++i) { + TLRPC.Dialog dialog = messagesController.dialogsCanAddUsers.get(i); + if (allowChannels && ChatObject.isChannelAndNotMegaGroup(-dialog.id, currentAccount) || + allowGroups && (ChatObject.isMegagroup(currentAccount, -dialog.id) || !ChatObject.isChannel(-dialog.id, currentAccount))) { + if (first) { + dialogs.add(new DialogsHeader(DialogsHeader.HEADER_TYPE_GROUPS)); + first = false; + } + dialogs.add(dialog); + } + } } return dialogs; } else if (dialogsType == 3) { @@ -7172,6 +7597,22 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } else if (dialogsType == 9) { return messagesController.dialogsForBlock; + } else if (dialogsType == DIALOGS_TYPE_START_ATTACH_BOT) { + ArrayList dialogs = new ArrayList<>(); + if (allowUsers || allowBots) { + for (TLRPC.Dialog d : messagesController.dialogsUsersOnly) { + if (messagesController.getUser(d.id).bot ? allowBots : allowUsers) { + dialogs.add(d); + } + } + } + if (allowGroups) { + dialogs.addAll(messagesController.dialogsGroupsOnly); + } + if (allowChannels) { + dialogs.addAll(messagesController.dialogsChannelsOnly); + } + return dialogs; } return new ArrayList<>(); } @@ -7656,7 +8097,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. sendPopupWindow.dismiss(); } }); - sendPopupLayout2.setShownFromBotton(false); + sendPopupLayout2.setShownFromBottom(false); sendPopupLayout2.setupRadialSelectors(getThemedColor(Theme.key_dialogButtonSelector)); ActionBarMenuSubItem sendWithoutSound = new ActionBarMenuSubItem(parentActivity, true, true, resourcesProvider); @@ -7709,14 +8150,13 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. sendPopupWindow.setInputMethodMode(ActionBarPopupWindow.INPUT_METHOD_NOT_NEEDED); sendPopupWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED); sendPopupWindow.getContentView().setFocusableInTouchMode(true); - SharedConfig.removeScheduledOrNoSuoundHint(); + SharedConfig.removeScheduledOrNoSoundHint(); layout.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(1000), View.MeasureSpec.AT_MOST)); sendPopupWindow.setFocusable(true); int[] location = new int[2]; view.getLocationInWindow(location); - int y; - y = location[1] - layout.getMeasuredHeight() - AndroidUtilities.dp(2); + int y = location[1] - layout.getMeasuredHeight() - AndroidUtilities.dp(2); sendPopupWindow.showAtLocation(view, Gravity.LEFT | Gravity.TOP, location[0] + view.getMeasuredWidth() - layout.getMeasuredWidth() + AndroidUtilities.dp(8), y); sendPopupWindow.dimBehind(); view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); @@ -7791,8 +8231,10 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (scrimPopupWindowItems != null) { for (int a = 0; a < scrimPopupWindowItems.length; a++) { - scrimPopupWindowItems[a].setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem), Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon)); - scrimPopupWindowItems[a].setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector)); + if (scrimPopupWindowItems[a] != null) { + scrimPopupWindowItems[a].setColors(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem), Theme.getColor(Theme.key_actionBarDefaultSubmenuItemIcon)); + scrimPopupWindowItems[a].setSelectorColor(Theme.getColor(Theme.key_dialogButtonSelector)); + } } } if (scrimPopupWindow != null) { @@ -7816,6 +8258,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. if (searchTabsView != null) { searchTabsView.updateColors(); } + if (blurredView != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + blurredView.setForeground(new ColorDrawable(ColorUtils.setAlphaComponent(getThemedColor(Theme.key_windowBackgroundWhite), 100))); + } + } if (searchItem != null) { EditTextBoldCursor editText = searchItem.getSearchField(); if (whiteActionBar) { @@ -7924,7 +8371,6 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted)); arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText)); arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon)); - arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon)); arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable, Theme.dialogs_fakeDrawable}, null, Theme.key_chats_draft)); arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_pinnedDrawable, Theme.dialogs_reorderDrawable}, null, Theme.key_chats_pinnedIcon)); arrayList.add(new ThemeDescription(list, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Paint[]{Theme.dialogs_namePaint[0], Theme.dialogs_namePaint[1], Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name)); @@ -8230,7 +8676,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } if (searchViewPager != null) { - searchViewPager.getThemeDescriptors(arrayList); + searchViewPager.getThemeDescriptions(arrayList); } return arrayList; @@ -8416,5 +8862,4 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } return ColorUtils.calculateLuminance(color) > 0.7f; } -} - +} \ No newline at end of file diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java b/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java index c07fb49a7..83e415ab6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java @@ -43,7 +43,9 @@ public class DownloadProgressIcon extends View implements NotificationCenter.Not this.currentAccount = currentAccount; downloadDrawable = new RLottieDrawable(R.raw.download_progress, "download_progress", AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); + downloadDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); downloadCompleteDrawable = new RLottieDrawable(R.raw.download_finish, "download_finish", AndroidUtilities.dp(28), AndroidUtilities.dp(28), true, null); + downloadCompleteDrawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); downloadImageReceiver.setImageBitmap(downloadDrawable); downloadCompleteImageReceiver.setImageBitmap(downloadCompleteDrawable); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java index 7cc7ef9cd..27a83ab34 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/EditWidgetActivity.java @@ -52,7 +52,6 @@ import org.telegram.messenger.ChatsWidgetProvider; import org.telegram.messenger.ContactsController; import org.telegram.messenger.ContactsWidgetProvider; import org.telegram.messenger.DialogObject; -import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessageObject; @@ -290,7 +289,7 @@ public class EditWidgetActivity extends BaseFragment { try { Bitmap bitmap = null; if (photoPath != null) { - File path = FileLoader.getPathToAttach(photoPath, true); + File path = getFileLoader().getPathToAttach(photoPath, true); bitmap = BitmapFactory.decodeFile(path.toString()); } @@ -563,7 +562,7 @@ public class EditWidgetActivity extends BaseFragment { try { Bitmap bitmap = null; if (photoPath != null) { - File path = FileLoader.getPathToAttach(photoPath, true); + File path = getFileLoader().getPathToAttach(photoPath, true); bitmap = BitmapFactory.decodeFile(path.toString()); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java b/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java index 105a421ef..ba955eebb 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/EmojiAnimationsOverlay.java @@ -16,6 +16,7 @@ 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.NotificationCenter; import org.telegram.messenger.R; @@ -27,6 +28,7 @@ import org.telegram.ui.Cells.ChatMessageCell; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.StickerSetBulletinLayout; +import org.telegram.ui.Components.StickersAlert; import java.util.ArrayList; import java.util.HashMap; @@ -227,30 +229,59 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe ChatMessageCell cell = (ChatMessageCell) child; if (cell.getMessageObject().getId() == drawingObject.messageId) { drawingObject.viewFound = true; - float viewX = listView.getX() + child.getX() + cell.getPhotoImage().getImageX(); - float viewY = listView.getY() + child.getY() + cell.getPhotoImage().getImageY(); - if (drawingObject.isOut) { - viewX += -cell.getPhotoImage().getImageWidth() * 2 + AndroidUtilities.dp(24); + float viewX = listView.getX() + child.getX(); + float viewY = listView.getY() + child.getY(); + if (drawingObject.isPremiumSticker) { + drawingObject.lastX = viewX + cell.getPhotoImage().getImageX(); + drawingObject.lastY = viewY + cell.getPhotoImage().getImageY(); + ; } else { - viewX += -AndroidUtilities.dp(24); + viewX += cell.getPhotoImage().getImageX(); + viewY += cell.getPhotoImage().getImageY(); + if (drawingObject.isOut) { + viewX += -cell.getPhotoImage().getImageWidth() * 2 + AndroidUtilities.dp(24); + } else { + viewX += -AndroidUtilities.dp(24); + } + viewY -= cell.getPhotoImage().getImageWidth(); + drawingObject.lastX = viewX; + drawingObject.lastY = viewY; } - viewY -= cell.getPhotoImage().getImageWidth(); - drawingObject.lastX = viewX; - drawingObject.lastY = viewY; drawingObject.lastW = cell.getPhotoImage().getImageWidth(); + drawingObject.lastH = cell.getPhotoImage().getImageHeight(); break; } } } - drawingObject.imageReceiver.setImageCoords(drawingObject.lastX + drawingObject.randomOffsetX, drawingObject.lastY + drawingObject.randomOffsetY, drawingObject.lastW * 3, drawingObject.lastW * 3); - if (!drawingObject.isOut) { - canvas.save(); - canvas.scale(-1f, 1, drawingObject.imageReceiver.getCenterX(), drawingObject.imageReceiver.getCenterY()); - drawingObject.imageReceiver.draw(canvas); - canvas.restore(); + if (drawingObject.isPremiumSticker) { + float size = drawingObject.lastH * 1.49926f; + float paddingHorizontal = size * 0.0546875f; + float centerY = drawingObject.lastY + drawingObject.lastH / 2f; + float top = centerY - size / 2f - size * 0.00279f; + if (!drawingObject.isOut) { + drawingObject.imageReceiver.setImageCoords(drawingObject.lastX - paddingHorizontal, top, size, size); + } else { + drawingObject.imageReceiver.setImageCoords(drawingObject.lastX + drawingObject.lastW - size + paddingHorizontal, top, size, size); + } + if (!drawingObject.isOut) { + canvas.save(); + canvas.scale(-1f, 1, drawingObject.imageReceiver.getCenterX(), drawingObject.imageReceiver.getCenterY()); + drawingObject.imageReceiver.draw(canvas); + canvas.restore(); + } else { + drawingObject.imageReceiver.draw(canvas); + } } else { - drawingObject.imageReceiver.draw(canvas); + drawingObject.imageReceiver.setImageCoords(drawingObject.lastX + drawingObject.randomOffsetX, drawingObject.lastY + drawingObject.randomOffsetY, drawingObject.lastW * 3, drawingObject.lastW * 3); + if (!drawingObject.isOut) { + canvas.save(); + canvas.scale(-1f, 1, drawingObject.imageReceiver.getCenterX(), drawingObject.imageReceiver.getCenterY()); + drawingObject.imageReceiver.draw(canvas); + canvas.restore(); + } else { + drawingObject.imageReceiver.draw(canvas); + } } if (drawingObject.wasPlayed && drawingObject.imageReceiver.getLottieAnimation() != null && drawingObject.imageReceiver.getLottieAnimation().getCurrentFrame() == drawingObject.imageReceiver.getLottieAnimation().getFramesCount() - 2) { drawingObjects.remove(i); @@ -262,19 +293,35 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe drawingObject.imageReceiver.getLottieAnimation().start(); } } + if (drawingObjects.isEmpty()) { + onAllEffectsEnd(); + } contentLayout.invalidate(); } } - public void onTapItem(ChatMessageCell view, ChatActivity chatActivity) { - if (chatActivity.currentUser == null || chatActivity.isSecretChat() || view.getMessageObject() == null || view.getMessageObject().getId() < 0) { - return; + public void onAllEffectsEnd() { + + } + + public boolean onTapItem(ChatMessageCell view, ChatActivity chatActivity) { + if (chatActivity.isSecretChat() || view.getMessageObject() == null || view.getMessageObject().getId() < 0) { + return false; + } + if (!view.getMessageObject().isPremiumSticker() && chatActivity.currentUser == null) { + return false; } boolean show = showAnimationForCell(view, -1, true, false); - if (show && !EmojiData.hasEmojiSupportVibration(view.getMessageObject().getStickerEmoji())) { + + if (show && (!EmojiData.hasEmojiSupportVibration(view.getMessageObject().getStickerEmoji()) || view.getMessageObject().isPremiumSticker())) { view.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); } - + if (view.getMessageObject().isPremiumSticker()) { + view.getMessageObject().forcePlayEffect = false; + view.getMessageObject().messageOwner.premiumEffectWasPlayed = true; + chatActivity.getMessagesStorage().updateMessageCustomParams(dialogId, view.getMessageObject().messageOwner); + return show; + } Integer printingType = MessagesController.getInstance(currentAccount).getPrintingStringType(dialogId, threadMsgId); boolean canShowHint = true; if (printingType != null && printingType == 5) { @@ -298,6 +345,7 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe } }, 1500); } + return show; } public void cancelHintRunnable() { @@ -314,7 +362,8 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe if (!view.getPhotoImage().hasNotThumb()) { return false; } - String emoji = view.getMessageObject().getStickerEmoji(); + MessageObject messageObject = view.getMessageObject(); + String emoji = messageObject.getStickerEmoji(); if (emoji == null) { return false; } @@ -325,47 +374,102 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe } emoji = unwrapEmoji(emoji); + boolean isPremiumSticker = messageObject.isPremiumSticker(); - if (supportedEmoji.contains(emoji)) { + if (supportedEmoji.contains(emoji) || isPremiumSticker) { ArrayList arrayList = emojiInteractionsStickersMap.get(emoji); - if (arrayList != null && !arrayList.isEmpty()) { - int sameAnimationsCount = 0; + if ((arrayList != null && !arrayList.isEmpty()) || isPremiumSticker) { + int sameAnimationsCountMessageId = 0; + int sameAnimationsCountDocumentId = 0; for (int i = 0; i < drawingObjects.size(); i++) { if (drawingObjects.get(i).messageId == view.getMessageObject().getId()) { - sameAnimationsCount++; + sameAnimationsCountMessageId++; if (drawingObjects.get(i).imageReceiver.getLottieAnimation() == null || drawingObjects.get(i).imageReceiver.getLottieAnimation().isGeneratingCache()) { return false; } } + if (drawingObjects.get(i).document != null && view.getMessageObject().getDocument() != null && drawingObjects.get(i).document.id == view.getMessageObject().getDocument().id) { + sameAnimationsCountDocumentId++; + } } - if (sameAnimationsCount >= 4) { + if (sendTap && isPremiumSticker && sameAnimationsCountMessageId > 0) { + if (Bulletin.getVisibleBulletin() != null && Bulletin.getVisibleBulletin().hash == messageObject.getId()) { + return false; + } + TLRPC.InputStickerSet inputStickerSet = messageObject.getInputStickerSet(); + TLRPC.TL_messages_stickerSet stickerSet = null; + if (inputStickerSet.short_name != null) { + stickerSet = MediaDataController.getInstance(currentAccount).getStickerSetByName(inputStickerSet.short_name); + } + if (stickerSet == null) { + stickerSet = MediaDataController.getInstance(currentAccount).getStickerSetById(inputStickerSet.id); + } + if (stickerSet == null) { + TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); + req.stickerset = inputStickerSet; + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + showStickerSetBulletin((TLRPC.TL_messages_stickerSet) response, messageObject); + })); + } else { + showStickerSetBulletin(stickerSet, messageObject); + } return false; } - if (animation < 0 || animation > arrayList.size() - 1) { - animation = Math.abs(random.nextInt()) % arrayList.size(); + if (sameAnimationsCountMessageId >= 4) { + return false; + } + TLRPC.Document document = null; + TLRPC.VideoSize videoSize = null; + if (isPremiumSticker) { + videoSize = messageObject.getPremiumStickerAnimation(); + } else { + if (animation < 0 || animation > arrayList.size() - 1) { + animation = Math.abs(random.nextInt()) % arrayList.size(); + } + document = arrayList.get(animation); + } + + if (document == null && videoSize == null) { + return false; } - TLRPC.Document document = arrayList.get(animation); DrawingObject drawingObject = new DrawingObject(); + drawingObject.isPremiumSticker = messageObject.isPremiumSticker(); drawingObject.randomOffsetX = imageW / 4 * ((random.nextInt() % 101) / 100f); drawingObject.randomOffsetY = imageH / 4 * ((random.nextInt() % 101) / 100f); drawingObject.messageId = view.getMessageObject().getId(); drawingObject.document = document; drawingObject.isOut = view.getMessageObject().isOutOwner(); - - Integer lastIndex = lastAnimationIndex.get(document.id); - int currentIndex = lastIndex == null ? 0 : lastIndex; - lastAnimationIndex.put(document.id, (currentIndex + 1) % 4); - - - ImageLocation imageLocation = ImageLocation.getForDocument(document); - drawingObject.imageReceiver.setUniqKeyPrefix(currentIndex + "_" + drawingObject.messageId + "_"); - int w = (int) (2f * imageW / AndroidUtilities.density); - drawingObject.imageReceiver.setImage(imageLocation, w + "_" + w + "_pcache", null, "tgs", set, 1); - drawingObject.imageReceiver.setLayerNum(Integer.MAX_VALUE); drawingObject.imageReceiver.setAllowStartAnimation(true); + int w; + if (document != null) { + w = (int) (2f * imageW / AndroidUtilities.density); + Integer lastIndex = lastAnimationIndex.get(document.id); + int currentIndex = lastIndex == null ? 0 : lastIndex; + lastAnimationIndex.put(document.id, (currentIndex + 1) % 4); + + ImageLocation imageLocation = ImageLocation.getForDocument(document); + drawingObject.imageReceiver.setUniqKeyPrefix(currentIndex + "_" + drawingObject.messageId + "_"); + + drawingObject.imageReceiver.setImage(imageLocation, w + "_" + w + "_pcache", null, "tgs", set, 1); + } else { + w = (int) (1.5f * imageW / AndroidUtilities.density); + if (sameAnimationsCountDocumentId > 0) { + Integer lastIndex = lastAnimationIndex.get(messageObject.getDocument().id); + int currentIndex = lastIndex == null ? 0 : lastIndex; + lastAnimationIndex.put(messageObject.getDocument().id, (currentIndex + 1) % 4); + drawingObject.imageReceiver.setUniqKeyPrefix(currentIndex + "_" + drawingObject.messageId + "_"); + } + drawingObject.document = messageObject.getDocument(); + drawingObject.imageReceiver.setImage(ImageLocation.getForDocument(videoSize, messageObject.getDocument()), w + "_" + w, null, "tgs", set, 1); + } + + drawingObject.imageReceiver.setLayerNum(Integer.MAX_VALUE); drawingObject.imageReceiver.setAutoRepeat(0); if (drawingObject.imageReceiver.getLottieAnimation() != null) { + if (drawingObject.isPremiumSticker) { + drawingObject.imageReceiver.getLottieAnimation().setCurrentFrame(0, false, true); + } drawingObject.imageReceiver.getLottieAnimation().start(); } drawingObjects.add(drawingObject); @@ -373,7 +477,7 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe drawingObject.imageReceiver.setParentView(contentLayout); contentLayout.invalidate(); - if (sendTap) { + if (sendTap && !isPremiumSticker) { if (lastTappedMsgId != 0 && lastTappedMsgId != view.getMessageObject().getId()) { if (sentInteractionsRunnable != null) { AndroidUtilities.cancelRunOnUIThread(sentInteractionsRunnable); @@ -411,6 +515,27 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe return false; } + private void showStickerSetBulletin(TLRPC.TL_messages_stickerSet stickerSet, MessageObject messageObject) { + if (MessagesController.getInstance(currentAccount).premiumLocked || chatActivity.getParentActivity() == null) { + return; + } + StickerSetBulletinLayout layout = new StickerSetBulletinLayout(contentLayout.getContext(), null, StickerSetBulletinLayout.TYPE_EMPTY, messageObject.getDocument(), chatActivity.getResourceProvider()); + layout.titleTextView.setText(stickerSet.set.title); + layout.subtitleTextView.setText(LocaleController.getString("PremiumStickerTooltip", R.string.PremiumStickerTooltip)); + + Bulletin.UndoButton viewButton = new Bulletin.UndoButton(chatActivity.getParentActivity(), true, chatActivity.getResourceProvider()); + layout.setButton(viewButton); + viewButton.setUndoAction(() -> { + StickersAlert alert = new StickersAlert(chatActivity.getParentActivity(), chatActivity, messageObject.getInputStickerSet(), null, chatActivity.chatActivityEnterView, chatActivity.getResourceProvider()); + alert.setCalcMandatoryInsets(chatActivity.isKeyboardVisible()); + chatActivity.showDialog(alert); + }); + viewButton.setText(LocaleController.getString("ViewAction", R.string.ViewAction)); + Bulletin bulletin = Bulletin.make(chatActivity, layout, Bulletin.DURATION_LONG); + bulletin.hash = messageObject.getId(); + bulletin.show(); + } + private String unwrapEmoji(String emoji) { CharSequence fixedEmoji = emoji; int length = emoji.length(); @@ -483,13 +608,27 @@ public class EmojiAnimationsOverlay implements NotificationCenter.NotificationCe } } + public boolean isIdle() { + return drawingObjects.isEmpty(); + } + + public boolean checkPosition(ChatMessageCell messageCell, float chatListViewPaddingTop, int bottom) { + float y = messageCell.getY() + messageCell.getPhotoImage().getCenterY(); + if (y > chatListViewPaddingTop && y < bottom) { + return true; + } + return false; + } + private class DrawingObject { public float lastX; public float lastY; public boolean viewFound; public float lastW; + public float lastH; public float randomOffsetX; public float randomOffsetY; + public boolean isPremiumSticker; boolean wasPlayed; boolean isOut; int messageId; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java index 225ff9a64..3d02a6373 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterCreateActivity.java @@ -16,6 +16,9 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DialogObject; @@ -49,9 +52,6 @@ import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; import java.util.Collections; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class FilterCreateActivity extends BaseFragment { private RecyclerListView listView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java index 4dd789549..8c79702e2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilterUsersActivity.java @@ -43,6 +43,11 @@ import android.view.inputmethod.EditorInfo; import android.widget.ImageView; import android.widget.ScrollView; +import androidx.annotation.Keep; +import androidx.collection.LongSparseArray; +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; @@ -69,15 +74,11 @@ import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.GroupCreateSpan; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; -import androidx.annotation.Keep; -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class FilterUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, View.OnClickListener { private ScrollView scrollView; @@ -695,7 +696,10 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen GroupCreateSpan span = selectedContacts.get(id); spansContainer.removeSpan(span); } else { - if (!(object instanceof String) && selectedCount >= 100) { + if (!(object instanceof String) && (!getUserConfig().isPremium() && selectedCount >= MessagesController.getInstance(currentAccount).dialogFiltersChatsLimitDefault) || selectedCount >= MessagesController.getInstance(currentAccount).dialogFiltersChatsLimitPremium) { + LimitReachedBottomSheet limitReachedBottomSheet = new LimitReachedBottomSheet(this, context, LimitReachedBottomSheet.TYPE_CHATS_IN_FOLDER, currentAccount); + limitReachedBottomSheet.setCurrentValue(selectedCount); + showDialog(limitReachedBottomSheet); return; } if (object instanceof TLRPC.User) { @@ -956,10 +960,11 @@ public class FilterUsersActivity extends BaseFragment implements NotificationCen } private void updateHint() { + int limit = getUserConfig().isPremium() ? getMessagesController().dialogFiltersChatsLimitPremium : getMessagesController().dialogFiltersChatsLimitDefault; if (selectedCount == 0) { - actionBar.setSubtitle(LocaleController.formatString("MembersCountZero", R.string.MembersCountZero, LocaleController.formatPluralString("Chats", 100))); + actionBar.setSubtitle(LocaleController.formatString("MembersCountZero", R.string.MembersCountZero, LocaleController.formatPluralString("Chats", limit))); } else { - actionBar.setSubtitle(String.format(LocaleController.getPluralString("MembersCountSelected", selectedCount), selectedCount, 100)); + actionBar.setSubtitle(String.format(LocaleController.getPluralString("MembersCountSelected", selectedCount), selectedCount, limit)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java index d2ea8ca7f..c0351fcf4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FilteredSearchView.java @@ -328,7 +328,7 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente } else if (view instanceof DialogCell) { if (!uiCallback.actionModeShowing()) { if (((DialogCell) view).isPointInsideAvatar(x, y)) { - chatPreviewDelegate.startChatPreview((DialogCell) view); + chatPreviewDelegate.startChatPreview(recyclerListView, (DialogCell) view); return true; } } @@ -378,7 +378,9 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente int visibleItemCount = Math.abs(lastVisibleItem - firstVisibleItem) + 1; int totalItemCount = recyclerView.getAdapter().getItemCount(); if (!isLoading && visibleItemCount > 0 && lastVisibleItem >= totalItemCount - 10 && !endReached) { - search(currentSearchDialogId, currentSearchMinDate, currentSearchMaxDate, currentSearchFilter, currentIncludeFolder, lastMessagesSearchString, false); + AndroidUtilities.runOnUIThread(() -> { + search(currentSearchDialogId, currentSearchMinDate, currentSearchMaxDate, currentSearchFilter, currentIncludeFolder, lastMessagesSearchString, false); + }); } if (adapter == sharedPhotoVideoAdapter) { @@ -1740,7 +1742,6 @@ public class FilteredSearchView extends FrameLayout implements NotificationCente arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countGrayPaint, null, null, Theme.key_chats_unreadCounterMuted)); arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class}, Theme.dialogs_countTextPaint, null, null, Theme.key_chats_unreadCounterText)); arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_lockDrawable}, null, Theme.key_chats_secretIcon)); - arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_groupDrawable, Theme.dialogs_broadcastDrawable, Theme.dialogs_botDrawable}, null, Theme.key_chats_nameIcon)); arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Drawable[]{Theme.dialogs_scamDrawable, Theme.dialogs_fakeDrawable}, null, Theme.key_chats_draft)); arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class}, null, new Drawable[]{Theme.dialogs_pinnedDrawable, Theme.dialogs_reorderDrawable}, null, Theme.key_chats_pinnedIcon)); arrayList.add(new ThemeDescription(recyclerListView, 0, new Class[]{DialogCell.class, ProfileSearchCell.class}, null, new Paint[]{Theme.dialogs_namePaint[0], Theme.dialogs_namePaint[1], Theme.dialogs_searchNamePaint}, null, null, Theme.key_chats_name)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java index 575889294..4bef4765f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java @@ -16,10 +16,17 @@ import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; +import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLog; @@ -27,6 +34,7 @@ import org.telegram.messenger.LocaleController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.Utilities; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.AlertDialog; @@ -39,17 +47,13 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.EmojiTextView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.ProgressButton; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.ItemTouchHelper; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class FiltersSetupActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private RecyclerListView listView; @@ -57,6 +61,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe private ItemTouchHelper itemTouchHelper; private boolean orderChanged; + private boolean showAllChats; private int filterHelpRow; private int recommendedHeaderRow; @@ -196,6 +201,14 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe canvas.drawLine(0, getHeight() - 1, getWidth() - getPaddingRight(), getHeight() - 1, Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setEnabled(true); + info.setText(addButton.getText()); + info.setClassName("android.widget.Button"); + } } @SuppressWarnings("FieldCanBeLocal") @@ -211,6 +224,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe imageView.setAnimation(R.raw.filters, 90, 90); imageView.setScaleType(ImageView.ScaleType.CENTER); imageView.playAnimation(); + imageView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); addView(imageView, LayoutHelper.createFrame(90, 90, Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 14, 0, 0)); imageView.setOnClickListener(v -> { if (!imageView.isPlaying()) { @@ -235,13 +249,14 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe public static class FilterCell extends FrameLayout { - private TextView textView; + private SimpleTextView textView; private TextView valueTextView; @SuppressWarnings("FieldCanBeLocal") private ImageView moveImageView; @SuppressWarnings("FieldCanBeLocal") private ImageView optionsImageView; private boolean needDivider; + float progressToLock; private MessagesController.DialogFilter currentFilter; @@ -258,14 +273,14 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe moveImageView.setClickable(true); addView(moveImageView, LayoutHelper.createFrame(48, 48, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, 6, 0, 6, 0)); - textView = new EmojiTextView(context); + textView = new SimpleTextView(context); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); - textView.setLines(1); + textView.setTextSize(16); textView.setMaxLines(1); - textView.setSingleLine(true); textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); - textView.setEllipsize(TextUtils.TruncateAt.END); + Drawable drawable = ContextCompat.getDrawable(getContext(), R.drawable.other_lockedfolders2); + drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_stickers_menu), PorterDuff.Mode.MULTIPLY)); + textView.setRightDrawable(drawable); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 80 : 64, 14, LocaleController.isRTL ? 64 : 80, 0)); valueTextView = new TextView(context); @@ -296,10 +311,13 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe } public void setFilter(MessagesController.DialogFilter filter, boolean divider) { + int oldId = currentFilter == null ? -1 : currentFilter.id; currentFilter = filter; + int newId = currentFilter == null ? -1 : currentFilter.id; + boolean animated = oldId != newId; StringBuilder info = new StringBuilder(); - if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) { + if (filter.isDefault() || (filter.flags & MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) == MessagesController.DIALOG_FILTER_FLAG_ALL_CHATS) { info.append(LocaleController.getString("FilterAllChats", R.string.FilterAllChats)); } else { if ((filter.flags & MessagesController.DIALOG_FILTER_FLAG_CONTACTS) != 0) { @@ -343,10 +361,24 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe info.append(LocaleController.getString("FilterNoChats", R.string.FilterNoChats)); } - textView.setText(filter.name); + String name = filter.name; + if (filter.isDefault()) { + name = LocaleController.getString("FilterAllChats", R.string.FilterAllChats); + } + if (!animated) { + progressToLock = currentFilter.locked ? 1f : 0; + } + textView.setText(Emoji.replaceEmoji(name, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false)); + valueTextView.setText(info); - //valueTextView.setVisibility(VISIBLE); needDivider = divider; + + if (filter.isDefault()) { + optionsImageView.setVisibility(View.GONE); + } else { + optionsImageView.setVisibility(View.VISIBLE); + } + invalidate(); } public MessagesController.DialogFilter getCurrentFilter() { @@ -362,6 +394,18 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe if (needDivider) { canvas.drawLine(0, getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight() - 1, Theme.dividerPaint); } + if (currentFilter != null) { + if (currentFilter.locked && progressToLock != 1f) { + progressToLock += 16 / 150f; + invalidate(); + } else if (!currentFilter.locked && progressToLock != 0) { + progressToLock -= 16 / 150f; + invalidate(); + } + } + progressToLock = Utilities.clamp(progressToLock, 1f, 0f); + textView.setRightDrawableScale(progressToLock); + textView.invalidate(); } @SuppressLint("ClickableViewAccessibility") @@ -388,6 +432,12 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe rowCount = 0; filterHelpRow = rowCount++; int count = getMessagesController().dialogFilters.size(); + if (!getUserConfig().isPremium()) { + count--; + showAllChats = false; + } else { + showAllChats = true; + } if (!suggestedFilters.isEmpty() && count < 10) { recommendedHeaderRow = rowCount++; recommendedStartRow = rowCount; @@ -406,7 +456,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe filtersStartRow = -1; filtersEndRow = -1; } - if (count < 10) { + if (count < getMessagesController().dialogFiltersLimitPremium) { createFilterRow = rowCount++; } else { createFilterRow = -1; @@ -429,7 +479,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe ArrayList filters = getMessagesController().dialogFilters; for (int a = 0, N = filters.size(); a < N; a++) { MessagesController.DialogFilter filter = filters.get(a); - req.order.add(filters.get(a).id); + req.order.add(filter.id); } getConnectionsManager().sendRequest(req, (response, error) -> { @@ -456,7 +506,17 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe FrameLayout frameLayout = (FrameLayout) fragmentView; frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - listView = new RecyclerListView(context); + listView = new RecyclerListView(context) { + @Override + public boolean onTouchEvent(MotionEvent e) { + if (e.getAction() == MotionEvent.ACTION_UP || e.getAction() == MotionEvent.ACTION_CANCEL) { + AndroidUtilities.runOnUIThread(() -> { + getMessagesController().lockFiltersInternal(); + }, 250); + } + return super.onTouchEvent(e); + } + }; ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setVerticalScrollBarEnabled(false); @@ -466,9 +526,25 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe listView.setAdapter(adapter = new ListAdapter(context)); listView.setOnItemClickListener((view, position, x, y) -> { if (position >= filtersStartRow && position < filtersEndRow) { - presentFragment(new FilterCreateActivity(getMessagesController().dialogFilters.get(position - filtersStartRow))); + int filterPosition = position - filtersStartRow; + if (!showAllChats) { + filterPosition++; + } + if (getMessagesController().dialogFilters.get(filterPosition).isDefault()) { + return; + } + MessagesController.DialogFilter filter = getMessagesController().dialogFilters.get(filterPosition); + if (filter.locked) { + showDialog(new LimitReachedBottomSheet(this, context, LimitReachedBottomSheet.TYPE_FOLDERS, currentAccount)); + } else { + presentFragment(new FilterCreateActivity(getMessagesController().dialogFilters.get(filterPosition))); + } } else if (position == createFilterRow) { - presentFragment(new FilterCreateActivity()); + if ((getMessagesController().dialogFilters.size() - 1 >= getMessagesController().dialogFiltersLimitDefault && !getUserConfig().isPremium()) || getMessagesController().dialogFilters.size() >= getMessagesController().dialogFiltersLimitPremium) { + showDialog(new LimitReachedBottomSheet(this, context, LimitReachedBottomSheet.TYPE_FOLDERS, currentAccount)); + } else { + presentFragment(new FilterCreateActivity()); + } } }); @@ -489,7 +565,13 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe if (ignoreUpdates) { return; } - updateRows(true); + int rowCount = this.rowCount; + updateRows(false); + if (rowCount != this.rowCount) { + adapter.notifyDataSetChanged(); + } else { + adapter.notifyItemRangeChanged(0, rowCount); + } getNotificationCenter().addObserver(this, NotificationCenter.suggestedFiltersLoaded); if (getMessagesController().suggestedFilters.isEmpty()) { getMessagesController().loadSuggestedFilters(); @@ -556,7 +638,11 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe }; builder1.setItems(items, icons, (dialog, which) -> { if (which == 0) { - presentFragment(new FilterCreateActivity(filter)); + if (filter.locked) { + showDialog(new LimitReachedBottomSheet(FiltersSetupActivity.this, mContext, LimitReachedBottomSheet.TYPE_FOLDERS, currentAccount)); + } else { + presentFragment(new FilterCreateActivity(filter)); + } } else if (which == 1) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("FilterDelete", R.string.FilterDelete)); @@ -584,6 +670,9 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe if (idx >= 0) { idx += filtersStartRow; } + if (!showAllChats) { + idx--; + } ignoreUpdates = true; getMessagesController().removeFilter(filter); getMessagesStorage().deleteDialogFilter(filter); @@ -732,7 +821,11 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe } case 2: { FilterCell filterCell = (FilterCell) holder.itemView; - filterCell.setFilter(getMessagesController().dialogFilters.get(position - filtersStartRow), true); + int filterPosition = position - filtersStartRow; + if (!showAllChats) { + filterPosition++; + } + filterCell.setFilter(getMessagesController().dialogFilters.get(filterPosition), true); break; } case 3: { @@ -786,6 +879,12 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe int idx1 = fromIndex - filtersStartRow; int idx2 = toIndex - filtersStartRow; int count = filtersEndRow - filtersStartRow; + if (!showAllChats) { + idx1++; + idx2++; + count++; + } + if (idx1 < 0 || idx2 < 0 || idx1 >= count || idx2 >= count) { return; } @@ -811,7 +910,8 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { - if (viewHolder.getItemViewType() != 2) { + boolean canMove = getUserConfig().isPremium() || !((viewHolder.itemView instanceof FilterCell) && ((FilterCell) viewHolder.itemView).currentFilter.isDefault()); + if (viewHolder.getItemViewType() != 2 || !canMove) { return makeMovementFlags(0, 0); } return makeMovementFlags(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0); @@ -819,7 +919,8 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { - if (source.getItemViewType() != target.getItemViewType()) { + boolean canMove = getUserConfig().isPremium() || !((target.itemView instanceof FilterCell) && ((FilterCell) target.itemView).currentFilter.isDefault()); + if (source.getItemViewType() != target.getItemViewType() || !canMove) { return false; } adapter.swapElements(source.getAdapterPosition(), target.getAdapterPosition()); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GLIconSettingsView.java b/TMessagesProj/src/main/java/org/telegram/ui/GLIconSettingsView.java new file mode 100644 index 000000000..a52dfefe7 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/GLIconSettingsView.java @@ -0,0 +1,236 @@ +package org.telegram.ui; + +import android.content.Context; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.LocaleController; +import org.telegram.ui.ActionBar.BottomSheet; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.ColorPicker; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.GLIcon.GLIconRenderer; +import org.telegram.ui.Components.SeekBarView; + +public class GLIconSettingsView extends LinearLayout { + + public static float smallStarsSize = 1f; + + public GLIconSettingsView(Context context, GLIconRenderer mRenderer) { + super(context); + setOrientation(VERTICAL); + + TextView saturationTextView = new TextView(context); + saturationTextView.setText("Spectral top "); + saturationTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + + SeekBarView seekBar = new SeekBarView(context); + seekBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + mRenderer.star.spec1 = 2 * progress; + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + seekBar.setProgress(mRenderer.star.spec1 / 2); + seekBar.setReportChanges(true); + addView(seekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 5, 4, 5, 0)); + + + saturationTextView = new TextView(context); + saturationTextView.setText("Spectral bottom "); + saturationTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + + seekBar = new SeekBarView(context); + seekBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + mRenderer.star.spec2 = 2 * progress; + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + seekBar.setProgress(mRenderer.star.spec2 / 2); + seekBar.setReportChanges(true); + addView(seekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 5, 4, 5, 0)); + + + saturationTextView = new TextView(context); + saturationTextView.setText("Setup spec color"); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setGravity(Gravity.CENTER); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setTextColor(Theme.getColor((Theme.key_featuredStickers_buttonText))); + saturationTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 4)); + saturationTextView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + ColorPicker colorPicker = new ColorPicker(context, false, new ColorPicker.ColorPickerDelegate() { + + @Override + public void setColor(int color, int num, boolean applyNow) { + mRenderer.star.specColor = color; + } + }) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(300), MeasureSpec.EXACTLY)); + } + }; + colorPicker.setColor(mRenderer.star.specColor, 0); + colorPicker.setType(-1, true, 1, 1, false, 0, false); + BottomSheet bottomSheet = new BottomSheet(context, false); + bottomSheet.setCustomView(colorPicker); + bottomSheet.setDimBehind(false); + bottomSheet.show(); + } + }); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + + + saturationTextView = new TextView(context); + saturationTextView.setText("Diffuse "); + saturationTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + + seekBar = new SeekBarView(context); + seekBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + mRenderer.star.diffuse = progress; + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + seekBar.setProgress(mRenderer.star.diffuse); + seekBar.setReportChanges(true); + addView(seekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 5, 4, 5, 0)); + + saturationTextView = new TextView(context); + saturationTextView.setText("Normal map spectral"); + saturationTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + + seekBar = new SeekBarView(context); + seekBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + mRenderer.star.normalSpec = 2 * progress; + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + seekBar.setProgress(mRenderer.star.normalSpec / 2); + seekBar.setReportChanges(true); + addView(seekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 5, 4, 5, 0)); + + + saturationTextView = new TextView(context); + saturationTextView.setText("Setup normal spec color"); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setGravity(Gravity.CENTER); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setTextColor(Theme.getColor((Theme.key_featuredStickers_buttonText))); + saturationTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_featuredStickers_addButton), 4)); + // addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + saturationTextView.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + ColorPicker colorPicker = new ColorPicker(context, false, new ColorPicker.ColorPickerDelegate() { + + @Override + public void setColor(int color, int num, boolean applyNow) { + if (num == 0) { + mRenderer.star.normalSpecColor = color; + } + } + }) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(300), MeasureSpec.EXACTLY)); + } + }; + colorPicker.setColor(mRenderer.star.normalSpecColor, 0); + colorPicker.setType(-1, true, 1, 1, false, 0, false); + BottomSheet bottomSheet = new BottomSheet(context, false); + bottomSheet.setCustomView(colorPicker); + bottomSheet.setDimBehind(false); + bottomSheet.show(); + } + }); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + + + + saturationTextView = new TextView(context); + saturationTextView.setText("Small starts size"); + saturationTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlue2)); + saturationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + saturationTextView.setLines(1); + saturationTextView.setMaxLines(1); + saturationTextView.setSingleLine(true); + saturationTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP); + addView(saturationTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, 21, 13, 21, 0)); + + seekBar = new SeekBarView(context); + seekBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + smallStarsSize = progress * 2; + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + seekBar.setProgress(smallStarsSize / 2); + seekBar.setReportChanges(true); + addView(seekBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, 0, 5, 4, 5, 0)); + + } + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java index a106668a1..a3415561f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCallActivity.java @@ -43,6 +43,7 @@ import android.text.InputType; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.Log; import android.util.Property; import android.util.TypedValue; import android.view.Gravity; @@ -382,6 +383,8 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter private HashMap buttonsAnimationParamsY = new HashMap<>(); boolean animateButtonsOnNextLayout; + private Runnable onUserLeaveHintListener = this::onUserLeaveHint; + private Runnable updateSchedeulRunnable = new Runnable() { @Override public void run() { @@ -1064,6 +1067,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter @Override public void dismiss() { + parentActivity.removeOnUserLeaveHintListener(onUserLeaveHintListener); parentActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); groupCallUiVisible = false; if (groupVoipInviteAlert != null) { @@ -1263,7 +1267,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (child instanceof ActionBarMenuSubItem && child.getTag() != null && (Integer) child.getTag() == 10) { ((ActionBarMenuSubItem) child).setTextAndIcon( TextUtils.isEmpty(participant.about) ? LocaleController.getString("VoipAddDescription", R.string.VoipAddDescription) : LocaleController.getString("VoipEditDescription", R.string.VoipEditDescription), - TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_bio + TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_info ); } } @@ -1304,7 +1308,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (child instanceof ActionBarMenuSubItem && child.getTag() != null && (Integer) child.getTag() == 10) { ((ActionBarMenuSubItem) child).setTextAndIcon( TextUtils.isEmpty(participant.about) ? LocaleController.getString("VoipAddBio", R.string.VoipAddBio) : LocaleController.getString("VoipEditBio", R.string.VoipEditBio), - TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_bio + TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_info ); } } @@ -1741,6 +1745,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter return true; } }); + drawDoubleNavigationBar = true; drawNavigationBar = true; if (Build.VERSION.SDK_INT >= 30) { getWindow().setNavigationBarColor(0xff000000); @@ -1761,7 +1766,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter BaseFragment fragment = parentActivity.getActionBarLayout().fragmentsStack.get(parentActivity.getActionBarLayout().fragmentsStack.size() - 1); if (anyEnterEventSent) { if (fragment instanceof ChatActivity) { - ((ChatActivity) fragment).onEditTextDialogClose(true); + ((ChatActivity) fragment).onEditTextDialogClose(true, true); } } }); @@ -2168,6 +2173,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter BottomSheet bottomSheet = builder.create(); bottomSheet.setBackgroundColor(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled)); + bottomSheet.fixNavigationBar(Theme.getColor(Theme.key_voipgroup_listViewBackgroundUnscrolled)); int selectedPosition; if (service.getCurrentAudioRoute() == VoIPService.AUDIO_ROUTE_SPEAKER) { selectedPosition = 0; @@ -2183,6 +2189,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter int color; if (i == selectedPosition) { color = Theme.getColor(Theme.key_voipgroup_listeningText); + cell.isSelected = true; } else { color = Theme.getColor(Theme.key_voipgroup_nameText); } @@ -6065,6 +6072,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } ObjectAnimator subtitleYAnimator; + ObjectAnimator additionalSubtitleYAnimator; public void invalidateActionBarAlpha() { actionBar.setAlpha((actionBar.getTag() != null ? 1f : 0f) * (1f - renderersContainer.progressToFullscreenMode)); @@ -6106,7 +6114,6 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter .setInterpolator(CubicBezierInterpolator.DEFAULT) .start(); - if (subtitleYAnimator != null) { subtitleYAnimator.removeAllListeners(); subtitleYAnimator.cancel(); @@ -6123,11 +6130,13 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter }); subtitleYAnimator.start(); - actionBar.getAdditionalSubtitleTextView().animate() - .translationY(show ? 0.0f : AndroidUtilities.dp(20)) - .setDuration(300) - .setInterpolator(CubicBezierInterpolator.DEFAULT) - .start(); + if (additionalSubtitleYAnimator != null) { + additionalSubtitleYAnimator.cancel(); + } + additionalSubtitleYAnimator = ObjectAnimator.ofFloat(actionBar.getAdditionalSubtitleTextView(), View.TRANSLATION_Y, show ? 0.0f : AndroidUtilities.dp(20)); + additionalSubtitleYAnimator.setDuration(300); + additionalSubtitleYAnimator.setInterpolator(CubicBezierInterpolator.DEFAULT); + additionalSubtitleYAnimator.start(); actionBarAnimation = new AnimatorSet(); actionBarAnimation.setDuration(140); @@ -7321,7 +7330,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } else { items.add(TextUtils.isEmpty(participant.about) ? LocaleController.getString("VoipAddDescription", R.string.VoipAddDescription) : LocaleController.getString("VoipEditDescription", R.string.VoipEditDescription)); } - icons.add(TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_bio); + icons.add(TextUtils.isEmpty(participant.about) ? R.drawable.msg_addbio : R.drawable.msg_info); options.add(10); items.add(peerId > 0 ? LocaleController.getString("VoipEditName", R.string.VoipEditName) : LocaleController.getString("VoipEditTitle", R.string.VoipEditTitle)); @@ -7955,7 +7964,7 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter if (ChatObject.isChannel(currentChat) && !currentChat.megagroup && !TextUtils.isEmpty(currentChat.username)) { textCell.setTextAndIcon(LocaleController.getString("VoipGroupShareLink", R.string.VoipGroupShareLink), R.drawable.msg_link, false); } else { - textCell.setTextAndIcon(LocaleController.getString("VoipGroupInviteMember", R.string.VoipGroupInviteMember), R.drawable.actions_addmember2, false); + textCell.setTextAndIcon(LocaleController.getString("VoipGroupInviteMember", R.string.VoipGroupInviteMember), R.drawable.msg_contact_add, false); } break; case VIEW_TYPE_PARTICIPANT: { @@ -8392,8 +8401,8 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } if (small != null && avatar != null) { - File destFile = FileLoader.getPathToAttach(small, true); - File src = FileLoader.getPathToAttach(avatar, true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(small, true); + File src = FileLoader.getInstance(currentAccount).getPathToAttach(avatar, true); src.renameTo(destFile); String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; @@ -8401,12 +8410,12 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter } if (big != null && avatarBig != null) { - File destFile = FileLoader.getPathToAttach(big, true); - File src = FileLoader.getPathToAttach(avatarBig, true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(big, true); + File src = FileLoader.getInstance(currentAccount).getPathToAttach(avatarBig, true); src.renameTo(destFile); } if (videoSize != null && videoPath != null) { - File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(videoSize, "mp4", true); File src = new File(videoPath); src.renameTo(destFile); } @@ -8617,6 +8626,20 @@ public class GroupCallActivity extends BottomSheet implements NotificationCenter return !renderersContainer.inFullscreenMode; } + private void onUserLeaveHint() { + if (isRtmpStream() && AndroidUtilities.checkInlinePermissions(parentActivity) && !RTMPStreamPipOverlay.isVisible()) { + dismiss(); + AndroidUtilities.runOnUIThread(RTMPStreamPipOverlay::show, 100); + } + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + parentActivity.addOnUserLeaveHintListener(onUserLeaveHintListener); + } + public void onResume() { paused = false; listAdapter.notifyDataSetChanged(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java index 7546393af..65bff5adf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java @@ -23,11 +23,6 @@ import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; -import androidx.annotation.Keep; -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - import android.text.Editable; import android.text.InputType; import android.text.SpannableStringBuilder; @@ -51,6 +46,11 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; +import androidx.annotation.Keep; +import androidx.collection.LongSparseArray; +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; @@ -1373,9 +1373,9 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen case 2: { TextCell textCell = (TextCell) holder.itemView; if (inviteViaLink == 2) { - textCell.setTextAndIcon(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), R.drawable.profile_link, false); + textCell.setTextAndIcon(LocaleController.getString("ChannelInviteViaLink", R.string.ChannelInviteViaLink), R.drawable.msg_link2, false); } else { - textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.profile_link, false); + textCell.setTextAndIcon(LocaleController.getString("InviteToGroupByLink", R.string.InviteToGroupByLink), R.drawable.msg_link2, false); } break; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java index d908fe2e9..d0ab0a93e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupStickersActivity.java @@ -8,36 +8,26 @@ package org.telegram.ui; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; +import android.annotation.SuppressLint; import android.content.Context; -import android.content.SharedPreferences; -import android.graphics.Canvas; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; -import android.graphics.Rect; -import android.net.Uri; -import android.text.Editable; -import android.text.InputType; import android.text.SpannableStringBuilder; import android.text.Spanned; -import android.text.TextWatcher; -import android.util.TypedValue; -import android.view.Gravity; +import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; -import android.view.inputmethod.EditorInfo; +import android.widget.EditText; import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; @@ -55,58 +45,46 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.StickerSetCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; -import org.telegram.ui.Components.ContextProgressView; -import org.telegram.ui.Components.EditTextBoldCursor; +import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.StickerEmptyView; import org.telegram.ui.Components.StickersAlert; import org.telegram.ui.Components.URLSpanNoUnderline; +import org.telegram.ui.Components.VerticalPositionAutoAnimator; import java.util.ArrayList; import java.util.List; - -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; +import java.util.Locale; +import java.util.Objects; public class GroupStickersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + private FrameLayout emptyFrameView; + private StickerEmptyView emptyView; + private FlickerLoadingView loadingView; + private RecyclerListView listView; private ListAdapter listAdapter; - private ActionBarMenuItem doneItem; - private ContextProgressView progressView; - private AnimatorSet doneItemAnimation; - private LinearLayout nameContainer; - private EditTextBoldCursor editText; - private EditTextBoldCursor usernameTextView; + private SearchAdapter searchAdapter; private LinearLayoutManager layoutManager; - private ImageView eraseImageView; - private Runnable queryRunnable; - - private boolean searchWas; - private boolean searching; - - private boolean ignoreTextChanges; - - private int reqId; + private int selectedStickerSetIndex = -1; private TLRPC.TL_messages_stickerSet selectedStickerSet; + private boolean removeStickerSet; private TLRPC.ChatFull info; private long chatId; - private boolean donePressed; - - private int nameRow; private int infoRow; - private int selectedStickerRow; private int headerRow; private int stickersStartRow; private int stickersEndRow; - private int stickersShadowRow; private int rowCount; - private final static int done_button = 1; + private ActionBarMenuItem searchItem; + private boolean searching; public GroupStickersActivity(long id) { super(); @@ -130,6 +108,10 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.chatInfoDidLoad); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupStickersDidLoad); + + if (selectedStickerSet != null || removeStickerSet) { + saveStickerSet(); + } } @Override @@ -142,218 +124,198 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC public void onItemClick(int id) { if (id == -1) { finishFragment(); - } else if (id == done_button) { - if (donePressed) { - return; - } - donePressed = true; - if (searching) { - showEditDoneProgress(true); - return; - } - saveStickerSet(); } } }); ActionBarMenu menu = actionBar.createMenu(); - doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); - progressView = new ContextProgressView(context, 1); - progressView.setAlpha(0.0f); - progressView.setScaleX(0.1f); - progressView.setScaleY(0.1f); - progressView.setVisibility(View.INVISIBLE); - doneItem.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - - nameContainer = new LinearLayout(context) { + searchItem = menu.addItem(0, R.drawable.ic_ab_search); + searchItem.setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(42), MeasureSpec.EXACTLY)); - } + public void onSearchExpand() {} @Override - protected void onDraw(Canvas canvas) { - if (selectedStickerSet != null) { - canvas.drawLine(0, getHeight() - 1, getWidth(), getHeight() - 1, Theme.dividerPaint); + public void onSearchCollapse() { + if (searching) { + searchAdapter.onSearchStickers(null); + searching = false; + listView.setAdapter(listAdapter); } } - }; - nameContainer.setWeightSum(1.0f); - nameContainer.setWillNotDraw(false); - nameContainer.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - nameContainer.setOrientation(LinearLayout.HORIZONTAL); - nameContainer.setPadding(AndroidUtilities.dp(17), 0, AndroidUtilities.dp(14), 0); - - editText = new EditTextBoldCursor(context); - editText.setText(MessagesController.getInstance(currentAccount).linkPrefix + "/addstickers/"); - editText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - editText.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - editText.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - editText.setMaxLines(1); - editText.setLines(1); - editText.setEnabled(false); - editText.setFocusable(false); - editText.setBackgroundDrawable(null); - editText.setPadding(0, 0, 0, 0); - editText.setGravity(Gravity.CENTER_VERTICAL); - editText.setSingleLine(true); - editText.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - editText.setImeOptions(EditorInfo.IME_ACTION_DONE); - nameContainer.addView(editText, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, 42)); - - usernameTextView = new EditTextBoldCursor(context); - usernameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - usernameTextView.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - usernameTextView.setCursorSize(AndroidUtilities.dp(20)); - usernameTextView.setCursorWidth(1.5f); - usernameTextView.setHintTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); - usernameTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); - usernameTextView.setMaxLines(1); - usernameTextView.setLines(1); - usernameTextView.setBackgroundDrawable(null); - usernameTextView.setPadding(0, 0, 0, 0); - usernameTextView.setSingleLine(true); - usernameTextView.setGravity(Gravity.CENTER_VERTICAL); - usernameTextView.setInputType(InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT); - usernameTextView.setImeOptions(EditorInfo.IME_ACTION_DONE); - usernameTextView.setHint(LocaleController.getString("ChooseStickerSetPlaceholder", R.string.ChooseStickerSetPlaceholder)); - usernameTextView.addTextChangedListener(new TextWatcher() { - - boolean ignoreTextChange; @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { + public void onTextChanged(EditText editText) { + String text = editText.getText().toString(); + searchAdapter.onSearchStickers(text); - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - - } - - @Override - public void afterTextChanged(Editable s) { - if (eraseImageView != null) { - eraseImageView.setVisibility(s.length() > 0 ? View.VISIBLE : View.INVISIBLE); - } - if (ignoreTextChange || ignoreTextChanges) { - return; - } - if (s.length() > 5) { - ignoreTextChange = true; - try { - Uri uri = Uri.parse(s.toString()); - if (uri != null) { - List segments = uri.getPathSegments(); - if (segments.size() == 2) { - if (segments.get(0).toLowerCase().equals("addstickers")) { - usernameTextView.setText(segments.get(1)); - usernameTextView.setSelection(usernameTextView.length()); - } - } - } - } catch (Exception ignore) { + boolean newSearching = !TextUtils.isEmpty(text); + if (newSearching != searching) { + searching = newSearching; + if (listView != null) { + listView.setAdapter(searching ? searchAdapter : listAdapter); } - ignoreTextChange = false; } - resolveStickerSet(); } }); - - nameContainer.addView(usernameTextView, LayoutHelper.createLinear(0, 42, 1.0f)); - - eraseImageView = new ImageView(context); - eraseImageView.setScaleType(ImageView.ScaleType.CENTER); - eraseImageView.setImageResource(R.drawable.ic_close_white); - eraseImageView.setPadding(AndroidUtilities.dp(16), 0, 0, 0); - eraseImageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3), PorterDuff.Mode.SRC_IN)); - eraseImageView.setVisibility(View.INVISIBLE); - eraseImageView.setOnClickListener(v -> { - searchWas = false; - selectedStickerSet = null; - usernameTextView.setText(""); - updateRows(); - }); - nameContainer.addView(eraseImageView, LayoutHelper.createLinear(42, 42, 0.0f)); - - if (info != null && info.stickerset != null) { - ignoreTextChanges = true; - usernameTextView.setText(info.stickerset.short_name); - usernameTextView.setSelection(usernameTextView.length()); - ignoreTextChanges = false; - } + searchItem.setSearchFieldHint(LocaleController.getString(R.string.Search)); listAdapter = new ListAdapter(context); + searchAdapter = new SearchAdapter(context); fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); listView = new RecyclerListView(context); - listView.setFocusable(true); - listView.setItemAnimator(null); - listView.setLayoutAnimation(null); - layoutManager = new LinearLayoutManager(context) { - @Override - public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect, boolean immediate, boolean focusedChildVisible) { - return false; - } - - @Override - public boolean supportsPredictiveItemAnimations() { - return false; - } - }; + DefaultItemAnimator defaultItemAnimator = new DefaultItemAnimator(); + defaultItemAnimator.setSupportsChangeAnimations(true); + listView.setItemAnimator(defaultItemAnimator); + layoutManager = new LinearLayoutManager(context); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); listView.setLayoutManager(layoutManager); + emptyFrameView = new FrameLayout(context); + emptyFrameView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + + loadingView = new FlickerLoadingView(context, getResourceProvider()); + loadingView.setViewType(FlickerLoadingView.STICKERS_TYPE); + loadingView.setIsSingleCell(true); + loadingView.setItemsCount((int) Math.ceil(AndroidUtilities.displaySize.y / AndroidUtilities.dpf2(58))); + emptyFrameView.addView(loadingView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); + + emptyView = new StickerEmptyView(context, loadingView, StickerEmptyView.STICKER_TYPE_SEARCH); + VerticalPositionAutoAnimator.attach(emptyView); + + emptyFrameView.addView(emptyView); + frameLayout.addView(emptyFrameView); + emptyFrameView.setVisibility(View.GONE); + listView.setEmptyView(emptyFrameView); + frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position) -> { if (getParentActivity() == null) { return; } - if (position == selectedStickerRow) { - if (selectedStickerSet == null) { - return; + if (searching) { + if (position > searchAdapter.searchEntries.size()) { + onStickerSetClicked(view, searchAdapter.localSearchEntries.get(position - searchAdapter.searchEntries.size() - 1), false); + } else if (position != searchAdapter.searchEntries.size()) { + onStickerSetClicked(view, searchAdapter.searchEntries.get(position), true); } - showDialog(new StickersAlert(getParentActivity(), GroupStickersActivity.this, null, selectedStickerSet, null)); - } else if (position >= stickersStartRow && position < stickersEndRow) { - boolean needScroll = selectedStickerRow == -1; + return; + } + + if (position >= stickersStartRow && position < stickersEndRow) { + TLRPC.TL_messages_stickerSet stickerSet = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE).get(position - stickersStartRow); + onStickerSetClicked(view, stickerSet, false); + } + }); + listView.setOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + } + } + }); + + return fragmentView; + } + + private void onStickerSetClicked(View view, TLRPC.TL_messages_stickerSet stickerSet, boolean remote) { + TLRPC.InputStickerSet inputStickerSet = null; + if (remote) { + TLRPC.TL_inputStickerSetShortName inputStickerSetShortName = new TLRPC.TL_inputStickerSetShortName(); + inputStickerSetShortName.short_name = stickerSet.set.short_name; + inputStickerSet = inputStickerSetShortName; + } + StickersAlert stickersAlert = new StickersAlert(getParentActivity(), GroupStickersActivity.this, inputStickerSet, !remote ? stickerSet : null, null); + boolean isSelected = ((StickerSetCell) view).isChecked(); + stickersAlert.setCustomButtonDelegate(new StickersAlert.StickersAlertCustomButtonDelegate() { + @Override + public String getCustomButtonTextColorKey() { + return isSelected ? Theme.key_dialogTextRed : Theme.key_featuredStickers_buttonText; + } + + @Override + public String getCustomButtonRippleColorKey() { + return !isSelected ? Theme.key_featuredStickers_addButtonPressed : null; + } + + @Override + public String getCustomButtonColorKey() { + return !isSelected ? Theme.key_featuredStickers_addButton : null; + } + + @Override + public String getCustomButtonText() { + return LocaleController.getString(isSelected ? R.string.RemoveGroupStickerSet : R.string.SetAsGroupStickerSet); + } + + @Override + public boolean onCustomButtonPressed() { int row = layoutManager.findFirstVisibleItemPosition(); int top = Integer.MAX_VALUE; RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.findViewHolderForAdapterPosition(row); if (holder != null) { top = holder.itemView.getTop(); } - selectedStickerSet = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE).get(position - stickersStartRow); - ignoreTextChanges = true; - usernameTextView.setText(selectedStickerSet.set.short_name); - usernameTextView.setSelection(usernameTextView.length()); - ignoreTextChanges = false; - AndroidUtilities.hideKeyboard(usernameTextView); - updateRows(); - if (needScroll && top != Integer.MAX_VALUE) { + int prevIndex = selectedStickerSetIndex; + if (isSelected) { + selectedStickerSet = null; + removeStickerSet = true; + } else { + selectedStickerSet = stickerSet; + removeStickerSet = false; + } + updateSelectedStickerSetIndex(); + + if (prevIndex != -1) { + boolean found = false; + if (!searching) { + for (int i = 0; i < listView.getChildCount(); i++) { + View ch = listView.getChildAt(i); + if (listView.getChildViewHolder(ch).getAdapterPosition() == stickersStartRow + prevIndex) { + ((StickerSetCell) ch).setChecked(false, true); + found = true; + break; + } + } + } + if (!found) { + listAdapter.notifyItemChanged(prevIndex); + } + } + if (selectedStickerSetIndex != -1) { + boolean found = false; + if (!searching) { + for (int i = 0; i < listView.getChildCount(); i++) { + View ch = listView.getChildAt(i); + if (listView.getChildViewHolder(ch).getAdapterPosition() == stickersStartRow + selectedStickerSetIndex) { + ((StickerSetCell) ch).setChecked(true, true); + found = true; + break; + } + } + } + if (!found) { + listAdapter.notifyItemChanged(selectedStickerSetIndex); + } + } + + if (top != Integer.MAX_VALUE) { layoutManager.scrollToPositionWithOffset(row + 1, top); } - } - }); - listView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { - AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); + if (searching) { + searchItem.setSearchFieldText("", false); + actionBar.closeSearchField(true); } - } - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - + return true; } }); - - return fragmentView; + stickersAlert.show(); } @Override @@ -373,7 +335,7 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC } } else if (id == NotificationCenter.groupStickersDidLoad) { long setId = (Long) args[0]; - if (info != null && info.stickerset != null && info.stickerset.id == id) { + if (info != null && info.stickerset != null && info.stickerset.id == setId) { updateRows(); } } @@ -386,104 +348,16 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC } } - private void resolveStickerSet() { - if (listAdapter == null) { - return; - } - if (reqId != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(reqId, true); - reqId = 0; - } - if (queryRunnable != null) { - AndroidUtilities.cancelRunOnUIThread(queryRunnable); - queryRunnable = null; - } - selectedStickerSet = null; - if (usernameTextView.length() <= 0) { - searching = false; - searchWas = false; - if (selectedStickerRow != -1) { - updateRows(); - } - return; - } - searching = true; - searchWas = true; - final String query = usernameTextView.getText().toString(); - TLRPC.TL_messages_stickerSet existingSet = MediaDataController.getInstance(currentAccount).getStickerSetByName(query); - if (existingSet != null) { - selectedStickerSet = existingSet; - } - if (selectedStickerRow == -1) { - updateRows(); - } else { - listAdapter.notifyItemChanged(selectedStickerRow); - } - if (existingSet != null) { - searching = false; - return; - } - AndroidUtilities.runOnUIThread(queryRunnable = () -> { - if (queryRunnable == null) { - return; - } - TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); - req.stickerset = new TLRPC.TL_inputStickerSetShortName(); - req.stickerset.short_name = query; - reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - searching = false; - if (response instanceof TLRPC.TL_messages_stickerSet) { - selectedStickerSet = (TLRPC.TL_messages_stickerSet) response; - if (donePressed) { - saveStickerSet(); - } else { - if (selectedStickerRow != -1) { - listAdapter.notifyItemChanged(selectedStickerRow); - } else { - updateRows(); - } - } - } else { - if (selectedStickerRow != -1) { - listAdapter.notifyItemChanged(selectedStickerRow); - } - if (donePressed) { - donePressed = false; - showEditDoneProgress(false); - if (getParentActivity() != null) { - Toast.makeText(getParentActivity(), LocaleController.getString("AddStickersNotFound", R.string.AddStickersNotFound), Toast.LENGTH_SHORT).show(); - } - } - } - reqId = 0; - })); - }, 500); - } - - @Override - public void onTransitionAnimationEnd(boolean isOpen, boolean backward) { - if (isOpen) { - AndroidUtilities.runOnUIThread(() -> { - if (usernameTextView != null) { - usernameTextView.requestFocus(); - AndroidUtilities.showKeyboard(usernameTextView); - } - }, 100); - } - } - private void saveStickerSet() { if (info == null || info.stickerset != null && selectedStickerSet != null && selectedStickerSet.set.id == info.stickerset.id || info.stickerset == null && selectedStickerSet == null) { - finishFragment(); return; } - showEditDoneProgress(true); TLRPC.TL_channels_setStickers req = new TLRPC.TL_channels_setStickers(); req.channel = MessagesController.getInstance(currentAccount).getInputChannel(chatId); - if (selectedStickerSet == null) { + if (removeStickerSet) { req.stickerset = new TLRPC.TL_inputStickerSetEmpty(); } else { - MessagesController.getEmojiSettings(currentAccount).edit().remove("group_hide_stickers_" + info.id).commit(); + MessagesController.getEmojiSettings(currentAccount).edit().remove("group_hide_stickers_" + info.id).apply(); req.stickerset = new TLRPC.TL_inputStickerSetID(); req.stickerset.id = selectedStickerSet.set.id; req.stickerset.access_hash = selectedStickerSet.set.access_hash; @@ -496,6 +370,8 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC info.stickerset = selectedStickerSet.set; MediaDataController.getInstance(currentAccount).putGroupStickerSet(selectedStickerSet); } + updateSelectedStickerSetIndex(); + if (info.stickerset == null) { info.flags |= 256; } else { @@ -505,111 +381,228 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.chatInfoDidLoad, info, 0, true, false); finishFragment(); } else { - Toast.makeText(getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text, Toast.LENGTH_SHORT).show(); - donePressed = false; - showEditDoneProgress(false); + if (getParentActivity() != null) { + Toast.makeText(getParentActivity(), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text, Toast.LENGTH_SHORT).show(); + } } })); } + private void updateSelectedStickerSetIndex() { + ArrayList stickerSets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); + selectedStickerSetIndex = -1; + + long selectedSet; + + if (removeStickerSet) { + selectedSet = 0; + } else if (selectedStickerSet != null) { + selectedSet = selectedStickerSet.set.id; + } else if (info != null && info.stickerset != null) { + selectedSet = info.stickerset.id; + } else { + selectedSet = 0; + } + + if (selectedSet != 0) { + for (int i = 0; i < stickerSets.size(); i++) { + TLRPC.TL_messages_stickerSet set = stickerSets.get(i); + if (set.set.id == selectedSet) { + selectedStickerSetIndex = i; + break; + } + } + } + } + + @SuppressLint("NotifyDataSetChanged") private void updateRows() { rowCount = 0; - nameRow = rowCount++; - if (selectedStickerSet != null || searchWas) { - selectedStickerRow = rowCount++; - } else { - selectedStickerRow = -1; - } - infoRow = rowCount++; ArrayList stickerSets = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); if (!stickerSets.isEmpty()) { headerRow = rowCount++; stickersStartRow = rowCount; stickersEndRow = rowCount + stickerSets.size(); rowCount += stickerSets.size(); - stickersShadowRow = rowCount++; } else { headerRow = -1; stickersStartRow = -1; stickersEndRow = -1; - stickersShadowRow = -1; - } - if (nameContainer != null) { - nameContainer.invalidate(); } + infoRow = rowCount++; + updateSelectedStickerSetIndex(); + if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } } - @Override - public void onResume() { - super.onResume(); - if (listAdapter != null) { - listAdapter.notifyDataSetChanged(); - } - SharedPreferences preferences = MessagesController.getGlobalMainSettings(); - boolean animations = preferences.getBoolean("view_animations", true); - if (!animations) { - usernameTextView.requestFocus(); - AndroidUtilities.showKeyboard(usernameTextView); - } - } + private class SearchAdapter extends RecyclerListView.SelectionAdapter { + private final static int TYPE_STICKER_SET = 0, + TYPE_MY_STICKERS_HEADER = 1; - private void showEditDoneProgress(final boolean show) { - if (doneItem == null) { - return; - } - if (doneItemAnimation != null) { - doneItemAnimation.cancel(); - } - doneItemAnimation = new AnimatorSet(); - if (show) { - progressView.setVisibility(View.VISIBLE); - doneItem.setEnabled(false); - doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 0.1f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 0.0f), - ObjectAnimator.ofFloat(progressView, "scaleX", 1.0f), - ObjectAnimator.ofFloat(progressView, "scaleY", 1.0f), - ObjectAnimator.ofFloat(progressView, "alpha", 1.0f)); - } else { - doneItem.getContentView().setVisibility(View.VISIBLE); - doneItem.setEnabled(true); - doneItemAnimation.playTogether( - ObjectAnimator.ofFloat(progressView, "scaleX", 0.1f), - ObjectAnimator.ofFloat(progressView, "scaleY", 0.1f), - ObjectAnimator.ofFloat(progressView, "alpha", 0.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleX", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "scaleY", 1.0f), - ObjectAnimator.ofFloat(doneItem.getContentView(), "alpha", 1.0f)); + private Context mContext; + private List searchEntries = new ArrayList<>(); + private List localSearchEntries = new ArrayList<>(); + private Runnable lastCallback; + private String lastQuery; + private int reqId; + + public SearchAdapter(Context context) { + mContext = context; + setHasStableIds(true); } - doneItemAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - if (doneItemAnimation != null && doneItemAnimation.equals(animation)) { - if (!show) { - progressView.setVisibility(View.INVISIBLE); - } else { - doneItem.getContentView().setVisibility(View.INVISIBLE); + + @Override + public long getItemId(int position) { + if (getItemViewType(position) == TYPE_STICKER_SET) { + List arrayList = position > searchEntries.size() ? localSearchEntries : searchEntries; + int row = position > searchEntries.size() ? position - searchEntries.size() - 1 : position; + + return arrayList.get(row).set.id; + } + return -1; + } + + @SuppressLint("NotifyDataSetChanged") + private void onSearchStickers(String query) { + if (reqId != 0) { + getConnectionsManager().cancelRequest(reqId, true); + reqId = 0; + } + + if (lastCallback != null) { + AndroidUtilities.cancelRunOnUIThread(lastCallback); + lastCallback = null; + } + lastQuery = null; + + int count = getItemCount(); + if (count > 0) { + searchEntries.clear(); + localSearchEntries.clear(); + notifyItemRangeRemoved(0, count); + } + + if (TextUtils.isEmpty(query)) { + emptyView.setVisibility(View.GONE); + emptyView.showProgress(false, true); + return; + } + + if (emptyView.getVisibility() != View.VISIBLE) { + emptyView.setVisibility(View.VISIBLE); + emptyView.showProgress(true, false); + } else { + emptyView.showProgress(true, true); + } + AndroidUtilities.runOnUIThread(lastCallback = ()-> { + lastQuery = query; + + TLRPC.TL_messages_searchStickerSets searchStickerSets = new TLRPC.TL_messages_searchStickerSets(); + searchStickerSets.q = query; + reqId = getConnectionsManager().sendRequest(searchStickerSets, (response, error) -> { + if (!Objects.equals(lastQuery, searchStickerSets.q)) { + return; } - } - } - @Override - public void onAnimationCancel(Animator animation) { - if (doneItemAnimation != null && doneItemAnimation.equals(animation)) { - doneItemAnimation = null; + if (response instanceof TLRPC.TL_messages_foundStickerSets) { + List newSearchEntries = new ArrayList<>(); + TLRPC.TL_messages_foundStickerSets foundStickerSets = (TLRPC.TL_messages_foundStickerSets) response; + for (TLRPC.StickerSetCovered stickerSetCovered : foundStickerSets.sets) { + TLRPC.TL_messages_stickerSet set = new TLRPC.TL_messages_stickerSet(); + set.set = stickerSetCovered.set; + set.documents = stickerSetCovered.covers; + newSearchEntries.add(set); + } + String lowQuery = query.toLowerCase(Locale.ROOT).trim(); + List newLocalEntries = new ArrayList<>(); + for (TLRPC.TL_messages_stickerSet localSet : MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE)) { + if (localSet.set.short_name.toLowerCase(Locale.ROOT).contains(lowQuery) || localSet.set.title.toLowerCase(Locale.ROOT).contains(lowQuery)) { + newLocalEntries.add(localSet); + } + } + AndroidUtilities.runOnUIThread(()->{ + searchEntries = newSearchEntries; + localSearchEntries = newLocalEntries; + notifyDataSetChanged(); + + emptyView.title.setVisibility(View.GONE); + emptyView.subtitle.setText(LocaleController.formatString(R.string.ChooseStickerNoResultsFound, query)); + emptyView.showProgress(false, true); + }); + } + }, ConnectionsManager.RequestFlagInvokeAfter | ConnectionsManager.RequestFlagFailOnServerErrors); + }, 300); + } + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + switch (viewType) { + case TYPE_STICKER_SET: + view = new StickerSetCell(mContext, 3); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + default: + case TYPE_MY_STICKERS_HEADER: + view = new HeaderCell(mContext, Theme.key_windowBackgroundWhiteGrayText4, 21, 0, 0, false, getResourceProvider()); + view.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + ((HeaderCell) view).setText(LocaleController.getString(R.string.ChooseStickerMyStickerSets)); + break; + } + view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); + return new RecyclerListView.Holder(view); + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { + switch (getItemViewType(position)) { + case TYPE_STICKER_SET: { + boolean local = position > searchEntries.size(); + List arrayList = local ? localSearchEntries : searchEntries; + int row = local ? position - searchEntries.size() - 1 : position; + StickerSetCell cell = (StickerSetCell) holder.itemView; + TLRPC.TL_messages_stickerSet set = arrayList.get(row); + cell.setStickersSet(set, row != arrayList.size() - 1, !local); + cell.setSearchQuery(set, lastQuery != null ? lastQuery.toLowerCase(Locale.ROOT) : "", getResourceProvider()); + long id; + if (selectedStickerSet != null) { + id = selectedStickerSet.set.id; + } else if (info != null && info.stickerset != null) { + id = info.stickerset.id; + } else { + id = 0; + } + cell.setChecked(set.set.id == id, false); + break; } } - }); - doneItemAnimation.setDuration(150); - doneItemAnimation.start(); + } + + @Override + public int getItemViewType(int position) { + return searchEntries.size() == position ? TYPE_MY_STICKERS_HEADER : TYPE_STICKER_SET; + } + + @Override + public int getItemCount() { + return searchEntries.size() + localSearchEntries.size() + (localSearchEntries.isEmpty() ? 0 : 1); + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + int viewType = getItemViewType(holder.getAdapterPosition()); + return viewType == TYPE_STICKER_SET; + } } private class ListAdapter extends RecyclerListView.SelectionAdapter { + private final static int TYPE_STICKER_SET = 0, + TYPE_INFO = 1, + TYPE_CHOOSE_HEADER = 4; private Context mContext; @@ -625,7 +618,7 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 0: { + case TYPE_STICKER_SET: { ArrayList arrayList = MediaDataController.getInstance(currentAccount).getStickerSets(MediaDataController.TYPE_IMAGE); int row = position - stickersStartRow; StickerSetCell cell = (StickerSetCell) holder.itemView; @@ -639,10 +632,10 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC } else { id = 0; } - cell.setChecked(set.set.id == id); + cell.setChecked(set.set.id == id, false); break; } - case 1: { + case TYPE_INFO: { if (position == infoRow) { String text = LocaleController.getString("ChooseStickerSetMy", R.string.ChooseStickerSetMy); String botName = "@stickers"; @@ -668,21 +661,8 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC } break; } - case 4: { - ((HeaderCell) holder.itemView).setText(LocaleController.getString("ChooseFromYourStickers", R.string.ChooseFromYourStickers)); - break; - } - case 5: { - StickerSetCell cell = (StickerSetCell) holder.itemView; - if (selectedStickerSet != null) { - cell.setStickersSet(selectedStickerSet, false); - } else { - if (searching) { - cell.setText(LocaleController.getString("Loading", R.string.Loading), null, 0, false); - } else { - cell.setText(LocaleController.getString("ChooseStickerSetNotFound", R.string.ChooseStickerSetNotFound), LocaleController.getString("ChooseStickerSetNotFoundInfo", R.string.ChooseStickerSetNotFoundInfo), R.drawable.ic_smiles2_sad, false); - } - } + case TYPE_CHOOSE_HEADER: { + ((HeaderCell) holder.itemView).setText(LocaleController.getString(R.string.ChooseStickerSetHeader)); break; } } @@ -691,30 +671,23 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); - return type == 0 || type == 2 || type == 5; + return type == TYPE_STICKER_SET; } + @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: - case 5: - view = new StickerSetCell(mContext, viewType == 0 ? 3 : 2); + case TYPE_STICKER_SET: + view = new StickerSetCell(mContext, 3); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 1: + case TYPE_INFO: view = new TextInfoPrivacyCell(mContext); - view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + view.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; - case 2: - view = nameContainer; - break; - case 3: - view = new ShadowSectionCell(mContext); - view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - break; - case 4: + case TYPE_CHOOSE_HEADER: default: view = new HeaderCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -727,19 +700,13 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC @Override public int getItemViewType(int i) { if (i >= stickersStartRow && i < stickersEndRow) { - return 0; - } else if (i == infoRow) { - return 1; - } else if (i == nameRow) { - return 2; - } else if (i == stickersShadowRow) { - return 3; + return TYPE_STICKER_SET; } else if (i == headerRow) { - return 4; - } else if (i == selectedStickerRow) { - return 5; + return TYPE_CHOOSE_HEADER; + } else if (i == infoRow) { + return TYPE_INFO; } - return 0; + return TYPE_STICKER_SET; } } @@ -760,11 +727,6 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider)); - themeDescriptions.add(new ThemeDescription(editText, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(editText, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); - themeDescriptions.add(new ThemeDescription(usernameTextView, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); - themeDescriptions.add(new ThemeDescription(usernameTextView, ThemeDescription.FLAG_HINTTEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteHintText)); - themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{TextInfoPrivacyCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText4)); themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_LINKCOLOR, new Class[]{TextInfoPrivacyCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteLinkText)); @@ -774,8 +736,6 @@ public class GroupStickersActivity extends BaseFragment implements NotificationC themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_BACKGROUNDFILTER, new Class[]{ShadowSectionCell.class}, null, null, null, Theme.key_windowBackgroundGrayShadow)); - themeDescriptions.add(new ThemeDescription(nameContainer, ThemeDescription.FLAG_BACKGROUND, null, null, null, null, Theme.key_windowBackgroundWhite)); - themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{StickerSetCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{StickerSetCell.class}, new String[]{"valueTextView"}, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_USEBACKGROUNDDRAWABLE | ThemeDescription.FLAG_DRAWABLESELECTEDSTATE, new Class[]{StickerSetCell.class}, new String[]{"optionsButton"}, null, null, null, Theme.key_stickers_menuSelector)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java index ee28e895c..eaaf271f9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/IntroActivity.java @@ -327,7 +327,7 @@ public class IntroActivity extends BaseFragment implements NotificationCenter.No } cellFlickerDrawable.setParentWidth(getMeasuredWidth()); AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); - cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4)); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null); invalidate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/KeyboardHideHelper.java b/TMessagesProj/src/main/java/org/telegram/ui/KeyboardHideHelper.java new file mode 100644 index 000000000..8a4cfae65 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/KeyboardHideHelper.java @@ -0,0 +1,192 @@ +package org.telegram.ui; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.graphics.Insets; +import android.os.Build; +import android.os.CancellationSignal; +import android.util.Log; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.WindowInsetsAnimationControlListener; +import android.view.WindowInsetsAnimationController; +import android.view.animation.LinearInterpolator; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.math.MathUtils; +import androidx.core.view.WindowInsetsCompat; +import androidx.recyclerview.widget.GridLayoutManagerFixed; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.AdjustPanLayoutHelper; +import org.telegram.ui.Components.ChatActivityEnterView; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.RecyclerListView; + +public class KeyboardHideHelper { + + public static boolean ENABLED = false; + + public KeyboardHideHelper() { + + } + + private View view, enterView; + private AdjustPanLayoutHelper panLayoutHelper; + private WindowInsetsAnimationController insetsController; + private boolean isKeyboard = false; + private boolean movingKeyboard = false, exactlyMovingKeyboard = false; + private boolean endingMovingKeyboard = false; + private boolean startedOutsideView = false; + private boolean startedAtBottom = false; + private VelocityTracker tracker; + private float rawT, lastT, lastDifferentT, t; + private float fromY; + private int keyboardSize, bottomNavBarSize; + + public boolean onTouch(AdjustPanLayoutHelper panLayoutHelper, View view, RecyclerListView listView, ChatActivityEnterView enterView, ChatActivity ca, MotionEvent ev) { + if (!ENABLED) { + return false; + } + this.panLayoutHelper = panLayoutHelper; + this.view = view; + this.enterView = enterView; + + if (view == null || enterView == null) { + return false; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + boolean isKeyboardVisible = view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.ime()).bottom > 0; + if (!movingKeyboard && !isKeyboardVisible && !endingMovingKeyboard /* && !enterView.isPopupShowing()*/) { + return false; + } + boolean insideEnterView = ev.getY() >= enterView.getTop(); + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + startedOutsideView = !insideEnterView; + startedAtBottom = !listView.canScrollVertically(1); + } + if (!movingKeyboard && insideEnterView && startedOutsideView && ev.getAction() == MotionEvent.ACTION_MOVE) { + movingKeyboard = true; + isKeyboard = !enterView.isPopupShowing(); + keyboardSize = ( + isKeyboard ? + view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.ime()).bottom : + enterView.getEmojiPadding() + ); + bottomNavBarSize = view.getRootWindowInsets().getInsets(WindowInsetsCompat.Type.navigationBars()).bottom; + view.getWindowInsetsController().controlWindowInsetsAnimation( + WindowInsetsCompat.Type.ime(), + -1, + new LinearInterpolator(), + new CancellationSignal(), + new WindowInsetsAnimationControlListener() { + @Override + public void onReady(@NonNull WindowInsetsAnimationController windowInsetsAnimationController, int i) { + insetsController = windowInsetsAnimationController; + } + + @Override + public void onFinished(@NonNull WindowInsetsAnimationController windowInsetsAnimationController) { + insetsController = null; + } + + @Override + public void onCancelled(@Nullable WindowInsetsAnimationController windowInsetsAnimationController) { + insetsController = null; + } + } + ); + fromY = ev.getRawY(); + exactlyMovingKeyboard = false; + panLayoutHelper.setEnabled(false); + update(0, false); + listView.stopScroll(); + t = rawT = lastT = lastDifferentT = 0; + panLayoutHelper.OnTransitionStart(true, view.getHeight()); + if (tracker == null) { + tracker = VelocityTracker.obtain(); + } + tracker.clear(); + } + + if (movingKeyboard) { + tracker.addMovement(ev); + t = MathUtils.clamp(rawT = (ev.getRawY() - fromY) / keyboardSize, 0, 1); + if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + movingKeyboard = false; + exactlyMovingKeyboard = false; + endingMovingKeyboard = true; + tracker.computeCurrentVelocity(1000); + final boolean end = t > .15f && t >= lastDifferentT || t > .8f; + final float endT = end ? 1 : 0; + ValueAnimator va = ValueAnimator.ofFloat(t, endT); + va.addUpdateListener(a -> { + update(t = (float) a.getAnimatedValue(), true); + }); + va.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + if (insetsController != null && isKeyboard) { + insetsController.finish(!end); + } + update(1, false); + rawT = endT; + panLayoutHelper.OnTransitionEnd(); + view.post(() -> { + panLayoutHelper.setEnabled(true); + endingMovingKeyboard = false; + }); + } + }); + va.setInterpolator(CubicBezierInterpolator.EASE_OUT); + va.setDuration(200); + va.start(); + if (end && startedAtBottom && ca != null) { + ca.scrollToLastMessage(true); + } + startedOutsideView = false; + return true; + } +// if (t > .15f && !exactlyMovingKeyboard) { +// exactlyMovingKeyboard = true; +// } +// if (exactlyMovingKeyboard) { + update(t, true); +// } + if (lastT != t) { + lastDifferentT = lastT; + } + lastT = t; + return true; + } + } + + return false; + } + + public boolean disableScrolling() { + return ENABLED && (movingKeyboard || endingMovingKeyboard) && rawT >= 0; + } + + private void update(float t, boolean withKeyboard) { + if (isKeyboard) { + float y = Math.max((1f - t) * keyboardSize - bottomNavBarSize - 1, 0); + panLayoutHelper.OnPanTranslationUpdate(y, t, true); + ((View) ((View) view.getParent()).getParent()).setTranslationY(-y); + if (withKeyboard) { + if (insetsController != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + insetsController.setInsetsAndAlpha(Insets.of(0, 0, 0, (int) (keyboardSize * (1f - t))), 1f, t); + } + } + } else { + float y = (1f - t) * keyboardSize; + panLayoutHelper.OnPanTranslationUpdate(y, t, true); +// ((View) ((View) view.getParent()).getParent()).setTranslationY(-y); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index ad9415781..71d67d85f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -8,12 +8,16 @@ package org.telegram.ui; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.res.Configuration; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.EditText; import android.widget.FrameLayout; @@ -69,7 +73,7 @@ public class LanguageSelectActivity extends BaseFragment implements Notification @Override public boolean onFragmentCreate() { fillLanguages(); - LocaleController.getInstance().loadRemoteLanguages(currentAccount); + LocaleController.getInstance().loadRemoteLanguages(currentAccount, false); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.suggestedLangpack); return super.onFragmentCreate(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index d225d7691..99909cc62 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -8,10 +8,14 @@ package org.telegram.ui; +import static org.telegram.ui.Components.Premium.LimitReachedBottomSheet.TYPE_ACCOUNTS; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; @@ -28,6 +32,7 @@ import android.graphics.Paint; import android.graphics.Point; import android.graphics.Shader; import android.location.Location; +import android.graphics.drawable.Drawable; import android.location.LocationManager; import android.media.AudioManager; import android.net.Uri; @@ -40,6 +45,7 @@ import android.provider.ContactsContract; import android.provider.Settings; import android.text.TextUtils; import android.util.Base64; +import android.util.Log; import android.util.TypedValue; import android.view.ActionMode; import android.view.Gravity; @@ -105,6 +111,9 @@ 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.ActionBarMenuItem; +import org.telegram.ui.ActionBar.ActionBarMenuSubItem; +import org.telegram.ui.ActionBar.ActionBarPopupWindow; import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.DrawerLayoutContainer; @@ -117,6 +126,7 @@ import org.telegram.ui.Cells.DrawerProfileCell; import org.telegram.ui.Cells.DrawerUserCell; import org.telegram.ui.Cells.LanguageCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.AppIconBulletinLayout; import org.telegram.ui.Components.AttachBotIntroTopView; import org.telegram.ui.Components.AudioPlayerAlert; import org.telegram.ui.Components.BlockingUpdateView; @@ -133,6 +143,7 @@ import org.telegram.ui.Components.MediaActionDrawable; 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.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RadialProgress2; @@ -237,6 +248,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar private SimpleTextView updateTextView; private TextView updateSizeTextView; private FrameLayout sideMenuContainer; + private View rippleAbove; private AlertDialog localeDialog; private boolean loadingLocaleDialog; @@ -259,8 +271,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar private boolean isNavigationBarColorFrozen = false; + private boolean navigateToPremiumBot; + private Runnable lockRunnable; + private List onUserLeaveHintListeners = new ArrayList<>(); + private static final int PLAY_SERVICES_REQUEST_CHECK_SETTINGS = 140; public static final int SCREEN_CAPTURE_REQUEST_CODE = 520; @@ -338,7 +354,13 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } }; - frameLayout = new FrameLayout(this); + frameLayout = new FrameLayout(this) { + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + drawRippleAbove(canvas, this); + } + }; setContentView(frameLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); if (Build.VERSION.SDK_INT >= 21) { themeSwitchImageView = new ImageView(this); @@ -554,9 +576,9 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar break; } } - if (freeAccount >= 0) { - presentFragment(new LoginActivity(freeAccount)); - } +// if (!UserConfig.hasPremiumOnAccounts()) { +// freeAccounts -= (UserConfig.MAX_ACCOUNT_COUNT - UserConfig.MAX_ACCOUNT_DEFAULT_COUNT); +// } drawerLayoutContainer.closeDrawer(false); } else if (view instanceof DrawerActionCheckCell) { int id = drawerLayoutAdapter.getId(position); @@ -566,7 +588,6 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar drawerLayoutContainer.closeDrawer(false); } else if (id == 14) { NekoXConfig.toggleKeepOnlineStatus(); - drawerLayoutAdapter.notifyDataSetChanged(); } } else { @@ -758,7 +779,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer); actionBarLayout.init(mainFragmentsStack); actionBarLayout.setFragmentStackChangedListener(() -> { - checkSystemBarColors(); + checkSystemBarColors(true, false); }); actionBarLayout.setDelegate(this); Theme.loadWallpaper(); @@ -941,6 +962,14 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } } + public void addOnUserLeaveHintListener(Runnable callback) { + onUserLeaveHintListeners.add(callback); + } + + public void removeOnUserLeaveHintListener(Runnable callback) { + onUserLeaveHintListeners.remove(callback); + } + private BaseFragment getClientNotActivatedFragment() { if (LoginActivity.loadCurrentState(false).getInt("currentViewNum", 0) != 0) { return new LoginActivity(); @@ -964,10 +993,18 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } private void checkSystemBarColors() { - checkSystemBarColors(true, !isNavigationBarColorFrozen); + checkSystemBarColors(false, true, !isNavigationBarColorFrozen); + } + + private void checkSystemBarColors(boolean useCurrentFragment) { + checkSystemBarColors(useCurrentFragment, true, !isNavigationBarColorFrozen); } private void checkSystemBarColors(boolean checkStatusBar, boolean checkNavigationBar) { + checkSystemBarColors(false, checkStatusBar, checkNavigationBar); + } + + private void checkSystemBarColors(boolean useCurrentFragment, boolean checkStatusBar, boolean checkNavigationBar) { BaseFragment currentFragment = !mainFragmentsStack.isEmpty() ? mainFragmentsStack.get(mainFragmentsStack.size() - 1) : null; if (currentFragment != null && (currentFragment.isRemovingFromStack() || currentFragment.isInPreviewMode())) { currentFragment = mainFragmentsStack.size() > 1 ? mainFragmentsStack.get(mainFragmentsStack.size() - 2) : null; @@ -984,9 +1021,16 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } AndroidUtilities.setLightStatusBar(getWindow(), enable, forceLightStatusBar); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && checkNavigationBar) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && checkNavigationBar && (!useCurrentFragment || currentFragment == null || !currentFragment.isInPreviewMode())) { final Window window = getWindow(); - int color = Theme.getColor(Theme.key_windowBackgroundGray, null, true); + final int color = currentFragment != null && useCurrentFragment ? currentFragment.getNavigationBarColor() : Theme.getColor(Theme.key_windowBackgroundGray, null, true); +// Theme.ResourcesProvider resourcesProvider = currentFragment != null ? currentFragment.getResourceProvider() : null; +// if (resourcesProvider != null) { +// color = resourcesProvider.getColor(Theme.key_windowBackgroundGray); +// } +// if (color == null) { +// color = Theme.getColor(Theme.key_windowBackgroundGray, null, true); +// } if (window.getNavigationBarColor() != color) { window.setNavigationBarColor(color); final float brightness = AndroidUtilities.computePerceivedBrightness(color); @@ -1131,6 +1175,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.groupCallUpdated); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.stickersImportComplete); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.newSuggestionsAvailable); + NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.currentUserShowLimitReachedDialog); } private void checkLayout() { @@ -1292,6 +1337,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar }); } + @SuppressLint("Range") private boolean handleIntent(Intent intent, boolean isNew, boolean restore, boolean fromPassword) { if (AndroidUtilities.handleProxyIntent(this, intent)) { actionBarLayout.showLastFragment(); @@ -1659,6 +1705,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar String unsupportedUrl = null; String botUser = null; String botChat = null; + String botChannel = null; String botChatAdminParams = null; String message = null; String phone = null; @@ -1670,6 +1717,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar String theme = null; String code = null; TLRPC.TL_wallPaper wallPaper = null; + String inputInvoiceSlug = null; Integer messageId = null; Long channelId = null; Integer threadId = null; @@ -1678,6 +1726,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar boolean hasUrl = false; String setAsAttachBot = null; String attachMenuBotToOpen = null; + String attachMenuBotChoose = null; final String scheme = data.getScheme(); boolean internal = intent.getExtras() != null && intent.getExtras().get("internal") != null && (boolean) intent.getExtras().get("internal"); if (scheme != null) { @@ -1689,7 +1738,11 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar String path = data.getPath(); if (path != null && path.length() > 1) { path = path.substring(1); - if (path.startsWith("bg/")) { + if (path.startsWith("$")) { + inputInvoiceSlug = path.substring(1); + } else if (path.startsWith("invoice/")) { + inputInvoiceSlug = path.substring(path.indexOf('/') + 1); + } else if (path.startsWith("bg/")) { wallPaper = new TLRPC.TL_wallPaper(); wallPaper.settings = new TLRPC.TL_wallPaperSettings(); wallPaper.slug = path.replace("bg/", ""); @@ -1857,11 +1910,13 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } botUser = data.getQueryParameter("start"); botChat = data.getQueryParameter("startgroup"); + botChannel = data.getQueryParameter("startchannel"); botChatAdminParams = data.getQueryParameter("admin"); game = data.getQueryParameter("game"); voicechat = data.getQueryParameter("voicechat"); livestream = data.getQueryParameter("livestream"); setAsAttachBot = data.getQueryParameter("startattach"); + attachMenuBotChoose = data.getQueryParameter("choose"); attachMenuBotToOpen = data.getQueryParameter("attach"); threadId = Utilities.parseInt(data.getQueryParameter("thread")); if (threadId == 0) { @@ -1882,6 +1937,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar url = url.replace("tg:resolve", "tg://telegram.org").replace("tg://resolve", "tg://telegram.org"); data = Uri.parse(url); username = data.getQueryParameter("domain"); + if (username == null) { + username = data.getQueryParameter("phone"); + if (username != null && username.startsWith("+")) { + username = username.substring(1); + } + } if ("telegrampassport".equals(username)) { username = null; auth = new HashMap<>(); @@ -1898,11 +1959,13 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } else { botUser = data.getQueryParameter("start"); botChat = data.getQueryParameter("startgroup"); + botChannel = data.getQueryParameter("startchannel"); botChatAdminParams = data.getQueryParameter("admin"); game = data.getQueryParameter("game"); voicechat = data.getQueryParameter("voicechat"); livestream = data.getQueryParameter("livestream"); setAsAttachBot = data.getQueryParameter("startattach"); + attachMenuBotChoose = data.getQueryParameter("choose"); attachMenuBotToOpen = data.getQueryParameter("attach"); messageId = Utilities.parseInt(data.getQueryParameter("post")); if (messageId == 0) { @@ -1917,6 +1980,11 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar commentId = null; } } + } + if (url.startsWith("tg:invoice") || url.startsWith("tg://invoice")) { + url = url.replace("tg:invoice", "tg://invoice"); + data = Uri.parse(url); + inputInvoiceSlug = data.getQueryParameter("slug"); } else if (url.startsWith("tg:privatepost") || url.startsWith("tg://privatepost")) { url = url.replace("tg:privatepost", "tg://telegram.org").replace("tg://privatepost", "tg://telegram.org"); data = Uri.parse(url); @@ -2232,11 +2300,11 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar AlertsCreator.processError(currentAccount, error, getActionBarLayout().getLastFragment(), req); } }), ConnectionsManager.RequestFlagFailOnServerErrors); - } else if (username != null || group != null || sticker != null || message != null || game != null || voicechat != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null || channelId != null || theme != null || login != null) { + } else if (username != null || group != null || sticker != null || message != null || game != null || voicechat != null || auth != null || unsupportedUrl != null || lang != null || code != null || wallPaper != null || inputInvoiceSlug != null || channelId != null || theme != null || login != null) { if (message != null && message.startsWith("@")) { message = " " + message; } - runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, botChatAdminParams, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, theme, voicechat, livestream, internal ? 3 : 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen); + runLinkRequest(intentAccount[0], username, group, sticker, botUser, botChat, botChannel, botChatAdminParams, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, login, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, internal ? 3 : 0, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose); } else { try (Cursor cursor = getContentResolver().query(intent.getData(), null, null, null, null)) { if (cursor != null) { @@ -2273,7 +2341,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } else if (intent.getAction().startsWith("com.tmessages.openchat")) { long chatId = intent.getLongExtra("chatId", intent.getIntExtra("chatId", 0)); - long userId = intent.getLongExtra("userId", intent.getIntExtra("userId", 0)); + long userId = intent.getLongExtra("userId", intent.getIntExtra("userId", 0)); int encId = intent.getIntExtra("encId", 0); int widgetId = intent.getIntExtra("appWidgetId", 0); if (widgetId != 0) { @@ -2647,7 +2715,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } catch (Throwable ignore) { } - if (videoTimestamp == - 1) { + if (videoTimestamp == -1) { DateFormat dateFormat = new SimpleDateFormat("mm:ss"); Date reference = null; try { @@ -2916,6 +2984,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar final String sticker, final String botUser, final String botChat, + final String botChannel, final String botChatAdminParams, final String message, final boolean hasUrl, @@ -2930,19 +2999,21 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar final String code, final String loginToken, final TLRPC.TL_wallPaper wallPaper, + final String inputInvoiceSlug, final String theme, final String voicechat, final String livestream, final int state, final int videoTimestamp, final String setAsAttachBot, - final String attachMenuBotToOpen) { + final String attachMenuBotToOpen, + final String attachMenuBotChoose) { if (state == 0 && UserConfig.getActivatedAccountsCount() >= 2) { AlertsCreator.createAccountSelectDialog(this, account -> { if (account != intentAccount) { switchToAccount(account, true); } - runLinkRequest(account, username, group, sticker, botUser, botChat, botChatAdminParams, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, theme, voicechat, livestream, 3, videoTimestamp, setAsAttachBot, attachMenuBotToOpen); + runLinkRequest(account, username, group, sticker, botUser, botChat, botChannel, botChatAdminParams, message, hasUrl, messageId, channelId, threadId, commentId, game, auth, lang, unsupportedUrl, code, loginToken, wallPaper, inputInvoiceSlug, theme, voicechat, livestream, 3, videoTimestamp, setAsAttachBot, attachMenuBotToOpen, attachMenuBotChoose); }).show(); return; } else if (code != null) { @@ -3004,7 +3075,32 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar final int[] requestId = new int[]{0}; Runnable cancelRunnable = null; - if (username != null) { + if (inputInvoiceSlug != null) { + TLRPC.TL_payments_getPaymentForm req = new TLRPC.TL_payments_getPaymentForm(); + TLRPC.TL_inputInvoiceSlug invoiceSlug = new TLRPC.TL_inputInvoiceSlug(); + invoiceSlug.slug = inputInvoiceSlug; + req.invoice = invoiceSlug; + requestId[0] = ConnectionsManager.getInstance(intentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (error != null) { + BulletinFactory.of(mainFragmentsStack.get(mainFragmentsStack.size() - 1)).createErrorBulletin(LocaleController.getString(R.string.PaymentInvoiceLinkInvalid)).show(); + } else if (!LaunchActivity.this.isFinishing()) { + Toast.makeText(LaunchActivity.this, LocaleController.getString("nekoXPaymentRemovedToast", R.string.nekoXPaymentRemovedToast), Toast.LENGTH_LONG).show(); +// if (response instanceof TLRPC.TL_payments_paymentForm) { +// TLRPC.TL_payments_paymentForm form = (TLRPC.TL_payments_paymentForm) response; +// MessagesController.getInstance(intentAccount).putUsers(form.users, false); +// presentFragment(new PaymentFormActivity(form, inputInvoiceSlug, getActionBarLayout().getLastFragment())); +// } else if (response instanceof TLRPC.TL_payments_paymentReceipt) { +// presentFragment(new PaymentFormActivity((TLRPC.TL_payments_paymentReceipt) response)); +// } + } + + try { + progressDialog.dismiss(); + } catch (Exception e) { + FileLog.e(e); + } + })); + } else if (username != null) { TLObject req; if (AndroidUtilities.isNumeric(username)) { TLRPC.TL_contacts_resolvePhone resolvePhone = new TLRPC.TL_contacts_resolvePhone(); @@ -3029,14 +3125,63 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar if (user.bot_attach_menu) { TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot(); getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(res.peer.user_id); - ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(()->{ + ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1; MessagesController.getInstance(intentAccount).putUsers(attachMenuBotsBot.users, false); TLRPC.TL_attachMenuBot attachMenuBot = attachMenuBotsBot.bot; BaseFragment lastFragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); + + List chooserTargets = new ArrayList<>(); + if (!TextUtils.isEmpty(attachMenuBotChoose)) { + for (String target : attachMenuBotChoose.split(" ")) { + if (MediaDataController.canShowAttachMenuBotForTarget(attachMenuBot, target)) { + chooserTargets.add(target); + } + } + } + DialogsActivity dialogsActivity; + + if (!chooserTargets.isEmpty()) { + Bundle args = new Bundle(); + args.putInt("dialogsType", DialogsActivity.DIALOGS_TYPE_START_ATTACH_BOT); + args.putBoolean("onlySelect", true); + + args.putBoolean("allowGroups", chooserTargets.contains("groups")); + args.putBoolean("allowUsers", chooserTargets.contains("users")); + args.putBoolean("allowChannels", chooserTargets.contains("channels")); + args.putBoolean("allowBots", chooserTargets.contains("bots")); + + dialogsActivity = new DialogsActivity(args); + dialogsActivity.setDelegate((fragment, dids, message1, param) -> { + long did = dids.get(0); + + Bundle args1 = new Bundle(); + args1.putBoolean("scrollToTopOnResume", true); + if (DialogObject.isEncryptedDialog(did)) { + args1.putInt("enc_id", DialogObject.getEncryptedChatId(did)); + } else if (DialogObject.isUserDialog(did)) { + args1.putLong("user_id", did); + } else { + args1.putLong("chat_id", -did); + } + args1.putString("attach_bot", user.username); + if (setAsAttachBot != null) { + args1.putString("attach_bot_start_command", setAsAttachBot); + } + if (MessagesController.getInstance(intentAccount).checkCanOpenChat(args1, fragment)) { + NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); + actionBarLayout.presentFragment(new ChatActivity(args1), true, false, true, false); + } + }); + } else { + dialogsActivity = null; + } + if (!attachMenuBot.inactive) { - if (lastFragment instanceof ChatActivity) { + if (dialogsActivity != null) { + presentFragment(dialogsActivity); + } else if (lastFragment instanceof ChatActivity) { ((ChatActivity) lastFragment).openAttachBotLayout(user.id, setAsAttachBot); } else { BulletinFactory.of(lastFragment).createErrorBulletin(LocaleController.getString(R.string.BotAlreadyAddedToAttachMenu)).show(); @@ -3054,10 +3199,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(res.peer.user_id); botRequest.enabled = true; ConnectionsManager.getInstance(intentAccount).sendRequest(botRequest, (response2, error2) -> AndroidUtilities.runOnUIThread(() -> { - if (error2 == null) { + if (response2 instanceof TLRPC.TL_boolTrue) { MediaDataController.getInstance(intentAccount).loadAttachMenuBots(false, true); - if (lastFragment instanceof ChatActivity) { + if (dialogsActivity != null) { + presentFragment(dialogsActivity); + } else if (lastFragment instanceof ChatActivity) { ((ChatActivity) lastFragment).openAttachBotLayout(user.id, setAsAttachBot); } } @@ -3135,7 +3282,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } else { drawerLayoutContainer.setAllowOpenDrawer(true, false); } - } else if (botChat != null) { + } else if (botChat != null || botChannel != null) { final TLRPC.User user = !res.users.isEmpty() ? res.users.get(0) : null; if (user == null || user.bot && user.bot_nochats) { try { @@ -3152,6 +3299,9 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar args.putInt("dialogsType", 2); args.putBoolean("resetDelegate", false); args.putBoolean("closeFragment", false); + args.putBoolean("allowGroups", botChat != null); + args.putBoolean("allowChannels", botChannel != null); + final String botHash = TextUtils.isEmpty(botChat) ? (TextUtils.isEmpty(botChannel) ? null : botChannel) : botChat; // args.putString("addToGroupAlertString", LocaleController.formatString("AddToTheGroupAlertText", R.string.AddToTheGroupAlertText, UserObject.getUserName(user), "%1$s")); DialogsActivity fragment = new DialogsActivity(args); fragment.setDelegate((fragment12, dids, message1, param) -> { @@ -3199,6 +3349,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar requestingRights.manage_call = true; break; case "manage_chat": + case "other": requestingRights.other = true; break; case "anonymous": @@ -3228,18 +3379,35 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar editRights.other = requestingRights.other || editRights.other; } } - ChatRightsEditActivity editRightsActivity = new ChatRightsEditActivity(user.id, -did, editRights, null, null, currentRank, ChatRightsEditActivity.TYPE_ADD_BOT, true, !isInChatAlready, null); - editRightsActivity.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { - @Override - public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { - fragment.removeSelfFromStack(); + if (isInChatAlready && requestingRights == null && !TextUtils.isEmpty(botHash)) { + Runnable onFinish = () -> { NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); - } - @Override - public void didChangeOwner(TLRPC.User user) {} - }); - actionBarLayout.presentFragment(editRightsActivity, false); + Bundle args1 = new Bundle(); + args1.putBoolean("scrollToTopOnResume", true); + args1.putLong("chat_id", chat.id); + if (!MessagesController.getInstance(currentAccount).checkCanOpenChat(args1, fragment)) { + return; + } + ChatActivity chatActivity = new ChatActivity(args1); + presentFragment(chatActivity, true, false); + }; + MessagesController.getInstance(currentAccount).addUserToChat(chat.id, user, 0, botHash, fragment, true, onFinish, null); + } else { + ChatRightsEditActivity editRightsActivity = new ChatRightsEditActivity(user.id, -did, editRights, null, null, currentRank, ChatRightsEditActivity.TYPE_ADD_BOT, true, !isInChatAlready, botHash); + editRightsActivity.setDelegate(new ChatRightsEditActivity.ChatRightsEditActivityDelegate() { + @Override + public void didSetRights(int rights, TLRPC.TL_chatAdminRights rightsAdmin, TLRPC.TL_chatBannedRights rightsBanned, String rank) { + fragment.removeSelfFromStack(); + NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); + } + + @Override + public void didChangeOwner(TLRPC.User user) { + } + }); + actionBarLayout.presentFragment(editRightsActivity, false); + } })); } else { AlertDialog.Builder builder = new AlertDialog.Builder(this); @@ -3254,7 +3422,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar ChatActivity chatActivity = new ChatActivity(args12); NotificationCenter.getInstance(intentAccount).postNotificationName(NotificationCenter.closeChats); - MessagesController.getInstance(intentAccount).addUserToChat(-did, user, 0, TextUtils.isEmpty(botChat) ? null : botChat, chatActivity, null); + MessagesController.getInstance(intentAccount).addUserToChat(-did, user, 0, botHash, chatActivity, null); actionBarLayout.presentFragment(chatActivity, true, false, true, false); }); builder.show(); @@ -3276,6 +3444,10 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar args.putString("botUser", botUser); isBot = true; } + if (navigateToPremiumBot) { + navigateToPremiumBot = false; + args.putBoolean("premium_bot", true); + } if (messageId != null) { args.putInt("message_id", messageId); } @@ -3317,7 +3489,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar voipLastFragment = lastFragment; } - AndroidUtilities.runOnUIThread(()->{ + AndroidUtilities.runOnUIThread(() -> { if (livestream != null) { AccountInstance accountInstance = AccountInstance.getInstance(currentAccount); ChatObject.Call cachedCall = accountInstance.getMessagesController().getGroupCall(-dialog_id, false); @@ -3366,6 +3538,8 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); if (error != null && error.text != null && error.text.startsWith("FLOOD_WAIT")) { BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("FloodWait", R.string.FloodWait)).show(); + } else if (AndroidUtilities.isNumeric(username)) { + BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("NoPhoneFound", R.string.NoPhoneFound)).show(); } else { BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound)).show(); } @@ -3439,7 +3613,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } } else { BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); - fragment.showDialog(new JoinGroupAlert(LaunchActivity.this, invite, group, fragment)); + fragment.showDialog(new JoinGroupAlert(LaunchActivity.this, invite, group, fragment, (fragment instanceof ChatActivity ? ((ChatActivity) fragment).themeDelegate : null))); } } else { AlertDialog.Builder builder = new AlertDialog.Builder(LaunchActivity.this); @@ -3720,7 +3894,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar TLRPC.TL_wallPaper object; if (settings.wallpaper instanceof TLRPC.TL_wallPaper) { object = (TLRPC.TL_wallPaper) settings.wallpaper; - File path = FileLoader.getPathToAttach(object.document, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(object.document, true); if (!path.exists()) { loadingThemeProgressDialog = progressDialog; loadingThemeAccent = true; @@ -4024,7 +4198,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar createUpdateUI(); updateSizeTextView.setText(AndroidUtilities.formatFileSize(SharedConfig.pendingAppUpdate.document.size)); String fileName = FileLoader.getAttachFileName(SharedConfig.pendingAppUpdate.document); - File path = FileLoader.getPathToAttach(SharedConfig.pendingAppUpdate.document, true); + File path = FileLoader.getInstance(currentAccount).getPathToAttach(SharedConfig.pendingAppUpdate.document, true); boolean showSize; if (path.exists()) { updateLayoutIcon.setIcon(MediaActionDrawable.ICON_UPDATE, true, false); @@ -4195,8 +4369,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } } + public void setNavigateToPremiumBot(boolean val) { + navigateToPremiumBot = val; + } + @Override - protected void onNewIntent(Intent intent) { + public void onNewIntent(Intent intent) { super.onNewIntent(intent); handleIntent(intent, true, false, false); } @@ -4416,6 +4594,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.groupCallUpdated); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.stickersImportComplete); NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.newSuggestionsAvailable); + NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.currentUserShowLimitReachedDialog); } NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.needShowAlert); @@ -4664,6 +4843,14 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar onFinish(); } + @Override + protected void onUserLeaveHint() { + for (Runnable callback : onUserLeaveHintListeners) { + callback.run(); + } + actionBarLayout.onUserLeaveHint(); + } + @Override protected void onResume() { super.onResume(); @@ -4942,7 +5129,7 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar if (args.length > 1) { checkNavigationBarColor = (boolean) args[1]; } - checkSystemBarColors(true, checkNavigationBarColor && !isNavigationBarColorFrozen); + checkSystemBarColors(args.length > 2 && (boolean) args[2], true, checkNavigationBarColor && !isNavigationBarColorFrozen && !actionBarLayout.isTransitionAnimationInProgress()); } else if (id == NotificationCenter.needSetDayNightTheme) { boolean instant = false; if (Build.VERSION.SDK_INT >= 21 && args[2] != null) { @@ -4958,11 +5145,21 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar if (!toDark) { darkThemeView.setVisibility(View.INVISIBLE); } + rippleAbove = null; + if (args.length > 6) { + rippleAbove = (View) args[6]; + } isNavigationBarColorFrozen = true; invalidateCachedViews(drawerLayoutContainer); + if (rippleAbove != null && rippleAbove.getBackground() != null) { + rippleAbove.getBackground().setAlpha(0); + } Bitmap bitmap = AndroidUtilities.snapshotView(drawerLayoutContainer); + if (rippleAbove != null && rippleAbove.getBackground() != null) { + rippleAbove.getBackground().setAlpha(255); + } frameLayout.removeView(themeSwitchImageView); if (toDark) { frameLayout.addView(themeSwitchImageView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -4986,6 +5183,9 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + rippleAbove = null; + drawerLayoutContainer.invalidate(); + themeSwitchImageView.invalidate(); themeSwitchImageView.setImageDrawable(null); themeSwitchImageView.setVisibility(View.GONE); themeSwitchSunView.setVisibility(View.GONE); @@ -4996,7 +5196,13 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar DrawerProfileCell.switchingTheme = false; } }); - AndroidUtilities.runOnUIThread(()->{ + if (rippleAbove != null) { + ValueAnimator invalidateAnimator = ValueAnimator.ofFloat(0, 1); + invalidateAnimator.addUpdateListener(a -> frameLayout.invalidate()); + invalidateAnimator.setDuration(anim.getDuration()); + invalidateAnimator.start(); + } + AndroidUtilities.runOnUIThread(() -> { if (isNavigationBarColorFrozen) { isNavigationBarColorFrozen = false; checkSystemBarColors(false, true); @@ -5018,12 +5224,12 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar DrawerProfileCell.switchingTheme = false; } Theme.ThemeInfo theme = (Theme.ThemeInfo) args[0]; - boolean nigthTheme = (Boolean) args[1]; + boolean nightTheme = (Boolean) args[1]; int accentId = (Integer) args[3]; - actionBarLayout.animateThemedValues(theme, accentId, nigthTheme, instant); + actionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant); if (AndroidUtilities.isTablet()) { - layersActionBarLayout.animateThemedValues(theme, accentId, nigthTheme, instant); - rightActionBarLayout.animateThemedValues(theme, accentId, nigthTheme, instant); + layersActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant); + rightActionBarLayout.animateThemedValues(theme, accentId, nightTheme, instant); } } else if (id == NotificationCenter.notificationsCountUpdated) { if (sideMenu != null) { @@ -5128,7 +5334,8 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar onPasscodePause(); } } else if (id == NotificationCenter.needCheckSystemBarColors) { - checkSystemBarColors(); + boolean useCurrentFragment = args.length > 0 && (boolean) args[0]; + checkSystemBarColors(useCurrentFragment); } else if (id == NotificationCenter.historyImportProgressChanged) { if (args.length > 1 && !mainFragmentsStack.isEmpty()) { AlertsCreator.processError(currentAccount, (TLRPC.TL_error) args[2], mainFragmentsStack.get(mainFragmentsStack.size() - 1), (TLObject) args[1]); @@ -5151,33 +5358,58 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); } - if (type == Bulletin.TYPE_NAME_CHANGED) { - long peerId = (long) args[1]; - String text = peerId > 0 ? LocaleController.getString("YourNameChanged", R.string.YourNameChanged) : LocaleController.getString("CannelTitleChanged", R.string.ChannelTitleChanged); - (container != null ? BulletinFactory.of(container, null) : BulletinFactory.of(fragment)).createErrorBulletin(text).show(); - } else if (type == Bulletin.TYPE_BIO_CHANGED) { - long peerId = (long) args[1]; - String text = peerId > 0 ? LocaleController.getString("YourBioChanged", R.string.YourBioChanged) : LocaleController.getString("CannelDescriptionChanged", R.string.ChannelDescriptionChanged); - (container != null ? BulletinFactory.of(container, null) : BulletinFactory.of(fragment)).createErrorBulletin(text).show(); - } else if (type == Bulletin.TYPE_STICKER) { - TLRPC.Document sticker = (TLRPC.Document) args[1]; - StickerSetBulletinLayout layout = new StickerSetBulletinLayout(this, null, (int) args[2], sticker, null); - if (fragment != null) { - Bulletin.make(fragment, layout, Bulletin.DURATION_SHORT).show(); - } else { - Bulletin.make(container, layout, Bulletin.DURATION_SHORT).show(); + switch (type) { + case Bulletin.TYPE_NAME_CHANGED: { + long peerId = (long) args[1]; + String text = peerId > 0 ? LocaleController.getString("YourNameChanged", R.string.YourNameChanged) : LocaleController.getString("CannelTitleChanged", R.string.ChannelTitleChanged); + (container != null ? BulletinFactory.of(container, null) : BulletinFactory.of(fragment)).createErrorBulletin(text).show(); + break; } - } else if (type == Bulletin.TYPE_ERROR) { - if (fragment != null) { - BulletinFactory.of(fragment).createErrorBulletin((String) args[1]).show(); - } else { - BulletinFactory.of(container, null).createErrorBulletin((String) args[1]).show(); + case Bulletin.TYPE_BIO_CHANGED: { + long peerId = (long) args[1]; + String text = peerId > 0 ? LocaleController.getString("YourBioChanged", R.string.YourBioChanged) : LocaleController.getString("CannelDescriptionChanged", R.string.ChannelDescriptionChanged); + (container != null ? BulletinFactory.of(container, null) : BulletinFactory.of(fragment)).createErrorBulletin(text).show(); + break; } - } if (type == Bulletin.TYPE_ERROR_SUBTITLE) { - if (fragment != null) { - BulletinFactory.of(fragment).createErrorBulletinSubtitle((String) args[1], (String) args[2], fragment.getResourceProvider()).show(); - } else { - BulletinFactory.of(container, null).createErrorBulletinSubtitle((String) args[1], (String) args[2], null).show(); + case Bulletin.TYPE_STICKER: { + TLRPC.Document sticker = (TLRPC.Document) args[1]; + int bulletinType = (int) args[2]; + StickerSetBulletinLayout layout = new StickerSetBulletinLayout(this, null, bulletinType, sticker, null); + int duration = Bulletin.DURATION_SHORT; + if (bulletinType == StickerSetBulletinLayout.TYPE_REPLACED_TO_FAVORITES || bulletinType == StickerSetBulletinLayout.TYPE_REPLACED_TO_FAVORITES_GIFS) { + duration = 3500; + } + if (fragment != null) { + Bulletin.make(fragment, layout, duration).show(); + } else { + Bulletin.make(container, layout, duration).show(); + } + break; + } + case Bulletin.TYPE_ERROR: + if (fragment != null) { + BulletinFactory.of(fragment).createErrorBulletin((String) args[1]).show(); + } else { + BulletinFactory.of(container, null).createErrorBulletin((String) args[1]).show(); + } + break; + case Bulletin.TYPE_ERROR_SUBTITLE: + if (fragment != null) { + BulletinFactory.of(fragment).createErrorBulletinSubtitle((String) args[1], (String) args[2], fragment.getResourceProvider()).show(); + } else { + BulletinFactory.of(container, null).createErrorBulletinSubtitle((String) args[1], (String) args[2], null).show(); + } + break; + case Bulletin.TYPE_APP_ICON: { + LauncherIconController.LauncherIcon icon = (LauncherIconController.LauncherIcon) args[1]; + AppIconBulletinLayout layout = new AppIconBulletinLayout(this, icon, null); + int duration = Bulletin.DURATION_SHORT; + if (fragment != null) { + Bulletin.make(fragment, layout, duration).show(); + } else { + Bulletin.make(container, layout, duration).show(); + } + break; } } } @@ -5197,6 +5429,13 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } } else if (id == NotificationCenter.appUpdateAvailable) { updateAppUpdateViews(mainFragmentsStack.size() == 1); + } else if (id == NotificationCenter.currentUserShowLimitReachedDialog) { + if (!mainFragmentsStack.isEmpty()) { + BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); + if (fragment.getParentActivity() != null) { + fragment.showDialog(new LimitReachedBottomSheet(fragment, fragment.getParentActivity(), (int) args[0], currentAccount)); + } + } } } @@ -5401,6 +5640,25 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar } } + private int[] tempLocation; + private void drawRippleAbove(Canvas canvas, View parent) { + if (parent == null || rippleAbove == null || rippleAbove.getBackground() == null) { + return; + } + if (tempLocation == null) { + tempLocation = new int[2]; + } + rippleAbove.getLocationInWindow(tempLocation); + int x = tempLocation[0], y = tempLocation[1]; + parent.getLocationInWindow(tempLocation); + x -= tempLocation[0]; + y -= tempLocation[1]; + canvas.save(); + canvas.translate(x, y); + rippleAbove.getBackground().draw(canvas); + canvas.restore(); + } + private void showLanguageAlert(boolean force) { if (!UserConfig.getInstance(currentAccount).isClientActivated()) { return; @@ -5673,7 +5931,9 @@ public class LaunchActivity extends BasePermissionsActivity implements ActionBar finish(); return; } - if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { + if (ContentPreviewViewer.hasInstance() && ContentPreviewViewer.getInstance().isVisible()) { + ContentPreviewViewer.getInstance().closeWithMenu(); + } if (SecretMediaViewer.hasInstance() && SecretMediaViewer.getInstance().isVisible()) { SecretMediaViewer.getInstance().closePhoto(true, false); } else if (PhotoViewer.hasInstance() && PhotoViewer.getInstance().isVisible()) { PhotoViewer.getInstance().closePhoto(true, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LauncherIconController.java b/TMessagesProj/src/main/java/org/telegram/ui/LauncherIconController.java new file mode 100644 index 000000000..6451e336e --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/LauncherIconController.java @@ -0,0 +1,71 @@ +package org.telegram.ui; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; + +import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.R; + +public class LauncherIconController { + public static void tryFixLauncherIconIfNeeded() { + for (LauncherIcon icon : LauncherIcon.values()) { + if (isEnabled(icon)) { + return; + } + } + + setIcon(LauncherIcon.DEFAULT); + } + + public static boolean isEnabled(LauncherIcon icon) { + Context ctx = ApplicationLoader.applicationContext; + int i = ctx.getPackageManager().getComponentEnabledSetting(icon.getComponentName(ctx)); + return i == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || i == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT && icon == LauncherIcon.DEFAULT; + } + + public static void setIcon(LauncherIcon icon) { + Context ctx = ApplicationLoader.applicationContext; + PackageManager pm = ctx.getPackageManager(); + for (LauncherIcon i : LauncherIcon.values()) { + pm.setComponentEnabledSetting(i.getComponentName(ctx), i == icon ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); + } + } + + public enum LauncherIcon { + DEFAULT("DefaultIcon", R.drawable.icon_background_sa, R.mipmap.icon_foreground_sa, R.string.AppIconDefault), + VINTAGE("VintageIcon", R.drawable.icon_6_background_sa, R.mipmap.icon_6_foreground_sa, R.string.AppIconVintage), + AQUA("AquaIcon", R.drawable.icon_4_background_sa, R.mipmap.icon_foreground_sa, R.string.AppIconAqua), + PREMIUM("PremiumIcon", R.drawable.icon_3_background_sa, R.mipmap.icon_3_foreground_sa, R.string.AppIconPremium, true), + TURBO("TurboIcon", R.drawable.icon_5_background_sa, R.mipmap.icon_5_foreground_sa, R.string.AppIconTurbo, true), + NOX("NoxIcon", R.drawable.icon_2_background_sa, R.mipmap.icon_foreground_sa, R.string.AppIconNox, true); + + public final String key; + public final int background; + public final int foreground; + public final int title; + public final boolean premium; + + private ComponentName componentName; + + public ComponentName getComponentName(Context ctx) { + if (componentName == null) { + componentName = new ComponentName(ctx.getPackageName(), "org.telegram.messenger." + key); + } + return componentName; + } + + LauncherIcon(String key, int background, int foreground, int title) { + this(key, background, foreground, title, false); + } + + LauncherIcon(String key, int background, int foreground, int title, boolean premium) { + this.key = key; + this.background = background; + this.foreground = foreground; + this.title = title; + this.premium = premium; + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java index d6928b55f..4d1cab37c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java @@ -58,7 +58,11 @@ import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; + +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import org.osmdroid.api.IGeoPoint; import org.osmdroid.api.IMapController; @@ -81,24 +85,23 @@ import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.BuildConfig; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; import org.telegram.messenger.DialogObject; -import org.telegram.messenger.FileLoader; -import org.telegram.messenger.ImageLocation; -import org.telegram.messenger.LocationController; -import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MessagesController; -import org.telegram.messenger.UserObject; -import org.telegram.tgnet.TLRPC; +import org.telegram.messenger.LocationController; import org.telegram.messenger.MessageObject; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; +import org.telegram.messenger.UserObject; +import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Adapters.LocationActivityAdapter; @@ -113,7 +116,6 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.SharingLiveLocationCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AvatarDrawable; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CubicBezierInterpolator; @@ -132,11 +134,6 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; -import androidx.collection.LongSparseArray; -import androidx.recyclerview.widget.DefaultItemAnimator; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class LocationActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { private ImageView locationButton; @@ -577,7 +574,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter otherItem = menu.addItem(0, R.drawable.ic_ab_other); otherItem.addSubItem(open_in, R.drawable.msg_openin, LocaleController.getString("OpenInExternalApp", R.string.OpenInExternalApp)); if (!getLocationController().isSharingLocation(dialogId)) { - otherItem.addSubItem(share_live_location, R.drawable.menu_location, LocaleController.getString("SendLiveLocationMenu", R.string.SendLiveLocationMenu)); + otherItem.addSubItem(share_live_location, R.drawable.msg_location, LocaleController.getString("SendLiveLocationMenu", R.string.SendLiveLocationMenu)); } otherItem.setContentDescription(LocaleController.getString("AccDescrMoreOptions", R.string.AccDescrMoreOptions)); } @@ -763,7 +760,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }); } mapTypeButton.setBackgroundDrawable(drawable); - mapTypeButton.setIcon(R.drawable.location_type); + mapTypeButton.setIcon(R.drawable.msg_map_type); mapViewClip.addView(mapTypeButton, LayoutHelper.createFrame(Build.VERSION.SDK_INT >= 21 ? 40 : 44, Build.VERSION.SDK_INT >= 21 ? 40 : 44, Gravity.RIGHT | Gravity.TOP, 0, 12, 12, 0)); mapTypeButton.setOnClickListener(v -> mapTypeButton.toggleSubMenu()); mapTypeButton.setDelegate(id -> { @@ -820,7 +817,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter }); } locationButton.setBackgroundDrawable(drawable); - locationButton.setImageResource(R.drawable.location_current); + locationButton.setImageResource(R.drawable.msg_current_location); locationButton.setScaleType(ImageView.ScaleType.CENTER); locationButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_location_actionActiveIcon), PorterDuff.Mode.MULTIPLY)); locationButton.setTag(Theme.key_location_actionActiveIcon); @@ -1405,7 +1402,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter RectF bitmapRect = new RectF(); canvas.save(); if (photo != null) { - File path = FileLoader.getPathToAttach(photo, true); + File path = getFileLoader().getPathToAttach(photo, true); Bitmap bitmap = BitmapFactory.decodeFile(path.toString()); if (bitmap != null) { BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 8b0cfd640..a76d6bc77 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -104,6 +104,7 @@ import org.telegram.messenger.Utilities; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.RequestDelegate; import org.telegram.tgnet.SerializedData; +import org.telegram.tgnet.TLObject; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBarMenu; @@ -172,6 +173,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No AUTH_TYPE_CALL = 4, AUTH_TYPE_MISSED_CALL = 11; + private final static int MODE_LOGIN = 0, + MODE_CANCEL_ACCOUNT_DELETION = 1, + MODE_CHANGE_PHONE_NUMBER = 2; + private final static int VIEW_PHONE_INPUT = 0, VIEW_CODE_MESSAGE = 1, VIEW_CODE_SMS = 2, @@ -199,6 +204,14 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No }) public @interface AuthType {} + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + MODE_LOGIN, + MODE_CANCEL_ACCOUNT_DELETION, + MODE_CHANGE_PHONE_NUMBER + }) + public @interface ActivityMode {} + @Retention(RetentionPolicy.SOURCE) @IntDef({ VIEW_PHONE_INPUT, @@ -240,7 +253,9 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private boolean syncContacts = false; private boolean testBackend = false; - private boolean cancelAccountDeletionMode = false; + @ActivityMode + private int activityMode = MODE_LOGIN; + private String cancelDeletionPhone; private Bundle cancelDeletionParams; private TLRPC.TL_auth_sentCode cancelDeletionCode; @@ -384,10 +399,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No cancelDeletionPhone = phone; cancelDeletionParams = params; cancelDeletionCode = sentCode; - cancelAccountDeletionMode = true; + activityMode = MODE_CANCEL_ACCOUNT_DELETION; return this; } + public LoginActivity changePhoneNumber() { + activityMode = MODE_CHANGE_PHONE_NUMBER; + return this; + } + + private boolean isInCancelAccountDeletionMode() { + return activityMode == MODE_CANCEL_ACCOUNT_DELETION; + } + @Override public void onFragmentDestroy() { super.onFragmentDestroy(); @@ -538,7 +562,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No slideViewsContainer.addView(views[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, AndroidUtilities.isTablet() ? 26 : 18, 30, AndroidUtilities.isTablet() ? 26 : 18, 0)); } - Bundle savedInstanceState = loadCurrentState(newAccount); + Bundle savedInstanceState = activityMode == MODE_LOGIN ? loadCurrentState(newAccount) : null; if (savedInstanceState != null) { currentViewNum = savedInstanceState.getInt("currentViewNum", 0); syncContacts = savedInstanceState.getInt("syncContacts", 0) == 1; @@ -683,7 +707,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } if (currentViewNum == a) { - backButtonView.setVisibility(v.needBackButton() || newAccount ? View.VISIBLE : View.GONE); + backButtonView.setVisibility(v.needBackButton() || newAccount || activityMode == MODE_CHANGE_PHONE_NUMBER ? View.VISIBLE : View.GONE); v.setVisibility(View.VISIBLE); v.onShow(); @@ -707,7 +731,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No updateColors(); - if (cancelAccountDeletionMode) { + if (isInCancelAccountDeletionMode()) { fillNextCodeParams(cancelDeletionParams, cancelDeletionCode, false); } @@ -1374,7 +1398,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } private void needShowProgress(int requestId, boolean animated) { - if (cancelAccountDeletionMode && requestId == 0) { + if (isInCancelAccountDeletionMode() && requestId == 0) { if (cancelDeleteProgressDialog != null || getParentActivity() == null || getParentActivity().isFinishing()) { return; } @@ -1401,7 +1425,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No progressRequestId = 0; } - if (cancelAccountDeletionMode && cancelDeleteProgressDialog != null) { + if (isInCancelAccountDeletionMode() && cancelDeleteProgressDialog != null) { cancelDeleteProgressDialog.dismiss(); cancelDeleteProgressDialog = null; } @@ -1651,13 +1675,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleView = new TextView(context); titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18); titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - titleView.setText(LocaleController.getString(R.string.YourNumber)); + titleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneNewNumber : R.string.YourNumber)); titleView.setGravity(Gravity.CENTER); titleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); addView(titleView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL, 32, 0, 32, 0)); subtitleView = new TextView(context); - subtitleView.setText(LocaleController.getString("StartText", R.string.StartText)); + subtitleView.setText(LocaleController.getString(activityMode == MODE_CHANGE_PHONE_NUMBER ? R.string.ChangePhoneHelp : R.string.StartText)); subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); subtitleView.setGravity(Gravity.CENTER); subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); @@ -1989,40 +2013,41 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No }); int bottomMargin = 72; + if (newAccount && activityMode == MODE_LOGIN) { + syncContactsBox = new CheckBoxCell(context, 2); + syncContactsBox.setText(LocaleController.getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); + addView(syncContactsBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); + bottomMargin -= 24; + syncContactsBox.setOnClickListener(v -> { + if (getParentActivity() == null) { + return; + } + CheckBoxCell cell = (CheckBoxCell) v; + syncContacts = !syncContacts; + cell.setChecked(syncContacts, true); + if (syncContacts) { + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, LocaleController.getString("SyncContactsOn", R.string.SyncContactsOn)).show(); + } else { + BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, LocaleController.getString("SyncContactsOff", R.string.SyncContactsOff)).show(); + } + }); + } - syncContactsBox = new CheckBoxCell(context, 2); - syncContactsBox.setText(LocaleController.getString("SyncContacts", R.string.SyncContacts), "", syncContacts, false); - addView(syncContactsBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); - bottomMargin -= 24; - syncContactsBox.setOnClickListener(v -> { - if (getParentActivity() == null) { - return; - } - CheckBoxCell cell = (CheckBoxCell) v; - syncContacts = !syncContacts; - cell.setChecked(syncContacts, true); - if (syncContacts) { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_on, LocaleController.getString("SyncContactsOn", R.string.SyncContactsOn)).show(); - } else { - BulletinFactory.of(slideViewsContainer, null).createSimpleBulletin(R.raw.contacts_sync_off, LocaleController.getString("SyncContactsOff", R.string.SyncContactsOff)).show(); - } - }); - - testBackendCheckBox = new CheckBoxCell(context, 2); - testBackendCheckBox.setText("Test Backend", "", testBackend, false); - addView(testBackendCheckBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); - bottomMargin -= 24; - testBackendCheckBox.setOnClickListener(v -> { - if (getParentActivity() == null) { - return; - } - CheckBoxCell cell = (CheckBoxCell) v; - testBackend = !testBackend; - cell.setChecked(testBackend, true); - }); -// testBackendCheckBox.setVisibility(BuildVars.DEBUG_VERSION ? VISIBLE : GONE); - testBackendCheckBox.setVisibility(GONE); - + if (BuildVars.DEBUG_PRIVATE_VERSION && activityMode == MODE_LOGIN) { + testBackendCheckBox = new CheckBoxCell(context, 2); + testBackendCheckBox.setText("Test Backend", "", testBackend, false); + addView(testBackendCheckBox, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 16, 0, 16 + (LocaleController.isRTL && AndroidUtilities.isSmallScreen() ? Build.VERSION.SDK_INT >= 21 ? 56 : 60 : 0), 0)); + bottomMargin -= 24; + testBackendCheckBox.setOnClickListener(v -> { + if (getParentActivity() == null) { + return; + } + CheckBoxCell cell = (CheckBoxCell) v; + testBackend = !testBackend; + cell.setChecked(testBackend, true); + }); + testBackendCheckBox.setVisibility(GONE); + } if (bottomMargin > 0 && !AndroidUtilities.isSmallScreen()) { Space bottomSpacer = new Space(context); bottomSpacer.setMinimumHeight(AndroidUtilities.dp(bottomMargin)); @@ -2128,6 +2153,27 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No List testCodeStr = new ArrayList<>(); testCodeStr.add("XX X XXXX"); phoneFormatMap.put(test_code, testCodeStr); + + if (activityMode == MODE_CHANGE_PHONE_NUMBER) { + String number = PhoneFormat.stripExceptNumbers(UserConfig.getInstance(currentAccount).getClientPhone()); + boolean ok = false; + if (!TextUtils.isEmpty(number)) { + if (number.length() > 4) { + for (int a = 4; a >= 1; a--) { + String sub = number.substring(0, a); + CountrySelectActivity.Country country2 = codesMap.get(sub); + if (country2 != null) { + ok = true; + codeField.setText(sub); + break; + } + } + if (!ok) { + codeField.setText(number.substring(0, 1)); + } + } + } + } } }); }, ConnectionsManager.RequestFlagWithoutLogin | ConnectionsManager.RequestFlagFailOnServerErrors); @@ -2286,7 +2332,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } String phoneNumber = "+" + codeField.getText() + " " + phoneField.getText(); - String phoneCode = codeField.getText().toString(); if (!confirmedNumber) { if (AndroidUtilities.displaySize.x > AndroidUtilities.displaySize.y && !isCustomKeyboardVisible() && sizeNotifierFrameLayout.measureKeyboardHeight() > AndroidUtilities.dp(20)) { keyboardHideCallback = () -> postDelayed(()-> onNextPressed(code), 200); @@ -2459,39 +2504,43 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No return; } String phone = PhoneFormat.stripExceptNumbers("" + codeField.getText() + phoneField.getText()); - if (!testBackend && "999".equals(codeField.getText().toString())) { - testBackend = true; - if (testBackendCheckBox != null) { - testBackendCheckBox.setChecked(true, true); - } - } - boolean testBackend = /*BuildVars.DEBUG_PRIVATE_VERSION && */getConnectionsManager().isTestBackend(); - if (testBackend != LoginActivity.this.testBackend) { - getConnectionsManager().switchBackend(false); - testBackend = LoginActivity.this.testBackend; - } - if (getParentActivity() instanceof LaunchActivity) { - for (int a : SharedConfig.activeAccounts) { - UserConfig userConfig = UserConfig.getInstance(a); - if (!userConfig.isClientActivated()) { - continue; + if (activityMode == MODE_LOGIN) { + if (!testBackend && "999".equals(codeField.getText().toString())) { + testBackend = true; + if (testBackendCheckBox != null) { + testBackendCheckBox.setChecked(true, true); + testBackendCheckBox.setVisibility(VISIBLE); } - String userPhone = userConfig.getCurrentUser().phone; - if (PhoneNumberUtils.compare(phone, userPhone) && ConnectionsManager.getInstance(a).isTestBackend() == testBackend) { - final int num = a; - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setTitle(LocaleController.getString(R.string.NekoX)); - builder.setMessage(LocaleController.getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); - builder.setPositiveButton(LocaleController.getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { - if (UserConfig.selectedAccount != num) { - ((LaunchActivity) getParentActivity()).switchToAccount(num, false); - } - finishFragment(); - }); - builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); - showDialog(builder.create()); - needHideProgress(false); - return; + } + boolean testBackend = BuildVars.DEBUG_PRIVATE_VERSION && getConnectionsManager().isTestBackend(); + if (testBackend != LoginActivity.this.testBackend) { + getConnectionsManager().switchBackend(false); + testBackend = LoginActivity.this.testBackend; + } + + if (getParentActivity() instanceof LaunchActivity) { + for (int a : SharedConfig.activeAccounts) { + UserConfig userConfig = UserConfig.getInstance(a); + if (!userConfig.isClientActivated()) { + continue; + } + String userPhone = userConfig.getCurrentUser().phone; + if (PhoneNumberUtils.compare(phone, userPhone) && ConnectionsManager.getInstance(a).isTestBackend() == testBackend) { + final int num = a; + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + builder.setTitle(LocaleController.getString(R.string.AppName)); + builder.setMessage(LocaleController.getString("AccountAlreadyLoggedIn", R.string.AccountAlreadyLoggedIn)); + builder.setPositiveButton(LocaleController.getString("AccountSwitch", R.string.AccountSwitch), (dialog, which) -> { + if (UserConfig.selectedAccount != num) { + ((LaunchActivity) getParentActivity()).switchToAccount(num, false); + } + finishFragment(); + }); + builder.setNegativeButton(LocaleController.getString("OK", R.string.OK), null); + showDialog(builder.create()); + needHideProgress(false); + return; + } } } } @@ -2519,6 +2568,11 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No req.settings.flags |= 64; } SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE); +// if (settings.allow_app_hash) { +// preferences.edit().putString("sms_hash", BuildVars.SMS_HASH).apply(); +// } else { +// preferences.edit().remove("sms_hash").apply(); +// } if (req.settings.allow_flashcall) { try { String number = ""; @@ -2539,7 +2593,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No FileLog.e(e); } } - final Bundle params = new Bundle(); + + TLObject reqFinal; + if (activityMode == MODE_CHANGE_PHONE_NUMBER) { + TLRPC.TL_account_sendChangePhoneCode changePhoneCode = new TLRPC.TL_account_sendChangePhoneCode(); + changePhoneCode.phone_number = phone; + changePhoneCode.settings = settings; + reqFinal = changePhoneCode; + } else { + ConnectionsManager.getInstance(currentAccount).cleanup(false); + reqFinal = req; + } + + Bundle params = new Bundle(); params.putString("phone", "+" + codeField.getText() + " " + phoneField.getText()); try { params.putString("ephone", "+" + PhoneFormat.stripExceptNumbers(codeField.getText().toString()) + " " + PhoneFormat.stripExceptNumbers(phoneField.getText().toString())); @@ -2553,7 +2619,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No phoneInputData.phoneNumber = "+" + codeField.getText() + " " + phoneField.getText(); phoneInputData.country = currentCountry; phoneInputData.patterns = phoneFormatMap.get(codeField.getText().toString()); - int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(reqFinal, (response, error) -> AndroidUtilities.runOnUIThread(() -> { nextPressed = false; if (error == null) { fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response); @@ -2657,13 +2723,13 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); } else if (error.text.contains("PHONE_NUMBER_INVALID")) { - needShowInvalidAlert(LoginActivity.this, req.phone_number, phoneInputData, false); + needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, false); } else if (error.text.contains("PHONE_PASSWORD_FLOOD")) { needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); } else if (error.text.contains("PHONE_NUMBER_FLOOD")) { needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("PhoneNumberFlood", R.string.PhoneNumberFlood)); } else if (error.text.contains("PHONE_NUMBER_BANNED")) { - needShowInvalidAlert(LoginActivity.this, req.phone_number, phoneInputData, true); + needShowInvalidAlert(LoginActivity.this, phone, phoneInputData, true); } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidCode", R.string.InvalidCode)); } else if (error.text.contains("PHONE_CODE_EXPIRED")) { @@ -2671,7 +2737,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else if (error.text.startsWith("FLOOD_WAIT")) { needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); } else if (error.code != -1000) { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error.text); + AlertsCreator.processError(currentAccount, error, LoginActivity.this, req, phoneInputData.phoneNumber); } } } @@ -2682,7 +2748,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No private boolean numberFilled; public void fillNumber() { - if (numberFilled) { + if (numberFilled || activityMode != MODE_LOGIN) { return; } try { @@ -2928,7 +2994,16 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No titleTextView.setLineSpacing(AndroidUtilities.dp(2), 1.0f); titleTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL); - String overrideTitle = cancelAccountDeletionMode ? LocaleController.getString(R.string.CancelAccountReset) : null; + String overrideTitle; + switch (activityMode) { + default: + case MODE_LOGIN: + overrideTitle = null; + break; + case MODE_CANCEL_ACCOUNT_DELETION: + overrideTitle = LocaleController.getString(R.string.CancelAccountReset); + break; + } FrameLayout centerContainer = null; if (currentType == AUTH_TYPE_MISSED_CALL) { titleTextView.setText(overrideTitle != null ? overrideTitle : LocaleController.getString("MissedCallDescriptionTitle", R.string.MissedCallDescriptionTitle)); @@ -3059,12 +3134,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } else { timeText.setText(LocaleController.getString("SendingSms", R.string.SendingSms)); } + Bundle params = new Bundle(); + params.putString("phone", phone); + params.putString("ephone", emailPhone); + params.putString("phoneFormated", requestPhone); + createCodeTimer(); TLRPC.TL_auth_resendCode req = new TLRPC.TL_auth_resendCode(); req.phone_number = requestPhone; req.phone_code_hash = phoneHash; ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { - if (error != null && error.text != null) { + if (response != null) { + AndroidUtilities.runOnUIThread(() -> fillNextCodeParams(params, (TLRPC.TL_auth_sentCode) response)); + } else if (error != null && error.text != null) { AndroidUtilities.runOnUIThread(() -> lastError = error.text); } }, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); @@ -3130,7 +3212,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (nextPressed) { return; } - boolean email = nextType == AUTH_TYPE_CALL && currentType == AUTH_TYPE_SMS || nextType == 0; + boolean email = nextType == 0; if (!email) { if (radialProgressView.getTag() != null) { return; @@ -3164,7 +3246,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public void updateColors() { - confirmTextView.setTextColor(Theme.getColor(cancelAccountDeletionMode ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_windowBackgroundWhiteGrayText6)); + confirmTextView.setTextColor(Theme.getColor(isInCancelAccountDeletionMode() ? Theme.key_windowBackgroundWhiteBlackText : Theme.key_windowBackgroundWhiteGrayText6)); confirmTextView.setLinkTextColor(Theme.getColor(Theme.key_chats_actionBackground)); titleTextView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -3247,6 +3329,19 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No tryShowProgress(reqId); } + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + if (codeFieldContainer != null && codeFieldContainer.codeField != null) { + for (CodeNumberField f : codeFieldContainer.codeField) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + f.setShowSoftInputOnFocusCompat(!(hasCustomKeyboard() && !isCustomKeyboardForceDisabled())); + } + } + } + } + private void tryShowProgress(int reqId) { tryShowProgress(reqId, true); } @@ -3388,7 +3483,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No String number = PhoneFormat.getInstance().format(phone); CharSequence str = ""; - if (cancelAccountDeletionMode) { + if (isInCancelAccountDeletionMode()) { SpannableStringBuilder spanned = new SpannableStringBuilder(AndroidUtilities.replaceTags(LocaleController.formatString("CancelAccountResetInfo2", R.string.CancelAccountResetInfo2, PhoneFormat.getInstance().format("+" + number)))); int startIndex = TextUtils.indexOf(spanned, '*'); @@ -3641,121 +3736,52 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } waitingForEvent = false; - if (cancelAccountDeletionMode) { - requestPhone = cancelDeletionPhone; - final TLRPC.TL_account_confirmPhone req = new TLRPC.TL_account_confirmPhone(); - req.phone_code = code; - req.phone_code_hash = phoneHash; - destroyTimer(); + switch (activityMode) { + case MODE_CHANGE_PHONE_NUMBER: { + TLRPC.TL_account_changePhone req = new TLRPC.TL_account_changePhone(); + req.phone_number = requestPhone; + req.phone_code = code; + req.phone_code_hash = phoneHash; + destroyTimer(); - codeFieldContainer.isFocusSuppressed = true; - for (CodeNumberField f : codeFieldContainer.codeField) { - f.animateFocusedProgress(0); - } - - int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - tryHideProgress(false); - nextPressed = false; - if (error == null) { - animateSuccess(()-> new AlertDialog.Builder(getParentActivity()) - .setTitle(LocaleController.getString(R.string.CancelLinkSuccessTitle)) - .setMessage(LocaleController.formatString("CancelLinkSuccess", R.string.CancelLinkSuccess, PhoneFormat.getInstance().format("+" + phone))) - .setPositiveButton(LocaleController.getString(R.string.Close), null) - .setOnDismissListener(dialog -> finishFragment()) - .show()); - } else { - lastError = error.text; - if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && - (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { - createTimer(); - } - if (currentType == AUTH_TYPE_SMS) { - AndroidUtilities.setWaitingForSms(true); - NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); - } else if (currentType == AUTH_TYPE_FLASH_CALL) { - AndroidUtilities.setWaitingForCall(true); - NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); - } - waitingForEvent = true; - if (currentType != AUTH_TYPE_FLASH_CALL) { - AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); - } - if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { - shakeWrongCode(); - } else if (error.text.contains("PHONE_CODE_EXPIRED")) { - onBackPressed(true); - setPage(VIEW_PHONE_INPUT, true, null, true); - } + codeFieldContainer.isFocusSuppressed = true; + for (CodeNumberField f : codeFieldContainer.codeField) { + f.animateFocusedProgress(0); } - }), ConnectionsManager.RequestFlagFailOnServerErrors); - tryShowProgress(reqId); - } else { - final TLRPC.TL_auth_signIn req = new TLRPC.TL_auth_signIn(); - req.phone_number = requestPhone; - req.phone_code = code; - req.phone_code_hash = phoneHash; - destroyTimer(); - codeFieldContainer.isFocusSuppressed = true; - for (CodeNumberField f : codeFieldContainer.codeField) { - f.animateFocusedProgress(0); - } - - int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { - tryHideProgress(false, true); - - boolean ok = false; - - if (error == null) { + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + tryHideProgress(false, true); nextPressed = false; - ok = true; - showDoneButton(false, true); - destroyTimer(); - destroyCodeTimer(); - if (response instanceof TLRPC.TL_auth_authorizationSignUpRequired) { - TLRPC.TL_auth_authorizationSignUpRequired authorization = (TLRPC.TL_auth_authorizationSignUpRequired) response; - if (authorization.terms_of_service != null) { - currentTermsOfService = authorization.terms_of_service; - } - Bundle params = new Bundle(); - params.putString("phoneFormated", requestPhone); - params.putString("phoneHash", phoneHash); - params.putString("code", req.phone_code); - - animateSuccess(() -> setPage(VIEW_REGISTER, true, params, false)); - } else { - animateSuccess(() -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); - } - } else { - lastError = error.text; - if (error.text.contains("SESSION_PASSWORD_NEEDED")) { - ok = true; - TLRPC.TL_account_getPassword req2 = new TLRPC.TL_account_getPassword(); - ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { - nextPressed = false; - showDoneButton(false, true); - if (error1 == null) { - TLRPC.TL_account_password password = (TLRPC.TL_account_password) response1; - if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { - AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); - return; - } - Bundle bundle = new Bundle(); - SerializedData data = new SerializedData(password.getObjectSize()); - password.serializeToStream(data); - bundle.putString("password", Utilities.bytesToHex(data.toByteArray())); - bundle.putString("phoneFormated", requestPhone); - bundle.putString("phoneHash", phoneHash); - bundle.putString("code", req.phone_code); - - animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); - } else { - needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); - } - }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + if (error == null) { + TLRPC.User user = (TLRPC.User) response; destroyTimer(); destroyCodeTimer(); + UserConfig.getInstance(currentAccount).setCurrentUser(user); + UserConfig.getInstance(currentAccount).saveConfig(true); + ArrayList users = new ArrayList<>(); + users.add(user); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(users, null, true, true); + MessagesController.getInstance(currentAccount).putUser(user, false); + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.mainUserInfoChanged); + getMessagesController().removeSuggestion(0, "VALIDATE_PHONE_NUMBER"); + + if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.endIncomingCall(); + } + + animateSuccess(()-> { + try { + fragmentView.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP, HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING); + } catch (Exception ignored) {} + new AlertDialog.Builder(getContext()) + .setTitle(LocaleController.getString(R.string.YourPasswordSuccess)) + .setMessage(LocaleController.getString(R.string.ChangePhoneNumberSuccess)) + .setPositiveButton(LocaleController.getString(R.string.OK), null) + .setOnDismissListener(dialog -> finishFragment()) + .show(); + }); } else { + lastError = error.text; nextPressed = false; showDoneButton(false, true); if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { @@ -3796,15 +3822,179 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } } } + }), ConnectionsManager.RequestFlagFailOnServerErrors); + tryShowProgress(reqId, true); + showDoneButton(true, true); + break; + } + case MODE_CANCEL_ACCOUNT_DELETION: { + requestPhone = cancelDeletionPhone; + TLRPC.TL_account_confirmPhone req = new TLRPC.TL_account_confirmPhone(); + req.phone_code = code; + req.phone_code_hash = phoneHash; + destroyTimer(); + + codeFieldContainer.isFocusSuppressed = true; + for (CodeNumberField f : codeFieldContainer.codeField) { + f.animateFocusedProgress(0); } - if (ok) { - if (currentType == AUTH_TYPE_FLASH_CALL) { - AndroidUtilities.endIncomingCall(); + + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + tryHideProgress(false); + nextPressed = false; + if (error == null) { + animateSuccess(() -> new AlertDialog.Builder(getParentActivity()) + .setTitle(LocaleController.getString(R.string.CancelLinkSuccessTitle)) + .setMessage(LocaleController.formatString("CancelLinkSuccess", R.string.CancelLinkSuccess, PhoneFormat.getInstance().format("+" + phone))) + .setPositiveButton(LocaleController.getString(R.string.Close), null) + .setOnDismissListener(dialog -> finishFragment()) + .show()); + } else { + lastError = error.text; + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && + (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + createTimer(); + } + if (currentType == AUTH_TYPE_SMS) { + AndroidUtilities.setWaitingForSms(true); + NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); + } else if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.setWaitingForCall(true); + NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); + } + waitingForEvent = true; + if (currentType != AUTH_TYPE_FLASH_CALL) { + AlertsCreator.processError(currentAccount, error, LoginActivity.this, req); + } + if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + shakeWrongCode(); + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + } } + }), ConnectionsManager.RequestFlagFailOnServerErrors); + tryShowProgress(reqId); + break; + } + default: { + TLRPC.TL_auth_signIn req = new TLRPC.TL_auth_signIn(); + req.phone_number = requestPhone; + req.phone_code = code; + req.phone_code_hash = phoneHash; + destroyTimer(); + + codeFieldContainer.isFocusSuppressed = true; + for (CodeNumberField f : codeFieldContainer.codeField) { + f.animateFocusedProgress(0); } - }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); - tryShowProgress(reqId, true); - showDoneButton(true, true); + + int reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + tryHideProgress(false, true); + + boolean ok = false; + + if (error == null) { + nextPressed = false; + ok = true; + showDoneButton(false, true); + destroyTimer(); + destroyCodeTimer(); + if (response instanceof TLRPC.TL_auth_authorizationSignUpRequired) { + TLRPC.TL_auth_authorizationSignUpRequired authorization = (TLRPC.TL_auth_authorizationSignUpRequired) response; + if (authorization.terms_of_service != null) { + currentTermsOfService = authorization.terms_of_service; + } + Bundle params = new Bundle(); + params.putString("phoneFormated", requestPhone); + params.putString("phoneHash", phoneHash); + params.putString("code", req.phone_code); + + animateSuccess(() -> setPage(VIEW_REGISTER, true, params, false)); + } else { + animateSuccess(() -> onAuthSuccess((TLRPC.TL_auth_authorization) response)); + } + } else { + lastError = error.text; + if (error.text.contains("SESSION_PASSWORD_NEEDED")) { + ok = true; + TLRPC.TL_account_getPassword req2 = new TLRPC.TL_account_getPassword(); + ConnectionsManager.getInstance(currentAccount).sendRequest(req2, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { + nextPressed = false; + showDoneButton(false, true); + if (error1 == null) { + TLRPC.TL_account_password password = (TLRPC.TL_account_password) response1; + if (!TwoStepVerificationActivity.canHandleCurrentPassword(password, true)) { + AlertsCreator.showUpdateAppAlert(getParentActivity(), LocaleController.getString("UpdateAppAlert", R.string.UpdateAppAlert), true); + return; + } + Bundle bundle = new Bundle(); + SerializedData data = new SerializedData(password.getObjectSize()); + password.serializeToStream(data); + bundle.putString("password", Utilities.bytesToHex(data.toByteArray())); + bundle.putString("phoneFormated", requestPhone); + bundle.putString("phoneHash", phoneHash); + bundle.putString("code", req.phone_code); + + animateSuccess(() -> setPage(VIEW_PASSWORD, true, bundle, false)); + } else { + needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), error1.text); + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + destroyTimer(); + destroyCodeTimer(); + } else { + nextPressed = false; + showDoneButton(false, true); + if (currentType == AUTH_TYPE_FLASH_CALL && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_SMS) || currentType == AUTH_TYPE_SMS && (nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_FLASH_CALL) || currentType == AUTH_TYPE_CALL && nextType == AUTH_TYPE_SMS) { + createTimer(); + } + if (currentType == AUTH_TYPE_SMS) { + AndroidUtilities.setWaitingForSms(true); + NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveSmsCode); + } else if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.setWaitingForCall(true); + NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); + } + waitingForEvent = true; + if (currentType != AUTH_TYPE_FLASH_CALL) { + boolean isWrongCode = false; + if (error.text.contains("PHONE_NUMBER_INVALID")) { + needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("InvalidPhoneNumber", R.string.InvalidPhoneNumber)); + } else if (error.text.contains("PHONE_CODE_EMPTY") || error.text.contains("PHONE_CODE_INVALID")) { + shakeWrongCode(); + isWrongCode = true; + } else if (error.text.contains("PHONE_CODE_EXPIRED")) { + onBackPressed(true); + setPage(VIEW_PHONE_INPUT, true, null, true); + needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("CodeExpired", R.string.CodeExpired)); + } else if (error.text.startsWith("FLOOD_WAIT")) { + needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("FloodWait", R.string.FloodWait)); + } else { + needShowAlert(LocaleController.getString(R.string.RestorePasswordNoEmailTitle), LocaleController.getString("ErrorOccurred", R.string.ErrorOccurred) + "\n" + error.text); + } + + if (!isWrongCode) { + for (int a = 0; a < codeFieldContainer.codeField.length; a++) { + codeFieldContainer.codeField[a].setText(""); + } + + codeFieldContainer.isFocusSuppressed = false; + codeFieldContainer.codeField[0].requestFocus(); + } + } + } + } + if (ok) { + if (currentType == AUTH_TYPE_FLASH_CALL) { + AndroidUtilities.endIncomingCall(); + } + } + }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); + tryShowProgress(reqId, true); + showDoneButton(true, true); + break; + } } } @@ -3858,7 +4048,7 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No @Override public boolean onBackPressed(boolean force) { - if (cancelAccountDeletionMode) { + if (activityMode != MODE_LOGIN) { finishFragment(); return false; } @@ -5363,7 +5553,6 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No avatarBig = null; showAvatarProgress(false, true); avatarImage.setImage(null, null, avatarDrawable, null); - avatarEditor.setImageResource(R.drawable.actions_setphoto); avatarEditor.setAnimation(cameraDrawable); cameraDrawable.setCurrentFrame(0); isCameraWaitAnimationAllowed = true; @@ -6186,6 +6375,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No } private void show() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ObjectAnimator.ofFloat(fabContainer, View.TRANSLATION_Z, fabContainer.getTranslationZ(), 0).setDuration(150).start(); + } + ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(250); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -6268,6 +6461,10 @@ public class LoginActivity extends BaseFragment implements NotificationCenter.No if (getParent() instanceof ViewGroup) { ((ViewGroup) getParent()).removeView(PhoneNumberConfirmView.this); } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + ObjectAnimator.ofFloat(fabContainer, View.TRANSLATION_Z, 0, AndroidUtilities.dp(2)).setDuration(150).start(); + } fabContainer.setVisibility(VISIBLE); } }); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java index 8ea0d6253..87436ff1a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LogoutActivity.java @@ -131,29 +131,32 @@ public class LogoutActivity extends BaseFragment { } else if (position == phoneRow) { presentFragment(new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER)); } else if (position == supportRow) { - showDialog(AlertsCreator.createSupportAlert(LogoutActivity.this)); + showDialog(AlertsCreator.createSupportAlert(LogoutActivity.this, null)); } else if (position == logoutRow) { if (getParentActivity() == null) { return; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - UserConfig userConfig = getUserConfig(); - builder.setMessage(LocaleController.getString("AreYouSureLogout", R.string.AreYouSureLogout)); - builder.setTitle(LocaleController.getString("LogOut", R.string.LogOut)); - builder.setPositiveButton(LocaleController.getString("LogOut", R.string.LogOut), (dialogInterface, i) -> MessagesController.getInstance(currentAccount).performLogout(1)); - builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - AlertDialog alertDialog = builder.create(); - showDialog(alertDialog); - TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); - if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); - } + showDialog(makeLogOutDialog(getParentActivity(), currentAccount)); } }); return fragmentView; } + public static AlertDialog makeLogOutDialog(Context context, int currentAccount) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setMessage(LocaleController.getString("AreYouSureLogout", R.string.AreYouSureLogout)); + builder.setTitle(LocaleController.getString("LogOut", R.string.LogOut)); + builder.setPositiveButton(LocaleController.getString("LogOut", R.string.LogOut), (dialogInterface, i) -> MessagesController.getInstance(currentAccount).performLogout(1)); + builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); + AlertDialog alertDialog = builder.create(); + TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + return alertDialog; + } + @Override protected void onDialogDismiss(Dialog dialog) { DownloadController.getInstance(currentAccount).checkAutodownloadSettings(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java index de84bb8d4..0b8e2ab92 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/MessageSeenView.java @@ -10,6 +10,7 @@ import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -247,7 +248,19 @@ public class MessageSeenView extends FrameLayout { } public RecyclerListView createListView() { - RecyclerListView recyclerListView = new RecyclerListView(getContext()); + RecyclerListView recyclerListView = new RecyclerListView(getContext()) { + @Override + protected void onMeasure(int widthSpec, int heightSpec) { + int height = MeasureSpec.getSize(heightSpec); + int listViewTotalHeight = AndroidUtilities.dp(8) + AndroidUtilities.dp(44) * getAdapter().getItemCount(); + + if (listViewTotalHeight > height) { + listViewTotalHeight = height; + } + + super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(listViewTotalHeight, MeasureSpec.EXACTLY)); + } + }; recyclerListView.setLayoutManager(new LinearLayoutManager(getContext())); recyclerListView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override @@ -305,6 +318,7 @@ public class MessageSeenView extends FrameLayout { nameView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); nameView.setLines(1); nameView.setEllipsize(TextUtils.TruncateAt.END); + nameView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); addView(nameView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL, 59, 0, 13, 0)); nameView.setTextColor(Theme.getColor(Theme.key_actionBarDefaultSubmenuItem)); @@ -323,5 +337,11 @@ public class MessageSeenView extends FrameLayout { nameView.setText(ContactsController.formatName(user.first_name, user.last_name)); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + info.setText(LocaleController.formatString("AccDescrPersonHasSeen", R.string.AccDescrPersonHasSeen, nameView.getText())); + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java index 7cc6a4390..33cf4392d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NewContactActivity.java @@ -16,7 +16,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; import android.content.Intent; -import android.graphics.Rect; import android.net.Uri; import android.telephony.TelephonyManager; import android.text.Editable; @@ -180,7 +179,7 @@ public class NewContactActivity extends BaseFragment implements AdapterView.OnIt avatarDrawable.setInfo(5, "", ""); ActionBarMenu menu = actionBar.createMenu(); - editDoneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + editDoneItem = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); editDoneItem.setContentDescription(LocaleController.getString("Done", R.string.Done)); editDoneItemProgress = new ContextProgressView(context, 1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java index 130bb03d5..f9c00062c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsCustomSettingsActivity.java @@ -40,6 +40,7 @@ import org.telegram.messenger.DialogObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationsController; import org.telegram.messenger.R; @@ -64,6 +65,8 @@ import org.telegram.ui.Cells.TextColorCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Cells.UserCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.BulletinFactory; +import org.telegram.ui.Components.ChatNotificationsPopupWrapper; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; @@ -267,8 +270,93 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements return; } - AlertsCreator.showCustomNotificationsDialog(NotificationsCustomSettingsActivity.this, exception.did, -1, null, currentAccount, null, param -> { - if (param == 0) { + long did = exception.did; + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(did); + ChatNotificationsPopupWrapper chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, null, true, true, new ChatNotificationsPopupWrapper.Callback() { + @Override + public void toggleSound() { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + boolean enabled = !preferences.getBoolean("sound_enabled_" + did, true); + preferences.edit().putBoolean("sound_enabled_" + did, enabled).apply(); + if (BulletinFactory.canShowBulletin(NotificationsCustomSettingsActivity.this)) { + BulletinFactory.createSoundEnabledBulletin(NotificationsCustomSettingsActivity.this, enabled ? NotificationsController.SETTING_SOUND_ON : NotificationsController.SETTING_SOUND_OFF, getResourceProvider()).show(); + } + } + + @Override + public void muteFor(int timeInSeconds) { + if (timeInSeconds == 0) { + if (getMessagesController().isDialogMuted(did)) { + toggleMute(); + } + if (BulletinFactory.canShowBulletin(NotificationsCustomSettingsActivity.this)) { + BulletinFactory.createMuteBulletin(NotificationsCustomSettingsActivity.this, NotificationsController.SETTING_MUTE_UNMUTE, timeInSeconds, getResourceProvider()).show(); + } + } else { + getNotificationsController().muteUntil(did, timeInSeconds); + if (BulletinFactory.canShowBulletin(NotificationsCustomSettingsActivity.this)) { + BulletinFactory.createMuteBulletin(NotificationsCustomSettingsActivity.this, NotificationsController.SETTING_MUTE_CUSTOM, timeInSeconds, getResourceProvider()).show(); + } + } + update(); + } + + @Override + public void showCustomize() { + if (did != 0) { + Bundle args = new Bundle(); + args.putLong("dialog_id", did); + ProfileNotificationsActivity fragment = new ProfileNotificationsActivity(args); + fragment.setDelegate(new ProfileNotificationsActivity.ProfileNotificationsActivityDelegate() { + @Override + public void didCreateNewException(NotificationsSettingsActivity.NotificationException exception) {} + + @Override + public void didRemoveException(long dialog_id) { + setDefault(); + } + }); + presentFragment(fragment); + } + } + + @Override + public void toggleMute() { + boolean muted = getMessagesController().isDialogMuted(did); + getNotificationsController().muteDialog(did, !muted); + BulletinFactory.createMuteBulletin(NotificationsCustomSettingsActivity.this, getMessagesController().isDialogMuted(did), null).show(); + update(); + } + + private void update() { + if (getMessagesController().isDialogMuted(did) != defaultEnabled) { + setDefault(); + } else { + setNotDefault(); + } + } + + private void setNotDefault() { + SharedPreferences preferences = getNotificationsSettings(); + exception.hasCustom = preferences.getBoolean("custom_" + exception.did, false); + exception.notify = preferences.getInt("notify2_" + exception.did, 0); + if (exception.notify != 0) { + int time = preferences.getInt("notifyuntil_" + exception.did, -1); + if (time != -1) { + exception.muteUntil = time; + } + } + if (newException) { + exceptions.add(exception); + exceptionsDict.put(exception.did, exception); + updateRows(true); + } else { + listView.getAdapter().notifyItemChanged(position); + } + actionBar.closeSearchField(); + } + + private void setDefault() { if (newException) { return; } @@ -291,29 +379,13 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements checkRowsEnabled(); } else { updateRows(true); - searchAdapter.notifyDataSetChanged(); - } - actionBar.closeSearchField(); - } else { - SharedPreferences preferences = getNotificationsSettings(); - exception.hasCustom = preferences.getBoolean("custom_" + exception.did, false); - exception.notify = preferences.getInt("notify2_" + exception.did, 0); - if (exception.notify != 0) { - int time = preferences.getInt("notifyuntil_" + exception.did, -1); - if (time != -1) { - exception.muteUntil = time; - } - } - if (newException) { - exceptions.add(exception); - exceptionsDict.put(exception.did, exception); - updateRows(true); - } else { - listView.getAdapter().notifyItemChanged(position); + searchAdapter.notifyItemChanged(position); } actionBar.closeSearchField(); } - }); + }, getResourceProvider()); + chatNotificationsPopupWrapper.update(did); + chatNotificationsPopupWrapper.showAsOptions(NotificationsCustomSettingsActivity.this, view, x, y); return; } if (position == exceptionsAddRow) { @@ -332,7 +404,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements Bundle args2 = new Bundle(); args2.putLong("dialog_id", dids.get(0)); args2.putBoolean("exception", true); - ProfileNotificationsActivity profileNotificationsActivity = new ProfileNotificationsActivity(args2); + ProfileNotificationsActivity profileNotificationsActivity = new ProfileNotificationsActivity(args2, getResourceProvider()); profileNotificationsActivity.setDelegate(exception -> { exceptions.add(0, exception); updateRows(true); @@ -438,7 +510,7 @@ public class NotificationsCustomSettingsActivity extends BaseFragment implements try { Bundle bundle = new Bundle(); bundle.putInt("type", currentType); - presentFragment(new NotificationsSoundActivity(bundle)); + presentFragment(new NotificationsSoundActivity(bundle, getResourceProvider())); // SharedPreferences preferences = getNotificationsSettings(); // Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); // tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java index b0d42f4f6..33c495aa2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSoundActivity.java @@ -78,6 +78,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta NumberTextView selectedTonesCountTextView; RecyclerListView listView; Adapter adapter; + Theme.ResourcesProvider resourcesProvider; int rowCount; int serverTonesHeaderRow; @@ -114,7 +115,12 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta private final int tonesStreamType = AudioManager.STREAM_ALARM; public NotificationsSoundActivity(Bundle args) { + this(args, null); + } + + public NotificationsSoundActivity(Bundle args, Theme.ResourcesProvider resourcesProvider) { super(args); + this.resourcesProvider = resourcesProvider; } @Override @@ -157,8 +163,15 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta return super.onFragmentCreate(); } + @Override + public Theme.ResourcesProvider getResourceProvider() { + return resourcesProvider; + } + @Override public View createView(final Context context) { + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_avatar_actionBarSelectorBlue, resourcesProvider), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider), false); actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setAllowOverlayTitle(false); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @@ -171,7 +184,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta finishFragment(); } } else if (id == deleteId) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.formatPluralString("DeleteTones", selectedTones.size())); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatPluralString("DeleteTonesMessage", selectedTones.size()))); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialog, which) -> { @@ -184,7 +197,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta AlertDialog dialog = builder.show(); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2, resourcesProvider)); } } else if (id == shareId) { if (selectedTones.size() == 1) { @@ -274,7 +287,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta actionBar.setTitle(LocaleController.getString("NotificationsSoundChannels", R.string.NotificationsSoundChannels)); } } else { - avatarContainer = new ChatAvatarContainer(context, null, false); + avatarContainer = new ChatAvatarContainer(context, null, false, resourcesProvider); avatarContainer.setOccupyStatusBar(!AndroidUtilities.isTablet()); actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0)); if (dialogId < 0) { @@ -296,7 +309,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta selectedTonesCountTextView = new NumberTextView(actionMode.getContext()); selectedTonesCountTextView.setTextSize(18); selectedTonesCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - selectedTonesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon)); + selectedTonesCountTextView.setTextColor(Theme.getColor(Theme.key_actionBarActionModeDefaultIcon, resourcesProvider)); actionMode.addView(selectedTonesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f, 72, 0, 0, 0)); selectedTonesCountTextView.setOnTouchListener((v, event) -> true); @@ -305,7 +318,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; - frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); listView = new RecyclerListView(context); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -317,7 +330,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta listView.setLayoutManager(new LinearLayoutManager(context)); listView.setOnItemClickListener((view, position) -> { if (position == uploadRow) { - chatAttachAlert = new ChatAttachAlert(context, NotificationsSoundActivity.this, false, false); + chatAttachAlert = new ChatAttachAlert(context, NotificationsSoundActivity.this, false, false, resourcesProvider); chatAttachAlert.setSoundPicker(); chatAttachAlert.init(); chatAttachAlert.show(); @@ -331,35 +344,39 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta if (lastPlayedRingtone != null) { lastPlayedRingtone.stop(); } - if (cell.tone.isSystemDefault) { - Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); - r.setStreamType(tonesStreamType); - lastPlayedRingtone = r; - r.play(); - } else if (cell.tone.uri != null && !cell.tone.fromServer) { - Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), Uri.parse(cell.tone.uri)); - r.setStreamType(tonesStreamType); - lastPlayedRingtone = r; - r.play(); - } else if (cell.tone.fromServer) { - File file = null; - if (!TextUtils.isEmpty(cell.tone.uri)) { - File localUriFile = new File(cell.tone.uri); - if (localUriFile.exists()) { - file = localUriFile; - } - } - if (file == null) { - file = FileLoader.getPathToAttach(cell.tone.document); - } - if (file != null && file.exists()) { - Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), Uri.parse(file.toString())); + try { + if (cell.tone.isSystemDefault) { + Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)); r.setStreamType(tonesStreamType); lastPlayedRingtone = r; r.play(); - } else { - getFileLoader().loadFile(cell.tone.document, cell.tone.document, 2, 0); + } else if (cell.tone.uri != null && !cell.tone.fromServer) { + Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), Uri.parse(cell.tone.uri)); + r.setStreamType(tonesStreamType); + lastPlayedRingtone = r; + r.play(); + } else if (cell.tone.fromServer) { + File file = null; + if (!TextUtils.isEmpty(cell.tone.uri)) { + File localUriFile = new File(cell.tone.uri); + if (localUriFile.exists()) { + file = localUriFile; + } + } + if (file == null) { + file = getFileLoader().getPathToAttach(cell.tone.document); + } + if (file != null && file.exists()) { + Ringtone r = RingtoneManager.getRingtone(context.getApplicationContext(), Uri.parse(file.toString())); + r.setStreamType(tonesStreamType); + lastPlayedRingtone = r; + r.play(); + } else { + getFileLoader().loadFile(cell.tone.document, cell.tone.document, 2, 0); + } } + } catch (Exception e) { + FileLog.e(e); } startSelectedTone = null; selectedTone = cell.tone; @@ -569,22 +586,22 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta Context context = parent.getContext(); switch (viewType) { case 0: - view = new ToneCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + view = new ToneCell(context, resourcesProvider); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); break; default: case 1: - view = new HeaderCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + view = new HeaderCell(context, resourcesProvider); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); break; case 2: - CreationTextCell creationTextCell = new CreationTextCell(context); + CreationTextCell creationTextCell = new CreationTextCell(context, resourcesProvider); creationTextCell.startPadding = 61; view = creationTextCell; - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite, resourcesProvider)); break; case 3: - view = new ShadowSectionCell(context); + view = new ShadowSectionCell(context, resourcesProvider); break; } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); @@ -627,8 +644,8 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta CreationTextCell textCell = (CreationTextCell) holder.itemView; Drawable drawable1 = textCell.getContext().getResources().getDrawable(R.drawable.poll_add_circle); Drawable drawable2 = textCell.getContext().getResources().getDrawable(R.drawable.poll_add_plus); - drawable1.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switchTrackChecked), PorterDuff.Mode.MULTIPLY)); - drawable2.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_checkboxCheck), PorterDuff.Mode.MULTIPLY)); + 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); textCell.setTextAndIcon(LocaleController.getString("UploadSound", R.string.UploadSound), combinedDrawable, false); break; @@ -670,16 +687,16 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta Tone tone; - public ToneCell(Context context) { + public ToneCell(Context context, Theme.ResourcesProvider resourcesProvider) { super(context); radioButton = new RadioButton(context); radioButton.setSize(AndroidUtilities.dp(20)); - radioButton.setColor(Theme.getColor(Theme.key_radioBackground), Theme.getColor(Theme.key_radioBackgroundChecked)); + radioButton.setColor(Theme.getColor(Theme.key_radioBackground, resourcesProvider), Theme.getColor(Theme.key_radioBackgroundChecked, resourcesProvider)); addView(radioButton, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL, (LocaleController.isRTL ? 0 : 20), 0, (LocaleController.isRTL ? 20 : 0), 0)); - checkBox = new CheckBox2(context, 24); + checkBox = new CheckBox2(context, 24, resourcesProvider); checkBox.setColor(null, Theme.key_windowBackgroundWhite, Theme.key_checkboxCheck); checkBox.setDrawUnchecked(false); checkBox.setDrawBackgroundAsArc(3); @@ -687,7 +704,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta checkBox.setChecked(true, false); textView = new TextView(context); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); textView.setLines(1); textView.setMaxLines(1); @@ -731,6 +748,11 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta getNotificationCenter().removeObserver(this, NotificationCenter.onUserRingtonesUpdated); } + @Override + public int getNavigationBarColor() { + return getThemedColor(Theme.key_windowBackgroundGray); + } + @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.onUserRingtonesUpdated) { @@ -933,7 +955,7 @@ public class NotificationsSoundActivity extends BaseFragment implements ChatAtta File file = new File(AndroidUtilities.getCacheDir(), fileName); if (!file.exists()) { try { - AndroidUtilities.copyFile(FileLoader.getPathToAttach(document), file); + AndroidUtilities.copyFile(FileLoader.getInstance(currentAccount).getPathToAttach(document), file); } catch (IOException e) { e.printStackTrace(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java index 68c32dfbc..08a12a301 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java @@ -426,6 +426,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter frameLayout.addView(innerLinearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); lockImageView = new RLottieImageView(context); + lockImageView.setFocusable(false); lockImageView.setAnimation(R.raw.tsv_setup_intro, 120, 120); lockImageView.setAutoRepeat(false); lockImageView.playAnimation(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java index a1441d489..3a3f202a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PassportActivity.java @@ -588,7 +588,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter public void updateButtonState(boolean animated) { String fileName = FileLoader.getAttachFileName(currentSecureDocument); - File path = FileLoader.getPathToAttach(currentSecureDocument); + File path = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(currentSecureDocument); boolean fileExists = path.exists(); if (TextUtils.isEmpty(fileName)) { radialProgress.setBackground(null, false, false); @@ -1287,7 +1287,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter if (currentActivityType != TYPE_REQUEST && currentActivityType != TYPE_MANAGE) { ActionBarMenu menu = actionBar.createMenu(); - doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneItem = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); progressView = new ContextProgressView(context, 1); progressView.setAlpha(0.0f); progressView.setScaleX(0.1f); @@ -1989,7 +1989,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter actionBar.setTitle(LocaleController.getString("TelegramPassport", R.string.TelegramPassport)); - actionBar.createMenu().addItem(info_item, R.drawable.profile_info); + actionBar.createMenu().addItem(info_item, R.drawable.msg_info); if (botUser != null) { FrameLayout avatarContainer = new FrameLayout(context); @@ -2413,7 +2413,7 @@ public class PassportActivity extends BaseFragment implements NotificationCenter actionBar.setTitle(LocaleController.getString("TelegramPassport", R.string.TelegramPassport)); - actionBar.createMenu().addItem(info_item, R.drawable.profile_info); + actionBar.createMenu().addItem(info_item, R.drawable.msg_info); headerCell = new HeaderCell(context); headerCell.setText(LocaleController.getString("PassportProvidedInformation", R.string.PassportProvidedInformation)); @@ -5512,9 +5512,9 @@ public class PassportActivity extends BaseFragment implements NotificationCenter } private void renameFile(SecureDocument oldDocument, TLRPC.TL_secureFile newSecureFile) { - File oldFile = FileLoader.getPathToAttach(oldDocument); + File oldFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(oldDocument); String oldKey = oldDocument.secureFile.dc_id + "_" + oldDocument.secureFile.id; - File newFile = FileLoader.getPathToAttach(newSecureFile); + File newFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToAttach(newSecureFile); String newKey = newSecureFile.dc_id + "_" + newSecureFile.id; oldFile.renameTo(newFile); ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, null, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java index 2a3a8d02b..dbe569cf8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PeopleNearbyActivity.java @@ -1009,10 +1009,10 @@ public class PeopleNearbyActivity extends BaseFragment implements NotificationCe actionCell.setText(LocaleController.getString("NearbyCreateGroup", R.string.NearbyCreateGroup), null, R.drawable.baseline_group_add_24, chatsStartRow != -1); } else if (position == showMeRow) { if (showingMe = (getUserConfig().sharingMyLocationUntil > getConnectionsManager().getCurrentTime())) { - actionCell.setText(LocaleController.getString("StopShowingMe", R.string.StopShowingMe), null, R.drawable.actions_nearby_off, usersStartRow != -1); + actionCell.setText(LocaleController.getString("StopShowingMe", R.string.StopShowingMe), null, R.drawable.msg_nearby_off, usersStartRow != -1); actionCell.setColors(Theme.key_windowBackgroundWhiteRedText5, Theme.key_windowBackgroundWhiteRedText5); } else { - actionCell.setText(LocaleController.getString("MakeMyselfVisible", R.string.MakeMyselfVisible), null, R.drawable.actions_nearby_on, usersStartRow != -1); + actionCell.setText(LocaleController.getString("MakeMyselfVisible", R.string.MakeMyselfVisible), null, R.drawable.msg_nearby, usersStartRow != -1); } } else if (position == showMoreRow) { actionCell.setText(LocaleController.formatPluralString("ShowVotes", users.size() - 5), null, R.drawable.arrow_more, false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java index 7e698e0ee..095ad499f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java @@ -42,6 +42,9 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.NotNull; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.LocaleController; @@ -476,7 +479,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati sendPopupWindow.dismiss(); } }); - sendPopupLayout.setShownFromBotton(false); + sendPopupLayout.setShownFromBottom(false); itemCells = new ActionBarMenuSubItem[2]; for (int a = 0; a < 3; a++) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java index 99269da11..040675ad4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java @@ -441,7 +441,7 @@ public class PhotoCropActivity extends BaseFragment { }); ActionBarMenu menu = actionBar.createMenu(); - menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); fragmentView = view = new PhotoCropView(context); ((PhotoCropView) fragmentView).freeform = getArguments().getBoolean("freeform", false); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java index 0f1b28145..b159ba7ab 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java @@ -23,6 +23,7 @@ import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.Editable; @@ -30,6 +31,7 @@ import android.text.InputFilter; import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; +import android.util.TypedValue; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; @@ -51,6 +53,9 @@ import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.RecyclerView; import org.jetbrains.annotations.NotNull; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ChatObject; @@ -89,12 +94,13 @@ import org.telegram.ui.Components.BackupImageView; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.EditTextBoldCursor; import org.telegram.ui.Components.EditTextEmoji; -import org.telegram.ui.Components.EmptyTextProgressView; +import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.RecyclerViewItemRangeSelector; import org.telegram.ui.Components.SizeNotifierFrameLayout; +import org.telegram.ui.Components.StickerEmptyView; import java.util.ArrayList; import java.util.HashMap; @@ -158,7 +164,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen private RecyclerListView listView; private ListAdapter listAdapter; private GridLayoutManager layoutManager; - private EmptyTextProgressView emptyView; + private StickerEmptyView emptyView; + private FlickerLoadingView flickerView; private ActionBarMenuItem searchItem; private ActionBarMenuSubItem showAsListItem; private int itemSize = 100; @@ -566,11 +573,17 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen ConnectionsManager.getInstance(currentAccount).cancelRequest(imageReqId, true); imageReqId = 0; } - emptyView.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); + emptyView.title.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); + emptyView.showProgress(false); updateSearchInterface(); + } else { + AndroidUtilities.cancelRunOnUIThread(updateSearch); + AndroidUtilities.runOnUIThread(updateSearch, 1200); } } + Runnable updateSearch = () -> processSearch(searchItem.getSearchField()); + @Override public void onSearchPressed(EditText editText) { processSearch(editText); @@ -913,18 +926,36 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen listView.addOnItemTouchListener(itemRangeSelector); } - emptyView = new EmptyTextProgressView(context); - emptyView.setTextColor(0xff93999d); - emptyView.setProgressBarColor(0xff527da3); + flickerView = new FlickerLoadingView(context, getResourceProvider()) { + @Override + public int getViewType() { + return PHOTOS_TYPE; + } + + @Override + public int getColumnsCount() { + return 3; + } + }; + flickerView.setAlpha(0); + flickerView.setVisibility(View.GONE); + + emptyView = new StickerEmptyView(context, flickerView, StickerEmptyView.STICKER_TYPE_SEARCH, getResourceProvider()); + emptyView.setAnimateLayoutChange(true); + emptyView.title.setTypeface(Typeface.DEFAULT); + emptyView.title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + emptyView.title.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText)); + emptyView.addView(flickerView, 0); if (selectedAlbum != null) { - emptyView.setShowAtCenter(false); - emptyView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); +// emptyView.setShowAtCenter(false); + emptyView.title.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos)); } else { - emptyView.setShowAtTop(true); - emptyView.setPadding(0, AndroidUtilities.dp(200), 0, 0); - emptyView.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); +// emptyView.setShowAtTop(true); +// emptyView.setPadding(0, AndroidUtilities.dp(200), 0, 0); + emptyView.title.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); } - sizeNotifierFrameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, selectPhotoType != PhotoAlbumPickerActivity.SELECT_TYPE_ALL ? 0 : 48)); + emptyView.showProgress(false, false); + sizeNotifierFrameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 126, 0, 0)); listView.setOnScrollListener(new RecyclerView.OnScrollListener() { @Override @@ -1084,7 +1115,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen sendPopupWindow.dismiss(); } }); - sendPopupLayout.setShownFromBotton(false); + sendPopupLayout.setShownFromBottom(false); itemCells = new ActionBarMenuSubItem[2]; for (int a = 0; a < 3; a++) { @@ -1202,6 +1233,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen allowIndices = (selectedAlbum != null || type == 0 || type == 1) && allowOrder; listView.setEmptyView(emptyView); + listView.setAnimateEmptyView(true, 0); updatePhotosButton(0); return fragmentView; @@ -1264,10 +1296,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (commentTextView.isPopupShowing()) { fragmentView.setTranslationY(y); listView.setTranslationY(0); - emptyView.setTranslationY(0); +// emptyView.setTranslationY(0); } else { listView.setTranslationY(y); - emptyView.setTranslationY(y); +// emptyView.setTranslationY(y); } } @@ -1317,6 +1349,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + emptyView.showProgress(false); saveRecentSearch(); } @@ -1389,23 +1422,26 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } } + private void addToRecentSearches(String query) { + for (int a = 0, N = recentSearches.size(); a < N; a++) { + String str = recentSearches.get(a); + if (str.equalsIgnoreCase(query)) { + recentSearches.remove(a); + break; + } + } + recentSearches.add(0, query); + while (recentSearches.size() > 20) { + recentSearches.remove(recentSearches.size() - 1); + } + saveRecentSearch(); + } + private void processSearch(EditText editText) { if (editText.getText().length() == 0) { return; } String text = editText.getText().toString(); - for (int a = 0, N = recentSearches.size(); a < N; a++) { - String str = recentSearches.get(a); - if (str.equalsIgnoreCase(text)) { - recentSearches.remove(a); - break; - } - } - recentSearches.add(0, text); - while (recentSearches.size() > 20) { - recentSearches.remove(recentSearches.size() - 1); - } - saveRecentSearch(); searchResult.clear(); searchResultKeys.clear(); imageSearchEndReached = true; @@ -1413,9 +1449,9 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen lastSearchString = text; if (lastSearchString.length() == 0) { lastSearchString = null; - emptyView.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); + emptyView.title.setText(LocaleController.getString("NoRecentSearches", R.string.NoRecentSearches)); } else { - emptyView.setText(LocaleController.getString("NoResult", R.string.NoResult)); + emptyView.title.setText(LocaleController.formatString("NoResultFoundFor", R.string.NoResultFoundFor, lastSearchString)); } updateSearchInterface(); } @@ -1631,10 +1667,10 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } - if (searching && searchResult.isEmpty()) { - emptyView.showProgress(); + if (searching || recentSearches.size() > 0 && (lastSearchString == null || TextUtils.isEmpty(lastSearchString))) { + emptyView.showProgress(true); } else { - emptyView.showTextView(); + emptyView.showProgress(false); } } @@ -1699,6 +1735,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen final int token = ++lastSearchToken; imageReqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + addToRecentSearches(query); if (token != lastSearchToken) { return; } @@ -1792,10 +1829,8 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen } else if (imageSearchEndReached) { listAdapter.notifyItemRemoved(searchResult.size() - 1); } - if (searching && searchResult.isEmpty()) { - emptyView.showProgress(); - } else { - emptyView.showTextView(); + if (searchResult.size() <= 0) { + emptyView.showProgress(false); } })); ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(imageReqId, classGuid); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java index c5e3fa681..16590290e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerSearchActivity.java @@ -8,6 +8,7 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.drawable.Drawable; +import android.os.Build; import android.view.Gravity; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -357,9 +358,8 @@ public class PhotoPickerSearchActivity extends BaseFragment { @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); - if (parentLayout != null) { - parentLayout.drawHeaderShadow(canvas, actionBar.getMeasuredHeight() + (int) actionBar.getTranslationY()); - } + float y = actionBar.getMeasuredHeight() + (int) actionBar.getTranslationY(); + canvas.drawLine(0, y, getWidth(), y, Theme.dividerPaint); } @Override @@ -651,7 +651,7 @@ public class PhotoPickerSearchActivity extends BaseFragment { sizeNotifierFrameLayout.addView(actionBar, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); - sizeNotifierFrameLayout.addView(imagesSearch.shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); +// sizeNotifierFrameLayout.addView(imagesSearch.shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 48)); sizeNotifierFrameLayout.addView(imagesSearch.frameLayout2, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); sizeNotifierFrameLayout.addView(imagesSearch.writeButtonContainer, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, 12, 10)); sizeNotifierFrameLayout.addView(imagesSearch.selectedCountView, LayoutHelper.createFrame(42, 24, Gravity.RIGHT | Gravity.BOTTOM, 0, 0, -2, 9)); @@ -660,6 +660,13 @@ public class PhotoPickerSearchActivity extends BaseFragment { switchToCurrentSelectedMode(false); swipeBackEnabled = scrollSlidingTextTabStrip.getCurrentTabId() == scrollSlidingTextTabStrip.getFirstTabId(); + int statusBarBackground = Theme.getColor(Theme.key_dialogBackground); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && AndroidUtilities.computePerceivedBrightness(statusBarBackground) >= 0.721f) { + fragmentView.setSystemUiVisibility( + fragmentView.getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR + ); + } + return fragmentView; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java index e507d2af1..e06b89de0 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java @@ -12,7 +12,9 @@ import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; +import android.animation.ArgbEvaluator; import android.animation.ObjectAnimator; +import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.Activity; @@ -106,6 +108,7 @@ import androidx.annotation.Keep; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.collection.ArrayMap; +import androidx.collection.LongSparseArray; import androidx.core.content.ContextCompat; import androidx.core.content.FileProvider; import androidx.core.graphics.ColorUtils; @@ -214,6 +217,7 @@ import org.telegram.ui.Components.PlayPauseDrawable; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RadialProgressView; import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.ShareAlert; import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto; import org.telegram.ui.Components.StickersAlert; import org.telegram.ui.Components.TextViewSwitcher; @@ -357,6 +361,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private ImageReceiver sideImage; private boolean isCurrentVideo; + private Runnable onUserLeaveHintListener = this::onUserLeaveHint; + private float currentVideoSpeed; private long lastPhotoSetTime; @@ -498,6 +504,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean textureUploaded; private boolean videoSizeSet; private boolean isInline; + private boolean pipVideoOverlayAnimateFlag = true; private boolean switchingInlineMode; private boolean videoCrossfadeStarted; private float videoCrossfadeAlpha; @@ -528,6 +535,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat protected void onRewindCanceled() { onTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0, 0, 0)); videoForwardDrawable.setShowing(false); + + PipVideoOverlay.onRewindCanceled(); } @Override @@ -537,6 +546,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoPlayerSeekbar.setProgress(progress); videoPlayerSeekbarView.invalidate(); } + + PipVideoOverlay.onUpdateRewindProgressUi(timeDiff, progress, rewindByBackSeek); } @Override @@ -545,6 +556,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat videoForwardDrawable.setLeftSide(!rewindForward); videoForwardDrawable.setShowing(true); containerView.invalidate(); + + PipVideoOverlay.onRewindStart(rewindForward); } }; @@ -638,7 +651,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void onLinkLongPress(URLSpan link, TextView widget, Runnable onDismiss) { int timestamp = -1; - BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity, false, resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity, false, resourcesProvider, 0xff1C2229); if (link.getURL().startsWith("video?")) { try { String timestampStr = link.getURL().substring(link.getURL().indexOf('?') + 1); @@ -725,7 +738,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat bottomSheet.setBackgroundColor(0xff1C2229); bottomSheet.setTitleColor(0xff8A8A8A); bottomSheet.setCalcMandatoryInsets(true); - bottomSheet.setOverlayNavBarColor(0xff1C2229); AndroidUtilities.setNavigationBarColor(bottomSheet.getWindow(), 0xff1C2229, false); AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false); bottomSheet.scrollNavBar = true; @@ -840,22 +852,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } updateVideoPlayerTime(); } - if (firstFrameView != null) { - firstFrameView.updateAlpha(); - if (!videoPlayer.isLooping() && videoPlayer.getDuration() != C.TIME_UNSET) { - if (videoPlayer.getCurrentPosition() > videoPlayer.getDuration() - FirstFrameView.fadeDuration) { - if (!shownControlsByEnd) { - actionBarWasShownBeforeByEnd = isActionBarVisible; - shownControlsByEnd = true; - toggleActionBar(true, true); - checkProgress(0, false, false); - } else { - shownControlsByEnd = false; - actionBarWasShownBeforeByEnd = false; - } - } - } - } +// if (!videoPlayer.isLooping() && videoPlayer.getDuration() != C.TIME_UNSET) { +// if (videoPlayer.getCurrentPosition() > videoPlayer.getDuration() - FirstFrameView.fadeDuration) { +// if (!shownControlsByEnd) { +// actionBarWasShownBeforeByEnd = isActionBarVisible; +// shownControlsByEnd = true; +// toggleActionBar(true, true); +// checkProgress(0, false, false); +// } else { +// shownControlsByEnd = false; +// actionBarWasShownBeforeByEnd = false; +// } +// } +// } +// } + } + if (firstFrameView != null) { + firstFrameView.updateAlpha(); } if (isPlaying) { AndroidUtilities.runOnUIThread(updateProgressRunnable, 17); @@ -902,9 +915,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat isInline = true; changedTextureView = new TextureView(parentActivity); - if (PipVideoOverlay.show(false, parentActivity, changedTextureView, videoWidth, videoHeight, true)) { + if (PipVideoOverlay.show(false, parentActivity, changedTextureView, videoWidth, videoHeight, pipVideoOverlayAnimateFlag)) { PipVideoOverlay.setPhotoViewer(PhotoViewer.this); } + pipVideoOverlayAnimateFlag = true; + changedTextureView.setVisibility(View.INVISIBLE); aspectRatioFrameLayout.removeView(videoTextureView); } @@ -1124,9 +1139,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private float translationX; private float translationY; private float scale = 1; + private float rotate = 0; + private float mirror = 0; private float animateToX; private float animateToY; private float animateToScale; + private float animateToRotate; + private float animateToMirror; private float animationValue; private boolean applying; private long animationStartTime; @@ -1172,7 +1191,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private SparseArray[] imagesByIds = new SparseArray[]{new SparseArray<>(), new SparseArray<>()}; private ArrayList imagesArrLocations = new ArrayList<>(); private ArrayList imagesArrLocationsVideo = new ArrayList<>(); - private ArrayList imagesArrLocationsSizes = new ArrayList<>(); + private ArrayList imagesArrLocationsSizes = new ArrayList<>(); private ArrayList imagesArrMessages = new ArrayList<>(); private ArrayList secureDocuments = new ArrayList<>(); private ArrayList avatarsArr = new ArrayList<>(); @@ -1206,7 +1225,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat Object getParentObject(); } - private android.graphics.Rect hitRect = new android.graphics.Rect(); + private Rect hitRect = new Rect(); private final static int gallery_menu_save = 1; private final static int gallery_menu_scan = 8; @@ -1512,7 +1531,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat playPauseDrawable = new PlayPauseDrawable(28); playPauseDrawable.setDuration(200); - final Drawable circleDrawable = ContextCompat.getDrawable(parentActivity, R.drawable.circle_big); + Drawable circleDrawable = ContextCompat.getDrawable(parentActivity, R.drawable.circle_big); playDrawable = new CombinedDrawable(circleDrawable.mutate(), playPauseDrawable); } @@ -1585,10 +1604,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } if (playPauseDrawable != null) { - boolean animatePlayPause = animateIcon && (backgroundState == 3 || backgroundState == 4); - if (state == 3) { + boolean animatePlayPause = animateIcon && (backgroundState == PROGRESS_PLAY || backgroundState == PROGRESS_PAUSE); + if (state == PROGRESS_PLAY) { playPauseDrawable.setPause(false, animatePlayPause); - } else if (state == 4) { + } else if (state == PROGRESS_PAUSE) { playPauseDrawable.setPause(true, animatePlayPause); } playPauseDrawable.setParent(parent); @@ -1744,7 +1763,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public ImageReceiver.BitmapHolder thumb; public long dialogId; public int index; - public int size; + public long size; public int[] radius; public int clipBottomAddition; public int clipTopAddition; @@ -1927,6 +1946,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat public void onApplyCaption(CharSequence caption) { } + + @Override + public void onOpen() { + + } + + @Override + public void onClose() { + + } } public interface PhotoViewerProvider { @@ -1994,6 +2023,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat boolean closeKeyboard(); boolean validateGroupId(long groupId); void onApplyCaption(CharSequence caption); + + void onOpen(); + void onClose(); } private class FrameLayoutDrawer extends SizeNotifierFrameLayoutPhoto { @@ -2002,7 +2034,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private boolean ignoreLayout; private boolean captionAbove; - AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this) { + AdjustPanLayoutHelper adjustPanLayoutHelper = new AdjustPanLayoutHelper(this, false) { @Override protected void onPanTranslationUpdate(float y, float progress, boolean keyboardVisible) { currentPanTranslationY = y; @@ -2053,6 +2085,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.setTranslationY(0); photoPaintView.getColorPicker().setTranslationY(y); photoPaintView.getToolsView().setTranslationY(y); + photoPaintView.getColorPickerBackground().setTranslationY(y); photoPaintView.getCurtainView().setTranslationY(y); } } else { @@ -2109,7 +2142,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override protected void onTransitionEnd() { super.onTransitionEnd(); - navigationBar.setVisibility(currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_CROP ? View.VISIBLE : View.INVISIBLE); + navigationBar.setVisibility(currentEditMode != EDIT_MODE_FILTER ? View.VISIBLE : View.INVISIBLE); if (captionEditText.getTag() == null) { captionEditText.setVisibility(View.GONE); } @@ -2370,6 +2403,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == leftPaintingOverlay || child == rightPaintingOverlay) { + return false; + } if (child != navigationBar) { canvas.save(); canvas.clipRect(0, 0, getWidth(), getHeight()); @@ -2417,7 +2453,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (child == checkImageView || child == photosCounterView) { if (captionEditText.getTag() != null) { bottomTouchEnabled = false; - return child.getAlpha() > 0; + if (child.getAlpha() < 0) { + return false; + } } else { bottomTouchEnabled = true; } @@ -2486,7 +2524,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private static final Property VPC_PROGRESS; static { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { VPC_PROGRESS = new FloatProperty("progress") { @Override public void setValue(VideoPlayerControlFrameLayout object, float value) { @@ -2552,7 +2590,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int extraWidth; ignoreLayout = true; - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) videoPlayerTime.getLayoutParams(); + LayoutParams layoutParams = (LayoutParams) videoPlayerTime.getLayoutParams(); if (parentWidth > parentHeight) { if (exitFullscreenButton.getVisibility() != VISIBLE) { exitFullscreenButton.setVisibility(VISIBLE); @@ -3529,10 +3567,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } if (f == null) { - f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + f = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); } } else if (currentFileLocationVideo != null) { - f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); + f = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); } else if (pageBlocksAdapter != null) { f = pageBlocksAdapter.getFile(currentIndex); } @@ -3598,7 +3636,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat centerImage.setCurrentAccount(currentAccount); leftImage.setCurrentAccount(currentAccount); rightImage.setCurrentAccount(currentAccount); + if (captionEditText != null) { + captionEditText.currentAccount = UserConfig.selectedAccount; + } if (parentActivity == activity || activity == null) { + updateColors(); return; } inBubbleMode = activity instanceof BubbleActivity; @@ -3607,7 +3649,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat touchSlop = ViewConfiguration.get(parentActivity).getScaledTouchSlop(); if (progressDrawables == null) { - final Drawable circleDrawable = ContextCompat.getDrawable(parentActivity, R.drawable.circle_big); + Drawable circleDrawable = ContextCompat.getDrawable(parentActivity, R.drawable.circle_big); progressDrawables = new Drawable[]{ circleDrawable, // PROGRESS_EMPTY ContextCompat.getDrawable(parentActivity, R.drawable.cancel_big), // PROGRESS_CANCEL @@ -3889,6 +3931,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat paintingOverlay = new PaintingOverlay(parentActivity); containerView.addView(paintingOverlay, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + leftPaintingOverlay = new PaintingOverlay(parentActivity); + containerView.addView(leftPaintingOverlay, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); + rightPaintingOverlay = new PaintingOverlay(parentActivity); + containerView.addView(rightPaintingOverlay, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); actionBar = new ActionBar(activity) { @Override @@ -3927,13 +3973,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentMessageObject != null) { if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && currentMessageObject.messageOwner.media.webpage != null && currentMessageObject.messageOwner.media.webpage.document == null) { TLObject fileLocation = getFileLocation(currentIndex, null); - f = FileLoader.getPathToAttach(fileLocation, true); + f = FileLoader.getInstance(currentAccount).getPathToAttach(fileLocation, true); } else { - f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + f = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); } isVideo = currentMessageObject.isVideo(); } else if (currentFileLocationVideo != null) { - f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); + f = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); isVideo = false; } else if (pageBlocksAdapter != null) { f = pageBlocksAdapter.getFile(currentIndex); @@ -3953,13 +3999,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentMessageObject != null) { if (currentMessageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && currentMessageObject.messageOwner.media.webpage != null && currentMessageObject.messageOwner.media.webpage.document == null) { TLObject fileLocation = getFileLocation(currentIndex, null); - f = FileLoader.getPathToAttach(fileLocation, true); + f = FileLoader.getInstance(currentAccount).getPathToAttach(fileLocation, true); } else { - f = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + f = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); } isVideo = currentMessageObject.isVideo(); } else if (currentFileLocationVideo != null) { - f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); + f = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); isVideo = false; } else if (pageBlocksAdapter != null) { f = pageBlocksAdapter.getFile(currentIndex); @@ -4029,22 +4075,78 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentMessageObject == null || !(parentActivity instanceof LaunchActivity)) { return; } + boolean isChannel = false; + if (!currentMessageObject.scheduled) { + long dialogId = currentMessageObject.getDialogId(); + if (DialogObject.isChatDialog(dialogId)) { + TLRPC.Chat chat = MessagesController.getInstance(currentAccount).getChat(-dialogId); + isChannel = ChatObject.isChannelAndNotMegaGroup(chat); + } + } ((LaunchActivity) parentActivity).switchToAccount(currentMessageObject.currentAccount, true); - Bundle args = new Bundle(); - args.putBoolean("onlySelect", true); - args.putInt("dialogsType", 3); - DialogsActivity fragment = new DialogsActivity(args); - final ArrayList fmessages = new ArrayList<>(); - fmessages.add(currentMessageObject); - final ChatActivity parentChatActivityFinal = parentChatActivity; - fragment.setDelegate((fragment1, dids, message, param) -> { - if (dids.size() > 1 || dids.get(0) == UserConfig.getInstance(currentAccount).getClientUserId() || message != null) { - for (int a = 0; a < dids.size(); a++) { - long did = dids.get(a); - if (message != null) { - SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null); + if (isChannel) { + ArrayList msgs = new ArrayList<>(1); + MessageObject.GroupedMessages group = parentChatActivity != null ? parentChatActivity.getGroup(currentMessageObject.getGroupId()) : null; + if (group != null) { + msgs.addAll(group.messages); + } else { + msgs.add(currentMessageObject); + } + + if (msgs.size() <= 1) { + showShareAlert(msgs); + } else { + boolean photos = true; + for (int i = 0; i < msgs.size(); ++i) { + if (!msgs.get(i).isPhoto() || msgs.get(i).isVideo()) { + photos = false; + break; } - if (id == gallery_menu_send_noquote) { + } + + AlertDialog dialog = new AlertDialog.Builder(parentActivity, resourcesProvider) + .setTitle(LocaleController.getString("ForwardGroupMedia", R.string.ForwardGroupMedia)) + .setMessage(LocaleController.getString("ForwardGroupMediaMessage", R.string.ForwardGroupMediaMessage)) + .setDialogButtonColorKey(Theme.key_voipgroup_listeningText) + .setNegativeButton((photos ? LocaleController.getString("ThisPhoto", R.string.ThisPhoto) : LocaleController.getString("ThisMedia", R.string.ThisMedia)), (di, a) -> { + ArrayList singleMessage = new ArrayList<>(1); + singleMessage.add(currentMessageObject); + showShareAlert(singleMessage); + }) + .setPositiveButton(photos ? LocaleController.formatPluralString("AllNPhotos", msgs.size()) : LocaleController.formatPluralString("AllNMedia", msgs.size()), (di, a) -> { + showShareAlert(msgs); + }) + .setNeutralButton(LocaleController.getString("Cancel", R.string.Cancel), (di, a) -> { + di.dismiss(); + }).create(); + dialog.setBackgroundColor(getThemedColor(Theme.key_voipgroup_dialogBackground)); + dialog.show(); + View neutralButton = dialog.getButton(Dialog.BUTTON_NEUTRAL); + if (neutralButton instanceof TextView) { + ((TextView) neutralButton).setTextColor(getThemedColor(Theme.key_dialogTextRed)); + neutralButton.setBackground(Theme.getRoundRectSelectorDrawable(getThemedColor(Theme.key_dialogTextRed))); + if (dialog.getButtonsLayout() instanceof LinearLayout && ((LinearLayout) dialog.getButtonsLayout()).getOrientation() == LinearLayout.VERTICAL) { + neutralButton.bringToFront(); + } + } + dialog.setTextColor(getThemedColor(Theme.key_voipgroup_actionBarItems)); + } + } else { + Bundle args = new Bundle(); + args.putBoolean("onlySelect", true); + args.putInt("dialogsType", 3); + DialogsActivity fragment = new DialogsActivity(args); + final ArrayList fmessages = new ArrayList<>(); + fmessages.add(currentMessageObject); + final ChatActivity parentChatActivityFinal = parentChatActivity; + fragment.setDelegate((fragment1, dids, message, param) -> { + if (dids.size() > 1 || dids.get(0) == UserConfig.getInstance(currentAccount).getClientUserId() || message != null) { + for (int a = 0; a < dids.size(); a++) { + long did = dids.get(a); + if (message != null) { + SendMessagesHelper.getInstance(currentAccount).sendMessage(message.toString(), did, null, null, null, true, null, null, null, true, 0, null); + } + if (id == gallery_menu_send_noquote) { //MessageHelper.getInstance(currentAccount).processForwardFromMyName(fmessages, did, true, 0); SendMessagesHelper.getInstance(currentAccount).sendMessage(fmessages, did, true, false, true, 0); } else { @@ -4065,25 +4167,26 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (id == gallery_menu_send_noquote) { args1.putBoolean("forward_noquote", true); } - args1.putBoolean("scrollToTopOnResume", true); - if (DialogObject.isEncryptedDialog(did)) { - args1.putInt("enc_id", DialogObject.getEncryptedChatId(did)); - } else if (DialogObject.isUserDialog(did)) { - args1.putLong("user_id", did); - } else { - args1.putLong("chat_id", -did); + args1.putBoolean("scrollToTopOnResume", true); + if (DialogObject.isEncryptedDialog(did)) { + args1.putInt("enc_id", DialogObject.getEncryptedChatId(did)); + } else if (DialogObject.isUserDialog(did)) { + args1.putLong("user_id", did); + } else { + args1.putLong("chat_id", -did); + } + NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); + ChatActivity chatActivity = new ChatActivity(args1); + if (((LaunchActivity) parentActivity).presentFragment(chatActivity, true, false)) { + chatActivity.showFieldPanelForForward(true, fmessages); + } else { + fragment1.finishFragment(); + } } - NotificationCenter.getInstance(currentAccount).postNotificationName(NotificationCenter.closeChats); - ChatActivity chatActivity = new ChatActivity(args1); - if (((LaunchActivity) parentActivity).presentFragment(chatActivity, true, false)) { - chatActivity.showFieldPanelForForward(true, fmessages); - } else { - fragment1.finishFragment(); - } - } - }); - ((LaunchActivity) parentActivity).presentFragment(fragment, false, true); - closePhoto(false, false); + }); + ((LaunchActivity) parentActivity).presentFragment(fragment, false, true); + closePhoto(false, false); + } } else if (id == gallery_menu_delete) { if (parentActivity == null || placeProvider == null) { return; @@ -4355,14 +4458,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (parentChatActivity != null && parentChatActivity.chatActivityEnterView != null) { parentChatActivity.chatActivityEnterView.addRecentGif(document); } else { - MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000), true); } MessagesController.getInstance(currentAccount).saveGif(currentMessageObject, document); } else if (pageBlocksAdapter != null) { TLObject object = pageBlocksAdapter.getMedia(currentIndex); if (object instanceof TLRPC.Document) { TLRPC.Document document = (TLRPC.Document) object; - MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000)); + MediaDataController.getInstance(currentAccount).addRecentGif(document, (int) (System.currentTimeMillis() / 1000), true); MessagesController.getInstance(currentAccount).saveGif(pageBlocksAdapter.getParentObject(), document); } } else { @@ -4442,7 +4545,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imagesArrLocationsVideo.remove(currentIndex); imagesArrLocationsVideo.add(0, location); - Integer size = imagesArrLocationsSizes.get(currentIndex); + Long size = imagesArrLocationsSizes.get(currentIndex); imagesArrLocationsSizes.remove(currentIndex); imagesArrLocationsSizes.add(0, size); @@ -4463,11 +4566,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.hideSubItem(gallery_menu_set_as_main); }, 300); } else if (id == gallery_menu_edit_avatar) { - File f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), true); boolean isVideo = currentFileLocationVideo.imageType == FileLoader.IMAGE_TYPE_ANIMATION; String thumb; if (isVideo) { - thumb = FileLoader.getPathToAttach(getFileLocation(currentFileLocation), getFileLocationExt(currentFileLocation), true).getAbsolutePath(); + thumb = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocation), getFileLocationExt(currentFileLocation), true).getAbsolutePath(); } else { thumb = null; } @@ -4480,7 +4583,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentMessageObject != null || currentSecureDocument != null) { return true; } else if (currentFileLocationVideo != null) { - File f = FileLoader.getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(getFileLocation(currentFileLocationVideo), getFileLocationExt(currentFileLocationVideo), avatarsDialogId != 0 || isEvent); return f.exists(); } else if (pageBlocksAdapter != null) { return true; @@ -4563,6 +4666,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat menuItem.addSubItem(gallery_menu_cancel_loading, R.drawable.baseline_cancel_24, LocaleController.getString("StopDownload", R.string.StopDownload)).setColors(0xfffafafa, 0xfffafafa); menuItem.redrawPopup(0xf9222222); setMenuItemIcon(); + menuItem.setPopupItemsSelectorColor(0x0fffffff); menuItem.setSubMenuDelegate(new ActionBarMenuItem.ActionBarSubMenuItemDelegate() { @Override @@ -4762,7 +4866,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat bottomLayout.addView(bottomButtonsLayout, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT)); paintButton = new ImageView(containerView.getContext()); - paintButton.setImageResource(R.drawable.photo_paint); + paintButton.setImageResource(R.drawable.msg_photo_draw); paintButton.setScaleType(ImageView.ScaleType.CENTER); paintButton.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); bottomButtonsLayout.addView(paintButton, LayoutHelper.createFrame(50, LayoutHelper.MATCH_PARENT)); @@ -5020,7 +5124,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void seekTo(float progress) { seekTo = (int) (videoDuration * progress); - if (seekToRunnable == null) { + if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_HIGH) { + if (videoPlayer != null) { + videoPlayer.seekTo(seekTo); + } + if (sendPhotoType == SELECT_TYPE_AVATAR) { + needCaptureFrameReadyAtTime = seekTo; + if (captureFrameReadyAtTime != needCaptureFrameReadyAtTime) { + captureFrameReadyAtTime = -1; + } + } + seekToRunnable = null; + } else if (seekToRunnable == null) { AndroidUtilities.runOnUIThread(seekToRunnable = () -> { if (videoPlayer != null) { videoPlayer.seekTo(seekTo); @@ -5195,7 +5310,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat sendPopupWindow.dismiss(); } }); - sendPopupLayout.setShownFromBotton(false); + sendPopupLayout.setShownFromBottom(false); sendPopupLayout.setBackgroundColor(0xf9222222); final boolean canReplace = placeProvider != null && placeProvider.canReplace(currentIndex); @@ -5249,7 +5364,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else if (a == 2) { cell.setTextAndIcon(LocaleController.getString("ReplacePhoto", R.string.ReplacePhoto), R.drawable.msg_replace); } else if (a == 3) { - cell.setTextAndIcon(LocaleController.getString("SendAsNewPhoto", R.string.SendAsNewPhoto), R.drawable.msg_sendphoto); + cell.setTextAndIcon(LocaleController.getString("SendAsNewPhoto", R.string.SendAsNewPhoto), R.drawable.msg_send); } else if (a == 4) { cell.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate); } else if (a == 5) { @@ -5384,7 +5499,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat cropItem = new ImageView(parentActivity); cropItem.setScaleType(ImageView.ScaleType.CENTER); - cropItem.setImageResource(R.drawable.photo_crop); + cropItem.setImageResource(R.drawable.msg_photo_crop); cropItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(cropItem, LayoutHelper.createLinear(48, 48)); cropItem.setOnClickListener(v -> { @@ -5410,41 +5525,23 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat rotateItem = new ImageView(parentActivity); rotateItem.setScaleType(ImageView.ScaleType.CENTER); - rotateItem.setImageResource(R.drawable.tool_rotate); + rotateItem.setImageResource(R.drawable.msg_photo_rotate); rotateItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(rotateItem, LayoutHelper.createLinear(48, 48)); - rotateItem.setOnClickListener(v -> { - if (photoCropView == null) { - return; - } - if (photoCropView.rotate()) { - rotateItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); - } else { - rotateItem.setColorFilter(null); - } - }); + rotateItem.setOnClickListener(v -> cropRotate(-90)); rotateItem.setContentDescription(LocaleController.getString("AccDescrRotate", R.string.AccDescrRotate)); mirrorItem = new ImageView(parentActivity); mirrorItem.setScaleType(ImageView.ScaleType.CENTER); - mirrorItem.setImageResource(R.drawable.photo_flip); + mirrorItem.setImageResource(R.drawable.msg_photo_flip); mirrorItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(mirrorItem, LayoutHelper.createLinear(48, 48)); - mirrorItem.setOnClickListener(v -> { - if (photoCropView == null) { - return; - } - if (photoCropView.mirror()) { - mirrorItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); - } else { - mirrorItem.setColorFilter(null); - } - }); + mirrorItem.setOnClickListener(v -> cropMirror()); mirrorItem.setContentDescription(LocaleController.getString("AccDescrMirror", R.string.AccDescrMirror)); paintItem = new ImageView(parentActivity); paintItem.setScaleType(ImageView.ScaleType.CENTER); - paintItem.setImageResource(R.drawable.photo_paint); + paintItem.setImageResource(R.drawable.msg_photo_draw); paintItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(paintItem, LayoutHelper.createLinear(48, 48)); paintItem.setOnClickListener(v -> { @@ -5505,7 +5602,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat tuneItem = new ImageView(parentActivity); tuneItem.setScaleType(ImageView.ScaleType.CENTER); - tuneItem.setImageResource(R.drawable.photo_tools); + tuneItem.setImageResource(R.drawable.msg_photo_settings); tuneItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); itemsLayout.addView(tuneItem, LayoutHelper.createLinear(48, 48)); tuneItem.setOnClickListener(v -> { @@ -5566,7 +5663,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat timeItem = new ImageView(parentActivity); timeItem.setScaleType(ImageView.ScaleType.CENTER); - timeItem.setImageResource(R.drawable.photo_timer); + timeItem.setImageResource(R.drawable.msg_autodelete); timeItem.setBackgroundDrawable(Theme.createSelectorDrawable(Theme.ACTION_BAR_WHITE_SELECTOR_COLOR)); timeItem.setContentDescription(LocaleController.getString("SetTimer", R.string.SetTimer)); itemsLayout.addView(timeItem, LayoutHelper.createLinear(48, 48)); @@ -5574,7 +5671,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (parentActivity == null || captionEditText.getTag() != null) { return; } - BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity, false, resourcesProvider); + BottomSheet.Builder builder = new BottomSheet.Builder(parentActivity, false, resourcesProvider, 0xff000000); builder.setUseHardwareLayer(false); LinearLayout linearLayout = new LinearLayout(parentActivity); linearLayout.setOrientation(LinearLayout.VERTICAL); @@ -5604,9 +5701,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat titleView.setOnTouchListener((v12, event) -> true); final BottomSheet bottomSheet = builder.create(); - bottomSheet.setCalcMandatoryInsets(true); - bottomSheet.setOverlayNavBarColor(0xff000000); - bottomSheet.scrollNavBar = true; final NumberPicker numberPicker = new NumberPicker(parentActivity, resourcesProvider); numberPicker.setMinValue(0); numberPicker.setMaxValue(28); @@ -5711,8 +5805,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textView.setPadding(AndroidUtilities.dp(10), 0, AndroidUtilities.dp(10), 0); buttonsLayout.addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, 36, Gravity.TOP | Gravity.RIGHT)); textView.setOnClickListener(v14 -> bottomSheet.dismiss()); - bottomSheet.show(); bottomSheet.setBackgroundColor(0xff000000); + bottomSheet.show(); AndroidUtilities.setNavigationBarColor(bottomSheet.getWindow(), 0xff000000, false); AndroidUtilities.setLightNavigationBar(bottomSheet.getWindow(), false); }); @@ -5723,8 +5817,36 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat editorDoneLayout.setVisibility(View.GONE); containerView.addView(editorDoneLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.BOTTOM)); editorDoneLayout.cancelButton.setOnClickListener(view -> { - cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, 1.0f, 1.0f, previousCropPw, previousCropPh, 0, 0, previousCropMirrored); - switchToEditMode(EDIT_MODE_NONE); + if (imageMoveAnimation != null) { + return; + } + Runnable onEnd = () -> { + cropTransform.setViewTransform(previousHasTransform, previousCropPx, previousCropPy, previousCropRotation, previousCropOrientation, previousCropScale, 1.0f, 1.0f, previousCropPw, previousCropPh, 0, 0, previousCropMirrored); +// if (previousHasTransform) { +// editState.cropState = new MediaController.CropState(); +// editState.cropState.cropPx = previousCropPx; +// editState.cropState.cropPy = previousCropPy; +// editState.cropState.cropRotate = previousCropRotation; +// editState.cropState.transformRotation = previousCropOrientation; +// editState.cropState.cropScale = previousCropScale; +// editState.cropState.cropPw = previousCropPw; +// editState.cropState.cropPh = previousCropPh; +// editState.cropState.mirrored = previousCropMirrored; +// editState.cropState.freeform = sendPhotoType != SELECT_TYPE_AVATAR; +// } else { +// editState.cropState = null; +// } + switchToEditMode(EDIT_MODE_NONE); + }; + if (!previousHasTransform) { + float backRotate = previousCropOrientation - photoCropView.cropView.getStateOrientation(); + if (Math.abs(backRotate) > 180) { + backRotate = backRotate < 0 ? 360 + backRotate : -(360 - backRotate); + } + cropRotate(backRotate, photoCropView.cropView.getStateMirror(), onEnd); + } else { + onEnd.run(); + } }); editorDoneLayout.doneButton.setOnClickListener(view -> { if (currentEditMode == EDIT_MODE_CROP && !photoCropView.isReady()) { @@ -5735,6 +5857,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }); resetButton = new TextView(activityContext); + resetButton.setClickable(false); resetButton.setVisibility(View.GONE); resetButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); resetButton.setTextColor(0xffffffff); @@ -5744,7 +5867,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat resetButton.setText(LocaleController.getString("Reset", R.string.CropReset).toUpperCase()); resetButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); editorDoneLayout.addView(resetButton, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.CENTER)); - resetButton.setOnClickListener(v -> photoCropView.reset()); + resetButton.setOnClickListener(v -> { + float backRotate = -photoCropView.cropView.getStateOrientation(); + if (Math.abs(backRotate) > 180) { + backRotate = backRotate < 0 ? 360 + backRotate : -(360 - backRotate); + } + cropRotate(backRotate, photoCropView.cropView.getStateMirror(), () -> { + photoCropView.reset(true); + }); + }); gestureDetector = new GestureDetector2(containerView.getContext(), this); gestureDetector.setIsLongpressEnabled(false); @@ -5942,7 +6073,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onEmojiViewCloseStart() { - navigationBar.setVisibility(currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_CROP ? View.VISIBLE : View.INVISIBLE); + navigationBar.setVisibility(currentEditMode != EDIT_MODE_FILTER ? View.VISIBLE : View.INVISIBLE); animateNavBarColorTo(0xff000000); setOffset(captionEditText.getEmojiPadding()); if (captionEditText.getTag() != null) { @@ -6017,6 +6148,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.addView(mentionListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 110, Gravity.LEFT | Gravity.BOTTOM)); mentionListView.setAdapter(mentionsAdapter = new MentionsAdapter(activityContext, true, 0, 0, new MentionsAdapter.MentionsAdapterDelegate() { + @Override + public void onItemCountUpdate(int oldCount, int newCount) { + + } + @Override public void needChangePanelVisibility(boolean show) { if (show) { @@ -6150,8 +6286,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat hintView.setColors(0xf9222222, 0xffffffff); containerView.addView(hintView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); - AccessibilityManager am = (AccessibilityManager) activityContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - if (am.isEnabled()) { + if (AndroidUtilities.isAccessibilityScreenReaderEnabled()) { playButtonAccessibilityOverlay = new View(activityContext); playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); playButtonAccessibilityOverlay.setFocusable(true); @@ -6289,6 +6424,54 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void showShareAlert(ArrayList messages) { + final FrameLayout photoContainerView = containerView; + requestAdjustToNothing(); + boolean openKeyboardOnShareAlertClose = false; + if (parentChatActivity != null && parentChatActivity.getChatActivityEnterView() != null && parentChatActivity.getFragmentView() != null) { + boolean keyboardVisible = parentChatActivity.getChatActivityEnterView().isKeyboardVisible(); + if (keyboardVisible) { + parentChatActivity.getChatActivityEnterView().showEmojiView(); + openKeyboardOnShareAlertClose = true; + } + AndroidUtilities.setAdjustResizeToNothing(parentChatActivity.getParentActivity(), classGuid); + parentChatActivity.getFragmentView().requestLayout(); + } + final boolean finalOpenKeyboardOnShareAlertClose = openKeyboardOnShareAlertClose; + ShareAlert alert = new ShareAlert(parentActivity, parentChatActivity, messages, null, null, false, null, null, false, true, null) { + @Override + protected void onSend(LongSparseArray dids, int count) { + AndroidUtilities.runOnUIThread(() -> { + BulletinFactory.createForwardedBulletin(parentActivity, photoContainerView, dids.size(), dids.size() == 1 ? dids.valueAt(0).id : 0, count, 0xf9222222, 0xffffffff).show(); + }, 250); + } + + @Override + public void dismissInternal() { + super.dismissInternal(); + if (finalOpenKeyboardOnShareAlertClose) { + AndroidUtilities.runOnUIThread(() -> { + if (parentChatActivity != null && parentChatActivity.getChatActivityEnterView() != null) { + parentChatActivity.getChatActivityEnterView().openKeyboard(); + } + }, 50); + } + requestAdjust(); + } + }; + alert.setFocusable(false); + alert.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING); + AndroidUtilities.runOnUIThread(() -> { + if (alert != null && alert.getWindow() != null) { + alert.setFocusable(true); + if (parentChatActivity != null && parentChatActivity.getChatActivityEnterView() != null) { + parentChatActivity.getChatActivityEnterView().hidePopup(false); + } + } + }, AdjustPanLayoutHelper.keyboardDuration); + alert.show(); + } + private void setMenuItemIcon() { if (speedItem.getVisibility() != View.VISIBLE) { menuItem.setIcon(R.drawable.ic_ab_other); @@ -6313,6 +6496,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat chooseSpeedLayout.update(currentVideoSpeed); } + public float getCurrentVideoSpeed() { + return currentVideoSpeed; + } + private boolean checkInlinePermissions() { if (parentActivity == null) { return false; @@ -6484,6 +6671,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.removeView(windowView); + onHideView(); } } catch (Exception e) { FileLog.e(e); @@ -6590,13 +6778,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat valueAnimator.addUpdateListener(animation -> { float xValue = (float) animation.getAnimatedValue(); float yValue = interpolator == null ? xValue : interpolator.getInterpolation(xValue); - textureImageView.setTranslationX(fromX * (1f - xValue) + toX * xValue); - textureImageView.setTranslationY(fromY2 * (1f - yValue) + toY * yValue); - textureImageView.invalidateOutline(); + if (textureImageView != null) { + textureImageView.setTranslationX(fromX * (1f - xValue) + toX * xValue); + textureImageView.setTranslationY(fromY2 * (1f - yValue) + toY * yValue); + textureImageView.invalidateOutline(); + } - videoTextureView.setTranslationX(fromX * (1f - xValue) + (toX2) * xValue); - videoTextureView.setTranslationY(fromY * (1f - yValue) + (toY2) * yValue); - videoTextureView.invalidateOutline(); + if (videoTextureView != null) { + videoTextureView.setTranslationX(fromX * (1f - xValue) + (toX2) * xValue); + videoTextureView.setTranslationY(fromY * (1f - yValue) + (toY2) * yValue); + videoTextureView.invalidateOutline(); + } if (firstFrameView != null) { firstFrameView.setTranslationX(videoTextureView.getTranslationX()); @@ -6650,6 +6842,117 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private boolean cropMirror() { + if (imageMoveAnimation != null || photoCropView == null) { + return false; + } + mirror = 0; + animateToMirror = 1; + animationStartTime = System.currentTimeMillis(); + imageMoveAnimation = new AnimatorSet(); + imageMoveAnimation.playTogether(ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1)); + imageMoveAnimation.setDuration(250); + imageMoveAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + imageMoveAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + imageMoveAnimation = null; + if (photoCropView == null) { + return; + } + if (photoCropView.mirror()) { + mirrorItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); + } else { + mirrorItem.setColorFilter(null); + } + mirror = animateToMirror = 0; + containerView.invalidate(); + } + }); + imageMoveAnimation.start(); + return !photoCropView.cropView.isMirrored(); + } + + private boolean cropRotate(float diff) { + return cropRotate(diff, false, null); + } + + private boolean cropRotate(final float diff, boolean restoreMirror, Runnable onEnd) { + if (imageMoveAnimation != null) { + return false; + } + if (photoCropView == null) { + return false; + } + photoCropView.cropView.maximize(true); + rotate = 0; + animateToRotate = rotate + diff; + if (restoreMirror) { + mirror = 0; + animateToMirror = 1; + } + animationStartTime = System.currentTimeMillis(); + imageMoveAnimation = new AnimatorSet(); + if (centerImage != null) { + int bitmapWidth = centerImage.getBitmapWidth(), bitmapHeight = centerImage.getBitmapHeight(); + if (Math.abs((int) photoCropView.cropView.getStateOrientation() / 90 % 2) == 1) { + int temp = bitmapWidth; + bitmapWidth = bitmapHeight; + bitmapHeight = temp; + } + if (editState.cropState != null) { + bitmapWidth *= editState.cropState.cropPw; + bitmapHeight *= editState.cropState.cropPh; + } + float oldScale = Math.min(getContainerViewWidth(EDIT_MODE_CROP) / (float) bitmapWidth, getContainerViewHeight(EDIT_MODE_CROP) / (float) bitmapHeight); + float newScale = oldScale; + if (Math.abs(diff / 90 % 2) == 1) { + newScale = Math.min(getContainerViewWidth(EDIT_MODE_CROP) / (float) bitmapHeight, getContainerViewHeight(EDIT_MODE_CROP) / (float) bitmapWidth); + } + animateToScale = newScale / oldScale; + } + ValueAnimator areaRotateAnimator = ValueAnimator.ofFloat(0, 1f); + final float wasRotation = photoCropView.wheelView.getRotation(); + areaRotateAnimator.addUpdateListener(a -> { + photoCropView.cropView.areaView.setRotationScaleTranslation((float) a.getAnimatedValue() * diff, scale + (animateToScale - scale) * animationValue, 0, 0); + photoCropView.wheelView.setRotation(AndroidUtilities.lerp(wasRotation, 0, (float) a.getAnimatedValue()), false); + }); + imageMoveAnimation.playTogether( + ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1), + areaRotateAnimator + ); + imageMoveAnimation.setDuration(250); + imageMoveAnimation.setInterpolator(CubicBezierInterpolator.DEFAULT); + imageMoveAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + imageMoveAnimation = null; + rotate = animateToRotate = 0; + mirror = animateToMirror = 0; + scale = animateToScale = 1; + containerView.invalidate(); + photoCropView.cropView.areaView.setRotationScaleTranslation(0, 1, 0, 0); + photoCropView.wheelView.setRotated(false); + if (Math.abs(diff) > 0) { + if (photoCropView.rotate(diff)) { + rotateItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.MULTIPLY)); + } else { + rotateItem.setColorFilter(null); + } + } + if (editState.cropState != null) { + editState.cropState.cropPx = editState.cropState.cropPy = 0; + editState.cropState.cropPw = editState.cropState.cropPh = 1; + } + if (onEnd != null) { + onEnd.run(); + } + } + }); + imageMoveAnimation.start(); + return Math.abs(photoCropView.cropView.getStateOrientation() + diff) > 0.01f; + } + public VideoPlayer getVideoPlayer() { return videoPlayer; } @@ -6738,6 +7041,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat isVisible = true; WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.addView(windowView, windowLayoutParams); + onShowView(); if (currentPlaceObject != null) { currentPlaceObject.imageReceiver.setVisible(false, false); } @@ -6750,6 +7054,47 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void onShowView() { + if (parentActivity instanceof LaunchActivity) { + LaunchActivity launchActivity = (LaunchActivity) parentActivity; + launchActivity.addOnUserLeaveHintListener(onUserLeaveHintListener); + } + } + + private void onHideView() { + if (parentActivity instanceof LaunchActivity) { + LaunchActivity launchActivity = (LaunchActivity) parentActivity; + launchActivity.removeOnUserLeaveHintListener(onUserLeaveHintListener); + } + } + + private void onUserLeaveHint() { + if (pipItem.getAlpha() != 1.0f || !AndroidUtilities.checkInlinePermissions(parentActivity) || PipVideoOverlay.isVisible()) { + return; + } + if (isEmbedVideo) { + if (photoViewerWebView != null && !photoViewerWebView.isInAppOnly() && photoViewerWebView.openInPip()) { + pipVideoOverlayAnimateFlag = false; + + if (PipInstance != null) { + PipInstance.destroyPhotoViewer(); + } + isInline = true; + PipInstance = Instance; + Instance = null; + isVisible = false; + if (currentPlaceObject != null && !currentPlaceObject.imageReceiver.getVisible()) { + currentPlaceObject.imageReceiver.setVisible(true, true); + } + dismissInternal(); + } + } else { + pipVideoOverlayAnimateFlag = false; + + switchToPip(false); + } + } + private void updateVideoSeekPreviewPosition() { int x = videoPlayerSeekbar.getThumbX() + AndroidUtilities.dp(2) - videoPreviewFrame.getMeasuredWidth() / 2; int min = AndroidUtilities.dp(10); @@ -7407,6 +7752,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } PipVideoOverlay.updatePlayButton(); + videoPlayerSeekbar.updateTimestamps(currentMessageObject, videoPlayer == null ? 0L : videoPlayer.getDuration()); updateVideoPlayerTime(); } @@ -7583,6 +7929,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat textureUploaded = true; containerView.invalidate(); } + if (firstFrameView != null && (videoPlayer == null || !videoPlayer.isLooping())) { + AndroidUtilities.runOnUIThread(() -> firstFrameView.updateAlpha(), 64); + } } @Override @@ -7592,6 +7941,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat needCaptureFrameReadyAtTime = -1; captureCurrentFrame(); } + if (firstFrameView != null && (videoPlayer == null || !videoPlayer.isLooping())) { + AndroidUtilities.runOnUIThread(() -> firstFrameView.updateAlpha(), 64); + } } @Override @@ -7912,7 +8264,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat firstFrameView.setPivotX(0); firstFrameView.setPivotY(0); firstFrameView.setScaleType(ImageView.ScaleType.FIT_XY); - firstFrameView.setAlpha(0f); aspectRatioFrameLayout.addView(firstFrameView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); if (sendPhotoType == SELECT_TYPE_AVATAR) { @@ -8244,7 +8595,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat MediaController.MediaEditState entry = (MediaController.MediaEditState) imagesArrLocals.get(currentIndex); if (currentEditMode == EDIT_MODE_CROP || currentEditMode == EDIT_MODE_NONE && sendPhotoType == SELECT_TYPE_AVATAR) { photoCropView.makeCrop(entry); - if (entry.cropState == null) { + if (entry.cropState == null && currentEditMode != EDIT_MODE_CROP) { return; } if (isCurrentVideo) { @@ -8291,54 +8642,56 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat editState.croppedPaintPath = entry.croppedPaintPath; editState.croppedMediaEntities = entry.croppedMediaEntities; - Bitmap croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); - if (entry.paintPath != null) { - Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); - Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); + if (entry.cropState != null) { + Bitmap croppedBitmap = createCroppedBitmap(bitmap, entry.cropState, orientation, true); + if (entry.paintPath != null) { + Bitmap paintBitmap = BitmapFactory.decodeFile(entry.fullPaintPath); + Bitmap croppedPaintBitmap = createCroppedBitmap(paintBitmap, entry.cropState, null, false); - if (!isCurrentVideo) { - if (hasAnimatedMediaEntities()) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getPathToAttach(size, true).toString(); - } else { - File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); - mergeImages(entry.imagePath = f.getAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); + if (!isCurrentVideo) { + if (hasAnimatedMediaEntities()) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } else { + File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); + mergeImages(entry.imagePath = f.getAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, AndroidUtilities.getPhotoSize(), true); + } } + File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); + mergeImages(entry.thumbPath = f.getAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); + if (croppedPaintBitmap != null) { + croppedPaintBitmap.recycle(); + } + if (paintBitmap != null) { + paintBitmap.recycle(); + } + } else { + if (!isCurrentVideo) { + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); + } + TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } - File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); - mergeImages(entry.thumbPath = f.getAbsolutePath(), null, croppedPaintBitmap, croppedBitmap, thumbSize, true); - if (croppedPaintBitmap != null) { - croppedPaintBitmap.recycle(); + if (currentEditMode == EDIT_MODE_NONE && isCurrentVideo) { + bitmap.recycle(); + bitmap = croppedBitmap; } - if (paintBitmap != null) { - paintBitmap.recycle(); - } - } else { - if (!isCurrentVideo) { - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getPathToAttach(size, true).toString(); - } - TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(croppedBitmap, thumbSize, thumbSize, 70, false, 101, 101); - entry.thumbPath = FileLoader.getPathToAttach(size, true).toString(); - } - if (currentEditMode == EDIT_MODE_NONE && isCurrentVideo) { - bitmap.recycle(); - bitmap = croppedBitmap; } } else if (currentEditMode == EDIT_MODE_FILTER) { if (entry.filterPath != null) { new File(entry.filterPath).delete(); } TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.filterPath = FileLoader.getPathToAttach(size, true).toString(); + entry.filterPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); Bitmap b = entry.cropState != null ? createCroppedBitmap(bitmap, entry.cropState, null, true) : bitmap; if (entry.paintPath == null) { if (!isCurrentVideo) { size = ImageLoader.scaleAndSaveImage(b, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getPathToAttach(size, true).toString(); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } size = ImageLoader.scaleAndSaveImage(b, Bitmap.CompressFormat.JPEG, thumbSize, thumbSize, 83, false, 101, 101); - entry.thumbPath = FileLoader.getPathToAttach(size, true).toString(); + entry.thumbPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } else { String path = entry.fullPaintPath; Bitmap fullPaintBitmap = entry.paintPath.equals(entry.fullPaintPath) ? paintingOverlay.getThumb() : null; @@ -8360,7 +8713,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (!isCurrentVideo) { if (hasAnimatedMediaEntities()) { size = ImageLoader.scaleAndSaveImage(b, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getPathToAttach(size, true).toString(); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } else { File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); mergeImages(entry.imagePath = f.getAbsolutePath(), path, paintBitmap, b, AndroidUtilities.getPhotoSize(), true); @@ -8385,12 +8738,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.PhotoSize size = ImageLoader.scaleAndSaveImage(bitmap, Bitmap.CompressFormat.PNG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); entry.stickers = stickers; - entry.paintPath = editState.paintPath = FileLoader.getPathToAttach(size, true).toString(); + entry.paintPath = editState.paintPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); paintingOverlay.setEntities(entry.mediaEntities = editState.mediaEntities = entities == null || entities.isEmpty() ? null : entities, isCurrentVideo, true); entry.averageDuration = editState.averageDuration = photoPaintView.getLcm(); if (entry.mediaEntities != null && paintThumbBitmap[0] != null) { size = ImageLoader.scaleAndSaveImage(paintThumbBitmap[0], Bitmap.CompressFormat.PNG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.fullPaintPath = FileLoader.getPathToAttach(size, true).toString(); + entry.fullPaintPath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } else { entry.fullPaintPath = entry.paintPath; } @@ -8471,7 +8824,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (!isCurrentVideo) { if (hasAnimatedMediaEntities()) { size = ImageLoader.scaleAndSaveImage(croppedBitmap, Bitmap.CompressFormat.JPEG, AndroidUtilities.getPhotoSize(), AndroidUtilities.getPhotoSize(), 87, false, 101, 101); - entry.imagePath = currentImagePath = FileLoader.getPathToAttach(size, true).toString(); + entry.imagePath = currentImagePath = FileLoader.getInstance(currentAccount).getPathToAttach(size, true).toString(); } else { File f = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), SharedConfig.getLastLocalId() + "_temp.jpg"); mergeImages(entry.imagePath = f.getAbsolutePath(), null, croppedBitmap, paintBitmap, AndroidUtilities.getPhotoSize(), false); @@ -8503,7 +8856,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (currentEditMode == EDIT_MODE_CROP) { entry.isCropped = true; - cropItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); + if (entry.isCropped) { + cropItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); + } else { + cropItem.setColorFilter(null); + } } else if (currentEditMode == EDIT_MODE_FILTER) { entry.isFiltered = true; tuneItem.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogFloatingButton), PorterDuff.Mode.SRC_IN)); @@ -8577,6 +8934,24 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void updateResetButtonVisibility(final boolean show) { + boolean isShown = resetButton.isClickable(); + if (isShown != show) { + resetButton.setClickable(show); + resetButton.setVisibility(View.VISIBLE); + resetButton.clearAnimation(); + resetButton.animate() + .alpha(show ? 1f : 0f) + .setInterpolator(CubicBezierInterpolator.DEFAULT) + .setDuration(150) + .withEndAction(() -> { + if (!show) { + resetButton.setVisibility(View.GONE); + } + }); + } + } + private void createCropView() { if (photoCropView != null) { return; @@ -8589,7 +8964,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoCropView.setDelegate(new PhotoCropView.PhotoCropViewDelegate() { @Override public void onChange(boolean reset) { - resetButton.setVisibility(reset ? View.GONE : View.VISIBLE); + updateResetButtonVisibility(!reset); } @Override @@ -8623,6 +8998,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat }, 860); } + @Override + public boolean rotate() { + return cropRotate(-90); + } + + @Override + public boolean mirror() { + return cropMirror(); + } + @Override public int getVideoThumbX() { return (int) (AndroidUtilities.dp(16) + (videoTimelineView.getMeasuredWidth() - AndroidUtilities.dp(32)) * avatarStartProgress); @@ -8647,9 +9032,20 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentEditMode == mode || (isCurrentVideo && photoProgressViews[0].backgroundState != 3) && !isCurrentVideo && (centerImage.getBitmap() == null || photoProgressViews[0].backgroundState != -1) || changeModeAnimation != null || imageMoveAnimation != null || captionEditText.getTag() != null) { return; } - windowView.setClipChildren(mode != EDIT_MODE_NONE && mode != EDIT_MODE_CROP); - navigationBar.setBackgroundColor(mode == EDIT_MODE_CROP ? 0xcc000000 : 0x7f000000); - navigationBar.setVisibility(mode == EDIT_MODE_NONE || mode == EDIT_MODE_CROP ? View.VISIBLE : View.INVISIBLE); + windowView.setClipChildren(mode == EDIT_MODE_FILTER); + int navigationBarColorFrom = 0x7f000000; + if (navigationBar.getBackground() instanceof ColorDrawable) { + navigationBarColorFrom = ((ColorDrawable) navigationBar.getBackground()).getColor(); + } + int navigationBarColorTo; + if (mode == EDIT_MODE_CROP) { + navigationBarColorTo = 0xcc000000; + } else if (mode == EDIT_MODE_PAINT) { + navigationBarColorTo = 0xff000000; + } else { + navigationBarColorTo = 0x7f000000; + } + navigationBar.setVisibility(mode != EDIT_MODE_FILTER ? View.VISIBLE : View.INVISIBLE); switchingToMode = mode; if (mode == EDIT_MODE_NONE) { Bitmap bitmap = centerImage.getBitmap(); @@ -8660,7 +9056,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float newScale; float oldScale; if (currentEditMode == EDIT_MODE_PAINT) { - if (sendPhotoType != SELECT_TYPE_AVATAR) { + if (sendPhotoType == SELECT_TYPE_AVATAR) { if (cropTransform.getOrientation() == 90 || cropTransform.getOrientation() == 270) { int temp = bitmapWidth; bitmapWidth = bitmapHeight; @@ -8678,7 +9074,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } newScale = Math.min(getContainerViewWidth(0) / (float) bitmapWidth, getContainerViewHeight(0) / (float) bitmapHeight); - oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); + oldScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); } else { if (currentEditMode != EDIT_MODE_CROP && editState.cropState != null && (editState.cropState.transformRotation == 90 || editState.cropState.transformRotation == 270)) { float scaleToFitX = getContainerViewWidth() / (float) bitmapHeight; @@ -8749,6 +9145,16 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animators.add(ObjectAnimator.ofFloat(editorDoneLayout, View.TRANSLATION_Y, AndroidUtilities.dp(48))); animators.add(ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1)); animators.add(ObjectAnimator.ofFloat(photoCropView, View.ALPHA, 0)); + ValueAnimator scaleAnimator = ValueAnimator.ofFloat(0, 1); + scaleAnimator.addUpdateListener(a -> { + photoCropView.cropView.areaView.setRotationScaleTranslation( + 0, + AndroidUtilities.lerp(scale, animateToScale, animationValue), + AndroidUtilities.lerp(translationX, animateToX, animationValue), + AndroidUtilities.lerp(translationY, animateToY, animationValue) + ); + }); + animators.add(scaleAnimator); } else if (currentEditMode == EDIT_MODE_FILTER) { photoFilterView.shutdown(); animators.add(ObjectAnimator.ofFloat(photoFilterView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(186))); @@ -8760,9 +9166,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.invalidate(); photoPaintView.shutdown(); animators.add(ObjectAnimator.ofFloat(photoPaintView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(126))); + animators.add(ObjectAnimator.ofFloat(photoPaintView.getColorPickerBackground(), View.TRANSLATION_Y, AndroidUtilities.dp(126))); animators.add(ObjectAnimator.ofFloat(photoPaintView.getColorPicker(), View.TRANSLATION_Y, AndroidUtilities.dp(126))); animators.add(ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1)); } + animators.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); imageMoveAnimation.playTogether(animators); imageMoveAnimation.setDuration(200); imageMoveAnimation.addListener(new AnimatorListenerAdapter() { @@ -8773,6 +9181,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoCropView.onHide(); editorDoneLayout.setVisibility(View.GONE); photoCropView.setVisibility(View.GONE); + photoCropView.cropView.areaView.setRotationScaleTranslation(0, 1, 0, 0); } else if (currentEditMode == EDIT_MODE_FILTER) { try { containerView.removeView(photoFilterView); @@ -8882,6 +9291,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, 0, -actionBar.getHeight())); + arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); if (needCaptionLayout) { arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, 0, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); } @@ -9076,6 +9486,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (muteItem.getTag() != null) { arrayList.add(ObjectAnimator.ofFloat(muteItem, View.ALPHA, 1, 0)); } + arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); changeModeAnimation.playTogether(arrayList); changeModeAnimation.setDuration(200); changeModeAnimation.addListener(new AnimatorListenerAdapter() { @@ -9169,7 +9580,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat arrayList.add(ObjectAnimator.ofFloat(pickerView, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(pickerViewSendButton, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); arrayList.add(ObjectAnimator.ofFloat(actionBar, View.TRANSLATION_Y, -actionBar.getHeight())); - + arrayList.add(ObjectAnimator.ofObject(navigationBar, "backgroundColor", new ArgbEvaluator(), navigationBarColorFrom, navigationBarColorTo)); if (needCaptionLayout) { arrayList.add(ObjectAnimator.ofFloat(captionTextViewSwitcher, View.TRANSLATION_Y, AndroidUtilities.dp(isCurrentVideo ? 154 : 96))); } @@ -9266,6 +9677,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat photoPaintView.getCancelTextView().setOnClickListener(v -> closePaintMode()); photoPaintView.getColorPicker().setTranslationY(AndroidUtilities.dp(126)); photoPaintView.getToolsView().setTranslationY(AndroidUtilities.dp(126)); + photoPaintView.getColorPickerBackground().setTranslationY(AndroidUtilities.dp(126)); } } @@ -9297,6 +9709,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } Bitmap bitmap = centerImage.getBitmap(); + final float finalScale = scale; if (bitmap != null) { int bitmapWidth = centerImage.getBitmapWidth(); int bitmapHeight = centerImage.getBitmapHeight(); @@ -9324,7 +9737,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } oldScale = Math.min(getContainerViewWidth() / (float) bitmapWidth, getContainerViewHeight() / (float) bitmapHeight); newScale = Math.min(getContainerViewWidth(3) / (float) bitmapWidth, getContainerViewHeight(3) / (float) bitmapHeight); - animateToScale = newScale / oldScale; + animateToScale = newScale / oldScale; // * finalScale; animateToX = getLeftInset() / 2 - getRightInset() / 2; animationStartTime = System.currentTimeMillis(); zoomAnimation = true; @@ -9336,7 +9749,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageMoveAnimation.playTogether( ObjectAnimator.ofFloat(PhotoViewer.this, AnimationProperties.PHOTO_VIEWER_ANIMATION_VALUE, 0, 1), ObjectAnimator.ofFloat(photoPaintView.getColorPicker(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0), - ObjectAnimator.ofFloat(photoPaintView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0) + ObjectAnimator.ofFloat(photoPaintView.getToolsView(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0), + ObjectAnimator.ofFloat(photoPaintView.getColorPickerBackground(), View.TRANSLATION_Y, AndroidUtilities.dp(126), 0) ); imageMoveAnimation.setDuration(200); imageMoveAnimation.addListener(new AnimatorListenerAdapter() { @@ -9352,10 +9766,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat imageMoveAnimation = null; currentEditMode = EDIT_MODE_PAINT; switchingToMode = -1; - animateToScale = 1; + animateToScale = scale = 1; animateToX = 0; animateToY = 0; - scale = 1; updateMinMax(scale); padImageForHorizontalInsets = true; containerView.invalidate(); @@ -9492,7 +9905,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat toggleActionBar(show, animated, ActionBarToggleParams.DEFAULT); } - private void toggleActionBar(final boolean show, final boolean animated, @NonNull final ActionBarToggleParams params) { + private void toggleActionBar(boolean show, final boolean animated, @NonNull final ActionBarToggleParams params) { + if (currentEditMode != EDIT_MODE_NONE || switchingToMode != EDIT_MODE_NONE && switchingToMode != -1) { + return; + } + final boolean finalShow = show; if (actionBarAnimator != null) { actionBarAnimator.cancel(); } @@ -9594,7 +10011,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @Override public void onAnimationEnd(Animator animation) { if (animation.equals(actionBarAnimator)) { - if (!show) { + if (!finalShow) { actionBar.setVisibility(View.INVISIBLE); if (bottomLayout.getTag() != null) { bottomLayout.setVisibility(View.INVISIBLE); @@ -9765,7 +10182,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return null; } - private ImageLocation getImageLocation(int index, int[] size) { + private ImageLocation getImageLocation(int index, long[] size) { if (index < 0) { return null; } @@ -9846,7 +10263,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return null; } - private TLObject getFileLocation(int index, int[] size) { + private TLObject getFileLocation(int index, long[] size) { if (index < 0) { return null; } @@ -10414,9 +10831,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void setImages() { if (animationInProgress == 0) { - setIndexToImage(centerImage, currentIndex, null, paintingOverlay); - setIndexToImage(rightImage, currentIndex + 1, rightCropTransform, rightPaintingOverlay); - setIndexToImage(leftImage, currentIndex - 1, leftCropTransform, leftPaintingOverlay); + setIndexToImage(centerImage, currentIndex, null); + setIndexToPaintingOverlay(currentIndex, paintingOverlay); + setIndexToImage(rightImage, currentIndex + 1, rightCropTransform); + setIndexToPaintingOverlay(currentIndex + 1, rightPaintingOverlay); + setIndexToImage(leftImage, currentIndex - 1, leftCropTransform); + setIndexToPaintingOverlay(currentIndex - 1, leftPaintingOverlay); } } @@ -11162,10 +11582,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (object instanceof TLRPC.BotInlineResult) { TLRPC.BotInlineResult botInlineResult = currentBotInlineResult = ((TLRPC.BotInlineResult) object); if (botInlineResult.document != null) { - currentPathObject = FileLoader.getPathToAttach(botInlineResult.document).getAbsolutePath(); + currentPathObject = FileLoader.getInstance(currentAccount).getPathToAttach(botInlineResult.document).getAbsolutePath(); isVideo = MessageObject.isVideoDocument(botInlineResult.document); } else if (botInlineResult.photo != null) { - currentPathObject = FileLoader.getPathToAttach(FileLoader.getClosestPhotoSizeWithSize(botInlineResult.photo.sizes, AndroidUtilities.getPhotoSize())).getAbsolutePath(); + currentPathObject = FileLoader.getInstance(currentAccount).getPathToAttach(FileLoader.getClosestPhotoSizeWithSize(botInlineResult.photo.sizes, AndroidUtilities.getPhotoSize())).getAbsolutePath(); } else if (botInlineResult.content instanceof TLRPC.TL_webDocument) { currentPathObject = botInlineResult.content.url; isVideo = botInlineResult.type.equals("video"); @@ -11287,6 +11707,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat animateToX = 0; animateToY = 0; animateToScale = 1; + animateToRotate = 0; animationStartTime = 0; zoomAnimation = false; imageMoveAnimation = null; @@ -11323,10 +11744,11 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (!imagesArrLocals.isEmpty()) { - paintingOverlay.setVisibility(View.VISIBLE); - paintingOverlay.setData(editState.paintPath, editState.mediaEntities, isCurrentVideo, false); +// paintingOverlay.setVisibility(View.VISIBLE); +// paintingOverlay.setData(editState.paintPath, editState.mediaEntities, isCurrentVideo, false); } else { - paintingOverlay.setVisibility(View.GONE); +// paintingOverlay.reset(); +// paintingOverlay.setVisibility(View.GONE); editState.reset(); } @@ -11334,7 +11756,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (prevIndex == -1) { setImages(); - for (int a = 0; a < 3; a++) { checkProgress(a, false, false); } @@ -11360,7 +11781,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat fullscreenButton[0].setTranslationY(tmp.getTranslationY()); leftCropState = null; - setIndexToImage(leftImage, currentIndex - 1, leftCropTransform, leftPaintingOverlay); + setIndexToPaintingOverlay(currentIndex - 1, leftPaintingOverlay); + setIndexToPaintingOverlay(currentIndex, paintingOverlay); + setIndexToPaintingOverlay(currentIndex + 1, rightPaintingOverlay); + setIndexToImage(leftImage, currentIndex - 1, leftCropTransform); updateAccessibilityOverlayVisibility(); checkProgress(1, true, false); @@ -11385,7 +11809,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat fullscreenButton[0].setTranslationY(tmp.getTranslationY()); rightCropState = null; - setIndexToImage(rightImage, currentIndex + 1, rightCropTransform, rightPaintingOverlay); + setIndexToPaintingOverlay(currentIndex - 1, leftPaintingOverlay); + setIndexToPaintingOverlay(currentIndex, paintingOverlay); + setIndexToPaintingOverlay(currentIndex + 1, rightPaintingOverlay); + setIndexToImage(rightImage, currentIndex + 1, rightCropTransform); updateAccessibilityOverlayVisibility(); checkProgress(1, true, false); @@ -11649,10 +12076,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (currentFileNames[a] != null) { File f1 = null; File f2 = null; + boolean fileExist = false; + FileLoader.FileResolver f2Resolver = null; boolean isVideo = false; boolean canStream = false; boolean canAutoPlay = false; MessageObject messageObject = null; + if (a == 0 && currentIndex == 0 && currentAnimation != null) { + fileExist = currentAnimation.hasBitmap(); + } if (currentMessageObject != null) { if (index < 0 || index >= imagesArr.size()) { photoProgressViews[a].setBackgroundState(PROGRESS_NONE, animated, true); @@ -11669,9 +12101,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (messageObject.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage && messageObject.messageOwner.media.webpage != null && messageObject.messageOwner.media.webpage.document == null) { TLObject fileLocation = getFileLocation(index, null); - f2 = FileLoader.getPathToAttach(fileLocation, true); + f2Resolver = () -> FileLoader.getInstance(currentAccount).getPathToAttach(fileLocation, true); } else { - f2 = FileLoader.getPathToMessage(messageObject.messageOwner); + TLRPC.Message finalMessage = messageObject.messageOwner; + f2Resolver = () -> FileLoader.getInstance(currentAccount).getPathToMessage(finalMessage); } if (messageObject.isVideo()) { canStream = SharedConfig.streamMedia && messageObject.canStreamVideo() && !DialogObject.isEncryptedDialog(messageObject.getDialogId()); @@ -11685,7 +12118,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.BotInlineResult botInlineResult = (TLRPC.BotInlineResult) imagesArrLocals.get(index); if (botInlineResult.type.equals("video") || MessageObject.isVideoDocument(botInlineResult.document)) { if (botInlineResult.document != null) { - f1 = FileLoader.getPathToAttach(botInlineResult.document); + f1 = FileLoader.getInstance(currentAccount).getPathToAttach(botInlineResult.document); } else if (botInlineResult.content instanceof TLRPC.TL_webDocument) { f1 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), Utilities.MD5(botInlineResult.content.url) + "." + ImageLoader.getHttpUrlExtension(botInlineResult.content.url, "mp4")); } @@ -11702,14 +12135,14 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } ImageLocation location = imagesArrLocationsVideo.get(index); - f1 = FileLoader.getPathToAttach(location.location, getFileLocationExt(location), avatarsDialogId != 0 || isEvent); + f1 = FileLoader.getInstance(currentAccount).getPathToAttach(location.location, getFileLocationExt(location), avatarsDialogId != 0 || isEvent); } else if (currentSecureDocument != null) { if (index < 0 || index >= secureDocuments.size()) { photoProgressViews[a].setBackgroundState(PROGRESS_NONE, animated, true); return; } SecureDocument location = secureDocuments.get(index); - f1 = FileLoader.getPathToAttach(location, true); + f1 = FileLoader.getInstance(currentAccount).getPathToAttach(location, true); } else if (currentPathObject != null) { f1 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_DOCUMENT), currentFileNames[a]); f2 = new File(FileLoader.getDirectory(FileLoader.MEDIA_DIR_CACHE), currentFileNames[a]); @@ -11720,17 +12153,24 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } File f1Final = f1; File f2Final = f2; + FileLoader.FileResolver finalF2Resolver = f2Resolver; MessageObject messageObjectFinal = messageObject; boolean canStreamFinal = canStream; boolean canAutoPlayFinal = !(a == 0 && dontAutoPlay) && canAutoPlay; boolean isVideoFinal = isVideo; + + boolean finalFileExist = fileExist; Utilities.globalQueue.postRunnable(() -> { - boolean exists = false; - if (f1Final != null) { + boolean exists = finalFileExist; + if (!exists && f1Final != null) { exists = f1Final.exists(); } - if (!exists && f2Final != null) { - exists = f2Final.exists(); + File f2Local = f2Final; + if (f2Local == null && finalF2Resolver != null) { + f2Local = finalF2Resolver.getFile(); + } + if (!exists && f2Local != null) { + exists = f2Local.exists(); } if (!exists && a != 0 && messageObjectFinal != null && canStreamFinal) { if (DownloadController.getInstance(currentAccount).canDownloadMedia(messageObjectFinal.messageOwner) != 0) { @@ -11743,12 +12183,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } boolean existsFinal = exists; + File finalF2Local = f2Local; AndroidUtilities.runOnUIThread(() -> { if (shownControlsByEnd && !actionBarWasShownBeforeByEnd && isPlaying) { photoProgressViews[a].setBackgroundState(PROGRESS_PLAY, false, false); return; } - if ((f1Final != null || f2Final != null) && (existsFinal || canStreamFinal)) { + if ((f1Final != null || finalF2Local != null) && (existsFinal || canStreamFinal)) { if (a != 0 || !isPlaying) { if (isVideoFinal && (!canAutoPlayFinal || a == 0 && playerWasPlaying)) { photoProgressViews[a].setBackgroundState(PROGRESS_PLAY, animated, true); @@ -11809,7 +12250,33 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return captionEditText != null ? captionEditText.getSelectionLength() : 0; } - private void setIndexToImage(ImageReceiver imageReceiver, int index, CropTransform cropTransform, PaintingOverlay paintingOverlay) { + private void setIndexToPaintingOverlay(int index, PaintingOverlay paintingOverlay) { + if (paintingOverlay == null) { + return; + } + paintingOverlay.reset(); + paintingOverlay.setVisibility(View.GONE); + if (!imagesArrLocals.isEmpty() && index >= 0 && index < imagesArrLocals.size()) { + Object object = imagesArrLocals.get(index); + boolean isVideo = false; + String paintPath = null; + ArrayList mediaEntities = null; + if (object instanceof MediaController.PhotoEntry) { + MediaController.PhotoEntry photoEntry = (MediaController.PhotoEntry) object; + isVideo = photoEntry.isVideo; + paintPath = photoEntry.paintPath; + mediaEntities = photoEntry.mediaEntities; + } else if (object instanceof MediaController.SearchImage) { + MediaController.SearchImage photoEntry = (MediaController.SearchImage) object; + paintPath = photoEntry.paintPath; + mediaEntities = photoEntry.mediaEntities; + } + paintingOverlay.setVisibility(View.VISIBLE); + paintingOverlay.setData(paintPath, mediaEntities, isVideo, false); + } + } + + private void setIndexToImage(ImageReceiver imageReceiver, int index, CropTransform cropTransform) { imageReceiver.setOrientation(0, false); if (!secureDocuments.isEmpty()) { if (index >= 0 && index < secureDocuments.size()) { @@ -11823,7 +12290,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeHolder = placeProvider.getThumbForPhoto(null, null, index); } SecureDocument document = secureDocuments.get(index); - int imageSize = document.secureFile.size; + long imageSize = document.secureFile.size; imageReceiver.setImage(ImageLocation.getForSecureDocument(document), "d", null, null, placeHolder != null ? new BitmapDrawable(placeHolder.bitmap) : null, imageSize, null, null, 0); } } else if (!imagesArrLocals.isEmpty()) { @@ -11844,7 +12311,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat TLRPC.PhotoSize photo = null; TLObject photoObject = null; MediaController.CropState cropState = null; - int imageSize = 0; + long imageSize = 0; String filter = null; boolean isVideo = false; int cacheType = 0; @@ -12055,7 +12522,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return; } } - int[] size = new int[1]; + long[] size = new long[1]; ImageLocation imageLocation = getImageLocation(index, size); TLObject fileLocation = getFileLocation(index, size); imageReceiver.setNeedsQualityThumb(true); @@ -12080,6 +12547,15 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (thumbLocation != null && thumbLocation == fileLocation) { thumbLocation = null; } + if (thumbLocation == null && imageLocation.photo != null && imageLocation.photo.sizes != null) { + for (int i = 0; i < imageLocation.photo.sizes.size(); ++i) { + if (imageLocation.photo.sizes.get(i) instanceof TLRPC.TL_photoStrippedSize) { + thumbLocation = imageLocation.photo.sizes.get(i); + photoObject = imageLocation.photo; + break; + } + } + } boolean cacheOnly = messageObject != null && messageObject.isWebpage() || avatarsDialogId != 0 || isEvent; Object parentObject; ImageLocation videoThumb = null; @@ -12098,6 +12574,12 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { parentObject = MessagesController.getInstance(currentAccount).getChat(-avatarsDialogId); } + if (photoObject != null) { + parentObject = photoObject; + } + if (placeHolder == null && thumbLocation instanceof TLRPC.TL_photoStrippedSize) { + placeHolder = new ImageReceiver.BitmapHolder(ImageLoader.getStrippedPhotoBitmap(thumbLocation.bytes, "b")); + } } else { parentObject = null; } @@ -12316,7 +12798,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } if (file == null) { - file = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + file = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); } } @@ -12516,6 +12998,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (attachedToWindow) { try { wm.removeView(windowView); + onHideView(); } catch (Exception e) { //don't promt } @@ -12544,6 +13027,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat windowView.setFocusable(false); containerView.setFocusable(false); wm.addView(windowView, windowLayoutParams); + onShowView(); } catch (Exception e) { FileLog.e(e); return false; @@ -12782,6 +13266,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } animationInProgress = 0; transitionAnimationStartTime = 0; + leftCropState = null; + leftCropTransform.setViewTransform(false); + rightCropState = null; + rightCropTransform.setViewTransform(false); setImages(); setCropBitmap(); containerView.invalidate(); @@ -12806,6 +13294,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (isEmbedVideo) { initEmbedVideo(embedSeekTime); } + + if (provider != null) { + provider.onOpen(); + } }; if (!openedFullScreenVideo) { @@ -12939,6 +13431,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (isEmbedVideo) { initEmbedVideo(embedSeekTime); } + + if (provider != null) { + provider.onOpen(); + } } }); animatorSet.start(); @@ -13011,6 +13507,26 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat containerView.setFocusable(true); } + private void requestAdjustToNothing() { + windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; + WindowManager wm1 = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + try { + wm1.updateViewLayout(windowView, windowLayoutParams); + } catch (Exception e) { + FileLog.e(e); + } + } + + private void requestAdjust() { + windowLayoutParams.softInputMode = (useSmoothKeyboard ? WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN : WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE) | WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION; + WindowManager wm1 = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); + try { + wm1.updateViewLayout(windowView, windowLayoutParams); + } catch (Exception e) { + FileLog.e(e); + } + } + public void injectVideoPlayerToMediaController() { if (videoPlayer.isPlaying()) { if (playerLooping) { @@ -13424,6 +13940,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.removeViewImmediate(windowView); + onHideView(); } windowView = null; } catch (Exception e) { @@ -13442,6 +13959,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } else { Instance = null; } + onHideView(); } private void onPhotoClosed(PlaceProviderObject object) { @@ -13498,6 +14016,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (windowView.getParent() != null) { WindowManager wm = (WindowManager) parentActivity.getSystemService(Context.WINDOW_SERVICE); wm.removeView(windowView); + onHideView(); } } catch (Exception e) { FileLog.e(e); @@ -13507,6 +14026,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat placeProvider.willHidePhotoViewer(); } groupedPhotosListView.clear(); + if (placeProvider != null) { + placeProvider.onClose(); + } placeProvider = null; selectedPhotosAdapter.notifyDataSetChanged(); pageBlocksAdapter = null; @@ -14034,11 +14556,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float ts = scale + (animateToScale - scale) * animationValue; float tx = translationX + (animateToX - translationX) * animationValue; float ty = translationY + (animateToY - translationY) * animationValue; + float tr = rotate + (animateToRotate - rotate) * animationValue; imageMoveAnimation.cancel(); scale = ts; translationX = tx; translationY = ty; animationStartTime = 0; + rotate = tr; updateMinMax(scale); zoomAnimation = false; containerView.invalidate(); @@ -14140,7 +14664,32 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat @SuppressLint({"NewApi", "DrawAllocation"}) private void onDraw(Canvas canvas) { - if (animationInProgress == 1 || animationInProgress == 3 || !isVisible && animationInProgress != 2 && !pipAnimationInProgress) { + if (animationInProgress == 1) { + float alpha = 1f; + if (padImageForHorizontalInsets) { + canvas.save(); + canvas.translate(getLeftInset() / 2 - getRightInset() / 2, 0); + } + if (animatingImageView != null) { + canvas.save(); + canvas.translate( + animatingImageView.getCenterX() - canvas.getWidth() / 2, + animatingImageView.getCenterY() - canvas.getHeight() / 2 + ); + float t = animatingImageView.getAnimationProgress(); + float scale = alpha = animationInProgress == 1 ? t : 1f - t; + canvas.scale(scale, scale, canvas.getWidth() / 2, canvas.getHeight() / 2); + } + drawProgress(canvas, 0, 1, 0, alpha); + if (animatingImageView != null) { + canvas.restore(); + } + if (padImageForHorizontalInsets) { + canvas.restore(); + } + return; + } + if (animationInProgress == 3 || !isVisible && animationInProgress != 2 && !pipAnimationInProgress) { return; } @@ -14152,6 +14701,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat float currentTranslationY; float currentTranslationX; float currentScale; + float currentRotation; + float currentMirror; float aty = -1; long newUpdateTime = System.currentTimeMillis(); long dt = newUpdateTime - videoCrossfadeAlphaLastTime; @@ -14166,13 +14717,17 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } float ts = scale + (animateToScale - scale) * animationValue; + float tr = rotate + (animateToRotate - rotate) * animationValue; float tx = translationX + (animateToX - translationX) * animationValue; float ty = translationY + (animateToY - translationY) * animationValue; + float tm = mirror + (animateToMirror - mirror) * animationValue; if (animateToScale == 1 && scale == 1 && translationX == 0) { aty = ty; } + currentMirror = tm; currentScale = ts; + currentRotation = tr; currentTranslationY = ty; currentTranslationX = tx; updateMinMax(currentScale); @@ -14213,6 +14768,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat switchImageAfterAnimation = 0; } currentScale = scale; + currentMirror = mirror; + currentRotation = rotate; currentTranslationY = translationY; currentTranslationX = translationX; if (!moving) { @@ -14306,8 +14863,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canvas.scale(1.0f - scaleDiff, 1.0f - scaleDiff); int bitmapWidth = sideImage.getBitmapWidth(); int bitmapHeight = sideImage.getBitmapHeight(); - if (!rightImageIsVideo && rightCropTransform.hasViewTransform()) { - applyCrop(canvas, containerWidth, containerHeight, bitmapWidth, bitmapHeight, currentScale, rightCropTransform, rightCropState); + if (!rightImageIsVideo && rightCropState != null && rightCropTransform.hasViewTransform()) { + applyCrop(canvas, containerWidth, containerHeight, bitmapWidth, bitmapHeight, 1f, rightCropTransform, rightCropState); } float scaleX = containerWidth / (float) bitmapWidth; @@ -14316,10 +14873,34 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int width = (int) (bitmapWidth * scale); int height = (int) (bitmapHeight * scale); + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + if (currentEditMode == EDIT_MODE_CROP || sendPhotoType == SELECT_TYPE_AVATAR) { + mirror = rightCropTransform.isMirrored(); + } else { + mirror = rightCropState != null && rightCropState.mirrored; + } + } + if (mirror) { + canvas.scale(-1, 1); + } + sideImage.setAlpha(alpha); sideImage.setImageCoords(-width / 2, -height / 2, width, height); sideImage.draw(canvas); + if (rightPaintingOverlay != null && rightPaintingOverlay.getVisibility() == View.VISIBLE) { + canvas.clipRect(-width/2, -height/2, width/2, height/2); + if (rightPaintingOverlay.getMeasuredWidth() != bitmapWidth || rightPaintingOverlay.getMeasuredHeight() != bitmapHeight) { + rightPaintingOverlay.measure(View.MeasureSpec.makeMeasureSpec(bitmapWidth, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(bitmapHeight, View.MeasureSpec.EXACTLY)); + rightPaintingOverlay.layout(0, 0, bitmapWidth, bitmapHeight); + } + canvas.scale(scale, scale); + canvas.translate(-bitmapWidth/2, -bitmapHeight/2); + rightPaintingOverlay.setAlpha(1.0f); + rightPaintingOverlay.draw(canvas); + } + canvas.restore(); } groupedPhotosListView.setMoveProgress(-alpha); @@ -14357,6 +14938,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canvas.translate(containerWidth / 2 + getAdditionX(), containerHeight / 2 + getAdditionY()); canvas.translate(translateX, currentTranslationY + (currentEditMode != EDIT_MODE_PAINT ? currentPanTranslationY : currentPanTranslationY / 2)); canvas.scale(currentScale - scaleDiff, currentScale - scaleDiff); + canvas.rotate(currentRotation); if (currentEditMode == EDIT_MODE_PAINT && keyboardSize > AndroidUtilities.dp(20)) { int trueH = getContainerViewHeight(true, 0); int h = getContainerViewHeight(false, 0); @@ -14414,10 +14996,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat boolean applyCrop; float scaleToFitX = 1.0f; if (!imagesArrLocals.isEmpty()) { - if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == 3) { + if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) { applyCrop = true; } else if (sendPhotoType == SELECT_TYPE_AVATAR) { - applyCrop = (switchingToMode == 0 || currentEditMode != EDIT_MODE_PAINT && currentEditMode != EDIT_MODE_FILTER); + applyCrop = (switchingToMode == EDIT_MODE_NONE || currentEditMode != EDIT_MODE_PAINT && currentEditMode != EDIT_MODE_FILTER); } else { applyCrop = imageMoveAnimation != null && switchingToMode != -1 || currentEditMode == EDIT_MODE_NONE || currentEditMode == EDIT_MODE_CROP || switchingToMode != -1; } @@ -14438,18 +15020,18 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat rotatedHeight = temp; } float cropAnimationValue; - if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == 3 || switchingToMode == 3)) { + if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { cropAnimationValue = 1.0f; } else if (imageMoveAnimation != null && switchingToMode != -1) { - if (currentEditMode == 1 || switchingToMode == 1 || (currentEditMode == 2 || currentEditMode == 3) && switchingToMode == -1) { + if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) { cropAnimationValue = 1.0f; - } else if (switchingToMode == 0) { + } else if (switchingToMode == EDIT_MODE_NONE) { cropAnimationValue = animationValue; } else { cropAnimationValue = 1.0f - animationValue; } } else { - cropAnimationValue = currentEditMode == 2 || currentEditMode == 3 ? 0.0f : 1.0f; + cropAnimationValue = currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT ? 0.0f : 1.0f; } float cropPw = cropTransform.getCropPw(); float cropPh = cropTransform.getCropPh(); @@ -14459,7 +15041,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (scaleToFitX * bitmapHeight > containerHeight) { scaleToFitX = containerHeight / (float) bitmapHeight; } - if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == 0) && editState.cropState != null) { + if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode != 1 || switchingToMode == EDIT_MODE_NONE) && editState.cropState != null) { float startW = bitmapWidth * scaleToFitX; float startH = bitmapHeight * scaleToFitX; float originalScaleToFitX = containerWidth / (float) originalWidth; @@ -14476,7 +15058,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } if (sendPhotoType == SELECT_TYPE_AVATAR || cropTransform.hasViewTransform()) { float cropScale; - if (currentEditMode == 1 || sendPhotoType == SELECT_TYPE_AVATAR) { + if (currentEditMode == EDIT_MODE_CROP || sendPhotoType == SELECT_TYPE_AVATAR) { if (videoTextureView != null) { videoTextureView.setScaleX(cropTransform.isMirrored() ? -1.0f : 1.0f); if (firstFrameView != null) { @@ -14491,9 +15073,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } cropScale *= scaleToFit / scale; if (sendPhotoType == SELECT_TYPE_AVATAR) { - if (currentEditMode == 3 || switchingToMode == 3) { + if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) { cropScale /= 1.0f + (cropTransform.getMinScale() - 1.0f) * (1.0f - cropAnimationValue); - } else if (switchingToMode == 0) { + } else if (switchingToMode == EDIT_MODE_NONE) { cropScale /= cropTransform.getMinScale(); } } @@ -14516,7 +15098,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (rotation > 180) { rotation -= 360; } - if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == 3 || switchingToMode == 3)) { + if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { canvas.rotate(rotation); } else { canvas.rotate(rotation * cropAnimationValue); @@ -14546,17 +15128,34 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat mirror = editState.cropState != null && editState.cropState.mirrored; } } + boolean restore = false; if (mirror) { canvas.save(); canvas.scale(-1, 1); + restore = true; + } + if (currentMirror > 0) { + if (!restore) { + canvas.save(); + restore = true; + } + canvas.scale(1 - currentMirror * 2, 1f); + canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); } if (photoViewerWebView == null || !photoViewerWebView.isLoaded()) { centerImage.draw(canvas); } - if (mirror) { + if (restore) { canvas.restore(); } } + boolean restoreMirror = false; + if (currentMirror > 0) { + canvas.save(); + canvas.scale(1 - currentMirror * 2, 1f); + canvas.skew(0, 4 * currentMirror * (1f - currentMirror) * .25f); + restoreMirror = true; + } canvas.translate(-width / 2, -height / 2); if (drawTextureView || paintingOverlay.getVisibility() == View.VISIBLE) { canvas.scale(scale, scale); @@ -14583,6 +15182,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } paintingOverlay.setAlpha(alpha); } + if (restoreMirror) { + canvas.restore(); + canvas.translate(-width / 2, -height / 2); + if (drawTextureView || paintingOverlay.getVisibility() == View.VISIBLE) { + canvas.scale(scale, scale); + } + } if (paintingOverlay.getVisibility() == View.VISIBLE && (isCurrentVideo || currentEditMode != EDIT_MODE_FILTER || switchingToMode != -1)) { canvas.clipRect(0, 0, paintingOverlay.getMeasuredWidth(), paintingOverlay.getMeasuredHeight()); paintingOverlay.draw(canvas); @@ -14617,43 +15223,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } } - boolean drawProgress; - if (isCurrentVideo) { - drawProgress = (videoTimelineView == null || !videoTimelineView.isDragging()) && (sendPhotoType != SELECT_TYPE_AVATAR || manuallyPaused) && (videoPlayer == null || !videoPlayer.isPlaying()); - } else { - drawProgress = true; - } - boolean drawMiniProgress = miniProgressView.getVisibility() == View.VISIBLE || miniProgressAnimator != null; - if (drawProgress) { - final float tx = !zoomAnimation && -translateX > maxX ? translateX + maxX : 0; - float ty = currentScale == 1.0f ? currentTranslationY : 0; - float progressAlpha = alpha; - if (drawMiniProgress) { - progressAlpha *= 1f - miniProgressView.getAlpha(); - } - if (pipAnimationInProgress) { - progressAlpha *= actionBar.getAlpha(); - } else if (photoProgressViews[0].backgroundState == PROGRESS_PAUSE) { - ty += AndroidUtilities.dpf2(8) * (1f - actionBar.getAlpha()); - } - canvas.save(); - canvas.translate(tx, ty); - photoProgressViews[0].setScale(1.0f - scaleDiff); - photoProgressViews[0].setAlpha(progressAlpha); - photoProgressViews[0].onDraw(canvas); - - if (isActionBarVisible && allowShowFullscreenButton && fullscreenButton[0].getTag() == null) { - fullscreenButton[0].setAlpha(Math.min(fullscreenButton[0].getAlpha(), alpha)); - } - - canvas.restore(); - } - if (drawMiniProgress && !pipAnimationInProgress) { - canvas.save(); - canvas.translate(miniProgressView.getLeft() + translateX, miniProgressView.getTop() + currentTranslationY / currentScale); - miniProgressView.draw(canvas); - canvas.restore(); - } + drawProgress(canvas, translateX, currentScale, currentTranslationY, alpha); if (sideImage == leftImage) { if (sideImage.hasBitmapImage()) { @@ -14662,7 +15232,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat canvas.translate(-(containerWidth * (scale + 1) + AndroidUtilities.dp(30)) / 2 + currentTranslationX, 0); int bitmapWidth = sideImage.getBitmapWidth(); int bitmapHeight = sideImage.getBitmapHeight(); - if (!leftImageIsVideo && leftCropTransform.hasViewTransform()) { + if (!leftImageIsVideo && leftCropState != null && leftCropTransform.hasViewTransform()) { applyCrop(canvas, containerWidth, containerHeight, bitmapWidth, bitmapHeight, currentScale, leftCropTransform, leftCropState); } float scaleX = containerWidth / (float) bitmapWidth; @@ -14671,10 +15241,34 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int width = (int) (bitmapWidth * scale); int height = (int) (bitmapHeight * scale); + boolean mirror = false; + if (!imagesArrLocals.isEmpty()) { + if (currentEditMode == EDIT_MODE_CROP || sendPhotoType == SELECT_TYPE_AVATAR) { + mirror = leftCropTransform.isMirrored(); + } else { + mirror = leftCropState != null && leftCropState.mirrored; + } + } + if (mirror) { + canvas.scale(-1, 1); + } + sideImage.setAlpha(1.0f); sideImage.setImageCoords(-width / 2, -height / 2, width, height); sideImage.draw(canvas); + if (leftPaintingOverlay != null && leftPaintingOverlay.getVisibility() == View.VISIBLE) { + canvas.clipRect(-width/2, -height/2, width/2, height/2); + if (leftPaintingOverlay.getMeasuredWidth() != bitmapWidth || leftPaintingOverlay.getMeasuredHeight() != bitmapHeight) { + leftPaintingOverlay.measure(View.MeasureSpec.makeMeasureSpec(bitmapWidth, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(bitmapHeight, View.MeasureSpec.EXACTLY)); + leftPaintingOverlay.layout(0, 0, bitmapWidth, bitmapHeight); + } + canvas.scale(scale, scale); + canvas.translate(-bitmapWidth/2, -bitmapHeight/2); + leftPaintingOverlay.setAlpha(1.0f); + leftPaintingOverlay.draw(canvas); + } + canvas.restore(); } groupedPhotosListView.setMoveProgress(1.0f - alpha); @@ -14734,6 +15328,46 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + private void drawProgress(Canvas canvas, float translateX, float currentScale, float currentTranslationY, float alpha) { + boolean drawProgress; + if (isCurrentVideo) { + drawProgress = (videoTimelineView == null || !videoTimelineView.isDragging()) && (sendPhotoType != SELECT_TYPE_AVATAR || manuallyPaused) && (videoPlayer == null || !videoPlayer.isPlaying()); + } else { + drawProgress = true; + } + boolean drawMiniProgress = miniProgressView.getVisibility() == View.VISIBLE || miniProgressAnimator != null; + if (drawProgress) { + final float tx = !zoomAnimation && -translateX > maxX ? translateX + maxX : 0; + float ty = currentScale == 1.0f ? currentTranslationY : 0; + float progressAlpha = alpha; + if (drawMiniProgress) { + progressAlpha *= 1f - miniProgressView.getAlpha(); + } + if (pipAnimationInProgress) { + progressAlpha *= actionBar.getAlpha(); + } else if (photoProgressViews[0].backgroundState == PROGRESS_PAUSE) { + ty += AndroidUtilities.dpf2(8) * (1f - actionBar.getAlpha()); + } + canvas.save(); + canvas.translate(tx, ty); + photoProgressViews[0].setScale(1.0f); + photoProgressViews[0].setAlpha(progressAlpha); + photoProgressViews[0].onDraw(canvas); + + if (isActionBarVisible && allowShowFullscreenButton && fullscreenButton[0].getTag() == null) { + fullscreenButton[0].setAlpha(Math.min(fullscreenButton[0].getAlpha(), alpha)); + } + + canvas.restore(); + } + if (drawMiniProgress && !pipAnimationInProgress) { + canvas.save(); + canvas.translate(miniProgressView.getLeft() + translateX, miniProgressView.getTop() + currentTranslationY / currentScale); + miniProgressView.draw(canvas); + canvas.restore(); + } + } + private int[] tempInt = new int[2]; private int[] applyCrop(Canvas canvas, int containerWidth, int containerHeight, int bitmapWidth, int bitmapHeight, float currentScale, CropTransform cropTransform, MediaController.CropState cropState) { @@ -14756,9 +15390,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (sendPhotoType != SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { cropAnimationValue = 1.0f; } else if (imageMoveAnimation != null && switchingToMode != -1) { - if (currentEditMode == 1 || switchingToMode == 1 || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) { + if (currentEditMode == EDIT_MODE_CROP || switchingToMode == EDIT_MODE_CROP || (currentEditMode == EDIT_MODE_FILTER || currentEditMode == EDIT_MODE_PAINT) && switchingToMode == -1) { cropAnimationValue = 1.0f; - } else if (switchingToMode == 0) { + } else if (switchingToMode == EDIT_MODE_NONE) { cropAnimationValue = animationValue; } else { cropAnimationValue = 1.0f - animationValue; @@ -14800,9 +15434,9 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } cropScale *= scaleToFit / scale; if (sendPhotoType == SELECT_TYPE_AVATAR) { - if (currentEditMode == 3 || switchingToMode == 3) { + if (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT) { cropScale /= 1.0f + (cropTransform.getMinScale() - 1.0f) * (1.0f - cropAnimationValue); - } else if (switchingToMode == 0) { + } else if (switchingToMode == EDIT_MODE_NONE) { cropScale /= cropTransform.getMinScale(); } } @@ -14819,7 +15453,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (rotation > 180) { rotation -= 360; } - if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == 3 || switchingToMode == 3)) { + if (sendPhotoType == SELECT_TYPE_AVATAR && (currentEditMode == EDIT_MODE_PAINT || switchingToMode == EDIT_MODE_PAINT)) { canvas.rotate(rotation); } else { canvas.rotate(rotation * cropAnimationValue); @@ -14845,7 +15479,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } if (file == null) { - file = FileLoader.getPathToMessage(currentMessageObject.messageOwner); + file = FileLoader.getInstance(currentAccount).getPathToMessage(currentMessageObject.messageOwner); if (!file.exists()) { file = null; if (SharedConfig.streamMedia && !DialogObject.isEncryptedDialog(currentMessageObject.getDialogId()) && currentMessageObject.isVideo() && currentMessageObject.canStreamVideo()) { @@ -14873,7 +15507,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } else if (currentBotInlineResult != null) { if (currentBotInlineResult.document != null) { - file = FileLoader.getPathToAttach(currentBotInlineResult.document); + file = FileLoader.getInstance(currentAccount).getPathToAttach(currentBotInlineResult.document); if (!file.exists()) { file = null; } @@ -15038,6 +15672,10 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } } + public VideoPlayerRewinder getVideoPlayerRewinder() { + return videoPlayerRewinder; + } + @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (scale != 1) { @@ -15625,7 +16263,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat } private void showQualityView(final boolean show) { - if (show && textureUploaded && videoSizeSet && !changingTextureView) { + if (show && textureUploaded && videoSizeSet && !changingTextureView && videoTextureView != null) { videoFrameBitmap = videoTextureView.getBitmap(); } @@ -15870,9 +16508,13 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private void updateAccessibilityOverlayVisibility() { if (playButtonAccessibilityOverlay != null) { final int state = photoProgressViews[0].backgroundState; - if (photoProgressViews[0].isVisible() && (state == PROGRESS_PLAY || state == PROGRESS_PAUSE)) { + if (photoProgressViews[0].isVisible() && (state == PROGRESS_PLAY || state == PROGRESS_PAUSE || state == PROGRESS_LOAD || state == PROGRESS_CANCEL)) { if (state == PROGRESS_PLAY) { playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionPlay", R.string.AccActionPlay)); + } else if (state == PROGRESS_LOAD) { + playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionDownload", R.string.AccActionDownload)); + } else if (state == PROGRESS_CANCEL) { + playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionCancelDownload", R.string.AccActionCancelDownload)); } else { playButtonAccessibilityOverlay.setContentDescription(LocaleController.getString("AccActionPause", R.string.AccActionPause)); } @@ -15914,7 +16556,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat int num = placeProvider.setPhotoChecked(idx, getCurrentVideoEditedInfo()); boolean checked = placeProvider.isPhotoChecked(idx); if (idx == currentIndex) { - checkImageView.setChecked(-1, false, true); + checkImageView.setChecked(-1, checked, true); } if (num >= 0) { selectedPhotosAdapter.notifyItemRemoved(num); @@ -15985,6 +16627,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat private class FirstFrameView extends ImageView { public FirstFrameView(Context context) { super(context); + setAlpha(0f); } public void clear() { @@ -16010,7 +16653,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat if (videoPlayer != null) { long timeToEnd = videoPlayer.getDuration() - videoPlayer.getCurrentPosition(); - if (!hasFrame && !gotError && !gettingFrame && timeToEnd < 1000 * 5) { // 5 seconds to get the first frame + if (!hasFrame && !gotError && !gettingFrame && timeToEnd < 1000 * 5 + fadeDuration) { // 5 seconds to get the first frame final Uri uri = videoPlayer.getCurrentUri(); final int index = ++gettingFrameIndex; Utilities.globalQueue.postRunnable(() -> { @@ -16043,11 +16686,44 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat return hasFrame; } - public final static float fadeDuration = 200; + public final static float fadeDuration = 250; + private final TimeInterpolator fadeInterpolator = CubicBezierInterpolator.EASE_IN; + + private ValueAnimator fadeAnimator; private void updateAlpha() { - if (videoPlayer != null && firstFrameView != null && videoPlayer.getDuration() != C.TIME_UNSET) { - long toDuration = videoPlayer.getDuration() - videoPlayer.getCurrentPosition(); - firstFrameView.setAlpha(1f - Math.max(Math.min(toDuration / fadeDuration, 1), 0)); + if (videoPlayer == null || videoPlayer.getDuration() == C.TIME_UNSET) { + if (fadeAnimator != null) { + fadeAnimator.cancel(); + fadeAnimator = null; + } + setAlpha(0f); + return; + } + long toDuration = Math.max(0, videoPlayer.getDuration() - videoPlayer.getCurrentPosition()); + float alpha = 1f - Math.max(Math.min(toDuration / fadeDuration, 1), 0); + if (alpha <= 0) { + if (fadeAnimator != null) { + fadeAnimator.cancel(); + fadeAnimator = null; + } + setAlpha(0f); + } else if (videoPlayer.isPlaying()) { + if (fadeAnimator == null) { + fadeAnimator = ValueAnimator.ofFloat(alpha, 1f); + fadeAnimator.addUpdateListener(a -> { + setAlpha((float) a.getAnimatedValue()); + }); + fadeAnimator.setDuration(toDuration); + fadeAnimator.setInterpolator(fadeInterpolator); + fadeAnimator.start(); + setAlpha(alpha); + } + } else { + if (fadeAnimator != null) { + fadeAnimator.cancel(); + fadeAnimator = null; + } + setAlpha(alpha); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java index b91d27358..659775b47 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java @@ -898,7 +898,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC if (currentPhotoObject != null) { boolean photoExist = true; if (messageObject.type == 1) { - File cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner); + File cacheFile = FileLoader.getInstance(UserConfig.selectedAccount).getPathToMessage(messageObject.messageOwner); if (!cacheFile.exists()) { photoExist = false; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java new file mode 100644 index 000000000..54668ef93 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumFeatureCell.java @@ -0,0 +1,72 @@ +package org.telegram.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.util.TypedValue; +import android.view.Gravity; +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.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; + +public class PremiumFeatureCell extends FrameLayout { + + private final TextView title; + private final TextView description; + public ImageView imageView; + boolean drawDivider; + public PremiumPreviewFragment.PremiumFeatureData data; + + public PremiumFeatureCell(Context context) { + super(context); + + LinearLayout linearLayout = new LinearLayout(context); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + title = new TextView(context); + title.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); + title.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + 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.setLineSpacing(AndroidUtilities.dp(2), 1f); + linearLayout.addView(description, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 0, 1, 0, 0)); + + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 62, 8, 48, 9)); + + imageView = new ImageView(context); + imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + addView(imageView, LayoutHelper.createFrame(28, 28, 0, 18, 12, 0, 0)); + + ImageView nextIcon = new ImageView(context); + nextIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE); + nextIcon.setImageResource(R.drawable.msg_arrowright); + nextIcon.setColorFilter(Theme.getColor(Theme.key_switchTrack)); + addView(nextIcon, LayoutHelper.createFrame(24, 24, Gravity.RIGHT | Gravity.CENTER_VERTICAL, 0, 0, 18, 0)); + } + + + public void setData(PremiumPreviewFragment.PremiumFeatureData data, boolean drawDivider) { + this.data = data; + title.setText(data.title); + description.setText(data.description); + imageView.setImageResource(data.icon); + this.drawDivider = drawDivider; + } + + @Override + protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (drawDivider) { + canvas.drawRect(AndroidUtilities.dp(62), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight(), Theme.dividerPaint); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java new file mode 100644 index 000000000..490a3702d --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -0,0 +1,1045 @@ +package org.telegram.ui; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.app.Dialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.LinearGradient; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextUtils; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.ScrollView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.graphics.ColorUtils; +import androidx.recyclerview.widget.RecyclerView; + +import org.telegram.PhoneFormat.PhoneFormat; +import org.telegram.messenger.AndroidUtilities; +import org.telegram.messenger.BuildVars; +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.MediaDataController; +import org.telegram.messenger.MessagesController; +import org.telegram.messenger.NotificationCenter; +import org.telegram.messenger.R; +import org.telegram.messenger.UserConfig; +import org.telegram.messenger.Utilities; +import org.telegram.tgnet.ConnectionsManager; +import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.ActionBar; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.ShadowSectionCell; +import org.telegram.ui.Cells.TextInfoPrivacyCell; +import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; +import org.telegram.ui.Components.FillLastLinearLayoutManager; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.AboutPremiumView; +import org.telegram.ui.Components.Premium.DoubledLimitsBottomSheet; +import org.telegram.ui.Components.Premium.GLIcon.GLIconRenderer; +import org.telegram.ui.Components.Premium.GLIcon.GLIconTextureView; +import org.telegram.ui.Components.Premium.PremiumButtonView; +import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; +import org.telegram.ui.Components.Premium.PremiumGradient; +import org.telegram.ui.Components.Premium.PremiumNotAvailableBottomSheet; +import org.telegram.ui.Components.Premium.StarParticlesView; +import org.telegram.ui.Components.RecyclerListView; +import org.telegram.ui.Components.SimpleThemeDescription; +import org.telegram.ui.Components.TextStyleSpan; +import org.telegram.ui.Components.URLSpanBotCommand; +import org.telegram.ui.Components.URLSpanBrowser; +import org.telegram.ui.Components.URLSpanMono; +import org.telegram.ui.Components.URLSpanNoUnderline; +import org.telegram.ui.Components.URLSpanReplacement; +import org.telegram.ui.Components.URLSpanUserMention; + +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Currency; +import java.util.List; + +public class PremiumPreviewFragment extends BaseFragment implements NotificationCenter.NotificationCenterDelegate { + RecyclerListView listView; + ArrayList premiumFeatures = new ArrayList<>(); + + int rowCount; + int paddingRow; + int featuresStartRow; + int featuresEndRow; + int sectionRow; + int helpUsRow; + int statusRow; + int privacyRow; + int lastPaddingRow; + Drawable shadowDrawable; + private FrameLayout buttonContainer; + private View buttonDivider; + + PremiumFeatureCell dummyCell; + int totalGradientHeight; + + FillLastLinearLayoutManager layoutManager; + //icons + Shader shader; + Matrix matrix = new Matrix(); + Paint gradientPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + BackgroundView backgroundView; + StarParticlesView particlesView; + boolean isLandscapeMode; + + public final static int PREMIUM_FEATURE_LIMITS = 0; + public final static int PREMIUM_FEATURE_UPLOAD_LIMIT = 1; + public final static int PREMIUM_FEATURE_DOWNLOAD_SPEED = 2; + public final static int PREMIUM_FEATURE_ADS = 3; + public final static int PREMIUM_FEATURE_REACTIONS = 4; + public final static int PREMIUM_FEATURE_STICKERS = 5; + public final static int PREMIUM_FEATURE_PROFILE_BADGE = 6; + public final static int PREMIUM_FEATURE_ANIMATED_AVATARS = 7; + public final static int PREMIUM_FEATURE_VOICE_TO_TEXT = 8; + public final static int PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT = 9; + public final static int PREMIUM_FEATURE_APPLICATION_ICONS = 10; + private int statusBarHeight; + private int firstViewHeight; + private boolean isDialogVisible; + + boolean inc; + float progress; + private int currentYOffset; + private FrameLayout contentView; + private PremiumButtonView premiumButtonView; + float totalProgress; + private String source; + + final Bitmap gradientTextureBitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888); + final Canvas gradientCanvas = new Canvas(gradientTextureBitmap); + PremiumGradient.GradientTools gradientTools = new PremiumGradient.GradientTools(Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4); + + private boolean forcePremium; + float progressToFull; + + public static int severStringToFeatureType(String s) { + switch (s) { + case "double_limits": + return PREMIUM_FEATURE_LIMITS; + case "more_upload": + return PREMIUM_FEATURE_UPLOAD_LIMIT; + case "faster_download": + return PREMIUM_FEATURE_DOWNLOAD_SPEED; + case "voice_to_text": + return PREMIUM_FEATURE_VOICE_TO_TEXT; + case "no_ads": + return PREMIUM_FEATURE_ADS; + case "unique_reactions": + return PREMIUM_FEATURE_REACTIONS; + case "premium_stickers": + return PREMIUM_FEATURE_STICKERS; + case "advanced_chat_management": + return PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT; + case "profile_badge": + return PREMIUM_FEATURE_PROFILE_BADGE; + case "animated_userpics": + return PREMIUM_FEATURE_ANIMATED_AVATARS; + case "app_icons": + return PREMIUM_FEATURE_APPLICATION_ICONS; + } + return -1; + } + + public static String featureTypeToServerString(int type) { + switch (type) { + case PREMIUM_FEATURE_LIMITS: + return "double_limits"; + case PREMIUM_FEATURE_UPLOAD_LIMIT: + return "more_upload"; + case PREMIUM_FEATURE_DOWNLOAD_SPEED: + return "faster_download"; + case PREMIUM_FEATURE_VOICE_TO_TEXT: + return "voice_to_text"; + case PREMIUM_FEATURE_ADS: + return "no_ads"; + case PREMIUM_FEATURE_REACTIONS: + return "unique_reactions"; + case PREMIUM_FEATURE_STICKERS: + return "premium_stickers"; + case PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT: + return "advanced_chat_management"; + case PREMIUM_FEATURE_PROFILE_BADGE: + return "profile_badge"; + case PREMIUM_FEATURE_ANIMATED_AVATARS: + return "animated_userpics"; + case PREMIUM_FEATURE_APPLICATION_ICONS: + return "app_icons"; + } + return null; + } + + public PremiumPreviewFragment setForcePremium() { + this.forcePremium = true; + return this; + } + + public PremiumPreviewFragment(String source) { + super(); + this.source = source; + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public View createView(Context context) { + hasOwnBackground = true; + shader = new LinearGradient(0, 0, 0, 100, new int[]{0xffF38926, 0xffDB5C9D, 0xffA767FF, 0xff55A5FF}, new float[]{0f, 0.32f, 0.5f, 1f}, Shader.TileMode.CLAMP); + shader.setLocalMatrix(matrix); + gradientPaint.setShader(shader); + + dummyCell = new PremiumFeatureCell(context); + + premiumFeatures.clear(); + fillPremiumFeaturesList(premiumFeatures, currentAccount); + + Rect padding = new Rect(); + shadowDrawable = context.getResources().getDrawable(R.drawable.sheet_shadow_round).mutate(); + shadowDrawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_dialogBackground), PorterDuff.Mode.MULTIPLY)); + shadowDrawable.getPadding(padding); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + statusBarHeight = AndroidUtilities.isTablet() ? 0 : AndroidUtilities.statusBarHeight; + } + + contentView = new FrameLayout(context) { + + int lastSize; + boolean iconInterceptedTouch; + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + float iconX = backgroundView.getX() + backgroundView.imageView.getX(); + float iconY = backgroundView.getY() + backgroundView.imageView.getY(); + AndroidUtilities.rectTmp.set(iconX, iconY, iconX + backgroundView.imageView.getMeasuredWidth(), iconY + backgroundView.imageView.getMeasuredHeight()); + if (AndroidUtilities.rectTmp.contains(ev.getX(), ev.getY()) || iconInterceptedTouch) { + ev.offsetLocation(-iconX, -iconY); + if (ev.getAction() == MotionEvent.ACTION_DOWN || ev.getAction() == MotionEvent.ACTION_MOVE) { + iconInterceptedTouch = true; + } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { + iconInterceptedTouch = false; + } + backgroundView.imageView.dispatchTouchEvent(ev); + return true; + } + return super.dispatchTouchEvent(ev); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) { + isLandscapeMode = true; + } else { + isLandscapeMode = false; + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + statusBarHeight = AndroidUtilities.isTablet() ? 0 : AndroidUtilities.statusBarHeight; + } + backgroundView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + particlesView.getLayoutParams().height = backgroundView.getMeasuredHeight(); + int buttonHeight = (getUserConfig().isPremium() || forcePremium ? 0 : AndroidUtilities.dp(68)); + layoutManager.setAdditionalHeight(buttonHeight + statusBarHeight - AndroidUtilities.dp(16)); + layoutManager.setMinimumLastViewHeight(buttonHeight); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int size = getMeasuredHeight() + getMeasuredWidth() << 16; + if (lastSize != size) { + updateBackgroundImage(); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + backgroundView.imageView.mRenderer.gradientScaleX = backgroundView.imageView.getMeasuredWidth() / (float) getMeasuredWidth(); + backgroundView.imageView.mRenderer.gradientScaleY = backgroundView.imageView.getMeasuredHeight() / (float) getMeasuredHeight(); + backgroundView.imageView.mRenderer.gradientStartX = (backgroundView.getX() + backgroundView.imageView.getX()) / getMeasuredWidth(); + backgroundView.imageView.mRenderer.gradientStartY = (backgroundView.getY() + backgroundView.imageView.getY()) / getMeasuredHeight(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + measureGradient(w, h); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + if (!isDialogVisible) { + if (inc) { + progress += 16f / 1000f; + if (progress > 3) { + inc = false; + } + } else { + progress -= 16f / 1000f; + if (progress < 1) { + inc = true; + } + } + } + View firstView = null; + if (listView.getLayoutManager() != null) { + firstView = listView.getLayoutManager().findViewByPosition(0); + } + + currentYOffset = firstView == null ? 0 : firstView.getBottom(); + int h = actionBar.getBottom() + AndroidUtilities.dp(16); + totalProgress = (1f - (currentYOffset - h) / (float) (firstViewHeight - h)); + totalProgress = Utilities.clamp(totalProgress, 1f, 0f); + + int maxTop = actionBar.getBottom() + AndroidUtilities.dp(16); + if (currentYOffset < maxTop) { + currentYOffset = maxTop; + } + + float oldProgress = progressToFull; + progressToFull = 0; + if (currentYOffset < maxTop + AndroidUtilities.dp(30)) { + progressToFull = (maxTop + AndroidUtilities.dp(30) - currentYOffset) / (float) AndroidUtilities.dp(30); + } + + if (isLandscapeMode) { + progressToFull = 1f; + totalProgress = 1f; + } + if (oldProgress != progressToFull) { + listView.invalidate(); + } + float fromTranslation = currentYOffset - (actionBar.getMeasuredHeight() + backgroundView.getMeasuredHeight() - statusBarHeight) + AndroidUtilities.dp(16); + float toTranslation = ((actionBar.getMeasuredHeight() - statusBarHeight - backgroundView.titleView.getMeasuredHeight()) / 2f) + statusBarHeight - backgroundView.getTop() - backgroundView.titleView.getTop(); + + float translationsY = Math.max(toTranslation, fromTranslation); + float iconTranslationsY = -translationsY / 4f + AndroidUtilities.dp(16); + backgroundView.setTranslationY(translationsY); + + backgroundView.imageView.setTranslationY(iconTranslationsY + AndroidUtilities.dp(16)); + float s = 0.6f + (1f - totalProgress) * 0.4f; + float alpha = 1f - (totalProgress > 0.5f ? (totalProgress - 0.5f) / 0.5f : 0f); + backgroundView.imageView.setScaleX(s); + backgroundView.imageView.setScaleY(s); + backgroundView.imageView.setAlpha(alpha); + backgroundView.subtitleView.setAlpha(alpha); + particlesView.setAlpha(1f - totalProgress); + + particlesView.setTranslationY(-(particlesView.getMeasuredHeight() - backgroundView.imageView.getMeasuredWidth()) / 2f + backgroundView.getY() + backgroundView.imageView.getY()); + float toX = AndroidUtilities.dp(72) - backgroundView.titleView.getLeft(); + float f = totalProgress > 0.3f ? (totalProgress - 0.3f) / 0.7f : 0f; + backgroundView.titleView.setTranslationX(toX * (1f - CubicBezierInterpolator.EASE_OUT_QUINT.getInterpolation(1 - f))); + + backgroundView.imageView.mRenderer.gradientStartX = (backgroundView.getX() + backgroundView.imageView.getX() + getMeasuredWidth() * 0.1f * progress) / getMeasuredWidth(); + backgroundView.imageView.mRenderer.gradientStartY = (backgroundView.getY() + backgroundView.imageView.getY()) / getMeasuredHeight(); + + if (!isDialogVisible) { + invalidate(); + } + gradientTools.gradientMatrix(0, 0, getMeasuredWidth(), getMeasuredHeight(), -getMeasuredWidth() * 0.1f * progress, 0); + canvas.drawRect(0, 0, getMeasuredWidth(), currentYOffset + AndroidUtilities.dp(20), gradientTools.paint); + + super.dispatchDraw(canvas); + } + + @Override + protected boolean drawChild(Canvas canvas, View child, long drawingTime) { + if (child == listView) { + canvas.save(); + canvas.clipRect(0, actionBar.getBottom(), getMeasuredWidth(), getMeasuredHeight()); + super.drawChild(canvas, child, drawingTime); + canvas.restore(); + return true; + } + return super.drawChild(canvas, child, drawingTime); + } + }; + contentView.setFitsSystemWindows(true); + + listView = new RecyclerListView(context) { + @Override + public void onDraw(Canvas canvas) { + shadowDrawable.setBounds((int) (-padding.left - AndroidUtilities.dp(16) * progressToFull), currentYOffset - padding.top - AndroidUtilities.dp(16), (int) (getMeasuredWidth() + padding.right + AndroidUtilities.dp(16) * progressToFull), getMeasuredHeight()); + shadowDrawable.draw(canvas); + super.onDraw(canvas); + } + }; + listView.setLayoutManager(layoutManager = new FillLastLinearLayoutManager(context, AndroidUtilities.dp(68) + statusBarHeight - AndroidUtilities.dp(16), listView)); + layoutManager.setFixedLastItemHeight(); + + listView.setAdapter(new Adapter()); + listView.addOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + super.onScrollStateChanged(recyclerView, newState); + if (newState == RecyclerView.SCROLL_STATE_IDLE) { + int maxTop = actionBar.getBottom() + AndroidUtilities.dp(16); + if (totalProgress > 0.5f) { + listView.smoothScrollBy(0, currentYOffset - maxTop); + } else { + View firstView = null; + if (listView.getLayoutManager() != null) { + firstView = listView.getLayoutManager().findViewByPosition(0); + } + if (firstView != null && firstView.getTop() < 0) { + listView.smoothScrollBy(0, firstView.getTop()); + } + } + } + checkButtonDivider(); + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + contentView.invalidate(); + checkButtonDivider(); + } + }); + + backgroundView = new BackgroundView(context) { + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return true; + } + }; + particlesView = new StarParticlesView(context); + backgroundView.imageView.setStarParticlesView(particlesView); + contentView.addView(particlesView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + contentView.addView(backgroundView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + listView.setOnItemClickListener((view, position) -> { + if (view instanceof PremiumFeatureCell) { + PremiumFeatureCell cell = (PremiumFeatureCell) view; + PremiumPreviewFragment.sentShowFeaturePreview(currentAccount, cell.data.type); + if (cell.data.type == PREMIUM_FEATURE_LIMITS) { + DoubledLimitsBottomSheet bottomSheet = new DoubledLimitsBottomSheet(PremiumPreviewFragment.this, currentAccount); + bottomSheet.setParentFragment(PremiumPreviewFragment.this); + showDialog(bottomSheet); + } else { + showDialog(new PremiumFeatureBottomSheet(PremiumPreviewFragment.this, cell.data.type, false)); + } + } + }); + contentView.addView(listView); + + premiumButtonView = new PremiumButtonView(context, false); + premiumButtonView.setButton(getPremiumButtonText(currentAccount), v -> { + buyPremium(this); + }); + buttonContainer = new FrameLayout(context); + + buttonDivider = new View(context); + buttonDivider.setBackgroundColor(Theme.getColor(Theme.key_divider)); + buttonContainer.addView(buttonDivider, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 1)); + buttonDivider.getLayoutParams().height = 1; + AndroidUtilities.updateViewVisibilityAnimated(buttonDivider, true, 1f, false); + + buttonContainer.addView(premiumButtonView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.CENTER_VERTICAL, 16, 0, 16, 0)); + buttonContainer.setBackgroundColor(getThemedColor(Theme.key_dialogBackground)); + contentView.addView(buttonContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 68, Gravity.BOTTOM)); + + fragmentView = contentView; + actionBar.setBackground(null); + actionBar.setCastShadows(false); + actionBar.setBackButtonImage(R.drawable.ic_ab_back); + actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { + @Override + public void onItemClick(int id) { + if (id == -1) { + finishFragment(); + } + } + }); + actionBar.setForceSkipTouches(true); + + updateColors(); + updateRows(); + + backgroundView.imageView.startEnterAnimation(-180, 200); + if (forcePremium) { + AndroidUtilities.runOnUIThread(() -> getMediaDataController().loadPremiumPromo(false), 400); + } + MediaDataController.getInstance(currentAccount).preloadPremiumPreviewStickers(); + + sentShowScreenStat(source); + return fragmentView; + } + + public static void buyPremium(BaseFragment fragment) { + buyPremium(fragment, "settings"); + } + + public static void fillPremiumFeaturesList(ArrayList premiumFeatures, int currentAccount) { + MessagesController messagesController = MessagesController.getInstance(currentAccount); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_LIMITS, R.drawable.msg_premium_limits, LocaleController.getString("PremiumPreviewLimits", R.string.PremiumPreviewLimits), LocaleController.formatString("PremiumPreviewLimitsDescription", R.string.PremiumPreviewLimitsDescription, + messagesController.channelsLimitPremium, messagesController.dialogFiltersLimitPremium, messagesController.dialogFiltersPinnedLimitPremium, messagesController.publicLinksLimitPremium, 4))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_UPLOAD_LIMIT, R.drawable.msg_premium_uploads, LocaleController.getString("PremiumPreviewUploads", R.string.PremiumPreviewUploads), LocaleController.getString("PremiumPreviewUploadsDescription", R.string.PremiumPreviewUploadsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_DOWNLOAD_SPEED, R.drawable.msg_premium_speed, LocaleController.getString("PremiumPreviewDownloadSpeed", R.string.PremiumPreviewDownloadSpeed), LocaleController.getString("PremiumPreviewDownloadSpeedDescription", R.string.PremiumPreviewDownloadSpeedDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_VOICE_TO_TEXT, R.drawable.msg_premium_voice, LocaleController.getString("PremiumPreviewVoiceToText", R.string.PremiumPreviewVoiceToText), LocaleController.getString("PremiumPreviewVoiceToTextDescription", R.string.PremiumPreviewVoiceToTextDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADS, R.drawable.msg_premium_ads, LocaleController.getString("PremiumPreviewNoAds", R.string.PremiumPreviewNoAds), LocaleController.getString("PremiumPreviewNoAdsDescription", R.string.PremiumPreviewNoAdsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_REACTIONS, R.drawable.msg_premium_reactions, LocaleController.getString("PremiumPreviewReactions", R.string.PremiumPreviewReactions), LocaleController.getString("PremiumPreviewReactionsDescription", R.string.PremiumPreviewReactionsDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_STICKERS, R.drawable.msg_premium_stickers, LocaleController.getString("PremiumPreviewStickers", R.string.PremiumPreviewStickers), LocaleController.getString("PremiumPreviewStickersDescription", R.string.PremiumPreviewStickersDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ADVANCED_CHAT_MANAGEMENT, R.drawable.msg_premium_tools, LocaleController.getString("PremiumPreviewAdvancedChatManagement", R.string.PremiumPreviewAdvancedChatManagement), LocaleController.getString("PremiumPreviewAdvancedChatManagementDescription", R.string.PremiumPreviewAdvancedChatManagementDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_PROFILE_BADGE, R.drawable.msg_premium_badge, LocaleController.getString("PremiumPreviewProfileBadge", R.string.PremiumPreviewProfileBadge), LocaleController.getString("PremiumPreviewProfileBadgeDescription", R.string.PremiumPreviewProfileBadgeDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_ANIMATED_AVATARS, R.drawable.msg_premium_avatar, LocaleController.getString("PremiumPreviewAnimatedProfiles", R.string.PremiumPreviewAnimatedProfiles), LocaleController.getString("PremiumPreviewAnimatedProfilesDescription", R.string.PremiumPreviewAnimatedProfilesDescription))); + premiumFeatures.add(new PremiumFeatureData(PREMIUM_FEATURE_APPLICATION_ICONS, R.drawable.msg_premium_icons, LocaleController.getString("PremiumPreviewAppIcon", R.string.PremiumPreviewAppIcon), LocaleController.getString("PremiumPreviewAppIconDescription", R.string.PremiumPreviewAppIconDescription))); + + if (messagesController.premiumFeaturesTypesToPosition.size() > 0) { + for (int i = 0; i < premiumFeatures.size(); i++) { + if (messagesController.premiumFeaturesTypesToPosition.get(premiumFeatures.get(i).type, -1) == -1) { + premiumFeatures.remove(i); + i--; + } + } + } + + Collections.sort(premiumFeatures, (o1, o2) -> { + int type1 = messagesController.premiumFeaturesTypesToPosition.get(o1.type, Integer.MAX_VALUE); + int type2 = messagesController.premiumFeaturesTypesToPosition.get(o2.type, Integer.MAX_VALUE); + return type1 - type2; + }); + } + + private void updateBackgroundImage() { + if (contentView.getMeasuredWidth() == 0 || contentView.getMeasuredHeight() == 0) { + return; + } + gradientTools.gradientMatrix(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), 0, 0); + gradientCanvas.save(); + gradientCanvas.scale(100f / contentView.getMeasuredWidth(), 100f / contentView.getMeasuredHeight()); + gradientCanvas.drawRect(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight(), gradientTools.paint); + gradientCanvas.restore(); + backgroundView.imageView.setBackgroundBitmap(gradientTextureBitmap); + } + + private void checkButtonDivider() { + AndroidUtilities.updateViewVisibilityAnimated(buttonDivider, listView.canScrollVertically(1), 1f, true); + } + + public static void buyPremium(BaseFragment fragment, String source) { + if (BuildVars.IS_BILLING_UNAVAILABLE) { + fragment.showDialog(new PremiumNotAvailableBottomSheet(fragment)); + return; + } + // NekoX: remove Google billing + } + + public static String getPremiumButtonText(int currentAccount) { + return LocaleController.getString(R.string.SubscribeToPremiumNotAvailable); + // NekoX: remove Google billing + } + + private void measureGradient(int w, int h) { + int yOffset = 0; + for (int i = 0; i < premiumFeatures.size(); i++) { + dummyCell.setData(premiumFeatures.get(i), false); + dummyCell.measure(View.MeasureSpec.makeMeasureSpec(w, View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(h, View.MeasureSpec.AT_MOST)); + premiumFeatures.get(i).yOffset = yOffset; + yOffset += dummyCell.getMeasuredHeight(); + } + + totalGradientHeight = yOffset; + } + + private void updateRows() { + rowCount = 0; + sectionRow = -1; + statusRow = -1; + privacyRow = -1; + + paddingRow = rowCount++; + featuresStartRow = rowCount; + rowCount += premiumFeatures.size(); + featuresEndRow = rowCount; + statusRow = rowCount++; + lastPaddingRow = rowCount++; + if (getUserConfig().isPremium() || forcePremium) { + buttonContainer.setVisibility(View.GONE); + } else { + buttonContainer.setVisibility(View.VISIBLE); + } + + int buttonHeight = buttonContainer.getVisibility() == View.VISIBLE ? AndroidUtilities.dp(64) : 0; + layoutManager.setAdditionalHeight(buttonHeight + statusBarHeight - AndroidUtilities.dp(16)); + layoutManager.setMinimumLastViewHeight(buttonHeight); + } + + @Override + public boolean isSwipeBackEnabled(MotionEvent event) { + return true; + } + + @Override + public boolean onFragmentCreate() { + if (getMessagesController().premiumLocked) { + return false; + } + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + getNotificationCenter().addObserver(this, NotificationCenter.premiumPromoUpdated); + + return super.onFragmentCreate(); + } + + @Override + public void onFragmentDestroy() { + super.onFragmentDestroy(); + + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.billingProductDetailsUpdated); + NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.currentUserPremiumStatusChanged); + getNotificationCenter().removeObserver(this, NotificationCenter.premiumPromoUpdated); + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void didReceivedNotification(int id, int account, Object... args) { + if (id == NotificationCenter.billingProductDetailsUpdated || id == NotificationCenter.premiumPromoUpdated) { + premiumButtonView.buttonTextView.setText(getPremiumButtonText(currentAccount)); + } + if (id == NotificationCenter.currentUserPremiumStatusChanged || id == NotificationCenter.premiumPromoUpdated) { + backgroundView.updateText(); + updateRows(); + listView.getAdapter().notifyDataSetChanged(); + } + } + + private class Adapter extends RecyclerListView.SelectionAdapter { + private final static int TYPE_PADDING = 0, + TYPE_FEATURE = 1, + TYPE_SHADOW_SECTION = 2, + TYPE_BUTTON = 3, + TYPE_HELP_US = 4, + TYPE_STATUS_TEXT = 5, + TYPE_BOTTOM_PADDING = 6; + + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + Context context = parent.getContext(); + switch (viewType) { + default: + case TYPE_PADDING: + view = new View(context) { + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + if (isLandscapeMode) { + firstViewHeight = statusBarHeight + actionBar.getMeasuredHeight() - AndroidUtilities.dp(16); + } else { + int h = AndroidUtilities.dp(300) + statusBarHeight; + if (backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24) > h) { + h = backgroundView.getMeasuredHeight() + AndroidUtilities.dp(24); + } + firstViewHeight = h; + } + super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(firstViewHeight, MeasureSpec.EXACTLY)); + } + }; + break; + case TYPE_STATUS_TEXT: + view = new TextInfoPrivacyCell(context); + break; + case TYPE_FEATURE: + view = new PremiumFeatureCell(context) { + @Override + protected void dispatchDraw(Canvas canvas) { + AndroidUtilities.rectTmp.set(imageView.getLeft(), imageView.getTop(), imageView.getRight(), imageView.getBottom()); + matrix.reset(); + matrix.postScale(1f, totalGradientHeight / 100f, 0, 0); + matrix.postTranslate(0, -data.yOffset); + shader.setLocalMatrix(matrix); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(8), AndroidUtilities.dp(8), gradientPaint); + super.dispatchDraw(canvas); + } + }; + break; + case TYPE_SHADOW_SECTION: + ShadowSectionCell shadowSectionCell = new ShadowSectionCell(context, 12, Theme.getColor(Theme.key_windowBackgroundGray)); + Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.getColor(Theme.key_windowBackgroundGrayShadow)); + Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + shadowSectionCell.setBackgroundDrawable(combinedDrawable); + view = shadowSectionCell; + break; + case TYPE_HELP_US: + view = new AboutPremiumView(context); + break; + case TYPE_BOTTOM_PADDING: + view = new View(context); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + 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) { + if (position >= featuresStartRow && position < featuresEndRow) { + ((PremiumFeatureCell) holder.itemView).setData(premiumFeatures.get(position - featuresStartRow), position != featuresEndRow - 1); + } else if (position == statusRow || position == privacyRow) { + TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; + + Drawable shadowDrawable = Theme.getThemedDrawable(privacyCell.getContext(), R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow)); + Drawable background = new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + privacyCell.setBackground(combinedDrawable); + + if (position == statusRow) { + TLRPC.TL_help_premiumPromo premiumPromo = getMediaDataController().getPremiumPromo(); + if (premiumPromo == null) { + return; + } + + SpannableString spannableString = new SpannableString(premiumPromo.status_text); + MediaDataController.addTextStyleRuns(premiumPromo.status_entities, premiumPromo.status_text, spannableString); + byte t = 0; + for (TextStyleSpan span : spannableString.getSpans(0, spannableString.length(), TextStyleSpan.class)) { + TextStyleSpan.TextStyleRun run = span.getTextStyleRun(); + boolean setRun = false; + String url = run.urlEntity != null ? TextUtils.substring(premiumPromo.status_text, run.urlEntity.offset, run.urlEntity.offset + run.urlEntity.length) : null; + if (run.urlEntity instanceof TLRPC.TL_messageEntityBotCommand) { + spannableString.setSpan(new URLSpanBotCommand(url, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityHashtag || run.urlEntity instanceof TLRPC.TL_messageEntityMention || run.urlEntity instanceof TLRPC.TL_messageEntityCashtag) { + spannableString.setSpan(new URLSpanNoUnderline(url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityEmail) { + spannableString.setSpan(new URLSpanReplacement("mailto:" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityUrl) { + String lowerCase = url.toLowerCase(); + if (!lowerCase.contains("://")) { + spannableString.setSpan(new URLSpanBrowser("http://" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + spannableString.setSpan(new URLSpanBrowser(url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityBankCard) { + spannableString.setSpan(new URLSpanNoUnderline("card:" + url, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityPhone) { + String tel = PhoneFormat.stripExceptNumbers(url); + if (url.startsWith("+")) { + tel = "+" + tel; + } + spannableString.setSpan(new URLSpanBrowser("tel:" + tel, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityTextUrl) { + URLSpanReplacement spanReplacement = new URLSpanReplacement(run.urlEntity.url, run); + spanReplacement.setNavigateToPremiumBot(true); + spannableString.setSpan(spanReplacement, run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_messageEntityMentionName) { + spannableString.setSpan(new URLSpanUserMention("" + ((TLRPC.TL_messageEntityMentionName) run.urlEntity).user_id, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if (run.urlEntity instanceof TLRPC.TL_inputMessageEntityMentionName) { + spannableString.setSpan(new URLSpanUserMention("" + ((TLRPC.TL_inputMessageEntityMentionName) run.urlEntity).user_id.user_id, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else if ((run.flags & TextStyleSpan.FLAG_STYLE_MONO) != 0) { + spannableString.setSpan(new URLSpanMono(spannableString, run.start, run.end, t, run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } else { + setRun = true; + spannableString.setSpan(new TextStyleSpan(run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (!setRun && (run.flags & TextStyleSpan.FLAG_STYLE_SPOILER) != 0) { + spannableString.setSpan(new TextStyleSpan(run), run.start, run.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + } + privacyCell.setText(spannableString); + } + } + } + + @Override + public int getItemCount() { + return rowCount; + } + + @Override + public int getItemViewType(int position) { + if (position == paddingRow) { + return TYPE_PADDING; + } else if (position >= featuresStartRow && position < featuresEndRow) { + return TYPE_FEATURE; + } else if (position == sectionRow) { + return TYPE_SHADOW_SECTION; + } else if (position == helpUsRow) { + return TYPE_HELP_US; + } else if (position == statusRow || position == privacyRow) { + return TYPE_STATUS_TEXT; + } else if (position == lastPaddingRow) { + return TYPE_BOTTOM_PADDING; + } + return TYPE_PADDING; + } + + @Override + public boolean isEnabled(RecyclerView.ViewHolder holder) { + return holder.getItemViewType() == TYPE_FEATURE; + } + } + + public static class PremiumFeatureData { + public final int type; + public final int icon; + public final String title; + public final String description; + public int yOffset; + + public PremiumFeatureData(int type, int icon, String title, String description) { + this.type = type; + this.icon = icon; + this.title = title; + this.description = description; + } + } + + FrameLayout settingsView; + + private class BackgroundView extends LinearLayout { + + TextView titleView; + private final TextView subtitleView; + private final GLIconTextureView imageView; + + public BackgroundView(Context context) { + super(context); + setOrientation(VERTICAL); + imageView = new GLIconTextureView(context, GLIconRenderer.FRAGMENT_STYLE) { + @Override + public void onLongPress() { + super.onLongPress(); + if (settingsView != null && !BuildVars.DEBUG_PRIVATE_VERSION) { + return; + } + + settingsView = new FrameLayout(context); + ScrollView scrollView = new ScrollView(context); + + LinearLayout linearLayout = new GLIconSettingsView(context, imageView.mRenderer); + scrollView.addView(linearLayout); + settingsView.addView(scrollView); + settingsView.setBackgroundColor(Theme.getColor(Theme.key_dialogBackground)); + contentView.addView(settingsView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.BOTTOM)); + ((MarginLayoutParams) settingsView.getLayoutParams()).topMargin = currentYOffset; + + settingsView.setTranslationY(AndroidUtilities.dp(1000)); + settingsView.animate().translationY(1).setDuration(300); + } + }; + addView(imageView, LayoutHelper.createLinear(190, 190, Gravity.CENTER_HORIZONTAL)); + + titleView = new TextView(context); + titleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 22); + titleView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + titleView.setGravity(Gravity.CENTER_HORIZONTAL); + addView(titleView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, 0, Gravity.CENTER_HORIZONTAL, 16, 20, 16, 0)); + + subtitleView = new TextView(context); + subtitleView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitleView.setLineSpacing(AndroidUtilities.dp(2), 1f); + subtitleView.setGravity(Gravity.CENTER_HORIZONTAL); + addView(subtitleView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 16, 7, 16, 0)); + + updateText(); + } + + public void updateText() { + titleView.setText(LocaleController.getString(forcePremium ? R.string.TelegramPremiumSubscribedTitle : R.string.TelegramPremium)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(getUserConfig().isPremium() || forcePremium ? R.string.TelegramPremiumSubscribedSubtitle : R.string.TelegramPremiumSubtitle))); + } + } + + @Override + public boolean isLightStatusBar() { + return false; + } + + @Override + public void onResume() { + super.onResume(); + backgroundView.imageView.setPaused(false); + backgroundView.imageView.setDialogVisible(false); + particlesView.setPaused(false); + } + + @Override + public void onPause() { + super.onPause(); + backgroundView.imageView.setDialogVisible(true); + particlesView.setPaused(true); + } + + @Override + public boolean canBeginSlide() { + return !backgroundView.imageView.touched; + } + + @Override + public ArrayList getThemeDescriptions() { + return SimpleThemeDescription.createThemeDescriptions(this::updateColors, + Theme.key_premiumGradient1, Theme.key_premiumGradient2, Theme.key_premiumGradient3, Theme.key_premiumGradient4, + Theme.key_premiumGradientBackground1, Theme.key_premiumGradientBackground2, Theme.key_premiumGradientBackground3, Theme.key_premiumGradientBackground4, + Theme.key_premiumGradientBackgroundOverlay, Theme.key_premiumStartGradient1, Theme.key_premiumStartGradient2, Theme.key_premiumStartSmallStarsColor, Theme.key_premiumStartSmallStarsColor2 + ); + } + + private void updateColors() { + if (backgroundView == null || actionBar == null) { + return; + } + actionBar.setItemsColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), false); + actionBar.setItemsBackgroundColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay), 60), false); + backgroundView.titleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); + backgroundView.subtitleView.setTextColor(Theme.getColor(Theme.key_premiumGradientBackgroundOverlay)); + particlesView.drawable.updateColors(); + if (backgroundView.imageView.mRenderer != null) { + backgroundView.imageView.mRenderer.updateColors(); + } + updateBackgroundImage(); + } + + @Override + public boolean onBackPressed() { + if (settingsView != null) { + closeSetting(); + return false; + } + return super.onBackPressed(); + } + + private void closeSetting() { + settingsView.animate().translationY(AndroidUtilities.dp(1000)).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + contentView.removeView(settingsView); + settingsView = null; + super.onAnimationEnd(animation); + } + }); + } + + @Override + public Dialog showDialog(Dialog dialog) { + Dialog d = super.showDialog(dialog); + updateDialogVisibility(d != null); + return d; + } + + @Override + protected void onDialogDismiss(Dialog dialog) { + super.onDialogDismiss(dialog); + updateDialogVisibility(false); + } + + private void updateDialogVisibility(boolean isVisible) { + if (isVisible != isDialogVisible) { + isDialogVisible = isVisible; + backgroundView.imageView.setDialogVisible(isVisible); + particlesView.setPaused(isVisible); + contentView.invalidate(); + } + } + + private void sentShowScreenStat() { + if (source == null) { + return; + } + sentShowScreenStat(source); + source = null; + } + + public static void sentShowScreenStat(String source) { + ConnectionsManager connectionsManager = ConnectionsManager.getInstance(UserConfig.selectedAccount); + TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog(); + TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent(); + event.time = connectionsManager.getCurrentTime(); + event.type = "premium.promo_screen_show"; + TLRPC.TL_jsonObject data = new TLRPC.TL_jsonObject(); + event.data = data; + + TLRPC.TL_jsonObjectValue sourceObj = new TLRPC.TL_jsonObjectValue(); + TLRPC.TL_jsonString jsonString = new TLRPC.TL_jsonString(); + jsonString.value = source; + + sourceObj.key = "source"; + sourceObj.value = jsonString; + + data.value.add(sourceObj); + req.events.add(event); + + connectionsManager.sendRequest(req, (response, error) -> { + + }); + } + + public static void sentPremiumButtonClick() { + TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog(); + TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent(); + event.time = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime(); + event.type = "premium.promo_screen_accept"; + event.data = new TLRPC.TL_jsonNull(); + req.events.add(event); + + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { + + }); + } + + public static void sentPremiumBuyCanceled() { + TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog(); + TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent(); + event.time = ConnectionsManager.getInstance(UserConfig.selectedAccount).getCurrentTime(); + event.type = "premium.promo_screen_fail"; + event.data = new TLRPC.TL_jsonNull(); + req.events.add(event); + + ConnectionsManager.getInstance(UserConfig.selectedAccount).sendRequest(req, (response, error) -> { + + }); + } + + public static void sentShowFeaturePreview(int currentAccount, int type) { + TLRPC.TL_help_saveAppLog req = new TLRPC.TL_help_saveAppLog(); + TLRPC.TL_inputAppEvent event = new TLRPC.TL_inputAppEvent(); + event.time = ConnectionsManager.getInstance(currentAccount).getCurrentTime(); + event.type = "premium.promo_screen_tap"; + TLRPC.TL_jsonObject data = new TLRPC.TL_jsonObject(); + event.data = data; + TLRPC.TL_jsonObjectValue item = new TLRPC.TL_jsonObjectValue(); + TLRPC.TL_jsonString jsonString = new TLRPC.TL_jsonString(); + jsonString.value = PremiumPreviewFragment.featureTypeToServerString(type); + item.key = "item"; + item.value = jsonString; + data.value.add(item); + req.events.add(event); + event.data = data; + + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { + + }); + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java index 7f9b6e183..b77d8ed10 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyControlActivity.java @@ -59,6 +59,7 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.BackgroundGradientDrawable; +import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.HintView; @@ -337,7 +338,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification }); ActionBarMenu menu = actionBar.createMenu(); - doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); + doneButton = menu.addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56), LocaleController.getString("Done", R.string.Done)); boolean hasChanges = hasChanges(); doneButton.setAlpha(hasChanges ? 1.0f : 0.0f); doneButton.setScaleX(hasChanges ? 1.0f : 0.0f); @@ -1020,9 +1021,7 @@ public class PrivacyControlActivity extends BaseFragment implements Notification android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); android.content.ClipData clip = android.content.ClipData.newPlainText("label", phoneLinkStr); clipboard.setPrimaryClip(clip); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { - BulletinFactory.of(PrivacyControlActivity.this).createCopyBulletin(LocaleController.getString("PhoneCopied", R.string.PhoneCopied)).show(); - } + BulletinFactory.of(PrivacyControlActivity.this).createCopyLinkBulletin(LocaleController.getString("LinkCopied", R.string.LinkCopied), getResourceProvider()).show(); } }, 0, phoneLinkStr.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index b31c7a428..1e797c043 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -523,7 +523,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio passwordRow = rowCount++; sessionsRow = rowCount++; sessionsDetailRow = rowCount++; - if (getMessagesController().autoarchiveAvailable) { + if (getMessagesController().autoarchiveAvailable || getUserConfig().isPremium()) { newChatsHeaderRow = rowCount++; newChatsRow = rowCount++; newChatsSectionRow = rowCount++; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java index 8cd5e3246..3f9effe58 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacyUsersActivity.java @@ -16,16 +16,21 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.DialogObject; import org.telegram.messenger.LocaleController; -import org.telegram.tgnet.TLRPC; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.ui.ActionBar.ActionBarMenu; import org.telegram.ui.ActionBar.ActionBarMenuItem; +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.HeaderCell; @@ -33,17 +38,12 @@ import org.telegram.ui.Cells.ManageChatTextCell; import org.telegram.ui.Cells.ManageChatUserCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; -import org.telegram.ui.ActionBar.ActionBar; -import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import java.util.ArrayList; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - public class PrivacyUsersActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, ContactsActivity.ContactsActivityDelegate { private RecyclerListView listView; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 28db68eaf..176f9737d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -8,6 +8,8 @@ package org.telegram.ui; +import static org.telegram.messenger.ContactsController.PRIVACY_RULES_TYPE_ADDED_BY_PHONE; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -45,6 +47,7 @@ import android.text.Spanned; import android.text.TextPaint; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; +import android.text.util.Linkify; import android.util.Property; import android.util.SparseIntArray; import android.util.TypedValue; @@ -61,7 +64,6 @@ import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.view.inputmethod.EditorInfo; import android.webkit.WebStorage; -import android.webkit.WebView; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ImageView; @@ -98,6 +100,7 @@ import org.telegram.messenger.ChatObject; import org.telegram.messenger.ChatThemeController; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; +import org.telegram.messenger.Emoji; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.ImageLoader; @@ -165,6 +168,9 @@ import org.telegram.ui.Components.HintView; import org.telegram.ui.Components.IdenticonDrawable; import org.telegram.ui.Components.ImageUpdater; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumGradient; +import org.telegram.ui.Components.Premium.PremiumPreviewBottomSheet; +import org.telegram.ui.Components.Premium.ProfilePremiumCell; import org.telegram.ui.Components.ProfileGalleryView; import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RLottieImageView; @@ -217,6 +223,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private ListAdapter listAdapter; private SearchAdapter searchAdapter; private SimpleTextView[] nameTextView = new SimpleTextView[2]; + private String nameTextViewRightDrawableContentDescription = null; private SimpleTextView[] onlineTextView = new SimpleTextView[2]; private AudioPlayerAlert.ClippingTextViewSwitcher mediaCounterTextView; private SimpleTextView idTextView; @@ -225,8 +232,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. // private AnimatorSet qrItemAnimation; private Drawable lockIconDrawable; private Drawable verifiedDrawable; + private Drawable premiumStarDrawable; private Drawable verifiedCheckDrawable; private CrossfadeDrawable verifiedCrossfadeDrawable; + private CrossfadeDrawable premuimCrossfadeDrawable; private ScamDrawable scamDrawable; private UndoView undoView; private OverlaysView overlaysView; @@ -264,6 +273,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }; private Paint actionBarBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private ActionBarPopupWindow scrimPopupWindow; + private Theme.ResourcesProvider resourcesProvider; private int overlayCountVisible; @@ -356,7 +366,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private TLRPC.ChatFull chatInfo; private TLRPC.UserFull userInfo; - private String currentBio; + private CharSequence currentBio; private long selectedUser; private int onlineCount = -1; @@ -455,6 +465,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private int reportRow; private int addToGroupButtonRow; private int addToGroupInfoRow; + private int premiumRow; + private int premiumSectionsRow; private int settingsTimerRow; private int settingsKeyRow; @@ -485,7 +497,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private boolean firstLayout = true; private boolean invalidateScroll = true; - private boolean isQrItemVisible; + private boolean isQrItemVisible = true; PinchToZoomHelper pinchToZoomHelper; @@ -718,7 +730,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. canvas.drawRect(0, 0, getMeasuredWidth(), y1, paint); } if (y1 != v) { - int color = Theme.getColor(Theme.key_windowBackgroundWhite); + int color = getThemedColor(Theme.key_windowBackgroundWhite); paint.setColor(color); AndroidUtilities.rectTmp2.set(0, y1, getMeasuredWidth(), (int) v); contentView.drawBlurRect(canvas, getY(), AndroidUtilities.rectTmp2, paint, true); @@ -1418,6 +1430,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().addObserver(this, NotificationCenter.blockedUsersDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.botInfoDidLoad); getNotificationCenter().addObserver(this, NotificationCenter.userInfoDidLoad); + getNotificationCenter().addObserver(this, NotificationCenter.privacyRulesUpdated); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.reloadInterface); userBlocked = getMessagesController().blockePeers.indexOfKey(userId) >= 0; @@ -1553,6 +1566,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getNotificationCenter().removeObserver(this, NotificationCenter.blockedUsersDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.botInfoDidLoad); getNotificationCenter().removeObserver(this, NotificationCenter.userInfoDidLoad); + getNotificationCenter().removeObserver(this, NotificationCenter.privacyRulesUpdated); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.reloadInterface); getMessagesController().cancelLoadFullUser(userId); } else if (chatId != 0) { @@ -1573,8 +1587,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override protected ActionBar createActionBar(Context context) { - ActionBar actionBar = new ActionBar(context) { - + BaseFragment lastFragment = parentLayout.getLastFragment(); + if (lastFragment instanceof ChatActivity && ((ChatActivity) lastFragment).themeDelegate != null && ((ChatActivity) lastFragment).themeDelegate.getCurrentTheme() != null) { + resourcesProvider = lastFragment.getResourceProvider(); + } + ActionBar actionBar = new ActionBar(context, resourcesProvider) { @Override public boolean onTouchEvent(MotionEvent event) { avatarContainer.getHitRect(rect); @@ -1592,9 +1609,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } }; + actionBar.setForceSkipTouches(true); actionBar.setBackgroundColor(Color.TRANSPARENT); - actionBar.setItemsBackgroundColor(AvatarDrawable.getButtonColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId), false); - actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon), false); + actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_avatar_actionBarSelectorBlue), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), false); actionBar.setBackButtonDrawable(new BackDrawable(false)); actionBar.setCastShadows(false); actionBar.setAddToContainer(false); @@ -1602,7 +1620,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. actionBar.setOccupyStatusBar(Build.VERSION.SDK_INT >= 21 && !AndroidUtilities.isTablet() && !inBubbleMode); ImageView backButton = actionBar.getBackButton(); backButton.setOnLongClickListener(e -> { - ActionBarPopupWindow menu = BackButtonMenu.show(this, backButton, getDialogId()); + ActionBarPopupWindow menu = BackButtonMenu.show(this, backButton, getDialogId(), resourcesProvider); if (menu != null) { menu.setOnDismissListener(() -> dimBehindView(false)); dimBehindView(backButton, 0.3f); @@ -1621,7 +1639,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public View createView(Context context) { Theme.createProfileResources(context); Theme.createChatResources(context, false); - + BaseFragment lastFragment = parentLayout.getLastFragment(); + if (lastFragment instanceof ChatActivity && ((ChatActivity) lastFragment).themeDelegate != null && ((ChatActivity) lastFragment).themeDelegate.getCurrentTheme() != null) { + resourcesProvider = lastFragment.getResourceProvider(); + } searchTransitionOffset = 0; searchTransitionProgress = 1f; searchMode = false; @@ -1657,9 +1678,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { getNotificationCenter().postNotificationName(NotificationCenter.peerSettingsDidLoad, userId); } - }, null); + }, resourcesProvider); } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("BlockUser", R.string.BlockUser)); builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureBlockContact2", R.string.AreYouSureBlockContact2, ContactsController.formatName(user.first_name, user.last_name)))); builder.setPositiveButton(LocaleController.getString("BlockContact", R.string.BlockContact), (dialogInterface, i) -> { @@ -1673,7 +1694,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + button.setTextColor(getThemedColor(Theme.key_dialogTextRed2)); } } } @@ -1691,7 +1712,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Bundle args = new Bundle(); args.putLong("user_id", user.id); args.putBoolean("addContact", true); - presentFragment(new ContactAddActivity(args)); + presentFragment(new ContactAddActivity(args, resourcesProvider)); } else if (id == share_contact) { Bundle args = new Bundle(); args.putBoolean("onlySelect", true); @@ -1704,13 +1725,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (id == edit_contact) { Bundle args = new Bundle(); args.putLong("user_id", userId); - presentFragment(new ContactAddActivity(args)); + presentFragment(new ContactAddActivity(args, resourcesProvider)); } else if (id == delete_contact) { final TLRPC.User user = getMessagesController().getUser(userId); if (user == null || getParentActivity() == null) { return; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("DeleteContact", R.string.DeleteContact)); builder.setMessage(LocaleController.getString("AreYouSureDeleteContact", R.string.AreYouSureDeleteContact)); builder.setPositiveButton(LocaleController.getString("Delete", R.string.Delete), (dialogInterface, i) -> { @@ -1723,7 +1744,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. showDialog(dialog); TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + button.setTextColor(getThemedColor(Theme.key_dialogTextRed2)); } } else if (id == leave_group) { leaveChatPressed(); @@ -1766,12 +1787,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } @Override - public void didChangeOwner(TLRPC.User user) {} + public void didChangeOwner(TLRPC.User user) { + } }); presentFragment(editRightsActivity); })); } else { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("AddBot", R.string.AddBot)); String chatName = chat == null ? "" : chat.title; builder.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("AddMembersAlertNamesText", R.string.AddMembersAlertNamesText, UserObject.getUserName(user), chatName))); @@ -1890,7 +1912,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (id == view_discussion) { openDiscussion(); } else if (id == start_secret_chat) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("AreYouSureSecretChatTitle", R.string.AreYouSureSecretChatTitle)); builder.setMessage(LocaleController.getString("AreYouSureSecretChat", R.string.AreYouSureSecretChat)); builder.setPositiveButton(LocaleController.getString("Start", R.string.Start), (dialogInterface, i) -> { @@ -1912,7 +1934,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return; } final boolean isVideo = location.imageType == FileLoader.IMAGE_TYPE_ANIMATION; - File f = FileLoader.getPathToAttach(location.location, isVideo ? "mp4" : null, true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(location.location, isVideo ? "mp4" : null, true); if (f.exists()) { MediaController.saveFile(f.toString(), getParentActivity(), 0, null, null, () -> { if (getParentActivity() == null) { @@ -1921,6 +1943,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. BulletinFactory.createSaveToGalleryBulletin(ProfileActivity.this, isVideo, null).show(); }); } + } else if (id == edit_name) { + presentFragment(new ChangeNameActivity(resourcesProvider)); } else if (id == logout) { presentFragment(new LogoutActivity()); } else if (id == set_as_main) { @@ -1975,18 +1999,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return; } - File f = FileLoader.getPathToAttach(PhotoViewer.getFileLocation(location), PhotoViewer.getFileLocationExt(location), true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(PhotoViewer.getFileLocation(location), PhotoViewer.getFileLocationExt(location), true); boolean isVideo = location.imageType == FileLoader.IMAGE_TYPE_ANIMATION; String thumb; if (isVideo) { ImageLocation imageLocation = avatarsViewPager.getRealImageLocation(position); - thumb = FileLoader.getPathToAttach(PhotoViewer.getFileLocation(imageLocation), PhotoViewer.getFileLocationExt(imageLocation), true).getAbsolutePath(); + thumb = FileLoader.getInstance(currentAccount).getPathToAttach(PhotoViewer.getFileLocation(imageLocation), PhotoViewer.getFileLocationExt(imageLocation), true).getAbsolutePath(); } else { thumb = null; } imageUpdater.openPhotoForEdit(f.getAbsolutePath(), thumb, 0, isVideo); } else if (id == delete_avatar) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); ImageLocation location = avatarsViewPager.getImageLocation(avatarsViewPager.getRealPosition()); if (location == null) { return; @@ -2033,16 +2057,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. showDialog(alertDialog); TextView button = (TextView) alertDialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { - button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + button.setTextColor(getThemedColor(Theme.key_dialogTextRed2)); } } else if (id == add_photo) { onWriteButtonClick(); - } /*else if (id == qr_button) { - Bundle args = new Bundle(); - args.putLong("chat_id", chatId); - args.putLong("user_id", userId); - presentFragment(new QrActivity(args)); - }*/ + } else if (id == qr_button) { +// if (qrItem != null && qrItem.getAlpha() > 0) { +// Bundle args = new Bundle(); +// args.putLong("chat_id", chatId); +// args.putLong("user_id", userId); +// presentFragment(new QrActivity(args)); +// } + } } }); @@ -2086,13 +2112,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int actionBarHeight = ActionBar.getCurrentActionBarHeight() + (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0); if (listView != null) { - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams(); + LayoutParams layoutParams = (LayoutParams) listView.getLayoutParams(); if (layoutParams.topMargin != actionBarHeight) { layoutParams.topMargin = actionBarHeight; } } if (searchListView != null) { - FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) searchListView.getLayoutParams(); + LayoutParams layoutParams = (LayoutParams) searchListView.getLayoutParams(); if (layoutParams.topMargin != actionBarHeight) { layoutParams.topMargin = actionBarHeight; } @@ -2154,7 +2180,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. allowPullingDown = true; isPulledDown = true; - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); /*if (otherItem != null) { if (!getMessagesController().isChatNoForwards(currentChat)) { otherItem.showSubItem(gallery_menu_save); @@ -2290,9 +2316,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override protected void dispatchDraw(Canvas canvas) { - whitePaint.setColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + whitePaint.setColor(getThemedColor(Theme.key_windowBackgroundWhite)); if (listView.getVisibility() == VISIBLE) { - grayPaint.setColor(Theme.getColor(Theme.key_windowBackgroundGray)); + grayPaint.setColor(getThemedColor(Theme.key_windowBackgroundGray)); if (transitionAnimationInProress) { whitePaint.setAlpha((int) (255 * listView.getAlpha())); } @@ -2396,7 +2422,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. int r = Math.max(scrimView.getMeasuredWidth(), scrimView.getMeasuredHeight()) / 2; int wasAlpha = actionBarBackgroundPaint.getAlpha(); actionBarBackgroundPaint.setAlpha((int) (wasAlpha * (scrimPaint.getAlpha() / 255f) / 0.3f)); - canvas.drawCircle(r, r, r * 0.8f, actionBarBackgroundPaint); + canvas.drawCircle(r, r, r * 0.7f, actionBarBackgroundPaint); actionBarBackgroundPaint.setAlpha(wasAlpha); } scrimView.draw(canvas); @@ -2414,7 +2440,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }; ArrayList users = chatInfo != null && chatInfo.participants != null && chatInfo.participants.participants.size() > 5 ? sortedUsers : null; - sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, users != null, this, this, SharedMediaLayout.VIEW_TYPE_PROFILE_ACTIVITY) { + sharedMediaLayout = new SharedMediaLayout(context, did, sharedMediaPreloader, userInfo != null ? userInfo.common_chats_count : 0, sortedUsers, chatInfo, users != null, this, this, SharedMediaLayout.VIEW_TYPE_PROFILE_ACTIVITY, resourcesProvider) { @Override protected void onSelectedTabChanged() { updateSelectedMediaTabText(); @@ -2466,6 +2492,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ActionBarMenu menu = actionBar.createMenu(); +// if (userId == getUserConfig().clientUserId) { +// qrItem = menu.addItem(qr_button, R.drawable.msg_qr_mini, getResourceProvider()); +// qrItem.setContentDescription(LocaleController.getString("GetQRCode", R.string.GetQRCode)); +// updateQrItemVisibility(false); +// if (ContactsController.getInstance(currentAccount).getPrivacyRules(PRIVACY_RULES_TYPE_ADDED_BY_PHONE) == null) { +// ContactsController.getInstance(currentAccount).loadPrivacySettings(); +// } +// } + if (imageUpdater != null) { searchItem = menu.addItem(search_button, R.drawable.ic_ab_search).setIsSearchField(true).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() { @@ -2509,9 +2544,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } editItem = menu.addItem(edit_channel, R.drawable.group_edit_profile); editItem.setContentDescription(LocaleController.getString("Edit", R.string.Edit)); - otherItem = menu.addItem(10, R.drawable.ic_ab_other); + otherItem = menu.addItem(10, R.drawable.ic_ab_other, resourcesProvider); ttlIconView = new ImageView(context); - ttlIconView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); + ttlIconView.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_actionBarDefaultIcon), PorterDuff.Mode.MULTIPLY)); AndroidUtilities.updateViewVisibilityAnimated(ttlIconView, false, 0.8f, false); ttlIconView.setImageResource(R.drawable.msg_mini_autodelete_timer); otherItem.addView(ttlIconView, LayoutHelper.createFrame(12, 12, Gravity.CENTER_VERTICAL | Gravity.LEFT, 8, 2, 0, 0)); @@ -2705,7 +2740,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. final int canScroll = view.getTop() - AndroidUtilities.dp(88); if (!allowPullingDown && canScroll > dy) { dy = canScroll; - if (avatarsViewPager.hasImages() && avatarImage.getImageReceiver().hasNotThumb() && !isInLandscapeMode && !AndroidUtilities.isTablet()) { + if (avatarsViewPager.hasImages() && avatarImage.getImageReceiver().hasNotThumb() && !AndroidUtilities.isAccessibilityScreenReaderEnabled() && !isInLandscapeMode && !AndroidUtilities.isTablet()) { allowPullingDown = avatarBig == null; } } else if (allowPullingDown) { @@ -2738,7 +2773,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. args.putInt("chat_id", DialogObject.getEncryptedChatId(dialogId)); presentFragment(new IdenticonActivity(args)); } else if (position == settingsTimerRow) { - showDialog(AlertsCreator.createTTLAlert(getParentActivity(), currentEncryptedChat, null).create()); + showDialog(AlertsCreator.createTTLAlert(getParentActivity(), currentEncryptedChat, resourcesProvider).create()); } else if (position == notificationsRow) { if (LocaleController.isRTL && x <= AndroidUtilities.dp(76) || !LocaleController.isRTL && x >= view.getMeasuredWidth() - AndroidUtilities.dp(76)) { NotificationsCheckCell checkCell = (NotificationsCheckCell) view; @@ -2792,11 +2827,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return; } ChatNotificationsPopupWrapper chatNotificationsPopupWrapper = new ChatNotificationsPopupWrapper(context, currentAccount, null, true, true, new ChatNotificationsPopupWrapper.Callback() { - @Override - public void dismiss() { - - } - @Override public void toggleSound() { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); @@ -2832,7 +2862,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (did != 0) { Bundle args = new Bundle(); args.putLong("dialog_id", did); - presentFragment(new ProfileNotificationsActivity(args)); + presentFragment(new ProfileNotificationsActivity(args, resourcesProvider)); } } @@ -2840,7 +2870,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public void toggleMute() { boolean muted = getMessagesController().isDialogMuted(did); getNotificationsController().muteDialog(did, !muted); - BulletinFactory.createMuteBulletin(ProfileActivity.this, getMessagesController().isDialogMuted(dialogId), null).show(); + BulletinFactory.createMuteBulletin(ProfileActivity.this, !muted, null).show(); if (notificationsRow >= 0) { listAdapter.notifyItemChanged(notificationsRow); } @@ -2862,7 +2892,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == sendMessageRow) { onWriteButtonClick(); } else if (position == reportRow) { - AlertsCreator.createReportAlert(getParentActivity(), getDialogId(), 0, ProfileActivity.this, null); + AlertsCreator.createReportAlert(getParentActivity(), getDialogId(), 0, ProfileActivity.this, resourcesProvider, null); } else if (position >= membersStartRow && position < membersEndRow) { TLRPC.ChatParticipant participant; if (!sortedUsers.isEmpty()) { @@ -2874,56 +2904,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == addMemberRow) { openAddMember(); } else if (position == usernameRow) { - - final String username; - if (userId != 0) { - final TLRPC.User user = getMessagesController().getUser(userId); - if (user == null || user.username == null) { - return; - } - username = user.username; - } else if (chatId != 0) { - final TLRPC.Chat chat = getMessagesController().getChat(chatId); - if (chat == null || chat.username == null) { - return; - } - username = chat.username; - } else { - return; - } - - BottomBuilder builder = new BottomBuilder(getParentActivity()); - builder.addTitle("@" + username); - - builder.addItem(LocaleController.getString("QrCode", R.string.QrCode), R.drawable.wallet_qr, __ -> { - Bundle args = new Bundle(); - args.putLong("chat_id", chatId); - args.putLong("user_id", userId); - presentFragment(new QrActivity(args)); - return Unit.INSTANCE; - }); - - if (chatInfo != null && chatInfo.can_set_username) { - builder.addItem(LocaleController.getString("Edit", R.string.Edit), R.drawable.baseline_edit_24, __ -> { - ChatEditTypeActivity fragment = new ChatEditTypeActivity(chatId, chatInfo.can_set_location); - fragment.setInfo(chatInfo); - presentFragment(fragment); - return Unit.INSTANCE; - }); - } - - builder.addItem(LocaleController.getString("Copy", R.string.Copy), R.drawable.baseline_content_copy_24, __ -> { - AlertUtil.copyAndAlert("@" + username); - return Unit.INSTANCE; - }); - - builder.addItem(LocaleController.getString("CopyLink", R.string.CopyLink), R.drawable.baseline_link_24, __ -> { - AlertUtil.copyAndAlert("https://t.me/" + username); - return Unit.INSTANCE; - }); - - builder.show(); - + processOnClickOrPress(position, view); } else if (position == locationRow) { if (chatInfo.location instanceof TLRPC.TL_channelLocation) { LocationActivity fragment = new LocationActivity(LocationActivity.LOCATION_TYPE_GROUP_VIEW); @@ -2966,6 +2947,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE)); } else if (position == filtersRow) { presentFragment(new FiltersSetupActivity()); + } else if (position == stickersRow) { + presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE)); } else if (position == devicesRow) { presentFragment(new SessionsActivity(0)); } else if (position == nekoRow) { @@ -2990,7 +2973,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (getParentActivity() == null) { return; } - AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder1 = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder1.setMessage(LocaleController.getString("AreYouSure", R.string.AreYouSure)); builder1.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder1.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialogInterface, i) -> { @@ -3251,6 +3234,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); } builder.show(); + } else if (position == premiumRow) { + presentFragment(new PremiumPreviewFragment("settings")); } else { ProfileActivity.this.processOnClickOrPress(position, view); } @@ -3265,7 +3250,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (position == versionRow) { pressCount++; if (pressCount >= 2 || BuildVars.DEBUG_PRIVATE_VERSION) { - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("DebugMenu", R.string.DebugMenu)); CharSequence[] items; items = new CharSequence[]{ @@ -3291,7 +3276,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. "Reset all notification channels", BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(SharedConfig.forceRtmpStream ? R.string.DebugMenuDisableForceRtmpStreamFlag : R.string.DebugMenuEnableForceRtmpStreamFlag) : null, BuildVars.DEBUG_PRIVATE_VERSION ? LocaleController.getString(R.string.DebugMenuClearWebViewCache) : null, - Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? LocaleController.getString(R.string.DebugMenuEnableWebViewDebug) : null + Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? LocaleController.getString(SharedConfig.debugWebView ? R.string.DebugMenuDisableWebViewDebug : R.string.DebugMenuEnableWebViewDebug) : null }; builder.setItems(items, (dialog, which) -> { if (which == 0) { @@ -3398,10 +3383,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ApplicationLoader.applicationContext.deleteDatabase("webviewCache.db"); WebStorage.getInstance().deleteAllData(); } else if (which == 19) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - WebView.setWebContentsDebuggingEnabled(true); - Toast.makeText(getParentActivity(), LocaleController.getString(R.string.DebugMenuWebViewDebugEnabled), Toast.LENGTH_SHORT).show(); - } + SharedConfig.toggleDebugWebView(); + Toast.makeText(getParentActivity(), LocaleController.getString(SharedConfig.debugWebView ? R.string.DebugMenuWebViewDebugEnabled : R.string.DebugMenuWebViewDebugDisabled), Toast.LENGTH_SHORT).show(); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -3432,12 +3415,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. searchListView = new RecyclerListView(context); searchListView.setVerticalScrollBarEnabled(false); searchListView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); - searchListView.setGlowColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue)); + searchListView.setGlowColor(getThemedColor(Theme.key_avatar_backgroundActionBarBlue)); searchListView.setAdapter(searchAdapter); searchListView.setItemAnimator(null); searchListView.setVisibility(View.GONE); searchListView.setLayoutAnimation(null); - searchListView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + searchListView.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); frameLayout.addView(searchListView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); searchListView.setOnItemClickListener((view, position) -> { if (position < 0) { @@ -3483,7 +3466,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (searchAdapter.isSearchWas() || searchAdapter.recentSearches.isEmpty()) { return false; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setMessage(LocaleController.getString("ClearSearch", R.string.ClearSearch)); builder.setPositiveButton(LocaleController.getString("ClearButton", R.string.ClearButton).toUpperCase(), (dialogInterface, i) -> searchAdapter.clearRecent()); @@ -3551,7 +3534,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); TextView textView = new TextView(context); - textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText)); + textView.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteRedText)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); textView.setGravity(Gravity.CENTER); textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -3565,7 +3548,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } topView = new TopView(context); - topView.setBackgroundColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue)); + topView.setBackgroundColor(getThemedColor(Theme.key_avatar_backgroundActionBarBlue)); frameLayout.addView(topView); contentView.blurBehindViews.add(topView); @@ -3577,7 +3560,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (transitionOnlineText != null) { canvas.save(); canvas.translate(onlineTextView[0].getX(), onlineTextView[0].getY()); - canvas.saveLayerAlpha(0 ,0, transitionOnlineText.getMeasuredWidth(), transitionOnlineText.getMeasuredHeight(), (int) (255 * (1f - animationProgress)), Canvas.ALL_SAVE_FLAG); + canvas.saveLayerAlpha(0, 0, transitionOnlineText.getMeasuredWidth(), transitionOnlineText.getMeasuredHeight(), (int) (255 * (1f - animationProgress)), Canvas.ALL_SAVE_FLAG); transitionOnlineText.draw(canvas); canvas.restore(); canvas.restore(); @@ -3610,20 +3593,32 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarImage.setPivotX(0); avatarImage.setPivotY(0); avatarContainer.addView(avatarImage, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); - avatarContainer.setOnClickListener(v -> { - if (imageUpdater != null) { - TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); - if (user == null) { - user = UserConfig.getInstance(currentAccount).getCurrentUser(); - } - if (user == null) { - return; - } - imageUpdater.openMenu(user.photo != null && user.photo.photo_big != null && !(user.photo instanceof TLRPC.TL_userProfilePhotoEmpty), () -> MessagesController.getInstance(currentAccount).deleteUserPhoto(null), dialog -> { - }); - } else { - openAvatar(); + avatarImage.setOnClickListener(v -> { + if (avatarBig != null) { + return; } + if (!AndroidUtilities.isTablet() && !isInLandscapeMode && avatarImage.getImageReceiver().hasNotThumb() && !AndroidUtilities.isAccessibilityScreenReaderEnabled()) { + openingAvatar = true; + allowPullingDown = true; + View child = null; + for (int i = 0; i < listView.getChildCount(); i++) { + if (listView.getChildAdapterPosition(listView.getChildAt(i)) == 0) { + child = listView.getChildAt(i); + break; + } + } + if (child != null) { + RecyclerView.ViewHolder holder = listView.findContainingViewHolder(child); + if (holder != null) { + Integer offset = positionToOffset.get(holder.getAdapterPosition()); + if (offset != null) { + listView.smoothScrollBy(0, -(offset + (listView.getPaddingTop() - child.getTop() - actionBar.getMeasuredHeight())), CubicBezierInterpolator.EASE_OUT_QUINT); + return; + } + } + } + } + openAvatar(); }); avatarProgressView = new RadialProgressView(context) { @@ -3671,15 +3666,35 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. frameLayout.addView(actionBar); + float rightMargin = (54 + ((callItemVisible && userId != 0) ? 54 : 0)); + int initialTitleWidth = LayoutHelper.WRAP_CONTENT; + if (parentLayout != null && parentLayout.getLastFragment() instanceof ChatActivity) { + ChatAvatarContainer avatarContainer = ((ChatActivity) parentLayout.getLastFragment()).getAvatarContainer(); + if (avatarContainer != null && avatarContainer.getLayoutParams() != null && avatarContainer.getTitleTextView() != null) { + rightMargin = + (((ViewGroup.MarginLayoutParams) avatarContainer.getLayoutParams()).rightMargin + + (avatarContainer.getWidth() - avatarContainer.getTitleTextView().getRight())) / AndroidUtilities.density; + initialTitleWidth = (int) (avatarContainer.getTitleTextView().getWidth() / AndroidUtilities.density); + } + } + for (int a = 0; a < nameTextView.length; a++) { if (playProfileAnimation == 0 && a == 0) { continue; } - nameTextView[a] = new SimpleTextView(context); + nameTextView[a] = new SimpleTextView(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (isFocusable() && nameTextViewRightDrawableContentDescription != null) { + info.setText(getText() + ", " + nameTextViewRightDrawableContentDescription); + } + } + }; if (a == 1) { - nameTextView[a].setTextColor(Theme.getColor(Theme.key_profile_title)); + nameTextView[a].setTextColor(getThemedColor(Theme.key_profile_title)); } else { - nameTextView[a].setTextColor(Theme.getColor(Theme.key_actionBarDefaultTitle)); + nameTextView[a].setTextColor(getThemedColor(Theme.key_actionBarDefaultTitle)); } nameTextView[a].setTextSize(18); nameTextView[a].setGravity(Gravity.LEFT); @@ -3707,21 +3722,20 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return false; }); } - int rightMargin = a == 0 - ? (48 + ((callItemVisible && userId != 0) ? 48 : 0)) - : 0; - avatarContainer2.addView(nameTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, rightMargin, 0)); + nameTextView[a].setFocusable(a == 0); + avatarContainer2.addView(nameTextView[a], LayoutHelper.createFrame(a == 0 ? initialTitleWidth : LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, a == 0 ? rightMargin : 0, 0)); } for (int a = 0; a < onlineTextView.length; a++) { onlineTextView[a] = new SimpleTextView(context); - onlineTextView[a].setTextColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); + onlineTextView[a].setTextColor(getThemedColor(Theme.key_avatar_subtitleInProfileBlue)); onlineTextView[a].setTextSize(14); onlineTextView[a].setGravity(Gravity.LEFT); onlineTextView[a].setAlpha(a == 0 || a == 2 ? 0.0f : 1.0f); if (a > 0) { onlineTextView[a].setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); } - avatarContainer2.addView(onlineTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, a == 0 ? 48 : 8, 0)); + onlineTextView[a].setFocusable(a == 0); + avatarContainer2.addView(onlineTextView[a], LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP, 118, 0, a == 0 ? rightMargin : 8, 0)); } idTextView = new SimpleTextView(context); @@ -3736,7 +3750,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override protected TextView createTextView() { TextView textView = new TextView(context); - textView.setTextColor(Theme.getColor(Theme.key_player_actionBarSubtitle)); + textView.setTextColor(getThemedColor(Theme.key_player_actionBarSubtitle)); textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); textView.setSingleLine(true); textView.setEllipsize(TextUtils.TruncateAt.END); @@ -3753,7 +3767,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Drawable shadowDrawable = context.getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.SRC_IN)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, - Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_profile_actionBackground), Theme.getColor(Theme.key_profile_actionPressedBackground)), + Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), getThemedColor(Theme.key_profile_actionBackground), getThemedColor(Theme.key_profile_actionPressedBackground)), 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); writeButton.setBackground(combinedDrawable); @@ -3770,7 +3784,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. writeButton.setImageResource(R.drawable.baseline_chat_bubble_24); writeButton.setContentDescription(LocaleController.getString("ViewDiscussion", R.string.ViewDiscussion)); } - writeButton.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_profile_actionIcon), PorterDuff.Mode.SRC_IN)); + writeButton.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_profile_actionIcon), PorterDuff.Mode.SRC_IN)); writeButton.setScaleType(ImageView.ScaleType.CENTER); frameLayout.addView(writeButton, LayoutHelper.createFrame(60, 60, Gravity.RIGHT | Gravity.TOP, 0, 0, 16, 0)); @@ -3821,7 +3835,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }); - undoView = new UndoView(context); + undoView = new UndoView(context, null, false, resourcesProvider); frameLayout.addView(undoView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.LEFT, 8, 0, 8, 8)); expandAnimator = ValueAnimator.ofFloat(0f, 1f); @@ -3854,17 +3868,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (scamDrawable != null) { - scamDrawable.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue), Color.argb(179, 255, 255, 255), value)); + scamDrawable.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_avatar_subtitleInProfileBlue), Color.argb(179, 255, 255, 255), value)); } if (lockIconDrawable != null) { - lockIconDrawable.setColorFilter(ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_lockIcon), Color.WHITE, value), PorterDuff.Mode.SRC_IN); + lockIconDrawable.setColorFilter(ColorUtils.blendARGB(getThemedColor(Theme.key_chat_lockIcon), Color.WHITE, value), PorterDuff.Mode.SRC_IN); } if (verifiedCrossfadeDrawable != null) { verifiedCrossfadeDrawable.setProgress(value); } + if (premuimCrossfadeDrawable != null) { + premuimCrossfadeDrawable.setProgress(value); + } + final float k = AndroidUtilities.dpf2(8f); final float nameTextViewXEnd = AndroidUtilities.dpf2(16f) - nameTextView[1].getLeft(); @@ -3899,9 +3917,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. final Object onlineTextViewTag = onlineTextView[1].getTag(); int statusColor; if (onlineTextViewTag instanceof String) { - statusColor = Theme.getColor((String) onlineTextViewTag); + statusColor = getThemedColor((String) onlineTextViewTag); } else { - statusColor = Theme.getColor(Theme.key_avatar_subtitleInProfileBlue); + statusColor = getThemedColor(Theme.key_avatar_subtitleInProfileBlue); } onlineTextView[1].setTextColor(ColorUtils.blendARGB(statusColor, Color.argb(179, 255, 255, 255), value)); idTextView.setTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue), Color.argb(179, 255, 255, 255), value)); @@ -3913,8 +3931,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. needLayoutText(Math.min(1f, extraHeight / AndroidUtilities.dp(88f))); - nameTextView[1].setTextColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_profile_title), Color.WHITE, value)); - actionBar.setItemsColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultIcon), Color.WHITE, value), false); + nameTextView[1].setTextColor(ColorUtils.blendARGB(getThemedColor(Theme.key_profile_title), Color.WHITE, value)); + actionBar.setItemsColor(ColorUtils.blendARGB(getThemedColor(Theme.key_actionBarDefaultIcon), Color.WHITE, value), false); avatarImage.setForegroundAlpha(value); @@ -3933,7 +3951,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public void onAnimationEnd(Animator animation) { - actionBar.setItemsBackgroundColor(isPulledDown ? Theme.ACTION_BAR_WHITE_SELECTOR_COLOR : Theme.getColor(Theme.key_avatar_actionBarSelectorBlue), false); + actionBar.setItemsBackgroundColor(isPulledDown ? Theme.ACTION_BAR_WHITE_SELECTOR_COLOR : getThemedColor(Theme.key_avatar_actionBarSelectorBlue), false); avatarImage.clearForeground(); doNotSetForeground = false; } @@ -3956,6 +3974,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. pinchToZoomHelper = new PinchToZoomHelper(decorView, frameLayout) { Paint statusBarPaint; + @Override protected void invalidateViews() { super.invalidateViews(); @@ -4021,13 +4040,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } Bitmap bitmap = pinchToZoomHelper.getPhotoImage() == null ? null : pinchToZoomHelper.getPhotoImage().getBitmap(); if (bitmap != null) { - topView.setBackgroundColor(ColorUtils.blendARGB(AndroidUtilities.calcBitmapColor(bitmap), Theme.getColor(Theme.key_windowBackgroundWhite), 0.1f)); + topView.setBackgroundColor(ColorUtils.blendARGB(AndroidUtilities.calcBitmapColor(bitmap), getThemedColor(Theme.key_windowBackgroundWhite), 0.1f)); } } }); avatarsViewPager.setPinchToZoomHelper(pinchToZoomHelper); scrimPaint.setAlpha(0); - actionBarBackgroundPaint.setColor(Theme.getColor(Theme.key_listSelector)); + actionBarBackgroundPaint.setColor(getThemedColor(Theme.key_listSelector)); contentView.blurBehindViews.add(sharedMediaLayout); updateTtlIcon(); return fragmentView; @@ -4061,6 +4080,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public TLRPC.Chat getCurrentChat() { return currentChat; } + public TLRPC.UserFull getUserInfo() { return userInfo; } @@ -4104,7 +4124,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private void onWriteButtonClick() { if (userId != 0) { if (imageUpdater != null) { - presentFragment(new ChangeNameActivity()); + presentFragment(new ChangeNameActivity(resourcesProvider)); //TODO: MERGE CONFLICT /* TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(UserConfig.getInstance(currentAccount).getClientUserId()); @@ -4261,14 +4281,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (items.isEmpty()) { return false; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder.setItems(items.toArray(new CharSequence[0]), AndroidUtilities.toIntArray(icons), (dialogInterface, i) -> { if (actions.get(i) == 2) { kickUser(selectedUser, participant); } else { int action = actions.get(i); if (action == 1 && (channelParticipant instanceof TLRPC.TL_channelParticipantAdmin || participant instanceof TLRPC.TL_chatParticipantAdmin)) { - AlertDialog.Builder builder2 = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder2 = new AlertDialog.Builder(getParentActivity(), resourcesProvider); builder2.setTitle(LocaleController.getString("NekoX", R.string.NekoX)); builder2.setMessage(LocaleController.formatString("AdminWillBeRemoved", R.string.AdminWillBeRemoved, ContactsController.formatName(user.first_name, user.last_name))); builder2.setPositiveButton(LocaleController.getString("OK", R.string.OK), (dialog, which) -> { @@ -4292,7 +4312,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. AlertDialog alertDialog = builder.create(); showDialog(alertDialog); if (hasRemove) { - alertDialog.setItemColor(items.size() - 1, Theme.getColor(Theme.key_dialogTextRed2), Theme.getColor(Theme.key_dialogRedIcon)); + alertDialog.setItemColor(items.size() - 1, getThemedColor(Theme.key_dialogTextRed2), getThemedColor(Theme.key_dialogRedIcon)); } } else { if (participant.user_id == getUserConfig().getClientUserId()) { @@ -4412,28 +4432,38 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { return false; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - builder.setItems(new CharSequence[]{LocaleController.getString("Copy", R.string.Copy)}, (dialogInterface, i) -> { - if (i == 0) { - try { - android.content.ClipboardManager clipboard = (android.content.ClipboardManager) ApplicationLoader.applicationContext.getSystemService(Context.CLIPBOARD_SERVICE); - String text; - if (userId != 0) { - text = "@" + username; - BulletinFactory.of(this).createCopyBulletin(LocaleController.getString("UsernameCopied", R.string.UsernameCopied)).show(); - } else { - text = "https://" + MessagesController.getInstance(UserConfig.selectedAccount).linkPrefix + "/" + username; - BulletinFactory.of(this).createCopyBulletin(LocaleController.getString("LinkCopied", R.string.LinkCopied)).show(); - } - android.content.ClipData clip = android.content.ClipData.newPlainText("label", text); - clipboard.setPrimaryClip(clip); - } catch (Exception e) { - FileLog.e(e); - } - } + BottomBuilder builder = new BottomBuilder(getParentActivity()); + builder.addTitle("@" + username); + + builder.addItem(LocaleController.getString("QrCode", R.string.QrCode), R.drawable.wallet_qr, __ -> { + Bundle args = new Bundle(); + args.putLong("chat_id", chatId); + args.putLong("user_id", userId); + presentFragment(new QrActivity(args)); + return Unit.INSTANCE; }); - showDialog(builder.create()); + + if (chatInfo != null && chatInfo.can_set_username) { + builder.addItem(LocaleController.getString("Edit", R.string.Edit), R.drawable.baseline_edit_24, __ -> { + ChatEditTypeActivity fragment = new ChatEditTypeActivity(chatId, chatInfo.can_set_location); + fragment.setInfo(chatInfo); + presentFragment(fragment); + return Unit.INSTANCE; + }); + } + + builder.addItem(LocaleController.getString("Copy", R.string.Copy), R.drawable.baseline_content_copy_24, __ -> { + AlertUtil.copyAndAlert("@" + username); + return Unit.INSTANCE; + }); + + builder.addItem(LocaleController.getString("CopyLink", R.string.CopyLink), R.drawable.baseline_link_24, __ -> { + AlertUtil.copyAndAlert("https://t.me/" + username); + return Unit.INSTANCE; + }); + + builder.show(); return true; } else if (position == phoneRow || position == numberRow) { final TLRPC.User user = getMessagesController().getUser(userId); @@ -4441,7 +4471,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return false; } - AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), resourcesProvider); ArrayList items = new ArrayList<>(); final ArrayList actions = new ArrayList<>(); if (position == phoneRow) { @@ -4537,13 +4567,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } private void leaveChatPressed() { - AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, null, false, true, (param) -> { + AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, null, false, false, true, (param) -> { playProfileAnimation = 0; getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.closeChats); getNotificationCenter().postNotificationName(NotificationCenter.closeChats); finishFragment(); getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, -currentChat.id, null, currentChat, param); - }); + }, resourcesProvider); } private void setChannelAlias() { @@ -4659,44 +4689,50 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. mediaHeaderAnimationProgress = value; topView.invalidate(); - int color1 = Theme.getColor(Theme.key_profile_title); - int color2 = Theme.getColor(Theme.key_player_actionBarTitle); + int color1 = getThemedColor(Theme.key_profile_title); + int color2 = getThemedColor(Theme.key_player_actionBarTitle); int c = AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f); nameTextView[1].setTextColor(c); if (lockIconDrawable != null) { lockIconDrawable.setColorFilter(c, PorterDuff.Mode.SRC_IN); } if (scamDrawable != null) { - color1 = Theme.getColor(Theme.key_avatar_subtitleInProfileBlue); + color1 = getThemedColor(Theme.key_avatar_subtitleInProfileBlue); scamDrawable.setColor(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f)); } - color1 = Theme.getColor(Theme.key_actionBarDefaultIcon); - color2 = Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2); + color1 = getThemedColor(Theme.key_actionBarDefaultIcon); + color2 = getThemedColor(Theme.key_windowBackgroundWhiteGrayText2); actionBar.setItemsColor(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), false); - color1 = Theme.getColor(Theme.key_avatar_actionBarSelectorBlue); - color2 = Theme.getColor(Theme.key_actionBarActionModeDefaultSelector); + color1 = getThemedColor(Theme.key_avatar_actionBarSelectorBlue); + color2 = getThemedColor(Theme.key_actionBarActionModeDefaultSelector); actionBar.setItemsBackgroundColor(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), false); topView.invalidate(); - otherItem.setIconColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); - callItem.setIconColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); - videoCallItem.setIconColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); - editItem.setIconColor(Theme.getColor(Theme.key_actionBarDefaultIcon)); + otherItem.setIconColor(getThemedColor(Theme.key_actionBarDefaultIcon)); + callItem.setIconColor(getThemedColor(Theme.key_actionBarDefaultIcon)); + videoCallItem.setIconColor(getThemedColor(Theme.key_actionBarDefaultIcon)); + editItem.setIconColor(getThemedColor(Theme.key_actionBarDefaultIcon)); if (verifiedDrawable != null) { - color1 = Theme.getColor(Theme.key_profile_verifiedBackground); - color2 = Theme.getColor(Theme.key_player_actionBarTitle); + color1 = getThemedColor(Theme.key_profile_verifiedBackground); + color2 = getThemedColor(Theme.key_player_actionBarTitle); verifiedDrawable.setColorFilter(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), PorterDuff.Mode.SRC_IN); } if (verifiedCheckDrawable != null) { - color1 = Theme.getColor(Theme.key_profile_verifiedCheck); - color2 = Theme.getColor(Theme.key_windowBackgroundWhite); + color1 = getThemedColor(Theme.key_profile_verifiedCheck); + color2 = getThemedColor(Theme.key_windowBackgroundWhite); verifiedCheckDrawable.setColorFilter(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), PorterDuff.Mode.SRC_IN); } + if (premiumStarDrawable != null) { + color1 = getThemedColor(Theme.key_profile_verifiedBackground); + color2 = getThemedColor(Theme.key_player_actionBarTitle); + premiumStarDrawable.setColorFilter(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), PorterDuff.Mode.MULTIPLY); + } + if (avatarsViewPagerIndicatorView.getSecondaryMenuItem() != null && (videoCallItemVisible || editItemVisible || callItemVisible)) { needLayoutText(Math.min(1f, extraHeight / AndroidUtilities.dp(88f))); } @@ -4742,6 +4778,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + if (actionBar != null) { + actionBar.createMenu().requestLayout(); + } + ArrayList animators = new ArrayList<>(); animators.add(ObjectAnimator.ofFloat(callItem, View.ALPHA, visible ? 0.0f : 1.0f)); @@ -4772,15 +4812,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (headerAnimatorSet != null) { if (mediaHeaderVisible) { if (callItemVisible) { - callItem.setVisibility(View.INVISIBLE); + callItem.setVisibility(View.GONE); } if (videoCallItemVisible) { - videoCallItem.setVisibility(View.INVISIBLE); + videoCallItem.setVisibility(View.GONE); } if (editItemVisible) { - editItem.setVisibility(View.INVISIBLE); + editItem.setVisibility(View.GONE); } - otherItem.setVisibility(View.INVISIBLE); + otherItem.setVisibility(View.GONE); } else { if (sharedMediaLayout.isSearchItemVisible()) { mediaSearchItem.setVisibility(View.VISIBLE); @@ -4810,7 +4850,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }); headerAnimatorSet.setDuration(150); headerAnimatorSet.start(); - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); } private void openAddMember() { @@ -5018,45 +5058,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } // if (qrItem != null) { -// boolean setQrVisible = diff > 0.5f; -// if (setQrVisible != isQrItemVisible) { -// isQrItemVisible = setQrVisible; -// if (qrItemAnimation != null) { -// qrItemAnimation.cancel(); -// qrItemAnimation = null; -// } -// if (animated) { -// qrItemAnimation = new AnimatorSet(); -// if (setQrVisible) { -// qrItemAnimation.setInterpolator(new DecelerateInterpolator()); -// qrItemAnimation.playTogether( -// ObjectAnimator.ofFloat(qrItem, View.ALPHA, 1.0f), -// ObjectAnimator.ofFloat(qrItem, View.SCALE_Y, 1f), -// ObjectAnimator.ofFloat(avatarsViewPagerIndicatorView, View.TRANSLATION_X, -AndroidUtilities.dp(48)) -// ); -// } else { -// qrItemAnimation.setInterpolator(new AccelerateInterpolator()); -// qrItemAnimation.playTogether( -// ObjectAnimator.ofFloat(qrItem, View.ALPHA, 0.0f), -// ObjectAnimator.ofFloat(qrItem, View.SCALE_Y, 0f), -// ObjectAnimator.ofFloat(avatarsViewPagerIndicatorView, View.TRANSLATION_X, 0) -// ); -// } -// qrItemAnimation.setDuration(150); -// qrItemAnimation.addListener(new AnimatorListenerAdapter() { -// @Override -// public void onAnimationEnd(Animator animation) { -// qrItemAnimation = null; -// } -// }); -// qrItemAnimation.start(); -// } else { -// qrItem.setAlpha(setQrVisible ? 1.0f : 0.0f); -// float translation = AndroidUtilities.dp(48) * qrItem.getAlpha(); -// qrItem.setTranslationX(translation); -// avatarsViewPagerIndicatorView.setTranslationX(translation - AndroidUtilities.dp(48)); -// } -// } +// // } } } @@ -5091,7 +5093,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. searchItem.setEnabled(false); } isPulledDown = true; - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); overlaysView.setOverlaysVisible(true, durationFactor); avatarsViewPagerIndicatorView.refreshVisibility(durationFactor); avatarsViewPager.setCreateThumbFromParent(true); @@ -5140,7 +5142,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { if (isPulledDown) { isPulledDown = false; - NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors); + NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needCheckSystemBarColors, true); /*if (otherItem != null) { otherItem.hideSubItem(gallery_menu_save); if (imageUpdater != null) { @@ -5169,7 +5171,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else { expandAnimator.setDuration(0); } - topView.setBackgroundColor(Theme.getColor(Theme.key_avatar_backgroundActionBarBlue)); + topView.setBackgroundColor(getThemedColor(Theme.key_avatar_backgroundActionBarBlue)); if (!doNotSetForeground) { BackupImageView imageView = avatarsViewPager.getCurrentItemView(); @@ -5227,18 +5229,22 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. avatarContainer.setScaleY(avatarScale); overlaysView.setAlphaValue(animationProgress, false); - actionBar.setItemsColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_actionBarDefaultIcon), Color.WHITE, animationProgress), false); + actionBar.setItemsColor(ColorUtils.blendARGB(getThemedColor(Theme.key_actionBarDefaultIcon), Color.WHITE, animationProgress), false); if (scamDrawable != null) { - scamDrawable.setColor(ColorUtils.blendARGB(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue), Color.argb(179, 255, 255, 255), animationProgress)); + scamDrawable.setColor(ColorUtils.blendARGB(getThemedColor(Theme.key_avatar_subtitleInProfileBlue), Color.argb(179, 255, 255, 255), animationProgress)); } if (lockIconDrawable != null) { - lockIconDrawable.setColorFilter(ColorUtils.blendARGB(Theme.getColor(Theme.key_chat_lockIcon), Color.WHITE, animationProgress), PorterDuff.Mode.SRC_IN); + lockIconDrawable.setColorFilter(ColorUtils.blendARGB(getThemedColor(Theme.key_chat_lockIcon), Color.WHITE, animationProgress), PorterDuff.Mode.SRC_IN); } if (verifiedCrossfadeDrawable != null) { verifiedCrossfadeDrawable.setProgress(animationProgress); nameTextView[1].invalidate(); } + if (premuimCrossfadeDrawable != null) { + premuimCrossfadeDrawable.setProgress(animationProgress); + nameTextView[1].invalidate(); + } final FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) avatarContainer.getLayoutParams(); params.width = params.height = (int) AndroidUtilities.lerp(AndroidUtilities.dpf2(42f), (extraHeight + newTop) / avatarScale, animationProgress); @@ -5303,6 +5309,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + public void updateQrItemVisibility(boolean animated) { + // NekoX: removed + } + private void setForegroundImage(boolean secondParent) { Drawable drawable = avatarImage.getImageReceiver().getDrawable(); if (drawable instanceof AnimatedFileDrawable) { @@ -5315,7 +5325,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. ImageLocation location = avatarsViewPager.getImageLocation(0); String filter; if (location != null && location.imageType == FileLoader.IMAGE_TYPE_ANIMATION) { - filter = ImageLoader.AUTOPLAY_FILTER; + filter = "avatar"; } else { filter = null; } @@ -5599,6 +5609,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. updateAutoDeleteItem(); updateTtlIcon(); } + } else if (id == NotificationCenter.privacyRulesUpdated) { +// if (qrItem != null) { +// updateQrItemVisibility(true); +// } } else if (id == NotificationCenter.didReceiveNewMessages) { boolean scheduled = (Boolean) args[2]; if (scheduled) { @@ -5865,10 +5879,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (playProfileAnimation == 2 && avatarColor != 0) { color = avatarColor; } else { - color = AvatarDrawable.getProfileBackColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId); + color = AvatarDrawable.getProfileBackColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId, resourcesProvider); } - int actionBarColor = actionBarAnimationColorFrom != 0 ? actionBarAnimationColorFrom : Theme.getColor(Theme.key_actionBarDefault); + int actionBarColor = actionBarAnimationColorFrom != 0 ? actionBarAnimationColorFrom : getThemedColor(Theme.key_actionBarDefault); int actionBarColor2 = actionBarColor; if (SharedConfig.chatBlurEnabled()) { actionBarColor = ColorUtils.setAlphaComponent(actionBarColor, 0); @@ -5876,12 +5890,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. topView.setBackgroundColor(ColorUtils.blendARGB(actionBarColor, color, progress)); timerDrawable.setBackgroundColor(ColorUtils.blendARGB(actionBarColor2, color, progress)); - color = AvatarDrawable.getIconColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId); - int iconColor = Theme.getColor(Theme.key_actionBarDefaultIcon); + color = AvatarDrawable.getIconColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId, resourcesProvider); + int iconColor = getThemedColor(Theme.key_actionBarDefaultIcon); actionBar.setItemsColor(ColorUtils.blendARGB(iconColor, color, progress), false); - color = Theme.getColor(Theme.key_profile_title); - int titleColor = Theme.getColor(Theme.key_actionBarDefaultTitle); + color = getThemedColor(Theme.key_profile_title); + int titleColor = getThemedColor(Theme.key_actionBarDefaultTitle); for (int i = 0; i < 2; i++) { if (nameTextView[i] == null || i == 1 && playProfileAnimation == 2) { continue; @@ -5889,8 +5903,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. nameTextView[i].setTextColor(ColorUtils.blendARGB(titleColor, color, progress)); } - color = isOnline[0] ? Theme.getColor(Theme.key_profile_status) : AvatarDrawable.getProfileTextColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId); - int subtitleColor = Theme.getColor(isOnline[0] ? Theme.key_chat_status : Theme.key_actionBarDefaultSubtitle); + color = isOnline[0] ? getThemedColor(Theme.key_profile_status) : AvatarDrawable.getProfileTextColorForId(userId != 0 || ChatObject.isChannel(chatId, currentAccount) && !currentChat.megagroup ? 5 : chatId, resourcesProvider); + int subtitleColor = getThemedColor(isOnline[0] ? Theme.key_chat_status : Theme.key_actionBarDefaultSubtitle); for (int i = 0; i < 2; i++) { if (onlineTextView[i] == null || i == 1 && playProfileAnimation == 2) { @@ -5899,7 +5913,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. onlineTextView[i].setTextColor(ColorUtils.blendARGB(subtitleColor, color, progress)); } extraHeight = initialAnimationExtraHeight * progress; - color = AvatarDrawable.getProfileColorForId(userId != 0 ? userId : chatId); + color = AvatarDrawable.getProfileColorForId(userId != 0 ? userId : chatId, resourcesProvider); int color2 = AvatarDrawable.getColorForId(userId != 0 ? userId : chatId); if (color != color2) { avatarDrawable.setColor(ColorUtils.blendARGB(color2, color, progress)); @@ -5921,6 +5935,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + @Override + public int getNavigationBarColor() { + return Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider); + } + boolean profileTransitionInProgress; @Override @@ -6025,7 +6044,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. BaseFragment previousFragment = parentLayout.fragmentsStack.size() > 1 ? parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2) : null; if (previousFragment instanceof ChatActivity) { ChatAvatarContainer avatarContainer = ((ChatActivity) previousFragment).getAvatarContainer(); - if (avatarContainer.getSubtitleTextView().getLeftDrawable() != null) { + if (avatarContainer.getSubtitleTextView().getLeftDrawable() != null || avatarContainer.statusMadeShorter[0]) { transitionOnlineText = avatarContainer.getSubtitleTextView(); avatarContainer2.invalidate(); onlineTextCrosafade = true; @@ -6078,12 +6097,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (ttlIconView != null) { animators.add(ObjectAnimator.ofFloat(ttlIconView, View.ALPHA, ttlIconView.getAlpha(), 0.0f)); } - boolean crossfadeOnlineText = false; BaseFragment previousFragment = parentLayout.fragmentsStack.size() > 1 ? parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2) : null; if (previousFragment instanceof ChatActivity) { ChatAvatarContainer avatarContainer = ((ChatActivity) previousFragment).getAvatarContainer(); - if (avatarContainer.getSubtitleTextView().getLeftDrawable() != null) { + if (avatarContainer.getSubtitleTextView().getLeftDrawable() != null || avatarContainer.statusMadeShorter[0]) { transitionOnlineText = avatarContainer.getSubtitleTextView(); avatarContainer2.invalidate(); crossfadeOnlineText = true; @@ -6291,11 +6309,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. notificationRow = -1; nekoRow = -1; languageRow = -1; + premiumRow = -1; + premiumSectionsRow = -1; privacyRow = -1; dataRow = -1; chatRow = -1; stickersRow = -1; filtersRow = -1; + stickersRow = -1; devicesRow = -1; devicesSectionRow = -1; helpHeaderRow = -1; @@ -6388,9 +6409,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. dataRow = rowCount++; privacyRow = rowCount++; chatRow = rowCount++; + stickersRow = rowCount++; + devicesRow = rowCount++; filtersRow = rowCount++; nekoRow = rowCount++; languageRow = rowCount++; + devicesSectionRow = rowCount++; + if (!getMessagesController().premiumLocked) { + premiumRow = rowCount++; + premiumSectionsRow = rowCount++; + } helpHeaderRow = rowCount++; faqRow = rowCount++; policyRow = rowCount++; @@ -6439,7 +6467,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } - if (user != null && isBot && !user.bot_nochats) { // TODO(dkaraush): and had invite button sent + if (user != null && isBot && !user.bot_nochats) { addToGroupButtonRow = rowCount++; addToGroupInfoRow = rowCount++; } @@ -6578,7 +6606,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. private Drawable getScamDrawable(int type) { if (scamDrawable == null) { scamDrawable = new ScamDrawable(11, type); - scamDrawable.setColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); + scamDrawable.setColor(getThemedColor(Theme.key_avatar_subtitleInProfileBlue)); } return scamDrawable; } @@ -6599,6 +6627,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return verifiedCrossfadeDrawable; } + + private Drawable getPremiumCrossfadeDrawable() { + if (premuimCrossfadeDrawable == null) { + premiumStarDrawable = ContextCompat.getDrawable(getParentActivity(), R.drawable.msg_premium_liststar).mutate(); + premiumStarDrawable.setColorFilter(getThemedColor(Theme.key_profile_verifiedBackground), PorterDuff.Mode.MULTIPLY); + premuimCrossfadeDrawable = new CrossfadeDrawable(premiumStarDrawable, ContextCompat.getDrawable(getParentActivity(), R.drawable.msg_premium_prolfilestar).mutate()); + } + return premuimCrossfadeDrawable; + } + private void updateProfileData() { if (avatarContainer == null || nameTextView == null) { return; @@ -6629,16 +6667,16 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. final ImageLocation imageLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_BIG); final ImageLocation thumbLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL); + final ImageLocation videoThumbLocation = ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_VIDEO_THUMB); final ImageLocation videoLocation = avatarsViewPager.getCurrentVideoLocation(thumbLocation, imageLocation); avatarsViewPager.initIfEmpty(imageLocation, thumbLocation); - String filter; - if (videoLocation != null && videoLocation.imageType == FileLoader.IMAGE_TYPE_ANIMATION) { - filter = ImageLoader.AUTOPLAY_FILTER; - } else { - filter = null; - } if (avatarBig == null) { - avatarImage.setImage(videoLocation, filter, thumbLocation, "50_50", avatarDrawable, user); + if (videoThumbLocation != null) { + avatarImage.getImageReceiver().setVideoThumbIsSame(true); + avatarImage.setImage(videoLocation, ImageLoader.AUTOPLAY_FILTER, videoThumbLocation, "avatar", avatarDrawable, user); + } else { + avatarImage.setImage(videoLocation, ImageLoader.AUTOPLAY_FILTER, thumbLocation, "50_50", avatarDrawable, user); + } } if (thumbLocation != null && setAvatarRow != -1 || thumbLocation == null && setAvatarRow == -1) { updateListAnimated(false); @@ -6649,7 +6687,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getFileLoader().loadFile(imageLocation, user, null, 0, 1); } - String newString = UserObject.getUserName(user); + CharSequence newString = UserObject.getUserName(user); String newString2; if (user.id == getUserConfig().getClientUserId()) { newString2 = LocaleController.getString("Online", R.string.Online); @@ -6666,10 +6704,14 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. String key = isOnline[0] ? Theme.key_profile_status : Theme.key_avatar_subtitleInProfileBlue; onlineTextView[1].setTag(key); if (!isPulledDown) { - onlineTextView[1].setTextColor(Theme.getColor(key)); + onlineTextView[1].setTextColor(getThemedColor(key)); } } } + try { + newString = Emoji.replaceEmoji(newString, nameTextView[1].getPaint().getFontMetricsInt(), AndroidUtilities.dp(24), false); + } catch (Exception ignore) { + } for (int a = 0; a < 2; a++) { if (nameTextView[a] == null) { continue; @@ -6688,19 +6730,53 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } Drawable leftIcon = currentEncryptedChat != null ? getLockIconDrawable() : null; Drawable rightIcon = null; + boolean rightIconIsPremium = false; if (a == 0) { if (user.scam || user.fake) { rightIcon = getScamDrawable(user.scam ? 0 : 1); + nameTextViewRightDrawableContentDescription = LocaleController.getString("ScamMessage", R.string.ScamMessage); + } else if (user.verified) { + rightIcon = getVerifiedCrossfadeDrawable(); + nameTextViewRightDrawableContentDescription = LocaleController.getString("AccDescrVerified", R.string.AccDescrVerified); + } else if (getMessagesController().isPremiumUser(user)) { + rightIconIsPremium = true; + rightIcon = getPremiumCrossfadeDrawable(); + nameTextViewRightDrawableContentDescription = LocaleController.getString("AccDescrPremium", R.string.AccDescrPremium); + } else if (getMessagesController().isDialogMuted(dialogId != 0 ? dialogId : userId)) { + rightIcon = getThemedDrawable(Theme.key_drawable_muteIconDrawable); + nameTextViewRightDrawableContentDescription = LocaleController.getString("NotificationsMuted", R.string.NotificationsMuted); } else { - rightIcon = getMessagesController().isDialogMuted(dialogId != 0 ? dialogId : userId) ? Theme.chat_muteIconDrawable : null; + rightIcon = null; + nameTextViewRightDrawableContentDescription = null; } } else if (user.scam || user.fake) { rightIcon = getScamDrawable(user.scam ? 0 : 1); } else if (user.verifiedExtended()) { rightIcon = getVerifiedCrossfadeDrawable(); + } else if (getMessagesController().isPremiumUser(user)) { + rightIconIsPremium = true; + rightIcon = getPremiumCrossfadeDrawable(); } nameTextView[a].setLeftDrawable(leftIcon); nameTextView[a].setRightDrawable(rightIcon); + if (a == 0) { + nameTextView[a].setCanHideRightDrawable(rightIconIsPremium); + } + if (!user.self && getMessagesController().isPremiumUser(user)) { + final SimpleTextView textView = nameTextView[a]; + nameTextView[a].setRightDrawableOnClick(v -> { + PremiumPreviewBottomSheet premiumPreviewBottomSheet = new PremiumPreviewBottomSheet(ProfileActivity.this, currentAccount, user); + int[] coords = new int[2]; + textView.getLocationOnScreen(coords); + premiumPreviewBottomSheet.startEnterFromX = textView.rightDrawableX; + premiumPreviewBottomSheet.startEnterFromY = textView.rightDrawableY; + premiumPreviewBottomSheet.startEnterFromScale = textView.getScaleX(); + premiumPreviewBottomSheet.startEnterFromX1 = textView.getLeft(); + premiumPreviewBottomSheet.startEnterFromY1 = textView.getTop(); + premiumPreviewBottomSheet.startEnterFromView = textView; + showDialog(premiumPreviewBottomSheet); + }); + } } if (user.photo != null && user.photo.dc_id != 0) { @@ -6788,7 +6864,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. continue; } if (chat.title != null) { - if (nameTextView[a].setText(chat.title)) { + CharSequence title = chat.title; + try { + title = Emoji.replaceEmoji(title, nameTextView[a].getPaint().getFontMetricsInt(), AndroidUtilities.dp(24), false); + } catch (Exception ignore) { + } + if (nameTextView[a].setText(title)) { changed = true; } } @@ -6796,16 +6877,23 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (a != 0) { if (chat.scam || chat.fake) { nameTextView[a].setRightDrawable(getScamDrawable(chat.scam ? 0 : 1)); + nameTextViewRightDrawableContentDescription = LocaleController.getString("ScamMessage", R.string.ScamMessage); } else if (chat.verifiedExtended()) { nameTextView[a].setRightDrawable(getVerifiedCrossfadeDrawable()); + nameTextViewRightDrawableContentDescription = LocaleController.getString("AccDescrVerified", R.string.AccDescrVerified); } else { nameTextView[a].setRightDrawable(null); + nameTextViewRightDrawableContentDescription = null; } } else { if (chat.scam || chat.fake) { nameTextView[a].setRightDrawable(getScamDrawable(chat.scam ? 0 : 1)); + } else if (chat.verified) { + nameTextView[a].setRightDrawable(getVerifiedCrossfadeDrawable()); + } else if (getMessagesController().isDialogMuted(-chatId)) { + nameTextView[a].setRightDrawable(getThemedDrawable(Theme.key_drawable_muteIconDrawable)); } else { - nameTextView[a].setRightDrawable(getMessagesController().isDialogMuted(-chatId) ? Theme.chat_muteIconDrawable : null); + nameTextView[a].setRightDrawable(null); } } if (a == 0 && onlineTextOverride != null) { @@ -6913,7 +7001,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. // NekoX: Move official qrItem into bottom menu when click id // if (qrItem != null) { -// qrItem.setVisibility(searchTransitionProgress > 0.5f && isQrNeedVisible() ? View.VISIBLE : View.GONE); +// updateQrItemVisibility(true); // } } } @@ -6953,9 +7041,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. createAutoDeleteItem(context); } if (isBot) { - if (!user.bot_nochats) { - otherItem.addSubItem(invite_to_group, R.drawable.baseline_group_add_24, LocaleController.getString("BotInvite", R.string.BotInvite)); - } +// if (!user.bot_nochats) { +// otherItem.addSubItem(invite_to_group, R.drawable.baseline_group_add_24, LocaleController.getString("BotInvite", R.string.BotInvite)); +// } otherItem.addSubItem(share, R.drawable.baseline_forward_24, LocaleController.getString("BotShare", R.string.BotShare)); } else { otherItem.addSubItem(add_contact, R.drawable.baseline_person_add_24, LocaleController.getString("AddContact", R.string.AddContact)); @@ -7066,7 +7154,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. // NekoX-TODO: Check Chnage if (imageUpdater != null) { - otherItem.addSubItem(set_as_main, R.drawable.menu_private, LocaleController.getString("SetAsMain", R.string.SetAsMain)); + otherItem.addSubItem(set_as_main, R.drawable.msg_openprofile, LocaleController.getString("SetAsMain", R.string.SetAsMain)); otherItem.addSubItem(gallery_menu_save, R.drawable.baseline_image_24, LocaleController.getString("SaveToGallery", R.string.SaveToGallery)); //otherItem.addSubItem(edit_avatar, R.drawable.photo_paint, LocaleController.getString("EditPhoto", R.string.EditPhoto)); otherItem.addSubItem(delete_avatar, R.drawable.baseline_delete_24, LocaleController.getString("Delete", R.string.Delete)); @@ -7162,7 +7250,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. public void setAutoDeleteHistory(int time, int action) { ProfileActivity.this.setAutoDeleteHistory(time, action); } - }, false, getResourceProvider()); + }, false, resourcesProvider); int ttl = 0; if (userInfo != null || chatInfo != null) { ttl = userInfo != null ? userInfo.ttl_period : chatInfo.ttl_period; @@ -7173,6 +7261,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. updateAutoDeleteItem(); } + @Override + public Theme.ResourcesProvider getResourceProvider() { + return resourcesProvider; + } + + public int getThemedColor(String key) { + return Theme.getColor(key, resourcesProvider); + } + + @Override + public Drawable getThemedDrawable(String drawableKey) { + Drawable drawable = resourcesProvider != null ? resourcesProvider.getDrawable(drawableKey) : null; + return drawable != null ? drawable : super.getThemedDrawable(drawableKey); + } + private void setAutoDeleteHistory(int time, int action) { long did = getDialogId(); getMessagesController().setDialogHistoryTTL(did, time); @@ -7304,8 +7407,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.setVisibility(itemVisibility); } // if (qrItem != null) { -// qrItem.setVisibility(isQrNeedVisible() && searchTransitionProgress > 0.5f ? View.VISIBLE : View.GONE); -// } + + // } searchItem.setVisibility(itemVisibility); searchItem.getSearchContainer().setVisibility(searchTransitionProgress > 0.5f ? View.GONE : View.VISIBLE); @@ -7357,8 +7460,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.setAlpha(progressHalf); } // if (qrItem != null) { -// qrItem.setAlpha(progressHalf); -// qrItem.setVisibility(searchTransitionProgress > 0.5f && isQrNeedVisible() ? View.VISIBLE : View.GONE); + // } searchItem.setVisibility(visibility); @@ -7424,8 +7526,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.setVisibility(hide); } // if (qrItem != null) { -// qrItem.setAlpha(1f); -// qrItem.setVisibility(enter || !isQrNeedVisible() ? View.GONE : View.VISIBLE); + // } searchItem.setVisibility(hide); @@ -7506,20 +7607,20 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } if (small != null && avatar != null) { - File destFile = FileLoader.getPathToAttach(small, true); - File src = FileLoader.getPathToAttach(avatar, true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(small, true); + File src = FileLoader.getInstance(currentAccount).getPathToAttach(avatar, true); src.renameTo(destFile); String oldKey = avatar.volume_id + "_" + avatar.local_id + "@50_50"; String newKey = small.location.volume_id + "_" + small.location.local_id + "@50_50"; ImageLoader.getInstance().replaceImageInCache(oldKey, newKey, ImageLocation.getForUserOrChat(user, ImageLocation.TYPE_SMALL), false); } if (big != null && avatarBig != null) { - File destFile = FileLoader.getPathToAttach(big, true); - File src = FileLoader.getPathToAttach(avatarBig, true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(big, true); + File src = FileLoader.getInstance(currentAccount).getPathToAttach(avatarBig, true); src.renameTo(destFile); } if (videoSize != null && videoPath != null) { - File destFile = FileLoader.getPathToAttach(videoSize, "mp4", true); + File destFile = FileLoader.getInstance(currentAccount).getPathToAttach(videoSize, "mp4", true); File src = new File(videoPath); src.renameTo(destFile); } @@ -7530,7 +7631,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. getMessagesStorage().putUsersAndChats(users, null, false, true); } - allowPullingDown = !AndroidUtilities.isTablet() && !isInLandscapeMode && avatarImage.getImageReceiver().hasNotThumb(); + allowPullingDown = !AndroidUtilities.isTablet() && !isInLandscapeMode && avatarImage.getImageReceiver().hasNotThumb() && !AndroidUtilities.isAccessibilityScreenReaderEnabled(); avatar = null; avatarBig = null; avatarsViewPager.setCreateThumbFromParent(false); @@ -7633,7 +7734,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. VIEW_TYPE_SHARED_MEDIA = 13, VIEW_TYPE_VERSION = 14, VIEW_TYPE_SUGGESTION = 15, - VIEW_TYPE_ADDTOGROUP_INFO = 17; + VIEW_TYPE_ADDTOGROUP_INFO = 17, + VIEW_TYPE_PREMIUM_TEXT_CELL = 18; private Context mContext; @@ -7646,35 +7748,21 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. View view; switch (viewType) { case VIEW_TYPE_HEADER: { - view = new HeaderCell(mContext, 23); + view = new HeaderCell(mContext, 23, resourcesProvider); break; } case VIEW_TYPE_TEXT_DETAIL: { - final TextDetailCell textDetailCell = new TextDetailCell(mContext); + final TextDetailCell textDetailCell = new TextDetailCell(mContext, resourcesProvider); textDetailCell.setContentDescriptionValueFirst(true); // textDetailCell.setImageClickListener(ProfileActivity.this::onTextDetailCellImageClicked); view = textDetailCell; break; } case VIEW_TYPE_ABOUT_LINK: { - view = aboutLinkCell = new AboutLinkCell(mContext, ProfileActivity.this) { + view = aboutLinkCell = new AboutLinkCell(mContext, ProfileActivity.this, resourcesProvider) { @Override protected void didPressUrl(String url) { - if (url.startsWith("@")) { - getMessagesController().openByUserName(url.substring(1), ProfileActivity.this, 0); - } else if (url.startsWith("#")) { - DialogsActivity fragment = new DialogsActivity(null); - fragment.setSearchString(url); - presentFragment(fragment); - } else if (url.startsWith("/")) { - if (parentLayout.fragmentsStack.size() > 1) { - BaseFragment previousFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2); - if (previousFragment instanceof ChatActivity) { - finishFragment(); - ((ChatActivity) previousFragment).chatActivityEnterView.setCommand(null, url, false, false); - } - } - } + openUrl(url); } @Override @@ -7690,24 +7778,24 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. break; } case VIEW_TYPE_TEXT: { - view = new TextCell(mContext); + view = new TextCell(mContext, resourcesProvider); break; } case VIEW_TYPE_DIVIDER: { - view = new DividerCell(mContext); + view = new DividerCell(mContext, resourcesProvider); view.setPadding(AndroidUtilities.dp(20), AndroidUtilities.dp(4), 0, 0); break; } case VIEW_TYPE_NOTIFICATIONS_CHECK: { - view = new NotificationsCheckCell(mContext, 23, 70, false); + view = new NotificationsCheckCell(mContext, 23, 70, false, resourcesProvider); break; } case VIEW_TYPE_SHADOW: { - view = new ShadowSectionCell(mContext); + view = new ShadowSectionCell(mContext, resourcesProvider); break; } case VIEW_TYPE_USER: { - view = new UserCell(mContext, addMemberRow == -1 ? 9 : 6, 0, true); + view = new UserCell(mContext, addMemberRow == -1 ? 9 : 6, 0, true, resourcesProvider); break; } case VIEW_TYPE_EMPTY: { @@ -7765,29 +7853,29 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. break; } case VIEW_TYPE_ADDTOGROUP_INFO: { - view = new TextInfoPrivacyCell(mContext); + view = new TextInfoPrivacyCell(mContext, resourcesProvider); break; } case VIEW_TYPE_VERSION: default: { - TextInfoPrivacyCell cell = new TextInfoPrivacyCell(mContext, 10); + TextInfoPrivacyCell cell = new TextInfoPrivacyCell(mContext, 10, resourcesProvider); cell.getTextView().setGravity(Gravity.CENTER_HORIZONTAL); - cell.getTextView().setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText3)); + cell.getTextView().setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteGrayText3)); cell.getTextView().setMovementMethod(null); - cell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + cell.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); cell.setText("Nekogram X v" + BuildConfig.VERSION_NAME + " " + FileUtil.getAbi() + " " + BuildConfig.FLAVOR + " " + BuildConfig.BUILD_TYPE); cell.getTextView().setPadding(0, AndroidUtilities.dp(14), 0, AndroidUtilities.dp(14)); view = cell; - Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow); + Drawable drawable = Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, getThemedColor(Theme.key_windowBackgroundGrayShadow)); CombinedDrawable combinedDrawable = new CombinedDrawable(new ColorDrawable(Theme.getColor(Theme.key_windowBackgroundGray)), drawable); combinedDrawable.setFullsize(true); - view.setBackgroundDrawable(combinedDrawable); + view.setBackground(combinedDrawable); break; } case VIEW_TYPE_SUGGESTION: { - view = new SettingsSuggestionCell(mContext) { + view = new SettingsSuggestionCell(mContext, resourcesProvider) { @Override protected void onYesClick(int type) { getNotificationCenter().removeObserver(ProfileActivity.this, NotificationCenter.newSuggestionsAvailable); @@ -7808,6 +7896,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. }; break; } + case VIEW_TYPE_PREMIUM_TEXT_CELL: + view = new ProfilePremiumCell(mContext, resourcesProvider); + break; } if (viewType != VIEW_TYPE_SHARED_MEDIA) { view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); @@ -7856,8 +7947,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. TextDetailCell detailCell = (TextDetailCell) holder.itemView; // if (position == usernameRow) { // Drawable drawable = ContextCompat.getDrawable(detailCell.getContext(), R.drawable.msg_qr_mini); -// drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_switch2TrackChecked), PorterDuff.Mode.MULTIPLY)); -// detailCell.setImage(drawable); +// drawable.setColorFilter(new PorterDuffColorFilter(getThemedColor(Theme.key_switch2TrackChecked), PorterDuff.Mode.MULTIPLY)); +// detailCell.setImage(drawable, LocaleController.getString("GetQRCode", R.string.GetQRCode)); // } else { // detailCell.setImage(null); // } @@ -7926,8 +8017,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. while (text.contains("\n\n\n")) { text = text.replace("\n\n\n", "\n\n"); } - aboutLinkCell.setText(text, true); - } else if (position == bioRow) { + aboutLinkCell.setText(text, ChatObject.isChannel(currentChat) && !currentChat.megagroup); + } + if (position == bioRow) { String value; if (userInfo == null || !TextUtils.isEmpty(userInfo.about)) { value = userInfo == null ? LocaleController.getString("Loading", R.string.Loading) : userInfo.about; @@ -7938,8 +8030,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. currentBio = null; } } - aboutLinkCell.setOnClickListener(e -> processOnClickOrPress(position, aboutLinkCell)); break; + case VIEW_TYPE_PREMIUM_TEXT_CELL: case VIEW_TYPE_TEXT: TextCell textCell = (TextCell) holder.itemView; textCell.setColors(Theme.key_windowBackgroundWhiteGrayIcon, Theme.key_windowBackgroundWhiteBlackText); @@ -7984,7 +8076,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (position == subscribersRequestsRow) { if (chatInfo != null) { - textCell.setTextAndValueAndIcon(LocaleController.getString("SubscribeRequests", R.string.SubscribeRequests), String.format("%d", chatInfo.requests_pending), R.drawable.actions_requests, position != membersSectionRow - 1); + textCell.setTextAndValueAndIcon(LocaleController.getString("SubscribeRequests", R.string.SubscribeRequests), String.format("%d", chatInfo.requests_pending), R.drawable.msg_requests, position != membersSectionRow - 1); } } else if (position == administratorsRow) { if (chatInfo != null) { @@ -7994,9 +8086,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else if (position == blockedUsersRow) { if (chatInfo != null) { - textCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(chatInfo.banned_count, chatInfo.kicked_count)), R.drawable.actions_removed, position != membersSectionRow - 1); + textCell.setTextAndValueAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), String.format("%d", Math.max(chatInfo.banned_count, chatInfo.kicked_count)), R.drawable.msg_user_remove, position != membersSectionRow - 1); } else { - textCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.actions_removed, position != membersSectionRow - 1); + textCell.setTextAndIcon(LocaleController.getString("ChannelBlacklist", R.string.ChannelBlacklist), R.drawable.msg_user_remove, position != membersSectionRow - 1); } } else if (position == addMemberRow) { textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); @@ -8043,8 +8135,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. textCell.setImageLeft(12); setAvatarCell = textCell; } else if (position == addToGroupButtonRow) { - textCell.setTextAndIcon(LocaleController.getString("AddToGroupOrChannel", R.string.AddToGroupOrChannel), R.drawable.groups_create, false); // TODO(dkaraush): text! icon! + textCell.setTextAndIcon(LocaleController.getString("AddToGroupOrChannel", R.string.AddToGroupOrChannel), R.drawable.msg_groups_create, false); textCell.setColors(Theme.key_windowBackgroundWhiteBlueIcon, Theme.key_windowBackgroundWhiteBlueButton); + } else if (position == premiumRow) { + textCell.setTextAndIcon(LocaleController.getString("TelegramPremium", R.string.TelegramPremium), PremiumGradient.getInstance().premiumStarMenuDrawable, false); + textCell.setImageLeft(23); } break; case VIEW_TYPE_NOTIFICATIONS_CHECK: @@ -8112,9 +8207,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. sectionCell.setTag(position); Drawable drawable; if (position == infoSectionRow && lastSectionRow == -1 && secretSettingsSectionRow == -1 && sharedMediaRow == -1 && membersSectionRow == -1 || position == secretSettingsSectionRow || position == lastSectionRow || position == membersSectionRow && lastSectionRow == -1 && sharedMediaRow == -1) { - sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, getThemedColor(Theme.key_windowBackgroundGrayShadow))); } else { - sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, getThemedColor(Theme.key_windowBackgroundGrayShadow))); } break; case VIEW_TYPE_USER: @@ -8167,8 +8262,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. break; case VIEW_TYPE_ADDTOGROUP_INFO: TextInfoPrivacyCell addToGroupInfo = (TextInfoPrivacyCell) holder.itemView; - addToGroupInfo.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); - addToGroupInfo.setText("This bot is able to manage a group or channel."); // TODO(dkaraush): text! + addToGroupInfo.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, getThemedColor(Theme.key_windowBackgroundGrayShadow))); + addToGroupInfo.setText(LocaleController.getString("BotAddToGroupOrChannelInfo", R.string.BotAddToGroupOrChannelInfo)); break; } } @@ -8187,9 +8282,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return position == notificationRow || position == numberRow || position == privacyRow || position == languageRow || position == setUsernameRow || position == bioRow || position == versionRow || position == dataRow || position == chatRow || - position == questionRow || position == devicesRow || position == filtersRow || + position == questionRow || position == devicesRow || position == filtersRow || position == stickersRow || position == faqRow || position == policyRow || position == sendLogsRow || position == sendLastLogsRow || - position == clearLogsRow || position == switchBackendRow || position == setAvatarRow || position == addToGroupButtonRow; + position == clearLogsRow || position == switchBackendRow || position == setAvatarRow || position == addToGroupButtonRow || position == premiumRow; } if (holder.itemView instanceof UserCell) { UserCell userCell = (UserCell) holder.itemView; @@ -8227,7 +8322,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. position == addMemberRow || position == joinRow || position == unblockRow || position == sendMessageRow || position == notificationRow || position == privacyRow || position == languageRow || position == dataRow || position == chatRow || - position == questionRow || position == devicesRow || position == filtersRow || + position == questionRow || position == devicesRow || position == filtersRow || position == stickersRow || position == faqRow || position == policyRow || position == sendLogsRow || position == sendLastLogsRow || position == clearLogsRow || position == switchBackendRow || position == setAvatarRow || position == addToGroupButtonRow) { return VIEW_TYPE_TEXT; @@ -8238,7 +8333,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } else if (position == infoSectionRow || position == lastSectionRow || position == membersSectionRow || position == secretSettingsSectionRow || position == settingsSectionRow || position == devicesSectionRow || position == helpSectionCell || position == setAvatarSectionRow || position == passwordSuggestionSectionRow || - position == phoneSuggestionSectionRow) { + position == phoneSuggestionSectionRow || position == premiumSectionsRow) { return VIEW_TYPE_SHADOW; } else if (position >= membersStartRow && position < membersEndRow) { return VIEW_TYPE_USER; @@ -8254,6 +8349,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return VIEW_TYPE_SUGGESTION; } else if (position == addToGroupInfoRow) { return VIEW_TYPE_ADDTOGROUP_INFO; + } else if (position == premiumRow) { + return VIEW_TYPE_PREMIUM_TEXT_CELL; } return 4; } @@ -8321,7 +8418,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } private SearchResult[] searchArray = new SearchResult[]{ - new SearchResult(500, LocaleController.getString("EditName", R.string.EditName), 0, () -> presentFragment(new ChangeNameActivity())), + new SearchResult(500, LocaleController.getString("EditName", R.string.EditName), 0, () -> presentFragment(new ChangeNameActivity(resourcesProvider))), new SearchResult(501, LocaleController.getString("ChangePhoneNumber", R.string.ChangePhoneNumber), 0, () -> presentFragment(new ActionIntroActivity(ActionIntroActivity.ACTION_TYPE_CHANGE_PHONE_NUMBER))), new SearchResult(502, LocaleController.getString("AddAnotherAccount", R.string.AddAnotherAccount), 0, () -> { int freeAccount; @@ -8341,90 +8438,90 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } }), - new SearchResult(1, LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(2, LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_PRIVATE, new ArrayList<>(), true))), - new SearchResult(3, LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_GROUP, new ArrayList<>(), true))), - new SearchResult(4, LocaleController.getString("NotificationsChannels", R.string.NotificationsChannels), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_CHANNEL, new ArrayList<>(), true))), - new SearchResult(5, LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings), "callsSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(6, LocaleController.getString("BadgeNumber", R.string.BadgeNumber), "badgeNumberSection", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(7, LocaleController.getString("InAppNotifications", R.string.InAppNotifications), "inappSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(8, LocaleController.getString("ContactJoined", R.string.ContactJoined), "contactJoinedRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(9, LocaleController.getString("PinnedMessages", R.string.PinnedMessages), "pinnedMessageRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(10, LocaleController.getString("ResetAllNotifications", R.string.ResetAllNotifications), "resetNotificationsRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.menu_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(1, LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(2, LocaleController.getString("NotificationsPrivateChats", R.string.NotificationsPrivateChats), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_PRIVATE, new ArrayList<>(), true))), + new SearchResult(3, LocaleController.getString("NotificationsGroups", R.string.NotificationsGroups), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_GROUP, new ArrayList<>(), true))), + new SearchResult(4, LocaleController.getString("NotificationsChannels", R.string.NotificationsChannels), LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsCustomSettingsActivity(NotificationsController.TYPE_CHANNEL, new ArrayList<>(), true))), + new SearchResult(5, LocaleController.getString("VoipNotificationSettings", R.string.VoipNotificationSettings), "callsSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(6, LocaleController.getString("BadgeNumber", R.string.BadgeNumber), "badgeNumberSection", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(7, LocaleController.getString("InAppNotifications", R.string.InAppNotifications), "inappSectionRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(8, LocaleController.getString("ContactJoined", R.string.ContactJoined), "contactJoinedRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(9, LocaleController.getString("PinnedMessages", R.string.PinnedMessages), "pinnedMessageRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), + new SearchResult(10, LocaleController.getString("ResetAllNotifications", R.string.ResetAllNotifications), "resetNotificationsRow", LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds), R.drawable.msg_notifications, () -> presentFragment(new NotificationsSettingsActivity())), - new SearchResult(100, LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(101, LocaleController.getString("BlockedUsers", R.string.BlockedUsers), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyUsersActivity())), - new SearchResult(105, LocaleController.getString("PrivacyPhone", R.string.PrivacyPhone), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_PHONE, true))), - new SearchResult(102, LocaleController.getString("PrivacyLastSeen", R.string.PrivacyLastSeen), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_LASTSEEN, true))), - new SearchResult(103, LocaleController.getString("PrivacyProfilePhoto", R.string.PrivacyProfilePhoto), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_PHOTO, true))), - new SearchResult(104, LocaleController.getString("PrivacyForwards", R.string.PrivacyForwards), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_FORWARDS, true))), - new SearchResult(122, LocaleController.getString("PrivacyP2P", R.string.PrivacyP2P), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_P2P, true))), - new SearchResult(106, LocaleController.getString("Calls", R.string.Calls), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_CALLS, true))), - new SearchResult(107, LocaleController.getString("GroupsAndChannels", R.string.GroupsAndChannels), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_INVITE, true))), - new SearchResult(108, LocaleController.getString("Passcode", R.string.Passcode), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(PasscodeActivity.determineOpenFragment())), - new SearchResult(109, LocaleController.getString("TwoStepVerification", R.string.TwoStepVerification), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new TwoStepVerificationActivity())), - new SearchResult(110, LocaleController.getString("SessionsTitle", R.string.SessionsTitle), R.drawable.menu_secret, () -> presentFragment(new SessionsActivity(0))), - getMessagesController().autoarchiveAvailable ? new SearchResult(121, LocaleController.getString("ArchiveAndMute", R.string.ArchiveAndMute), "newChatsRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())) : null, - new SearchResult(112, LocaleController.getString("DeleteAccountIfAwayFor2", R.string.DeleteAccountIfAwayFor2), "deleteAccountRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(113, LocaleController.getString("PrivacyPaymentsClear", R.string.PrivacyPaymentsClear), "paymentsClearRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(114, LocaleController.getString("WebSessionsTitle", R.string.WebSessionsTitle), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new SessionsActivity(1))), - new SearchResult(115, LocaleController.getString("SyncContactsDelete", R.string.SyncContactsDelete), "contactsDeleteRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(116, LocaleController.getString("SyncContacts", R.string.SyncContacts), "contactsSyncRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(117, LocaleController.getString("SuggestContacts", R.string.SuggestContacts), "contactsSuggestRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(118, LocaleController.getString("MapPreviewProvider", R.string.MapPreviewProvider), "secretMapRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(119, LocaleController.getString("SecretWebPage", R.string.SecretWebPage), "secretWebpageRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.menu_secret, () -> presentFragment(new PrivacySettingsActivity())), - new SearchResult(120, LocaleController.getString("Devices", R.string.Devices), R.drawable.menu_secret, () -> presentFragment(new SessionsActivity(0))), + new SearchResult(100, LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(101, LocaleController.getString("BlockedUsers", R.string.BlockedUsers), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyUsersActivity())), + new SearchResult(105, LocaleController.getString("PrivacyPhone", R.string.PrivacyPhone), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_PHONE, true))), + new SearchResult(102, LocaleController.getString("PrivacyLastSeen", R.string.PrivacyLastSeen), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_LASTSEEN, true))), + new SearchResult(103, LocaleController.getString("PrivacyProfilePhoto", R.string.PrivacyProfilePhoto), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_PHOTO, true))), + new SearchResult(104, LocaleController.getString("PrivacyForwards", R.string.PrivacyForwards), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_FORWARDS, true))), + new SearchResult(122, LocaleController.getString("PrivacyP2P", R.string.PrivacyP2P), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_P2P, true))), + new SearchResult(106, LocaleController.getString("Calls", R.string.Calls), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_CALLS, true))), + new SearchResult(107, LocaleController.getString("GroupsAndChannels", R.string.GroupsAndChannels), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacyControlActivity(ContactsController.PRIVACY_RULES_TYPE_INVITE, true))), + new SearchResult(108, LocaleController.getString("Passcode", R.string.Passcode), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(PasscodeActivity.determineOpenFragment())), + new SearchResult(109, LocaleController.getString("TwoStepVerification", R.string.TwoStepVerification), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new TwoStepVerificationActivity())), + new SearchResult(110, LocaleController.getString("SessionsTitle", R.string.SessionsTitle), R.drawable.msg_secret, () -> presentFragment(new SessionsActivity(0))), + getMessagesController().autoarchiveAvailable ? new SearchResult(121, LocaleController.getString("ArchiveAndMute", R.string.ArchiveAndMute), "newChatsRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())) : null, + new SearchResult(112, LocaleController.getString("DeleteAccountIfAwayFor2", R.string.DeleteAccountIfAwayFor2), "deleteAccountRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(113, LocaleController.getString("PrivacyPaymentsClear", R.string.PrivacyPaymentsClear), "paymentsClearRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(114, LocaleController.getString("WebSessionsTitle", R.string.WebSessionsTitle), LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new SessionsActivity(1))), + new SearchResult(115, LocaleController.getString("SyncContactsDelete", R.string.SyncContactsDelete), "contactsDeleteRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(116, LocaleController.getString("SyncContacts", R.string.SyncContacts), "contactsSyncRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(117, LocaleController.getString("SuggestContacts", R.string.SuggestContacts), "contactsSuggestRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(118, LocaleController.getString("MapPreviewProvider", R.string.MapPreviewProvider), "secretMapRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(119, LocaleController.getString("SecretWebPage", R.string.SecretWebPage), "secretWebpageRow", LocaleController.getString("PrivacySettings", R.string.PrivacySettings), R.drawable.msg_secret, () -> presentFragment(new PrivacySettingsActivity())), + new SearchResult(120, LocaleController.getString("Devices", R.string.Devices), R.drawable.msg_secret, () -> presentFragment(new SessionsActivity(0))), - new SearchResult(200, LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(201, LocaleController.getString("DataUsage", R.string.DataUsage), "usageSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(202, LocaleController.getString("StorageUsage", R.string.StorageUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), - new SearchResult(203, LocaleController.getString("KeepMedia", R.string.KeepMedia), "keepMediaRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), - new SearchResult(204, LocaleController.getString("ClearMediaCache", R.string.ClearMediaCache), "cacheRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), - new SearchResult(205, LocaleController.getString("LocalDatabase", R.string.LocalDatabase), "databaseRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.menu_data, () -> presentFragment(new CacheControlActivity())), - new SearchResult(206, LocaleController.getString("NetworkUsage", R.string.NetworkUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataUsageActivity())), - new SearchResult(207, LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload), "mediaDownloadSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(208, LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(0))), - new SearchResult(209, LocaleController.getString("WhenConnectedOnWiFi", R.string.WhenConnectedOnWiFi), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(1))), - new SearchResult(210, LocaleController.getString("WhenRoaming", R.string.WhenRoaming), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataAutoDownloadActivity(2))), - new SearchResult(211, LocaleController.getString("ResetAutomaticMediaDownload", R.string.ResetAutomaticMediaDownload), "resetDownloadRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(212, LocaleController.getString("AutoplayMedia", R.string.AutoplayMedia), "autoplayHeaderRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(213, LocaleController.getString("AutoplayGIF", R.string.AutoplayGIF), "autoplayGifsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(214, LocaleController.getString("AutoplayVideo", R.string.AutoplayVideo), "autoplayVideoRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(215, LocaleController.getString("Streaming", R.string.Streaming), "streamSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(216, LocaleController.getString("EnableStreaming", R.string.EnableStreaming), "enableStreamRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(217, LocaleController.getString("Calls", R.string.Calls), "callsSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(218, LocaleController.getString("VoipUseLessData", R.string.VoipUseLessData), "useLessDataForCallsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(219, LocaleController.getString("VoipQuickReplies", R.string.VoipQuickReplies), "quickRepliesRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(220, LocaleController.getString("ProxySettings", R.string.ProxySettings), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new ProxyListActivity())), - new SearchResult(221, LocaleController.getString("UseProxyForCalls", R.string.UseProxyForCalls), "callsRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("ProxySettings", R.string.ProxySettings), R.drawable.menu_data, () -> presentFragment(new ProxyListActivity())), - new SearchResult(111, LocaleController.getString("PrivacyDeleteCloudDrafts", R.string.PrivacyDeleteCloudDrafts), "clearDraftsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.menu_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(200, LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(201, LocaleController.getString("DataUsage", R.string.DataUsage), "usageSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(202, LocaleController.getString("StorageUsage", R.string.StorageUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(203, LocaleController.getString("KeepMedia", R.string.KeepMedia), "keepMediaRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.msg_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(204, LocaleController.getString("ClearMediaCache", R.string.ClearMediaCache), "cacheRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.msg_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(205, LocaleController.getString("LocalDatabase", R.string.LocalDatabase), "databaseRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("StorageUsage", R.string.StorageUsage), R.drawable.msg_data, () -> presentFragment(new CacheControlActivity())), + new SearchResult(206, LocaleController.getString("NetworkUsage", R.string.NetworkUsage), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataUsageActivity())), + new SearchResult(207, LocaleController.getString("AutomaticMediaDownload", R.string.AutomaticMediaDownload), "mediaDownloadSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(208, LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataAutoDownloadActivity(0))), + new SearchResult(209, LocaleController.getString("WhenConnectedOnWiFi", R.string.WhenConnectedOnWiFi), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataAutoDownloadActivity(1))), + new SearchResult(210, LocaleController.getString("WhenRoaming", R.string.WhenRoaming), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataAutoDownloadActivity(2))), + new SearchResult(211, LocaleController.getString("ResetAutomaticMediaDownload", R.string.ResetAutomaticMediaDownload), "resetDownloadRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(212, LocaleController.getString("AutoplayMedia", R.string.AutoplayMedia), "autoplayHeaderRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(213, LocaleController.getString("AutoplayGIF", R.string.AutoplayGIF), "autoplayGifsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(214, LocaleController.getString("AutoplayVideo", R.string.AutoplayVideo), "autoplayVideoRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(215, LocaleController.getString("Streaming", R.string.Streaming), "streamSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(216, LocaleController.getString("EnableStreaming", R.string.EnableStreaming), "enableStreamRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(217, LocaleController.getString("Calls", R.string.Calls), "callsSectionRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(218, LocaleController.getString("VoipUseLessData", R.string.VoipUseLessData), "useLessDataForCallsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(219, LocaleController.getString("VoipQuickReplies", R.string.VoipQuickReplies), "quickRepliesRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), + new SearchResult(220, LocaleController.getString("ProxySettings", R.string.ProxySettings), LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new ProxyListActivity())), + new SearchResult(221, LocaleController.getString("UseProxyForCalls", R.string.UseProxyForCalls), "callsRow", LocaleController.getString("DataSettings", R.string.DataSettings), LocaleController.getString("ProxySettings", R.string.ProxySettings), R.drawable.msg_data, () -> presentFragment(new ProxyListActivity())), + new SearchResult(111, LocaleController.getString("PrivacyDeleteCloudDrafts", R.string.PrivacyDeleteCloudDrafts), "clearDraftsRow", LocaleController.getString("DataSettings", R.string.DataSettings), R.drawable.msg_data, () -> presentFragment(new DataSettingsActivity())), - new SearchResult(300, LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(301, LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader), "textSizeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(302, LocaleController.getString("ChatBackground", R.string.ChatBackground), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), - new SearchResult(303, LocaleController.getString("SetColor", R.string.SetColor), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_COLOR))), - new SearchResult(304, LocaleController.getString("ResetChatBackgrounds", R.string.ResetChatBackgrounds), "resetRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.menu_chats, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), - new SearchResult(305, LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT))), - new SearchResult(306, LocaleController.getString("ColorTheme", R.string.ColorTheme), "themeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(307, LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), "customTabsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(308, LocaleController.getString("DirectShare", R.string.DirectShare), "directShareRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(309, LocaleController.getString("EnableAnimations", R.string.EnableAnimations), "enableAnimationsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(310, LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), "raiseToSpeakRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(311, LocaleController.getString("SendByEnter", R.string.SendByEnter), "sendByEnterRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(312, LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), "saveToGalleryRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(318, LocaleController.getString("DistanceUnits", R.string.DistanceUnits), "distanceRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), - new SearchResult(313, LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE))), - new SearchResult(314, LocaleController.getString("SuggestStickers", R.string.SuggestStickers), "suggestRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE))), - new SearchResult(315, LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new FeaturedStickersActivity())), - new SearchResult(316, LocaleController.getString("Masks", R.string.Masks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_MASK))), - new SearchResult(317, LocaleController.getString("ArchivedStickers", R.string.ArchivedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new ArchivedStickersActivity(MediaDataController.TYPE_IMAGE))), - new SearchResult(317, LocaleController.getString("ArchivedMasks", R.string.ArchivedMasks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.menu_chats, () -> presentFragment(new ArchivedStickersActivity(MediaDataController.TYPE_MASK))), + new SearchResult(300, LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(301, LocaleController.getString("TextSizeHeader", R.string.TextSizeHeader), "textSizeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(302, LocaleController.getString("ChatBackground", R.string.ChatBackground), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), + new SearchResult(303, LocaleController.getString("SetColor", R.string.SetColor), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.msg_msgbubble3, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_COLOR))), + new SearchResult(304, LocaleController.getString("ResetChatBackgrounds", R.string.ResetChatBackgrounds), "resetRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("ChatBackground", R.string.ChatBackground), R.drawable.msg_msgbubble3, () -> presentFragment(new WallpapersListActivity(WallpapersListActivity.TYPE_ALL))), + new SearchResult(305, LocaleController.getString("AutoNightTheme", R.string.AutoNightTheme), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT))), + new SearchResult(306, LocaleController.getString("ColorTheme", R.string.ColorTheme), "themeHeaderRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(307, LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), "customTabsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(308, LocaleController.getString("DirectShare", R.string.DirectShare), "directShareRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(309, LocaleController.getString("EnableAnimations", R.string.EnableAnimations), "enableAnimationsRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(310, LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), "raiseToSpeakRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(311, LocaleController.getString("SendByEnter", R.string.SendByEnter), "sendByEnterRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(312, LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), "saveToGalleryRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(318, LocaleController.getString("DistanceUnits", R.string.DistanceUnits), "distanceRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_BASIC))), + new SearchResult(313, LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), LocaleController.getString("ChatSettings", R.string.ChatSettings), R.drawable.msg_msgbubble3, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE))), + new SearchResult(314, LocaleController.getString("SuggestStickers", R.string.SuggestStickers), "suggestRow", LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.msg_msgbubble3, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE))), + new SearchResult(315, LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.msg_msgbubble3, () -> presentFragment(new FeaturedStickersActivity())), + new SearchResult(316, LocaleController.getString("Masks", R.string.Masks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.msg_msgbubble3, () -> presentFragment(new StickersActivity(MediaDataController.TYPE_MASK))), + new SearchResult(317, LocaleController.getString("ArchivedStickers", R.string.ArchivedStickers), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.msg_msgbubble3, () -> presentFragment(new ArchivedStickersActivity(MediaDataController.TYPE_IMAGE))), + new SearchResult(317, LocaleController.getString("ArchivedMasks", R.string.ArchivedMasks), null, LocaleController.getString("ChatSettings", R.string.ChatSettings), LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), R.drawable.msg_msgbubble3, () -> presentFragment(new ArchivedStickersActivity(MediaDataController.TYPE_MASK))), - new SearchResult(400, LocaleController.getString("Language", R.string.Language), R.drawable.menu_language, () -> presentFragment(new LanguageSelectActivity())), + new SearchResult(400, LocaleController.getString("Language", R.string.Language), R.drawable.msg_language, () -> presentFragment(new LanguageSelectActivity())), - new SearchResult(402, LocaleController.getString("AskAQuestion", R.string.AskAQuestion), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> showDialog(AlertsCreator.createSupportAlert(ProfileActivity.this))), - new SearchResult(403, LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl))), - new SearchResult(404, LocaleController.getString("PrivacyPolicy", R.string.PrivacyPolicy), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.menu_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("PrivacyPolicyUrl", R.string.PrivacyPolicyUrl))), + new SearchResult(402, LocaleController.getString("AskAQuestion", R.string.AskAQuestion), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.msg_help, () -> showDialog(AlertsCreator.createSupportAlert(ProfileActivity.this, null))), + new SearchResult(403, LocaleController.getString("TelegramFAQ", R.string.TelegramFAQ), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.msg_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("TelegramFaqUrl", R.string.TelegramFaqUrl))), + new SearchResult(404, LocaleController.getString("PrivacyPolicy", R.string.PrivacyPolicy), LocaleController.getString("SettingsHelp", R.string.SettingsHelp), R.drawable.msg_help, () -> Browser.openUrl(getParentActivity(), LocaleController.getString("PrivacyPolicyUrl", R.string.PrivacyPolicyUrl))), }; private ArrayList faqSearchArray = new ArrayList<>(); @@ -8757,7 +8854,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (stringBuilder == null) { stringBuilder = new SpannableStringBuilder(result.searchTitle); } - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { break; } @@ -8797,7 +8894,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (stringBuilder == null) { stringBuilder = new SpannableStringBuilder(result.title); } - stringBuilder.setSpan(new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + stringBuilder.setSpan(new ForegroundColorSpan(getThemedColor(Theme.key_windowBackgroundWhiteBlueText4)), index, index + searchString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } else { break; } @@ -8833,19 +8930,41 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } + private void openUrl(String url) { + if (url.startsWith("@")) { + getMessagesController().openByUserName(url.substring(1), ProfileActivity.this, 0); + } else if (url.startsWith("#")) { + DialogsActivity fragment = new DialogsActivity(null); + fragment.setSearchString(url); + presentFragment(fragment); + } else if (url.startsWith("/")) { + if (parentLayout.fragmentsStack.size() > 1) { + BaseFragment previousFragment = parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 2); + if (previousFragment instanceof ChatActivity) { + finishFragment(); + ((ChatActivity) previousFragment).chatActivityEnterView.setCommand(null, url, false, false); + } + } + } + } + private void dimBehindView(View view, boolean enable) { scrimView = view; dimBehindView(enable); } + private void dimBehindView(View view, float value) { scrimView = view; dimBehindView(value); } + private void dimBehindView(boolean enable) { dimBehindView(enable ? 0.2f : 0); } + private AnimatorSet scrimAnimatorSet = null; + private void dimBehindView(float value) { boolean enable = value > 0; fragmentView.invalidate(); @@ -8879,6 +8998,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. @Override public ArrayList getThemeDescriptions() { + if (resourcesProvider != null) { + return null; + } ThemeDescription.ThemeDescriptionDelegate themeDelegate = () -> { if (listView != null) { int count = listView.getChildCount(); @@ -8893,24 +9015,24 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (onlineTextView[1] != null) { final Object onlineTextViewTag = onlineTextView[1].getTag(); if (onlineTextViewTag instanceof String) { - onlineTextView[1].setTextColor(Theme.getColor((String) onlineTextViewTag)); + onlineTextView[1].setTextColor(getThemedColor((String) onlineTextViewTag)); } else { - onlineTextView[1].setTextColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); + onlineTextView[1].setTextColor(getThemedColor(Theme.key_avatar_subtitleInProfileBlue)); } } if (lockIconDrawable != null) { - lockIconDrawable.setColorFilter(Theme.getColor(Theme.key_chat_lockIcon), PorterDuff.Mode.SRC_IN); + lockIconDrawable.setColorFilter(getThemedColor(Theme.key_chat_lockIcon), PorterDuff.Mode.SRC_IN); } if (scamDrawable != null) { - scamDrawable.setColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); + scamDrawable.setColor(getThemedColor(Theme.key_avatar_subtitleInProfileBlue)); } if (nameTextView[1] != null) { - nameTextView[1].setTextColor(Theme.getColor(Theme.key_profile_title)); + nameTextView[1].setTextColor(getThemedColor(Theme.key_profile_title)); idTextView.setTextColor(Theme.getColor(Theme.key_avatar_subtitleInProfileBlue)); } if (actionBar != null) { - actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon), false); - actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_avatar_actionBarSelectorBlue), false); + actionBar.setItemsColor(getThemedColor(Theme.key_actionBarDefaultIcon), false); + actionBar.setItemsBackgroundColor(getThemedColor(Theme.key_avatar_actionBarSelectorBlue), false); } } }; @@ -9116,15 +9238,37 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. Drawable shadowDrawable = fragmentView.getContext().getResources().getDrawable(R.drawable.floating_shadow_profile).mutate(); shadowDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY)); CombinedDrawable combinedDrawable = new CombinedDrawable(shadowDrawable, - Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), Theme.getColor(Theme.key_profile_actionBackground), Theme.getColor(Theme.key_profile_actionPressedBackground)), + Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(56), getThemedColor(Theme.key_profile_actionBackground), getThemedColor(Theme.key_profile_actionPressedBackground)), 0, 0); combinedDrawable.setIconSize(AndroidUtilities.dp(56), AndroidUtilities.dp(56)); writeButton.setBackground(combinedDrawable); - } catch (Exception e) {} + } catch (Exception e) { + } } private boolean isQrNeedVisible() { - return !TextUtils.isEmpty(getUserConfig().getCurrentUser().username); + if (!TextUtils.isEmpty(getUserConfig().getCurrentUser().username)) { + return true; + } + final ArrayList privacyRules = ContactsController.getInstance(currentAccount).getPrivacyRules(ContactsController.PRIVACY_RULES_TYPE_PHONE); + if (privacyRules == null) { + return false; + } + int type = 2; + for (int i = 0; i < privacyRules.size(); ++i) { + TLRPC.PrivacyRule rule = privacyRules.get(i); + if (rule instanceof TLRPC.TL_privacyValueAllowAll) { + type = 0; + break; + } else if (rule instanceof TLRPC.TL_privacyValueDisallowAll) { + type = 2; + break; + } else if (rule instanceof TLRPC.TL_privacyValueAllowContacts) { + type = 1; + break; + } + } + return type == 0 || type == 1; } private class DiffCallback extends DiffUtil.Callback { @@ -9195,10 +9339,13 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. put(++pointer, settingsSectionRow2, sparseIntArray); put(++pointer, notificationRow, sparseIntArray); put(++pointer, languageRow, sparseIntArray); + put(++pointer, premiumRow, sparseIntArray); + put(++pointer, premiumSectionsRow, sparseIntArray); put(++pointer, privacyRow, sparseIntArray); put(++pointer, dataRow, sparseIntArray); put(++pointer, chatRow, sparseIntArray); put(++pointer, filtersRow, sparseIntArray); + put(++pointer, stickersRow, sparseIntArray); put(++pointer, devicesRow, sparseIntArray); put(++pointer, devicesSectionRow, sparseIntArray); put(++pointer, helpHeaderRow, sparseIntArray); @@ -9257,11 +9404,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. return false; } if (actionBar.isActionModeShowed()) { - color = Theme.getColor(Theme.key_actionBarActionModeDefault); + color = getThemedColor(Theme.key_actionBarActionModeDefault); } else if (mediaHeaderVisible) { - color = Theme.getColor(Theme.key_windowBackgroundWhite); + color = getThemedColor(Theme.key_windowBackgroundWhite); } else { - color = Theme.getColor(Theme.key_actionBarDefault); + color = getThemedColor(Theme.key_actionBarDefault); } return ColorUtils.calculateLuminance(color) > 0.7f; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index 070ad4fcf..2138b09ae 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -11,8 +11,10 @@ package org.telegram.ui; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.media.Ringtone; @@ -25,7 +27,9 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -52,6 +56,7 @@ import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.ActionBar; import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.AlertDialog; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; @@ -76,20 +81,18 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private RecyclerListView listView; private ListAdapter adapter; private AnimatorSet animatorSet; + private Theme.ResourcesProvider resourcesProvider; private long dialogId; private boolean addingException; - private boolean customEnabled; private boolean notificationsEnabled; private ProfileNotificationsActivityDelegate delegate; ChatAvatarContainer avatarContainer; - private int customRow; - private int customInfoRow; private int generalRow; private int avatarRow; private int avatarSectionRow; @@ -101,6 +104,8 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private int priorityRow; private int priorityInfoRow; private int popupRow; +// private int popupEnabledRow; +// private int popupDisabledRow; private int popupInfoRow; private int callsRow; private int ringtoneRow; @@ -109,6 +114,8 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private int ledRow; private int colorRow; private int ledInfoRow; + private int customResetRow; + private int customResetShadowRow; private int disableMentionNotificationsRow; private int disableMentionNotificationsInfoRow; @@ -118,31 +125,36 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi private int rowCount; + private boolean needReset; + private final static int done_button = 1; public interface ProfileNotificationsActivityDelegate { void didCreateNewException(NotificationsSettingsActivity.NotificationException exception); + default void didRemoveException(long dialog_id) {} } public ProfileNotificationsActivity(Bundle args) { + this(args, null); + } + + public ProfileNotificationsActivity(Bundle args, Theme.ResourcesProvider resourcesProvider) { super(args); + this.resourcesProvider = resourcesProvider; dialogId = args.getLong("dialog_id"); addingException = args.getBoolean("exception", false); } + @Override public boolean onFragmentCreate() { rowCount = 0; if (addingException) { avatarRow = rowCount++; avatarSectionRow = rowCount++; - customRow = -1; - customInfoRow = -1; } else { avatarRow = -1; avatarSectionRow = -1; - customRow = rowCount++; - customInfoRow = rowCount++; } generalRow = rowCount++; if (addingException) { @@ -201,23 +213,35 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi colorRow = rowCount++; ledInfoRow = rowCount++; - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - customEnabled = preferences.getBoolean("custom_" + dialogId, false) || addingException; - - boolean hasOverride = preferences.contains("notify2_" + dialogId); - int value = preferences.getInt("notify2_" + dialogId, 0); - if (value == 0) { - if (hasOverride) { - notificationsEnabled = true; - } else { - notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); - } - } else if (value == 1) { - notificationsEnabled = true; - } else if (value == 2) { - notificationsEnabled = false; + if (!addingException) { + customResetRow = rowCount++; + customResetShadowRow = rowCount++; } else { - notificationsEnabled = false; + customResetRow = -1; + customResetShadowRow = -1; + } + + boolean defaultEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + if (addingException) { + notificationsEnabled = !defaultEnabled; + } else { + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + + boolean hasOverride = preferences.contains("notify2_" + dialogId); + int value = preferences.getInt("notify2_" + dialogId, 0); + if (value == 0) { + if (hasOverride) { + notificationsEnabled = true; + } else { + notificationsEnabled = NotificationsController.getInstance(currentAccount).isGlobalNotificationsEnabled(dialogId); + } + } else if (value == 1) { + notificationsEnabled = true; + } else if (value == 2) { + notificationsEnabled = false; + } else { + notificationsEnabled = false; + } } NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.notificationsSettingsUpdated); @@ -227,26 +251,35 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public void onFragmentDestroy() { super.onFragmentDestroy(); + if (!needReset) { + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("custom_" + dialogId, true).apply(); + } NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.notificationsSettingsUpdated); } + @Override + public Theme.ResourcesProvider getResourceProvider() { + return resourcesProvider; + } + @Override public View createView(final Context context) { + actionBar.setItemsBackgroundColor(Theme.getColor(Theme.key_avatar_actionBarSelectorBlue, resourcesProvider), false); + actionBar.setItemsColor(Theme.getColor(Theme.key_actionBarDefaultIcon, resourcesProvider), false); actionBar.setBackButtonImage(R.drawable.ic_ab_back); actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() { @Override public void onItemClick(int id) { if (id == -1) { - if (!addingException && notificationsEnabled && customEnabled) { + if (!addingException && notificationsEnabled) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putInt("notify2_" + dialogId, 0).commit(); + preferences.edit().putInt("notify2_" + dialogId, 0).apply(); } } else if (id == done_button) { SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); SharedPreferences.Editor editor = preferences.edit(); editor.putBoolean("custom_" + dialogId, true); - TLRPC.Dialog dialog = MessagesController.getInstance(currentAccount).dialogs_dict.get(dialogId); if (notificationsEnabled) { editor.putInt("notify2_" + dialogId, 0); @@ -264,7 +297,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } } - editor.commit(); + editor.apply(); NotificationsController.getInstance(currentAccount).updateServerNotificationsSettings(dialogId); if (delegate != null) { NotificationsSettingsActivity.NotificationException exception = new NotificationsSettingsActivity.NotificationException(); @@ -281,7 +314,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } }); - avatarContainer = new ChatAvatarContainer(context, null, false); + avatarContainer = new ChatAvatarContainer(context, null, false, resourcesProvider); avatarContainer.setOccupyStatusBar(!AndroidUtilities.isTablet()); actionBar.addView(avatarContainer, 0, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, !inPreviewMode ? 56 : 0, 0, 40, 0)); @@ -307,7 +340,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; - frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); + frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray, resourcesProvider)); listView = new RecyclerListView(context); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); @@ -320,138 +353,134 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi return false; } }); - listView.setOnItemClickListener(new RecyclerListView.OnItemClickListener() { - @Override - public void onItemClick(View view, int position) { - if (position == customRow && view instanceof TextCheckCell) { - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - customEnabled = !customEnabled; - notificationsEnabled = customEnabled; - preferences.edit().putBoolean("custom_" + dialogId, customEnabled).apply(); - TextCheckCell cell = (TextCheckCell) view; - cell.setChecked(customEnabled); - int clr = Theme.getColor(customEnabled ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked); - if (customEnabled) { - cell.setBackgroundColorAnimated(customEnabled, clr); - } else { - cell.setBackgroundColorAnimatedReverse(clr); - } - checkRowsEnabled(); - } else if (customEnabled) { - if (!view.isEnabled()) { - return; - } - if (position == soundRow) { - Bundle bundle = new Bundle(); - bundle.putLong("dialog_id", dialogId); - presentFragment(new NotificationsSoundActivity(bundle)); - } else if (position == ringtoneRow) { - try { - Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - Uri currentSound = null; - - String defaultPath = null; - Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI; - if (defaultUri != null) { - defaultPath = defaultUri.getPath(); - } - - String path = preferences.getString("ringtone_path_" + dialogId, defaultPath); - if (path != null && !path.equals("NoSound")) { - if (path.equals(defaultPath)) { - currentSound = defaultUri; - } else { - currentSound = Uri.parse(path); - } - } - - tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentSound); - startActivityForResult(tmpIntent, 13); - } catch (Exception e) { - FileLog.e(e); - } - } else if (position == vibrateRow) { - showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), dialogId, false, false, () -> { - if (adapter != null) { - adapter.notifyItemChanged(vibrateRow); - } - })); - } else if (position == enableRow) { - TextCheckCell checkCell = (TextCheckCell) view; - notificationsEnabled = !checkCell.isChecked(); - checkCell.setChecked(notificationsEnabled); - checkRowsEnabled(); - } else if (position == previewRow) { - TextCheckCell checkCell = (TextCheckCell) view; - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - preferences.edit().putBoolean("content_preview_" + dialogId, !checkCell.isChecked()).commit(); - checkCell.setChecked(!checkCell.isChecked()); - } else if (position == callsVibrateRow) { - showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), dialogId, "calls_vibrate_" + dialogId, () -> { - if (adapter != null) { - adapter.notifyItemChanged(callsVibrateRow); - } - })); - } else if (position == priorityRow) { - showDialog(AlertsCreator.createPrioritySelectDialog(getParentActivity(), dialogId, -1, () -> { - if (adapter != null) { - adapter.notifyItemChanged(priorityRow); - } - })); - } else if (position == smartRow) { - if (getParentActivity() == null) { - return; - } - final Context context1 = getParentActivity(); - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - int notifyMaxCount = preferences.getInt("smart_max_count_" + dialogId, 2); - int notifyDelay = preferences.getInt("smart_delay_" + dialogId, 3 * 60); - if (notifyMaxCount == 0) { - notifyMaxCount = 2; - } - AlertsCreator.createSoundFrequencyPickerDialog(getParentActivity(), notifyMaxCount, notifyDelay, (time, minute) -> { - MessagesController.getNotificationsSettings(currentAccount).edit() - .putInt("smart_max_count_" + dialogId, time) - .putInt("smart_delay_" + dialogId, minute) - .apply(); - if (adapter != null) { - adapter.notifyItemChanged(smartRow); - } - }); - } else if (position == colorRow) { - if (getParentActivity() == null) { - return; - } - showDialog(AlertsCreator.createColorSelectDialog(getParentActivity(), dialogId, -1, () -> { - if (adapter != null) { - adapter.notifyItemChanged(colorRow); - } - })); - } else if (position == popupRow) { - SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - int popup = preferences.getInt("popup_" + dialogId, 0); - if (popup == -1) { - popup = preferences.getInt((int) dialogId < 0 ? "popupGroup" : "popupAll", 0); - if (popup != 0) { - popup = 1; - } else { - popup = 2; - } - } - if (popup == 1) popup = 2; - else popup = 1; - preferences.edit().putInt("popup_" + dialogId, popup).apply(); - - ((TextCheckCell) view).setChecked(popup == 1); - adapter.notifyItemChanged(position); - } - } + listView.setOnItemClickListener((view, position) -> { + if (!view.isEnabled()) { + return; } + if (position == customResetRow) { + AlertDialog dialog = new AlertDialog.Builder(context, resourcesProvider) + .setTitle(LocaleController.getString(R.string.ResetCustomNotificationsAlertTitle)) + .setMessage(LocaleController.getString(R.string.ResetCustomNotificationsAlert)) + .setPositiveButton(LocaleController.getString(R.string.Reset), (d, w) -> { + needReset = true; + + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("custom_" + dialogId, false).remove("notify2_" + dialogId).apply(); + finishFragment(); + if (delegate != null) { + delegate.didRemoveException(dialogId); + } + }) + .setNegativeButton(LocaleController.getString(R.string.Cancel), null) + .create(); + showDialog(dialog); + TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); + if (button != null) { + button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); + } + } else if (position == soundRow) { + Bundle bundle = new Bundle(); + bundle.putLong("dialog_id", dialogId); + presentFragment(new NotificationsSoundActivity(bundle, resourcesProvider)); + } else if (position == ringtoneRow) { + try { + Intent tmpIntent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)); + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + Uri currentSound = null; + + String defaultPath = null; + Uri defaultUri = Settings.System.DEFAULT_NOTIFICATION_URI; + if (defaultUri != null) { + defaultPath = defaultUri.getPath(); + } + + String path = preferences.getString("ringtone_path_" + dialogId, defaultPath); + if (path != null && !path.equals("NoSound")) { + if (path.equals(defaultPath)) { + currentSound = defaultUri; + } else { + currentSound = Uri.parse(path); + } + } + + tmpIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, currentSound); + startActivityForResult(tmpIntent, 13); + } catch (Exception e) { + FileLog.e(e); + } + } else if (position == vibrateRow) { + showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), dialogId, false, false, () -> { + if (adapter != null) { + adapter.notifyItemChanged(vibrateRow); + } + }, resourcesProvider)); + } else if (position == enableRow) { + TextCheckCell checkCell = (TextCheckCell) view; + notificationsEnabled = !checkCell.isChecked(); + checkCell.setChecked(notificationsEnabled); + checkRowsEnabled(); + } else if (position == previewRow) { + TextCheckCell checkCell = (TextCheckCell) view; + MessagesController.getNotificationsSettings(currentAccount).edit().putBoolean("content_preview_" + dialogId, !checkCell.isChecked()).apply(); + checkCell.setChecked(!checkCell.isChecked()); + } else if (position == callsVibrateRow) { + showDialog(AlertsCreator.createVibrationSelectDialog(getParentActivity(), dialogId, "calls_vibrate_" + dialogId, () -> { + if (adapter != null) { + adapter.notifyItemChanged(callsVibrateRow); + } + }, resourcesProvider)); + } else if (position == priorityRow) { + showDialog(AlertsCreator.createPrioritySelectDialog(getParentActivity(), dialogId, -1, () -> { + if (adapter != null) { + adapter.notifyItemChanged(priorityRow); + } + }, resourcesProvider)); + } else if (position == smartRow) { + if (getParentActivity() == null) { + return; + } + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + int notifyMaxCount = preferences.getInt("smart_max_count_" + dialogId, 2); + int notifyDelay = preferences.getInt("smart_delay_" + dialogId, 3 * 60); + if (notifyMaxCount == 0) { + notifyMaxCount = 2; + } + AlertsCreator.createSoundFrequencyPickerDialog(getParentActivity(), notifyMaxCount, notifyDelay, (time, minute) -> { + MessagesController.getNotificationsSettings(currentAccount).edit() + .putInt("smart_max_count_" + dialogId, time) + .putInt("smart_delay_" + dialogId, minute) + .apply(); + if (adapter != null) { + adapter.notifyItemChanged(smartRow); + } + }, resourcesProvider); + } else if (position == colorRow) { + if (getParentActivity() == null) { + return; + } + showDialog(AlertsCreator.createColorSelectDialog(getParentActivity(), dialogId, -1, () -> { + if (adapter != null) { + adapter.notifyItemChanged(colorRow); + } + }, resourcesProvider)); + } /* else if (position == popupEnabledRow) { + MessagesController.getNotificationsSettings(currentAccount).edit().putInt("popup_" + dialogId, 1).apply(); + ((RadioCell) view).setChecked(true, true); + view = listView.findViewWithTag(2); + if (view != null) { + ((RadioCell) view).setChecked(false, true); + } + } else if (position == popupDisabledRow) { + MessagesController.getNotificationsSettings(currentAccount).edit().putInt("popup_" + dialogId, 2).apply(); + ((RadioCell) view).setChecked(true, true); + view = listView.findViewWithTag(1); + if (view != null) { + ((RadioCell) view).setChecked(false, true); + } + } */ }); return fragmentView; @@ -506,21 +535,20 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi editor.putString("ringtone_path_" + dialogId, "NoSound"); } } - editor.commit(); + editor.apply(); if (adapter != null) { adapter.notifyItemChanged(requestCode == 13 ? ringtoneRow : soundRow); } } } + @SuppressLint("NotifyDataSetChanged") @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.notificationsSettingsUpdated) { try { adapter.notifyDataSetChanged(); - } catch (Exception e) { - - } + } catch (Exception ignored) {} } } @@ -536,32 +564,37 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi RecyclerListView.Holder holder = (RecyclerListView.Holder) listView.getChildViewHolder(child); int type = holder.getItemViewType(); int position = holder.getAdapterPosition(); - if (position != customRow && position != enableRow) { + if (position != enableRow && position != customResetRow) { switch (type) { - case 0: { + case ListAdapter.VIEW_TYPE_HEADER: { HeaderCell textCell = (HeaderCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, animators); + textCell.setEnabled(notificationsEnabled, animators); break; } - case 1: { + case ListAdapter.VIEW_TYPE_TEXT_SETTINGS: { TextSettingsCell textCell = (TextSettingsCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, animators); + textCell.setEnabled(notificationsEnabled, animators); break; } - case 2: { + case ListAdapter.VIEW_TYPE_INFO: { TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, animators); + textCell.setEnabled(notificationsEnabled, animators); break; } - case 3: { + case ListAdapter.VIEW_TYPE_TEXT_COLOR: { TextColorCell textCell = (TextColorCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, animators); + textCell.setEnabled(notificationsEnabled, animators); break; } - case 8: { + case ListAdapter.VIEW_TYPE_RADIO: { + RadioCell radioCell = (RadioCell) holder.itemView; + radioCell.setEnabled(notificationsEnabled, animators); + break; + } + case ListAdapter.VIEW_TYPE_TEXT_CHECK: { if (position == previewRow || position == popupRow) { TextCheckCell checkCell = (TextCheckCell) holder.itemView; - checkCell.setEnabled(customEnabled && notificationsEnabled, animators); + checkCell.setEnabled(notificationsEnabled, animators); } break; } @@ -588,6 +621,14 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } private class ListAdapter extends RecyclerListView.SelectionAdapter { + private final static int VIEW_TYPE_HEADER = 0, + VIEW_TYPE_TEXT_SETTINGS = 1, + VIEW_TYPE_INFO = 2, + VIEW_TYPE_TEXT_COLOR = 3, + VIEW_TYPE_RADIO = 4, + VIEW_TYPE_USER = 5, + VIEW_TYPE_SHADOW = 6, + VIEW_TYPE_TEXT_CHECK = 7; private Context context; @@ -602,64 +643,68 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { - int position = holder.getAdapterPosition(); + if (holder.getAdapterPosition() == previewRow) { + return notificationsEnabled; + } else if (holder.getAdapterPosition() == customResetRow) { + return true; + } switch (holder.getItemViewType()) { - case 1: - case 3: - case 0: - case 2: - case 6: - case 7: { + case VIEW_TYPE_TEXT_SETTINGS: + case VIEW_TYPE_TEXT_COLOR: + case VIEW_TYPE_RADIO: { + return notificationsEnabled; + } + case VIEW_TYPE_HEADER: + case VIEW_TYPE_INFO: + case VIEW_TYPE_USER: + case VIEW_TYPE_SHADOW: { return false; } - case 8: { - if (position == previewRow || position == popupRow) { - return customEnabled && notificationsEnabled; - } else { - return true; - } + case VIEW_TYPE_TEXT_CHECK: { + return true; } } return true; } + @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: - view = new HeaderCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + case VIEW_TYPE_HEADER: + view = new HeaderCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; - case 1: - view = new TextSettingsCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + case VIEW_TYPE_TEXT_SETTINGS: + view = new TextSettingsCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; - case 2: - view = new TextInfoPrivacyCell(context); + case VIEW_TYPE_INFO: + view = new TextInfoPrivacyCell(context, resourcesProvider); break; - case 3: - view = new TextColorCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + case VIEW_TYPE_TEXT_COLOR: + view = new TextColorCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; - case 5: + case VIEW_TYPE_RADIO: + view = new RadioCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + break; + case VIEW_TYPE_USER: TextCheckCell checkBoxCell = new TextCheckCell(context); checkBoxCell.setHeight(56); checkBoxCell.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); checkBoxCell.setColors(Theme.key_windowBackgroundCheckText, Theme.key_switchTrackBlue, Theme.key_switchTrackBlueChecked, Theme.key_switchTrackBlueThumb, Theme.key_switchTrackBlueThumbChecked); view = checkBoxCell; break; - case 6: - view = new UserCell2(context, 4, 0); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + case VIEW_TYPE_SHADOW: + view = new ShadowSectionCell(context, resourcesProvider); break; - case 7: - view = new ShadowSectionCell(context); - break; - case 8: + case VIEW_TYPE_TEXT_CHECK: default: - view = new TextCheckCell(context); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + view = new TextCheckCell(context, resourcesProvider); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); break; } view.setLayoutParams(new RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT, RecyclerView.LayoutParams.WRAP_CONTENT)); @@ -669,7 +714,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 0: { + case VIEW_TYPE_HEADER: { HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == generalRow) { headerCell.setText(LocaleController.getString("General", R.string.General)); @@ -680,103 +725,106 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } break; } - case 1: { + case VIEW_TYPE_TEXT_SETTINGS: { TextSettingsCell textCell = (TextSettingsCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); - if (position == soundRow) { - String value = preferences.getString("sound_" + dialogId, LocaleController.getString("SoundDefault", R.string.SoundDefault)); - long documentId = preferences.getLong("sound_document_id_" + dialogId, 0); - if (documentId != 0) { - TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId); - if (document == null) { - value = LocaleController.getString("CustomSound", R.string.CustomSound); - } else { - value = NotificationsSoundActivity.trimTitle(document, document.file_name_fixed); + if (position == customResetRow) { + textCell.setText(LocaleController.getString(R.string.ResetCustomNotifications), false); + textCell.setTextColor(getThemedColor(Theme.key_dialogTextRed)); + } else { + textCell.setTextColor(getThemedColor(Theme.key_windowBackgroundWhiteBlackText)); + if (position == soundRow) { + String value = preferences.getString("sound_" + dialogId, LocaleController.getString("SoundDefault", R.string.SoundDefault)); + long documentId = preferences.getLong("sound_document_id_" + dialogId, 0); + if (documentId != 0) { + TLRPC.Document document = getMediaDataController().ringtoneDataStore.getDocument(documentId); + if (document == null) { + value = LocaleController.getString("CustomSound", R.string.CustomSound); + } else { + value = NotificationsSoundActivity.trimTitle(document, document.file_name_fixed); + } + } else if (value.equals("NoSound")) { + value = LocaleController.getString("NoSound", R.string.NoSound); + } else if (value.equals("Default")) { + value = LocaleController.getString("SoundDefault", R.string.SoundDefault); + } + textCell.setTextAndValue(LocaleController.getString("Sound", R.string.Sound), value, true); + } else if (position == ringtoneRow) { + String value = preferences.getString("ringtone_" + dialogId, LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone)); + if (value.equals("NoSound")) { + value = LocaleController.getString("NoSound", R.string.NoSound); + } + textCell.setTextAndValue(LocaleController.getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, false); + } else if (position == vibrateRow) { + int value = preferences.getInt("vibrate_" + dialogId, 0); + if (value == 0 || value == 4) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), smartRow != -1 || priorityRow != -1); + } else if (value == 1) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), smartRow != -1 || priorityRow != -1); + } else if (value == 2) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), smartRow != -1 || priorityRow != -1); + } else if (value == 3) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), smartRow != -1 || priorityRow != -1); + } + } else if (position == priorityRow) { + int value = preferences.getInt("priority_" + dialogId, 3); + if (value == 0) { + textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityHigh", R.string.NotificationsPriorityHigh), false); + } else if (value == 1 || value == 2) { + textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityUrgent", R.string.NotificationsPriorityUrgent), false); + } else if (value == 3) { + textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPrioritySettings", R.string.NotificationsPrioritySettings), false); + } else if (value == 4) { + textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityLow", R.string.NotificationsPriorityLow), false); + } else if (value == 5) { + textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityMedium", R.string.NotificationsPriorityMedium), false); + } + } else if (position == smartRow) { + int notifyMaxCount = preferences.getInt("smart_max_count_" + dialogId, 2); + int notifyDelay = preferences.getInt("smart_delay_" + dialogId, 3 * 60); + if (notifyMaxCount == 0) { + textCell.setTextAndValue(LocaleController.getString("SmartNotifications", R.string.SmartNotifications), LocaleController.getString("SmartNotificationsDisabled", R.string.SmartNotificationsDisabled), priorityRow != -1); + } else { + String minutes = LocaleController.formatPluralString("Minutes", notifyDelay / 60); + textCell.setTextAndValue(LocaleController.getString("SmartNotifications", R.string.SmartNotifications), LocaleController.formatString("SmartNotificationsInfo", R.string.SmartNotificationsInfo, notifyMaxCount, minutes), priorityRow != -1); + } + } else if (position == callsVibrateRow) { + int value = preferences.getInt("calls_vibrate_" + dialogId, 0); + if (value == 0 || value == 4) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), true); + } else if (value == 1) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), true); + } else if (value == 2) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), true); + } else if (value == 3) { + textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), true); } - } else if (value.equals("NoSound")) { - value = LocaleController.getString("NoSound", R.string.NoSound); - } else if (value.equals("Default")) { - value = LocaleController.getString("SoundDefault", R.string.SoundDefault); - } - textCell.setTextAndValue(LocaleController.getString("Sound", R.string.Sound), value, true); - } else if (position == ringtoneRow) { - String value = preferences.getString("ringtone_" + dialogId, LocaleController.getString("DefaultRingtone", R.string.DefaultRingtone)); - if (value.equals("NoSound")) { - value = LocaleController.getString("NoSound", R.string.NoSound); - } - textCell.setTextAndValue(LocaleController.getString("VoipSettingsRingtone", R.string.VoipSettingsRingtone), value, false); - } else if (position == vibrateRow) { - int value = preferences.getInt("vibrate_" + dialogId, 0); - if (value == 0 || value == 4) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), smartRow != -1 || priorityRow != -1); - } else if (value == 1) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), smartRow != -1 || priorityRow != -1); - } else if (value == 2) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), smartRow != -1 || priorityRow != -1); - } else if (value == 3) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), smartRow != -1 || priorityRow != -1); - } - } else if (position == priorityRow) { - int value = preferences.getInt("priority_" + dialogId, 3); - if (value == 0) { - textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityHigh", R.string.NotificationsPriorityHigh), false); - } else if (value == 1 || value == 2) { - textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityUrgent", R.string.NotificationsPriorityUrgent), false); - } else if (value == 3) { - textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPrioritySettings", R.string.NotificationsPrioritySettings), false); - } else if (value == 4) { - textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityLow", R.string.NotificationsPriorityLow), false); - } else if (value == 5) { - textCell.setTextAndValue(LocaleController.getString("NotificationsImportance", R.string.NotificationsImportance), LocaleController.getString("NotificationsPriorityMedium", R.string.NotificationsPriorityMedium), false); - } - } else if (position == smartRow) { - int notifyMaxCount = preferences.getInt("smart_max_count_" + dialogId, 2); - int notifyDelay = preferences.getInt("smart_delay_" + dialogId, 3 * 60); - if (notifyMaxCount == 0) { - textCell.setTextAndValue(LocaleController.getString("SmartNotifications", R.string.SmartNotifications), LocaleController.getString("SmartNotificationsDisabled", R.string.SmartNotificationsDisabled), priorityRow != -1); - } else { - String minutes = LocaleController.formatPluralString("Minutes", notifyDelay / 60); - textCell.setTextAndValue(LocaleController.getString("SmartNotifications", R.string.SmartNotifications), LocaleController.formatString("SmartNotificationsInfo", R.string.SmartNotificationsInfo, notifyMaxCount, minutes), priorityRow != -1); - } - } else if (position == callsVibrateRow) { - int value = preferences.getInt("calls_vibrate_" + dialogId, 0); - if (value == 0 || value == 4) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), true); - } else if (value == 1) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), true); - } else if (value == 2) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled), true); - } else if (value == 3) { - textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Long", R.string.Long), true); } } break; } - case 2: { + case VIEW_TYPE_INFO: { TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; if (position == popupInfoRow) { textCell.setText(LocaleController.getString("ProfilePopupNotificationInfo", R.string.ProfilePopupNotificationInfo)); - textCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + textCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == ledInfoRow) { textCell.setText(LocaleController.getString("NotificationsLedInfo", R.string.NotificationsLedInfo)); - textCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + textCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else if (position == priorityInfoRow) { if (priorityRow == -1) { textCell.setText(""); } else { textCell.setText(LocaleController.getString("PriorityInfo", R.string.PriorityInfo)); } - textCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); - } else if (position == customInfoRow) { - textCell.setText(null); - textCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + textCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == ringtoneInfoRow) { textCell.setText(LocaleController.getString("VoipRingtoneInfo", R.string.VoipRingtoneInfo)); - textCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + textCell.setBackground(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } break; } - case 3: { + case VIEW_TYPE_TEXT_COLOR: { TextColorCell textCell = (TextColorCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); int color; @@ -798,13 +846,28 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi textCell.setTextAndColor(LocaleController.getString("NotificationsLedColor", R.string.NotificationsLedColor), color, false); break; } - case 5: { - TextCheckCell cell = (TextCheckCell) holder.itemView; - cell.setBackgroundColor(Theme.getColor(customEnabled && notificationsEnabled ? Theme.key_windowBackgroundChecked : Theme.key_windowBackgroundUnchecked)); - cell.setTextAndCheck(LocaleController.getString("NotificationsEnableCustom", R.string.NotificationsEnableCustom), customEnabled && notificationsEnabled, false); + case VIEW_TYPE_RADIO: { + RadioCell radioCell = (RadioCell) holder.itemView; + SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); + int popup = preferences.getInt("popup_" + dialogId, 0); + if (popup == 0) { + popup = preferences.getInt(DialogObject.isChatDialog(dialogId) ? "popupGroup" : "popupAll", 0); + if (popup != 0) { + popup = 1; + } else { + popup = 2; + } + } + if (position == popupEnabledRow) { + radioCell.setText(LocaleController.getString("PopupEnabled", R.string.PopupEnabled), popup == 1, true); + radioCell.setTag(1); + } else if (position == popupDisabledRow) { + radioCell.setText(LocaleController.getString("PopupDisabled", R.string.PopupDisabled), popup == 2, false); + radioCell.setTag(2); + } break; } - case 6: { + case VIEW_TYPE_USER: { UserCell2 userCell2 = (UserCell2) holder.itemView; TLObject object; if (DialogObject.isUserDialog(dialogId)) { @@ -815,7 +878,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi userCell2.setData(object, null, null, 0); break; } - case 8: { + case VIEW_TYPE_TEXT_CHECK: { TextCheckCell checkCell = (TextCheckCell) holder.itemView; SharedPreferences preferences = MessagesController.getNotificationsSettings(currentAccount); if (position == enableRow) { @@ -842,35 +905,39 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { switch (holder.getItemViewType()) { - case 0: { + case VIEW_TYPE_HEADER: { HeaderCell textCell = (HeaderCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, null); + textCell.setEnabled(notificationsEnabled, null); break; } - case 1: { + case VIEW_TYPE_TEXT_SETTINGS: { TextSettingsCell textCell = (TextSettingsCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, null); + if (holder.getAdapterPosition() == customResetRow) { + textCell.setEnabled(true, null); + } else { + textCell.setEnabled(notificationsEnabled, null); + } break; } - case 2: { + case VIEW_TYPE_INFO: { TextInfoPrivacyCell textCell = (TextInfoPrivacyCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, null); + textCell.setEnabled(notificationsEnabled, null); break; } - case 3: { + case VIEW_TYPE_TEXT_COLOR: { TextColorCell textCell = (TextColorCell) holder.itemView; - textCell.setEnabled(customEnabled && notificationsEnabled, null); + textCell.setEnabled(notificationsEnabled, null); break; } - case 4: { + case VIEW_TYPE_RADIO: { RadioCell radioCell = (RadioCell) holder.itemView; - radioCell.setEnabled(customEnabled && notificationsEnabled, null); + radioCell.setEnabled(notificationsEnabled, null); break; } - case 8: { + case VIEW_TYPE_TEXT_CHECK: { TextCheckCell checkCell = (TextCheckCell) holder.itemView; if (holder.getAdapterPosition() == previewRow || holder.getAdapterPosition() == popupRow) { - checkCell.setEnabled(customEnabled && notificationsEnabled, null); + checkCell.setEnabled(notificationsEnabled, null); } else { checkCell.setEnabled(true, null); } @@ -881,26 +948,31 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi @Override public int getItemViewType(int position) { if (position == generalRow || position == ledRow || position == callsRow) { - return 0; - } else if (position == soundRow || position == vibrateRow || position == priorityRow || position == smartRow || position == ringtoneRow || position == callsVibrateRow) { - return 1; - } else if (position == popupInfoRow || position == ledInfoRow || position == priorityInfoRow || position == customInfoRow || position == ringtoneInfoRow) { - return 2; + return VIEW_TYPE_HEADER; + } else if (position == soundRow || position == vibrateRow || position == priorityRow || position == smartRow || position == ringtoneRow || position == callsVibrateRow || position == customResetRow) { + return VIEW_TYPE_TEXT_SETTINGS; + } else if (position == popupInfoRow || position == ledInfoRow || position == priorityInfoRow || position == ringtoneInfoRow) { + return VIEW_TYPE_INFO; } else if (position == colorRow) { - return 3; - } else if (position == customRow) { - return 5; + return VIEW_TYPE_TEXT_COLOR; + } else if (position == popupEnabledRow || position == popupDisabledRow) { + return VIEW_TYPE_RADIO; } else if (position == avatarRow) { - return 6; - } else if (position == avatarSectionRow) { - return 7; + return VIEW_TYPE_USER; + } else if (position == avatarSectionRow || position == customResetShadowRow) { + return VIEW_TYPE_SHADOW; } else if (position == enableRow || position == previewRow || position == popupRow) { - return 8; + return VIEW_TYPE_TEXT_CHECK; } - return 0; + return VIEW_TYPE_HEADER; } } + @Override + public int getNavigationBarColor() { + return getThemedColor(Theme.key_windowBackgroundGray); + } + @Override public ArrayList getThemeDescriptions() { ArrayList themeDescriptions = new ArrayList<>(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java index 1fc9be8ed..00b42c308 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProxyListActivity.java @@ -29,6 +29,7 @@ import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; +import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; @@ -41,6 +42,11 @@ import com.v2ray.ang.V2RayConfig; import org.json.JSONArray; import org.json.JSONObject; +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java index 75ce3477c..2bf3e7a57 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProxySettingsActivity.java @@ -249,7 +249,7 @@ public class ProxySettingsActivity extends BaseFragment { } }); - doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_done, AndroidUtilities.dp(56)); + doneItem = actionBar.createMenu().addItemWithWidth(done_button, R.drawable.ic_ab_done, AndroidUtilities.dp(56)); doneItem.setContentDescription(LocaleController.getString("Done", R.string.Done)); fragmentView = new FrameLayout(context); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java index 830d1ff8e..eb3da7d2a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/QrActivity.java @@ -38,7 +38,7 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.view.animation.DecelerateInterpolator; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -66,6 +66,7 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SvgHelper; +import org.telegram.messenger.UserObject; import org.telegram.tgnet.ResultCallback; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBarLayout; @@ -260,12 +261,19 @@ public class QrActivity extends BaseFragment { AvatarDrawable avatarDrawable = null; String username = null; + boolean isPhone = false; + String userfullname = null; ImageLocation imageLocationSmall = null; ImageLocation imageLocation = null; if (userId != 0) { TLRPC.User user = getMessagesController().getUser(userId); if (user != null) { username = user.username; + if (username == null) { + userfullname = UserObject.getUserName(user); + username = user.phone; + isPhone = true; + } avatarDrawable = new AvatarDrawable(user); imageLocationSmall = ImageLocation.getForUser(user, ImageLocation.TYPE_SMALL); imageLocation = ImageLocation.getForUser(user, ImageLocation.TYPE_BIG); @@ -283,7 +291,7 @@ public class QrActivity extends BaseFragment { String link = "https://" + MessagesController.getInstance(currentAccount).linkPrefix + "/" + username; qrView = new QrView(context); qrView.setColors(0xFF71B654, 0xFF2C9077, 0xFF9ABB3E, 0xFF68B55E); - qrView.setData(link, username); + qrView.setData(link, userfullname != null ? userfullname : username, isPhone); qrView.setCenterChangedListener((left, top, right, bottom) -> { logoRect.set(left, top, right, bottom); qrView.requestLayout(); @@ -476,7 +484,7 @@ public class QrActivity extends BaseFragment { private void onPatternLoaded(Bitmap bitmap, int intensity, boolean withAnimation) { if (bitmap != null) { - currMotionDrawable.setPatternBitmap(intensity, bitmap); + currMotionDrawable.setPatternBitmap(intensity, bitmap, true); if (patternIntensityAnimator != null) { patternIntensityAnimator.cancel(); } @@ -491,34 +499,6 @@ public class QrActivity extends BaseFragment { } } - @Override - protected AnimatorSet onCustomTransitionAnimation(boolean isOpen, Runnable callback) { - if (isOpen) { - fragmentView.setAlpha(0f); - fragmentView.setTranslationX(AndroidUtilities.dp(48)); - } - - AnimatorSet animator = new AnimatorSet(); - animator.playTogether( - ObjectAnimator.ofFloat(fragmentView, View.TRANSLATION_X, isOpen ? 0 : AndroidUtilities.dp(48)), - ObjectAnimator.ofFloat(fragmentView, View.ALPHA, isOpen ? 1f : 0f) - ); - if (!isOpen) - animator.setInterpolator(new DecelerateInterpolator(1.5f)); - else - animator.setInterpolator(CubicBezierInterpolator.EASE_IN); - animator.setDuration(isOpen ? 200 : 150); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animator) { - if (callback != null) - callback.run(); - } - }); - animator.start(); - return animator; - } - private void onItemSelected(EmojiThemes newTheme, int position, boolean withAnimation) { selectedPosition = position; final EmojiThemes prevTheme = currentTheme; @@ -562,7 +542,12 @@ public class QrActivity extends BaseFragment { } }); } else { - currMotionDrawable.setPatternBitmap(34, SvgHelper.getBitmap(R.raw.default_pattern, backgroundView.getWidth(), backgroundView.getHeight(), Color.BLACK)); + ChatThemeController.chatThemeQueue.postRunnable(() -> { + final Bitmap bitmap = SvgHelper.getBitmap(R.raw.default_pattern, backgroundView.getWidth(), backgroundView.getHeight(), Color.BLACK); + AndroidUtilities.runOnUIThread(() -> { + onPatternLoaded(bitmap, 34, true); + }); + }); } currMotionDrawable.setPatternColorFilter(currMotionDrawable.getPatternColor()); @@ -729,6 +714,7 @@ public class QrActivity extends BaseFragment { private Bitmap backgroundBitmap; private Bitmap contentBitmap; private String username; + private boolean isPhone; private String link; QrView(Context context) { @@ -781,8 +767,9 @@ public class QrActivity extends BaseFragment { this.centerChangedListener = centerChangedListener; } - void setData(String link, String username) { + void setData(String link, String username, boolean isPhone) { this.username = username; + this.isPhone = isPhone; this.link = link; prepareContent(getWidth(), getHeight()); invalidate(); @@ -832,8 +819,10 @@ public class QrActivity extends BaseFragment { drawable.setColorFilter(new PorterDuffColorFilter(qrColor, PorterDuff.Mode.SRC_IN)); } - SpannableStringBuilder string = new SpannableStringBuilder(" " + username.toUpperCase()); - string.setSpan(new SettingsSearchCell.VerticalImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + SpannableStringBuilder string = new SpannableStringBuilder(" " + (isPhone ? username : username.toUpperCase())); + if (!isPhone) { + string.setSpan(new SettingsSearchCell.VerticalImageSpan(drawable), 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } float textWidth = textPaint.measureText(string, 1, string.length()) + drawable.getBounds().width(); if (i <= 1 && textWidth > textMaxWidth) { continue; @@ -1045,7 +1034,17 @@ public class QrActivity extends BaseFragment { darkThemeDrawable.setPlayInDirectionOfCustomEndFrame(true); darkThemeDrawable.setColorFilter(new PorterDuffColorFilter(drawableColor, PorterDuff.Mode.MULTIPLY)); - darkThemeView = new RLottieImageView(context); + darkThemeView = new RLottieImageView(context) { + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (isCurrentThemeDark) { + info.setText(LocaleController.getString("AccDescrSwitchToDayTheme", R.string.AccDescrSwitchToDayTheme)); + } else { + info.setText(LocaleController.getString("AccDescrSwitchToNightTheme", R.string.AccDescrSwitchToNightTheme)); + } + } + }; darkThemeView.setAnimation(darkThemeDrawable); darkThemeView.setScaleType(ImageView.ScaleType.CENTER); darkThemeView.setOnClickListener(view -> { @@ -1094,7 +1093,7 @@ public class QrActivity extends BaseFragment { rootLayout.addView(bottomShadow); shareButton = new TextView(context); - shareButton.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), fragment.getThemedColor(Theme.key_featuredStickers_addButton), fragment.getThemedColor(Theme.key_featuredStickers_addButtonPressed))); + shareButton.setBackground(Theme.AdaptiveRipple.filledRect(fragment.getThemedColor(Theme.key_featuredStickers_addButton), 6)); shareButton.setEllipsize(TextUtils.TruncateAt.END); shareButton.setGravity(Gravity.CENTER); shareButton.setLines(1); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java index 07260f7c6..113527b1d 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SecretMediaViewer.java @@ -97,6 +97,19 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD protected boolean drawChild(Canvas canvas, View child, long drawingTime) { return child != aspectRatioFrameLayout && super.drawChild(canvas, child, drawingTime); } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + centerImage.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + centerImage.onDetachedFromWindow(); + } } private class SecretDeleteTimer extends FrameLayout { @@ -797,7 +810,7 @@ public class SecretMediaViewer implements NotificationCenter.NotificationCenterD if (f.exists()) { preparePlayer(f); } else { - File file = FileLoader.getPathToMessage(messageObject.messageOwner); + File file = FileLoader.getInstance(currentAccount).getPathToMessage(messageObject.messageOwner); File encryptedFile = new File(file.getAbsolutePath() + ".enc"); if (encryptedFile.exists()) { file = encryptedFile; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionBottomSheet.java index fe6906984..a628e04d5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionBottomSheet.java @@ -10,6 +10,7 @@ import android.os.Build; import android.util.TypedValue; import android.view.Gravity; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; @@ -47,6 +48,7 @@ public class SessionBottomSheet extends BottomSheet { Context context = fragment.getParentActivity(); this.session = session; this.parentFragment = fragment; + fixNavigationBar(); LinearLayout linearLayout = new LinearLayout(context); linearLayout.setOrientation(LinearLayout.VERTICAL); @@ -120,7 +122,7 @@ public class SessionBottomSheet extends BottomSheet { if (session.country.length() != 0) { ItemView locationItemView = new ItemView(context, false); locationItemView.valueText.setText(session.country); - drawable = ContextCompat.getDrawable(context, R.drawable.menu_location).mutate(); + drawable = ContextCompat.getDrawable(context, R.drawable.msg_location).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); locationItemView.iconView.setImageDrawable(drawable); locationItemView.descriptionText.setText(LocaleController.getString("Location", R.string.Location)); @@ -150,7 +152,7 @@ public class SessionBottomSheet extends BottomSheet { if (session.ip.length() != 0) { ItemView locationItemView = new ItemView(context, false); locationItemView.valueText.setText(session.ip); - drawable = ContextCompat.getDrawable(context, R.drawable.menu_language).mutate(); + drawable = ContextCompat.getDrawable(context, R.drawable.msg_language).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); locationItemView.iconView.setImageDrawable(drawable); locationItemView.descriptionText.setText(LocaleController.getString("IpAddress", R.string.IpAddress)); @@ -183,7 +185,7 @@ public class SessionBottomSheet extends BottomSheet { if (secretChatsEnabled(session)) { ItemView acceptSecretChats = new ItemView(context, true); acceptSecretChats.valueText.setText(LocaleController.getString("AcceptSecretChats", R.string.AcceptSecretChats)); - drawable = ContextCompat.getDrawable(context, R.drawable.menu_secret).mutate(); + drawable = ContextCompat.getDrawable(context, R.drawable.msg_secret).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); acceptSecretChats.iconView.setImageDrawable(drawable); acceptSecretChats.switchView.setChecked(!session.encrypted_requests_disabled, false); @@ -207,7 +209,7 @@ public class SessionBottomSheet extends BottomSheet { ItemView acceptCalls = new ItemView(context, true); acceptCalls.valueText.setText(LocaleController.getString("AcceptCalls", R.string.AcceptCalls)); - drawable = ContextCompat.getDrawable(context, R.drawable.menu_calls).mutate(); + drawable = ContextCompat.getDrawable(context, R.drawable.msg_calls).mutate(); drawable.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_windowBackgroundWhiteGrayIcon), PorterDuff.Mode.SRC_IN)); acceptCalls.iconView.setImageDrawable(drawable); acceptCalls.switchView.setChecked(!session.call_requests_disabled, false); @@ -236,7 +238,7 @@ public class SessionBottomSheet extends BottomSheet { buttonTextView.setText(LocaleController.getString("TerminateSession", R.string.TerminateSession)); buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); - buttonTextView.setBackgroundDrawable(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_chat_attachAudioBackground), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhite), 120))); + buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_chat_attachAudioBackground), ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhite), 120))); linearLayout.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, 0, 16, 15, 16, 16)); @@ -408,6 +410,17 @@ public class SessionBottomSheet extends BottomSheet { canvas.drawRect(AndroidUtilities.dp(64), getMeasuredHeight() - 1, getMeasuredWidth(), getMeasuredHeight(), Theme.dividerPaint); } } + + @Override + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(info); + if (switchView != null) { + info.setClassName("android.widget.Switch"); + info.setCheckable(true); + info.setChecked(switchView.isChecked()); + info.setText(valueText.getText() + "\n" + descriptionText.getText() + "\n" + (switchView.isChecked() ? LocaleController.getString("NotificationsOn", R.string.NotificationsOn) : LocaleController.getString("NotificationsOff", R.string.NotificationsOff))); + } + } } public interface Callback { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index 71242fa1c..ef8ba315e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -13,20 +13,17 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; import android.net.Uri; import android.os.Build; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.util.Base64; +import android.util.Log; import android.util.TypedValue; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; -import android.widget.AbsListView; import android.widget.FrameLayout; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -36,6 +33,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -72,16 +70,20 @@ import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.BackupImageView; +import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.EmptyTextProgressView; import org.telegram.ui.Components.FlickerLoadingView; import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.LinkSpanDrawable; import org.telegram.ui.Components.RecyclerItemsEnterAnimator; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.URLSpanNoUnderline; import org.telegram.ui.Components.UndoView; import java.util.ArrayList; +import java.util.Objects; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; @@ -90,9 +92,6 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter private ListAdapter listAdapter; private RecyclerListView listView; - private ImageView imageView; - private TextView textView1; - private TextView textView2; private EmptyTextProgressView emptyView; private FlickerLoadingView globalFlickerLoadingView; @@ -100,9 +99,8 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter private ArrayList passwordSessions = new ArrayList<>(); private TLRPC.TL_authorization currentSession; private boolean loading; - private LinearLayout emptyLayout; private UndoView undoView; - private RecyclerItemsEnterAnimator itemsEnterAnimator; +// private RecyclerItemsEnterAnimator itemsEnterAnimator; private int ttlDays; private int currentType; @@ -127,6 +125,8 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter private int ttlRow; private int ttlDivideRow; + private int repeatLoad = 0; + public SessionsActivity(int type) { currentType = type; } @@ -174,56 +174,27 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter FrameLayout frameLayout = (FrameLayout) fragmentView; frameLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); - emptyLayout = new LinearLayout(context); - emptyLayout.setOrientation(LinearLayout.VERTICAL); - emptyLayout.setGravity(Gravity.CENTER); - emptyLayout.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); - emptyLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight())); - - imageView = new ImageView(context); - if (currentType == 0) { - imageView.setImageResource(R.drawable.devices); - } else { - imageView.setImageResource(R.drawable.no_apps); - } - imageView.setColorFilter(new PorterDuffColorFilter(Theme.getColor(Theme.key_sessions_devicesImage), PorterDuff.Mode.SRC_IN)); - emptyLayout.addView(imageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT)); - - textView1 = new TextView(context); - textView1.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); - textView1.setGravity(Gravity.CENTER); - textView1.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - textView1.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - if (currentType == 0) { - textView1.setText(LocaleController.getString("NoOtherSessions", R.string.NoOtherSessions)); - } else { - textView1.setText(LocaleController.getString("NoOtherWebSessions", R.string.NoOtherWebSessions)); - } - emptyLayout.addView(textView1, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 16, 0, 0)); - - textView2 = new TextView(context); - textView2.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteGrayText2)); - textView2.setGravity(Gravity.CENTER); - textView2.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17); - textView2.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0); - if (currentType == 0) { - textView2.setText(LocaleController.getString("NoOtherSessionsInfo", R.string.NoOtherSessionsInfo)); - } else { - textView2.setText(LocaleController.getString("NoOtherWebSessionsInfo", R.string.NoOtherWebSessionsInfo)); - } - emptyLayout.addView(textView2, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 14, 0, 0)); - emptyView = new EmptyTextProgressView(context); emptyView.showProgress(); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); listView = new RecyclerListView(context); - listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); + listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { + @Override + public boolean supportsPredictiveItemAnimations() { + return true; + } + }); listView.setVerticalScrollBarEnabled(false); listView.setEmptyView(emptyView); listView.setAnimateEmptyView(true, 0); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(150); + itemAnimator.setMoveInterpolator(CubicBezierInterpolator.DEFAULT); + itemAnimator.setTranslationInterpolator(CubicBezierInterpolator.DEFAULT); + listView.setItemAnimator(itemAnimator); listView.setOnItemClickListener((view, position) -> { if (position == ttlRow) { if (getParentActivity() == null) { @@ -310,9 +281,8 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter return; } if (error == null && response instanceof TLRPC.TL_boolTrue) { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("TerminateAllSessions", R.string.TerminateAllSessions), Toast.LENGTH_SHORT); - toast.show(); - finishFragment(); + BulletinFactory.of(SessionsActivity.this).createSimpleBulletin(R.raw.contact_check, LocaleController.getString("AllSessionsTerminated", R.string.AllSessionsTerminated)).show(); + loadSessions(false); } }); @@ -334,13 +304,11 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter return; } if (error == null && response instanceof TLRPC.TL_boolTrue) { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("TerminateAllWebSessions", R.string.TerminateAllWebSessions), Toast.LENGTH_SHORT); - toast.show(); + BulletinFactory.of(SessionsActivity.this).createSimpleBulletin(R.raw.contact_check, LocaleController.getString("AllWebSessionsTerminated", R.string.AllWebSessionsTerminated)).show(); } else { - Toast toast = Toast.makeText(getParentActivity(), LocaleController.getString("UnknownError", R.string.UnknownError), Toast.LENGTH_SHORT); - toast.show(); + BulletinFactory.of(SessionsActivity.this).createSimpleBulletin(R.raw.error, LocaleController.getString("UnknownError", R.string.UnknownError)).show(); } - finishFragment(); + loadSessions(false); })); } }); @@ -478,20 +446,20 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter AndroidUtilities.runOnUIThread(() -> undoView.showWithAction(0, UndoView.ACTION_QR_SESSION_ACCEPTED, newAuthorizationToOpen), 3000L); } - itemsEnterAnimator = new RecyclerItemsEnterAnimator(listView, true) { - @Override - public View getProgressView() { - View progressView = null; - for (int i = 0; i < listView.getChildCount(); i++) { - View child = listView.getChildAt(i); - if (listView.getChildAdapterPosition(child) >= 0 && child instanceof SessionCell && ((SessionCell) child).isStub()) { - progressView = child; - } - } - return progressView; - } - }; - itemsEnterAnimator.animateAlphaProgressView = false; +// itemsEnterAnimator = new RecyclerItemsEnterAnimator(listView, true) { +// @Override +// public View getProgressView() { +// View progressView = null; +// for (int i = 0; i < listView.getChildCount(); i++) { +// View child = listView.getChildAt(i); +// if (listView.getChildAdapterPosition(child) >= 0 && child instanceof SessionCell && ((SessionCell) child).isStub()) { +// progressView = child; +// } +// } +// return progressView; +// } +// }; +// itemsEnterAnimator.animateAlphaProgressView = false; updateRows(); return fragmentView; @@ -634,10 +602,17 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter ttlDays = res.authorization_ttl_days; updateRows(); } - itemsEnterAnimator.showItemsAnimated(oldItemsCount + 1); +// itemsEnterAnimator.showItemsAnimated(oldItemsCount + 1); if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + + if (repeatLoad > 0) { + repeatLoad--; + if (repeatLoad > 0) { + AndroidUtilities.runOnUIThread(() -> loadSessions(silent), 2500); + } + } })); ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); } else { @@ -651,10 +626,17 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter sessions.addAll(res.authorizations); updateRows(); } - itemsEnterAnimator.showItemsAnimated(0); +// itemsEnterAnimator.showItemsAnimated(0); if (listAdapter != null) { listAdapter.notifyDataSetChanged(); } + + if (repeatLoad > 0) { + repeatLoad--; + if (repeatLoad > 0) { + AndroidUtilities.runOnUIThread(() -> loadSessions(silent), 2500); + } + } })); ConnectionsManager.getInstance(currentAccount).bindRequestToGuid(reqId, classGuid); } @@ -681,8 +663,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter ttlRow = -1; ttlDivideRow = -1; - boolean hasQr = currentType == 0 && getMessagesController().qrLoginCamera; - if (hasQr) { + if (currentType == 0 && getMessagesController().qrLoginCamera) { qrCodeRow = rowCount++; qrCodeDividerRow = rowCount++; } @@ -732,12 +713,20 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } } + private final int VIEW_TYPE_TEXT = 0; + private final int VIEW_TYPE_INFO = 1; + private final int VIEW_TYPE_HEADER = 2; + private final int VIEW_TYPE_SESSION = 4; + private final int VIEW_TYPE_SCANQR = 5; + private final int VIEW_TYPE_SETTINGS = 6; + private class ListAdapter extends RecyclerListView.SelectionAdapter { private Context mContext; public ListAdapter(Context context) { mContext = context; + setHasStableIds(true); } @Override @@ -755,27 +744,25 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: + case VIEW_TYPE_TEXT: view = new TextCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 1: + case VIEW_TYPE_INFO: view = new TextInfoPrivacyCell(mContext); break; - case 2: + case VIEW_TYPE_HEADER: view = new HeaderCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 3: - view = emptyLayout; - break; - case 5: + case VIEW_TYPE_SCANQR: view = new ScanQRCodeView(mContext); break; - case 6: + case VIEW_TYPE_SETTINGS: view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; + case VIEW_TYPE_SESSION: default: view = new SessionCell(mContext, currentType); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -787,7 +774,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 0: + case VIEW_TYPE_TEXT: TextCell textCell = (TextCell) holder.itemView; if (position == terminateAllSessionsRow) { textCell.setColors(Theme.key_windowBackgroundWhiteRedText2, Theme.key_windowBackgroundWhiteRedText2); @@ -800,10 +787,10 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } else if (position == qrCodeRow) { textCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); textCell.setTag(Theme.key_windowBackgroundWhiteBlueText4); - textCell.setTextAndIcon(LocaleController.getString("AuthAnotherClient", R.string.AuthAnotherClient), R.drawable.msg_qrcode, !sessions.isEmpty()); + textCell.setTextAndIcon(LocaleController.getString("AuthAnotherClient", R.string.AuthAnotherClient), R.drawable.wallet_qr, !sessions.isEmpty()); } break; - case 1: + case VIEW_TYPE_INFO: TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; privacyCell.setFixedSize(0); if (position == terminateAllSessionsDetailRow) { @@ -837,7 +824,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter privacyCell.setFixedSize(12); } break; - case 2: + case VIEW_TYPE_HEADER: HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == currentSessionSectionRow) { headerCell.setText(LocaleController.getString("CurrentSession", R.string.CurrentSession)); @@ -853,16 +840,9 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter headerCell.setText(LocaleController.getString("TerminateOldSessionHeader", R.string.TerminateOldSessionHeader)); } break; - case 3: - ViewGroup.LayoutParams layoutParams = emptyLayout.getLayoutParams(); - if (layoutParams != null) { - layoutParams.height = Math.max(AndroidUtilities.dp(220), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(128 + (qrCodeRow == -1 ? 0 : 30)) - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0)); - emptyLayout.setLayoutParams(layoutParams); - } + case VIEW_TYPE_SCANQR: break; - case 5: - break; - case 6: + case VIEW_TYPE_SETTINGS: TextSettingsCell textSettingsCell = (TextSettingsCell) holder.itemView; String value; if (ttlDays > 30 && ttlDays <= 183) { @@ -872,8 +852,9 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } else { value = LocaleController.formatPluralString("Weeks", ttlDays / 7); } - textSettingsCell.setTextAndValue(LocaleController.getString("IfInactiveFor", R.string.IfInactiveFor), value, false); + textSettingsCell.setTextAndValue(LocaleController.getString("IfInactiveFor", R.string.IfInactiveFor), value, true, false); break; + case VIEW_TYPE_SESSION: default: SessionCell sessionCell = (SessionCell) holder.itemView; if (position == currentSessionRow) { @@ -891,22 +872,70 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } } + @Override + public long getItemId(int position) { + if (position == terminateAllSessionsRow) { + return Objects.hash(0, 0); + } else if (position == terminateAllSessionsDetailRow) { + return Objects.hash(0, 1); + } else if (position == otherSessionsTerminateDetail) { + return Objects.hash(0, 2); + } else if (position == passwordSessionsDetailRow) { + return Objects.hash(0, 3); + } else if (position == qrCodeDividerRow) { + return Objects.hash(0, 4); + } else if (position == ttlDivideRow) { + return Objects.hash(0, 5); + } else if (position == noOtherSessionsRow) { + return Objects.hash(0, 6); + } else if (position == currentSessionSectionRow) { + return Objects.hash(0, 7); + } else if (position == otherSessionsSectionRow) { + return Objects.hash(0, 8); + } else if (position == passwordSessionsSectionRow) { + return Objects.hash(0, 9); + } else if (position == ttlHeaderRow) { + return Objects.hash(0, 10); + } else if (position == currentSessionRow) { + return Objects.hash(0, 11); + } else if (position >= otherSessionsStartRow && position < otherSessionsEndRow) { + TLObject session = sessions.get(position - otherSessionsStartRow); + if (session instanceof TLRPC.TL_authorization) { + return Objects.hash(1, ((TLRPC.TL_authorization) session).hash); + } else if (session instanceof TLRPC.TL_webAuthorization) { + return Objects.hash(1, ((TLRPC.TL_webAuthorization) session).hash); + } + } else if (position >= passwordSessionsStartRow && position < passwordSessionsEndRow) { + TLObject session = passwordSessions.get(position - passwordSessionsStartRow); + if (session instanceof TLRPC.TL_authorization) { + return Objects.hash(2, ((TLRPC.TL_authorization) session).hash); + } else if (session instanceof TLRPC.TL_webAuthorization) { + return Objects.hash(2, ((TLRPC.TL_webAuthorization) session).hash); + } + } else if (position == qrCodeRow) { + return Objects.hash(0, 12); + } else if (position == ttlRow) { + return Objects.hash(0, 13); + } + return Objects.hash(0, -1); + } + @Override public int getItemViewType(int position) { if (position == terminateAllSessionsRow) { - return 0; + return VIEW_TYPE_TEXT; } else if (position == terminateAllSessionsDetailRow || position == otherSessionsTerminateDetail || position == passwordSessionsDetailRow || position == qrCodeDividerRow || position == ttlDivideRow || position == noOtherSessionsRow) { - return 1; + return VIEW_TYPE_INFO; } else if (position == currentSessionSectionRow || position == otherSessionsSectionRow || position == passwordSessionsSectionRow || position == ttlHeaderRow) { - return 2; + return VIEW_TYPE_HEADER; } else if (position == currentSessionRow || position >= otherSessionsStartRow && position < otherSessionsEndRow || position >= passwordSessionsStartRow && position < passwordSessionsEndRow) { - return 4; + return VIEW_TYPE_SESSION; } else if (position == qrCodeRow) { - return 5; + return VIEW_TYPE_SCANQR; } else if (position == ttlRow) { - return 6; + return VIEW_TYPE_SETTINGS; } - return 0; + return VIEW_TYPE_TEXT; } } @@ -943,7 +972,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter colors[6] = 0x212020; colors[7] = Theme.getColor(Theme.key_windowBackgroundWhite); - textView = new TextView(context); + textView = new LinkSpanDrawable.LinksTextView(context); addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 36, 152, 36, 0)); textView.setGravity(Gravity.CENTER_HORIZONTAL); textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); @@ -1076,7 +1105,13 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter public void didFindQr(String link) { if (response instanceof TLRPC.TL_authorization) { TLRPC.TL_authorization authorization = (TLRPC.TL_authorization) response; - sessions.add(0, authorization); + if (((TLRPC.TL_authorization) response).password_pending) { + passwordSessions.add(0, authorization); + repeatLoad = 4; + loadSessions(false); + } else { + sessions.add(0, authorization); + } updateRows(); listAdapter.notifyDataSetChanged(); undoView.showWithAction(0, UndoView.ACTION_QR_SESSION_ACCEPTED, response); @@ -1140,9 +1175,6 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{View.class}, Theme.dividerPaint, null, null, Theme.key_divider)); - themeDescriptions.add(new ThemeDescription(imageView, ThemeDescription.FLAG_IMAGECOLOR, null, null, null, null, Theme.key_sessions_devicesImage)); - themeDescriptions.add(new ThemeDescription(textView1, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); - themeDescriptions.add(new ThemeDescription(textView2, ThemeDescription.FLAG_TEXTCOLOR, null, null, null, null, Theme.key_windowBackgroundWhiteGrayText2)); themeDescriptions.add(new ThemeDescription(emptyView, ThemeDescription.FLAG_PROGRESSBAR, null, null, null, null, Theme.key_progressCircle)); themeDescriptions.add(new ThemeDescription(listView, ThemeDescription.FLAG_TEXTCOLOR | ThemeDescription.FLAG_CHECKTAG, new Class[]{TextSettingsCell.class}, new String[]{"textView"}, null, null, null, Theme.key_windowBackgroundWhiteRedText2)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java index ebbd1a289..0accce6fa 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SponsoredMessageInfoView.java @@ -77,7 +77,7 @@ public class SponsoredMessageInfoView extends FrameLayout { button.setPadding(AndroidUtilities.dp(12), 0, AndroidUtilities.dp(12), 0); button.setText(LocaleController.getString("SponsoredMessageAlertLearnMoreUrl", R.string.SponsoredMessageAlertLearnMoreUrl)); button.setTextColor(Theme.getColor(Theme.key_featuredStickers_addButton, resourcesProvider)); - button.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_dialogBackground, resourcesProvider), Theme.getColor(Theme.key_featuredStickers_addButtonPressed, resourcesProvider))); + button.setBackground(Theme.AdaptiveRipple.filledRect(Theme.getColor(Theme.key_dialogBackground, resourcesProvider), 4)); button.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); button.setGravity(Gravity.CENTER_VERTICAL); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java index 4dfd602a1..9e4311976 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StatisticActivity.java @@ -499,7 +499,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente items.add(LocaleController.getString("ViewMessage", R.string.ViewMessage)); actions.add(1); - icons.add(R.drawable.menu_chats); + icons.add(R.drawable.msg_msgbubble3); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); @@ -2564,10 +2564,10 @@ public class StatisticActivity extends BaseFragment implements NotificationCente } items.add(LocaleController.getString("StatisticOpenProfile", R.string.StatisticOpenProfile)); - icons.add(R.drawable.menu_private); + icons.add(R.drawable.msg_openprofile); actions.add(2); items.add(LocaleController.getString("StatisticSearchUserHistory", R.string.StatisticSearchUserHistory)); - icons.add(R.drawable.menu_chats); + icons.add(R.drawable.msg_msgbubble3); actions.add(1); if (userIsPracticant && currentParticipant == null) { @@ -2643,7 +2643,7 @@ public class StatisticActivity extends BaseFragment implements NotificationCente if (canEditAdmin) { isAdmin = channelParticipant.admin_rights == null; items.add(isAdmin ? LocaleController.getString("SetAsAdmin", R.string.SetAsAdmin) : LocaleController.getString("EditAdminRights", R.string.EditAdminRights)); - icons.add(isAdmin ? R.drawable.actions_addadmin : R.drawable.actions_permissions); + icons.add(isAdmin ? R.drawable.msg_admins : R.drawable.msg_permissions); actions.add(0); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java index 38336148f..8895a3769 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java @@ -42,8 +42,22 @@ import com.google.gson.JsonObject; import com.google.gson.internal.Streams; import com.google.gson.stream.JsonWriter; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.collection.LongSparseArray; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.DiffUtil; +import androidx.recyclerview.widget.ItemTouchHelper; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.ListUpdateCallback; +import androidx.recyclerview.widget.RecyclerView; + import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.DocumentObject; +import org.telegram.messenger.FileLog; +import org.telegram.messenger.ImageLocation; +import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.FileLog; import org.telegram.messenger.LocaleController; import org.telegram.messenger.MediaDataController; @@ -52,6 +66,7 @@ import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SharedConfig; +import org.telegram.messenger.SvgHelper; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.TLRPC; import org.telegram.ui.ActionBar.ActionBar; @@ -62,9 +77,12 @@ import org.telegram.ui.ActionBar.BackDrawable; import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.FeaturedStickerSetCell2; +import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.StickerSetCell; +import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; @@ -126,22 +144,33 @@ public class StickersActivity extends BaseFragment implements NotificationCenter private int activeReorderingRequests; private boolean needReorder; - private final int currentType; + private int currentType; private int suggestRow; private int loopRow; private int loopInfoRow; - private int featuredRow; + private int largeEmojiRow; + private int reactionsDoubleTapRow; private int stickersBotInfo; private int masksRow; private int masksInfoRow; private int archivedRow; private int archivedInfoRow; + + private int featuredStickersHeaderRow; + private int featuredStickersStartRow; + private int featuredStickersEndRow; + private int featuredStickersShowMoreRow; + private int featuredStickersShadowRow; + + private int stickersHeaderRow; private int stickersStartRow; private int stickersEndRow; private int stickersShadowRow; private int rowCount; + private boolean isListeningForFeaturedUpdate; + public class TouchHelperCallback extends ItemTouchHelper.Callback { @Override @@ -150,7 +179,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } @Override - public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + public int getMovementFlags(@NonNull RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { if (viewHolder.getItemViewType() != 0) { return makeMovementFlags(0, 0); } @@ -158,7 +187,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } @Override - public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { + public boolean onMove(@NonNull RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) { if (source.getItemViewType() != target.getItemViewType()) { return false; } @@ -194,7 +223,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } @Override - public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { + public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive); } @@ -210,12 +239,11 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - + public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { } @Override - public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); viewHolder.itemView.setPressed(false); } @@ -260,6 +288,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter private int menu_export = 3; private int menu_import = 4; + @SuppressLint("ClickableViewAccessibility") @Override public View createView(Context context) { actionBar.setBackButtonDrawable(new BackDrawable(false)); @@ -324,7 +353,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter otherItem.addSubItem(menu_export, R.drawable.baseline_file_download_24, LocaleController.getString("ExportStickers", R.string.ExportStickers)); otherItem.addSubItem(menu_import, R.drawable.baseline_playlist_add_24, LocaleController.getString("ImportStickersX", R.string.ImportStickersX)); - final ActionBarMenu actionMode = actionBar.createActionMode(); + ActionBarMenu actionMode = actionBar.createActionMode(); selectedCountTextView = new NumberTextView(actionMode.getContext()); selectedCountTextView.setTextSize(18); selectedCountTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); @@ -337,8 +366,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter archiveMenuItem = actionMode.addItemWithWidth(MENU_ARCHIVE, R.drawable.baseline_archive_24, AndroidUtilities.dp(54)); deleteMenuItem = actionMode.addItemWithWidth(MENU_DELETE, R.drawable.baseline_delete_24, AndroidUtilities.dp(54)); - - listAdapter = new ListAdapter(context, MediaDataController.getInstance(currentAccount).getStickerSets(currentType)); + listAdapter = new ListAdapter(context, MessagesController.getInstance(currentAccount).filterPremiumStickers(MediaDataController.getInstance(currentAccount).getStickerSets(currentType)), MediaDataController.getInstance(currentAccount).getFeaturedStickerSets()); fragmentView = new FrameLayout(context); FrameLayout frameLayout = (FrameLayout) fragmentView; @@ -368,19 +396,14 @@ public class StickersActivity extends BaseFragment implements NotificationCenter frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT)); listView.setAdapter(listAdapter); listView.setOnItemClickListener((view, position) -> { - if (position >= stickersStartRow && position < stickersEndRow && getParentActivity() != null) { - if (!listAdapter.hasSelected()) { - final TLRPC.TL_messages_stickerSet stickerSet = listAdapter.stickerSets.get(position - stickersStartRow); - ArrayList stickers = stickerSet.documents; - if (stickers == null || stickers.isEmpty()) { - return; - } - showDialog(new StickersAlert(getParentActivity(), StickersActivity.this, null, stickerSet, null)); - } else { - listAdapter.toggleSelected(position); - } - } else if (position == featuredRow) { - final TrendingStickersLayout.Delegate trendingDelegate = new TrendingStickersLayout.Delegate() { + if (position >= featuredStickersStartRow && position < featuredStickersEndRow && getParentActivity() != null) { + TLRPC.StickerSetCovered setCovered = listAdapter.featuredStickerSets.get(position - featuredStickersStartRow); + TLRPC.TL_inputStickerSetID inputStickerSetID = new TLRPC.TL_inputStickerSetID(); + inputStickerSetID.id = setCovered.set.id; + inputStickerSetID.access_hash = setCovered.set.access_hash; + showDialog(new StickersAlert(getParentActivity(), StickersActivity.this, inputStickerSetID, null, null)); + } else if (position == featuredStickersShowMoreRow) { + TrendingStickersLayout.Delegate trendingDelegate = new TrendingStickersLayout.Delegate() { @Override public void onStickerSetAdd(TLRPC.StickerSetCovered stickerSet, boolean primary) { MediaDataController.getInstance(currentAccount).toggleStickerSet(getParentActivity(), stickerSet, 2, StickersActivity.this, false, false); @@ -393,6 +416,17 @@ public class StickersActivity extends BaseFragment implements NotificationCenter }; trendingStickersAlert = new TrendingStickersAlert(context, this, new TrendingStickersLayout(context, trendingDelegate), null); trendingStickersAlert.show(); + } else if (position >= stickersStartRow && position < stickersEndRow && getParentActivity() != null) { + if (!listAdapter.hasSelected()) { + TLRPC.TL_messages_stickerSet stickerSet = listAdapter.stickerSets.get(position - stickersStartRow); + ArrayList stickers = stickerSet.documents; + if (stickers == null || stickers.isEmpty()) { + return; + } + showDialog(new StickersAlert(getParentActivity(), StickersActivity.this, null, stickerSet, null)); + } else { + listAdapter.toggleSelected(position); + } } else if (position == archivedRow) { presentFragment(new ArchivedStickersActivity(currentType)); } else if (position == masksRow) { @@ -409,7 +443,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter LocaleController.getString("SuggestStickersNone", R.string.SuggestStickersNone), }; - final LinearLayout linearLayout = new LinearLayout(getParentActivity()); + LinearLayout linearLayout = new LinearLayout(getParentActivity()); linearLayout.setOrientation(LinearLayout.VERTICAL); builder.setView(linearLayout); @@ -431,6 +465,11 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } else if (position == loopRow) { SharedConfig.toggleLoopStickers(); listAdapter.notifyItemChanged(loopRow, ListAdapter.UPDATE_LOOP_STICKERS); + } else if (position == largeEmojiRow) { + SharedConfig.toggleBigEmoji(); + ((TextCheckCell) view).setChecked(SharedConfig.allowBigEmoji); + } else if (position == reactionsDoubleTapRow) { + presentFragment(new ReactionsDoubleTapManageActivity()); } }); listView.setOnItemLongClickListener((view, position) -> { @@ -573,15 +612,10 @@ public class StickersActivity extends BaseFragment implements NotificationCenter FileUtil.writeUtf8String(stringWriter.toString(), cacheFile); UIUtil.runOnUIThread(() -> { - pro.dismiss(); - ShareUtil.shareFile(ctx, cacheFile); - }); - }); - } @Override @@ -596,16 +630,15 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public void didReceivedNotification(int id, int account, Object... args) { if (id == NotificationCenter.stickersDidLoad) { - final int type = (int) args[0]; + int type = (int) args[0]; if (type == currentType) { + listAdapter.loadingFeaturedStickerSets.clear(); updateRows(); } else if (currentType == MediaDataController.TYPE_IMAGE && type == MediaDataController.TYPE_MASK) { listAdapter.notifyItemChanged(masksRow); } } else if (id == NotificationCenter.featuredStickersDidLoad) { - if (listAdapter != null) { - listAdapter.notifyItemChanged(0); - } + updateRows(); } else if (id == NotificationCenter.archivedStickersCountDidLoad) { if ((Integer) args[0] == currentType) { updateRows(); @@ -630,20 +663,29 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } private void updateRows() { - final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); - final List newList = mediaDataController.getStickerSets(currentType); + MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); + List newList = MessagesController.getInstance(currentAccount).filterPremiumStickers(mediaDataController.getStickerSets(currentType)); + + boolean truncatedFeaturedStickers = false; + List featuredStickerSets = mediaDataController.getFeaturedStickerSets(); + if (featuredStickerSets.size() > 3) { + featuredStickerSets = featuredStickerSets.subList(0, 3); + truncatedFeaturedStickers = true; + } + List featuredStickersList = featuredStickerSets; if (MediaDataController.TYPE_IMAGE == currentType && NekoConfig.enableStickerPin.Bool()) { PinnedStickerHelper.getInstance(currentAccount).reorderPinnedStickers(newList); } DiffUtil.DiffResult diffResult = null; + DiffUtil.DiffResult featuredDiffResult = null; if (listAdapter != null) { if (!isPaused) { diffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { - final List oldList = listAdapter.stickerSets; + List oldList = listAdapter.stickerSets; @Override public int getOldListSize() { @@ -662,31 +704,63 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { - final TLRPC.StickerSet oldSet = oldList.get(oldItemPosition).set; - final TLRPC.StickerSet newSet = newList.get(newItemPosition).set; + TLRPC.StickerSet oldSet = oldList.get(oldItemPosition).set; + TLRPC.StickerSet newSet = newList.get(newItemPosition).set; return TextUtils.equals(oldSet.title, newSet.title) && oldSet.count == newSet.count; } }); + featuredDiffResult = DiffUtil.calculateDiff(new DiffUtil.Callback() { + List oldList = listAdapter.featuredStickerSets; + + @Override + public int getOldListSize() { + return oldList.size(); + } + + @Override + public int getNewListSize() { + return featuredStickersList.size(); + } + + @Override + public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) { + return oldList.get(oldItemPosition).set.id == featuredStickersList.get(newItemPosition).set.id; + } + + @Override + public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) { + TLRPC.StickerSet oldSet = oldList.get(oldItemPosition).set; + TLRPC.StickerSet newSet = featuredStickersList.get(newItemPosition).set; + return TextUtils.equals(oldSet.title, newSet.title) && oldSet.count == newSet.count && oldSet.installed == newSet.installed; + } + }); } listAdapter.setStickerSets(newList, false); // NekoX: dont reorder here + listAdapter.setFeaturedStickerSets(featuredStickersList); } rowCount = 0; if (currentType == MediaDataController.TYPE_IMAGE) { suggestRow = rowCount++; + largeEmojiRow = rowCount++; loopRow = rowCount++; loopInfoRow = rowCount++; - featuredRow = -1; } else { suggestRow = -1; + largeEmojiRow = -1; loopRow = -1; loopInfoRow = -1; - featuredRow = -1; + } + + if (currentType == MediaDataController.TYPE_IMAGE) { + masksRow = rowCount++; + } else { + masksRow = -1; } if (mediaDataController.getArchivedStickersCount(currentType) != 0) { - final boolean inserted = archivedRow == -1; + boolean inserted = archivedRow == -1; archivedRow = rowCount++; archivedInfoRow = currentType == MediaDataController.TYPE_MASK ? rowCount++ : -1; @@ -695,8 +769,8 @@ public class StickersActivity extends BaseFragment implements NotificationCenter listAdapter.notifyItemRangeInserted(archivedRow, archivedInfoRow != -1 ? 2 : 1); } } else { - final int oldArchivedRow = archivedRow; - final int oldArchivedInfoRow = archivedInfoRow; + int oldArchivedRow = archivedRow; + int oldArchivedInfoRow = archivedInfoRow; archivedRow = -1; archivedInfoRow = -1; @@ -707,15 +781,41 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } if (currentType == MediaDataController.TYPE_IMAGE) { - masksRow = rowCount++; + reactionsDoubleTapRow = rowCount++; stickersBotInfo = rowCount++; } else { - masksRow = -1; + reactionsDoubleTapRow = -1; stickersBotInfo = -1; } - final int stickerSetsCount = newList.size(); + if (!featuredStickersList.isEmpty() && currentType == MediaDataController.TYPE_IMAGE) { + featuredStickersHeaderRow = rowCount++; + featuredStickersStartRow = rowCount; + rowCount += featuredStickersList.size(); + featuredStickersEndRow = rowCount; + + if (truncatedFeaturedStickers) { + featuredStickersShowMoreRow = rowCount++; + } else { + featuredStickersShowMoreRow = -1; + } + featuredStickersShadowRow = rowCount++; + } else { + featuredStickersHeaderRow = -1; + featuredStickersStartRow = -1; + featuredStickersEndRow = -1; + featuredStickersShowMoreRow = -1; + featuredStickersShadowRow = -1; + } + + int stickerSetsCount = newList.size(); if (stickerSetsCount > 0) { + if (featuredStickersHeaderRow != -1) { + stickersHeaderRow = rowCount++; + } else { + stickersHeaderRow = -1; + } + stickersStartRow = rowCount; rowCount += stickerSetsCount; stickersEndRow = rowCount; @@ -728,6 +828,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter stickersShadowRow = -1; } } else { + stickersHeaderRow = -1; stickersStartRow = -1; stickersEndRow = -1; stickersShadowRow = -1; @@ -736,7 +837,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter if (listAdapter != null) { if (diffResult != null) { - final int startRow = stickersStartRow >= 0 ? stickersStartRow : rowCount; + int startRow = stickersStartRow >= 0 ? stickersStartRow : rowCount; listAdapter.notifyItemRangeChanged(0, startRow); diffResult.dispatchUpdatesTo(new ListUpdateCallback() { @Override @@ -753,6 +854,30 @@ public class StickersActivity extends BaseFragment implements NotificationCenter public void onMoved(int fromPosition, int toPosition) { } + @Override + public void onChanged(int position, int count, @Nullable Object payload) { + listAdapter.notifyItemRangeChanged(startRow + position, count); + } + }); + } + if (featuredDiffResult != null) { + int startRow = featuredStickersStartRow >= 0 ? featuredStickersStartRow : rowCount; + listAdapter.notifyItemRangeChanged(0, startRow); + featuredDiffResult.dispatchUpdatesTo(new ListUpdateCallback() { + @Override + public void onInserted(int position, int count) { + listAdapter.notifyItemRangeInserted(startRow + position, count); + } + + @Override + public void onRemoved(int position, int count) { + listAdapter.notifyItemRangeRemoved(startRow + position, count); + } + + @Override + public void onMoved(int fromPosition, int toPosition) { + } + @Override public void onChanged(int position, int count, @Nullable Object payload) { listAdapter.notifyItemRangeChanged(startRow + position, count); @@ -762,6 +887,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } } + @SuppressLint("NotifyDataSetChanged") @Override public void onResume() { super.onResume(); @@ -771,20 +897,31 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } private class ListAdapter extends RecyclerListView.SelectionAdapter { + private final static int TYPE_STICKER_SET = 0, + TYPE_INFO = 1, + TYPE_TEXT_AND_VALUE = 2, + TYPE_SHADOW = 3, + TYPE_SWITCH = 4, + TYPE_DOUBLE_TAP_REACTIONS = 5, + TYPE_HEADER = 6, + TYPE_FEATURED_STICKER_SET = 7; public static final int UPDATE_LOOP_STICKERS = 0; public static final int UPDATE_SELECTION = 1; public static final int UPDATE_REORDERABLE = 2; public static final int UPDATE_DIVIDER = 3; + public static final int UPDATE_FEATURED_ANIMATED = 4; private final LongSparseArray selectedItems = new LongSparseArray<>(); private final List stickerSets = new ArrayList<>(); + private final List featuredStickerSets = new ArrayList<>(); + private final List loadingFeaturedStickerSets = new ArrayList<>(); private Context mContext; private int pinnedStickersCount = 0; // to count how many stickers are pinned, used in notifyItemMoved, need to be updated when pin/unpin - public ListAdapter(Context context, List stickerSets) { + public ListAdapter(Context context, List stickerSets, List featuredStickerSets) { mContext = context; List temp = new ArrayList<>(stickerSets); if (MediaDataController.TYPE_IMAGE == currentType && NekoConfig.enableStickerPin.Bool()) { @@ -799,6 +936,21 @@ public class StickersActivity extends BaseFragment implements NotificationCenter this.pinnedStickersCount = PinnedStickerHelper.getInstance(currentAccount).pinnedList.size(); } this.stickerSets.addAll(stickerSets); + if (featuredStickerSets.size() > 3) { + setFeaturedStickerSets(featuredStickerSets.subList(0, 3)); + } else { + setFeaturedStickerSets(featuredStickerSets); + } + } + + @SuppressLint("NotifyDataSetChanged") + @Override + public void notifyDataSetChanged() { + super.notifyDataSetChanged(); + + if (isListeningForFeaturedUpdate) { + isListeningForFeaturedUpdate = false; + } } public void setStickerSets(List stickerSets) { @@ -815,6 +967,11 @@ public class StickersActivity extends BaseFragment implements NotificationCenter this.stickerSets.addAll(stickerSets); } + public void setFeaturedStickerSets(List featuredStickerSets) { + this.featuredStickerSets.clear(); + this.featuredStickerSets.addAll(featuredStickerSets); + } + @Override public int getItemCount() { return rowCount; @@ -822,10 +979,10 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public long getItemId(int i) { - if (i >= stickersStartRow && i < stickersEndRow) { + if (i >= featuredStickersStartRow && i < featuredStickersEndRow) { + return featuredStickerSets.get(i - featuredStickersStartRow).set.id; + } else if (i >= stickersStartRow && i < stickersEndRow) { return stickerSets.get(i - stickersStartRow).set.id; - } else if (i == suggestRow || i == loopInfoRow || i == archivedRow || i == archivedInfoRow || i == featuredRow || i == stickersBotInfo || i == masksRow) { - return Integer.MIN_VALUE; } return i; } @@ -834,7 +991,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter if (which == MENU_SHARE) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0, size = stickerSets.size(); i < size; i++) { - final TLRPC.TL_messages_stickerSet stickerSet = stickerSets.get(i); + TLRPC.TL_messages_stickerSet stickerSet = stickerSets.get(i); if (selectedItems.get(stickerSet.set.id, false)) { if (stringBuilder.length() != 0) { stringBuilder.append("\n"); @@ -858,10 +1015,10 @@ public class StickersActivity extends BaseFragment implements NotificationCenter }); shareAlert.show(); } else if (which == MENU_EXPORT || which == MENU_ARCHIVE || which == MENU_DELETE) { - final ArrayList stickerSetList = new ArrayList<>(selectedItems.size()); + ArrayList stickerSetList = new ArrayList<>(selectedItems.size()); for (int i = 0, size = stickerSets.size(); i < size; i++) { - final TLRPC.StickerSet stickerSet = stickerSets.get(i).set; + TLRPC.StickerSet stickerSet = stickerSets.get(i).set; if (selectedItems.get(stickerSet.id, false)) { stickerSetList.add(stickerSet); } @@ -899,14 +1056,14 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } - final int count = stickerSetList.size(); + int count = stickerSetList.size(); switch (count) { case 0: break; case 1: for (int i = 0, size = stickerSets.size(); i < size; i++) { - final TLRPC.TL_messages_stickerSet stickerSet = stickerSets.get(i); + TLRPC.TL_messages_stickerSet stickerSet = stickerSets.get(i); if (selectedItems.get(stickerSet.set.id, false)) { processSelectionOption(which, stickerSet); break; @@ -915,9 +1072,9 @@ public class StickersActivity extends BaseFragment implements NotificationCenter listAdapter.clearSelected(); break; default: - final AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); + AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); - final String buttonText; + String buttonText; if (which == MENU_DELETE) { builder.setTitle(LocaleController.formatString("DeleteStickerSetsAlertTitle", R.string.DeleteStickerSetsAlertTitle, LocaleController.formatPluralString("StickerSets", count))); builder.setMessage(LocaleController.formatString("DeleteStickersAlertMessage", R.string.DeleteStickersAlertMessage, count)); @@ -933,10 +1090,10 @@ public class StickersActivity extends BaseFragment implements NotificationCenter }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); - final AlertDialog dialog = builder.create(); + AlertDialog dialog = builder.create(); showDialog(dialog); if (which == MENU_DELETE) { - final TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); + TextView button = (TextView) dialog.getButton(DialogInterface.BUTTON_POSITIVE); if (button != null) { button.setTextColor(Theme.getColor(Theme.key_dialogTextRed2)); } @@ -979,7 +1136,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter FileLog.e(e); } } else if (which == 4) { - final int index = stickerSets.indexOf(stickerSet); + int index = stickerSets.indexOf(stickerSet); if (index >= 0) { listAdapter.toggleSelected(stickersStartRow + index); } @@ -1020,15 +1177,51 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 0: + case TYPE_HEADER: + HeaderCell headerCell = (HeaderCell) holder.itemView; + if (position == featuredStickersHeaderRow) { + headerCell.setText(LocaleController.getString(R.string.FeaturedStickers)); + } else if (position == stickersHeaderRow) { + headerCell.setText(LocaleController.getString(R.string.ChooseStickerMyStickerSets)); + } + break; + case TYPE_FEATURED_STICKER_SET: { + FeaturedStickerSetCell2 stickerSetCell = (FeaturedStickerSetCell2) holder.itemView; + int row = position - featuredStickersStartRow; + TLRPC.StickerSetCovered setCovered = featuredStickerSets.get(row); + boolean animated = isListeningForFeaturedUpdate || stickerSetCell.getStickerSet() != null && stickerSetCell.getStickerSet().set.id == setCovered.set.id; + stickerSetCell.setStickersSet(setCovered, true, false, false, animated); + stickerSetCell.setDrawProgress(loadingFeaturedStickerSets.contains(setCovered.set.id), animated); + + stickerSetCell.setAddOnClickListener(v -> { + FeaturedStickerSetCell2 cell = (FeaturedStickerSetCell2) v.getParent(); + TLRPC.StickerSetCovered pack = cell.getStickerSet(); + if (loadingFeaturedStickerSets.contains(pack.set.id)) { + return; + } + + isListeningForFeaturedUpdate = true; + loadingFeaturedStickerSets.add(pack.set.id); + + cell.setDrawProgress(true, true); + if (cell.isInstalled()) { + MediaDataController.getInstance(currentAccount).toggleStickerSet(getParentActivity(), pack, 0, StickersActivity.this, false, false); + } else { + MediaDataController.getInstance(currentAccount).toggleStickerSet(getParentActivity(), pack, 2, StickersActivity.this, false, false); + } + }); + + break; + } + case TYPE_STICKER_SET: + StickerSetCell stickerSetCell = (StickerSetCell) holder.itemView; int row = position - stickersStartRow; - final StickerSetCell stickerSetCell = (StickerSetCell) holder.itemView; stickerSetCell.setStickersSet(stickerSets.get(row), row != stickerSets.size() - 1); stickerSetCell.setChecked(selectedItems.get(getItemId(position), false), false); stickerSetCell.setReorderable(hasSelected(), false); break; - case 1: - final TextInfoPrivacyCell infoPrivacyCell = (TextInfoPrivacyCell) holder.itemView; + case TYPE_INFO: + TextInfoPrivacyCell infoPrivacyCell = (TextInfoPrivacyCell) holder.itemView; if (position == stickersBotInfo) { infoPrivacyCell.setText(addStickersBotSpan(LocaleController.getString("StickersBotInfo", R.string.StickersBotInfo))); } else if (position == archivedInfoRow) { @@ -1043,52 +1236,72 @@ public class StickersActivity extends BaseFragment implements NotificationCenter infoPrivacyCell.setText(LocaleController.getString("MasksInfo", R.string.MasksInfo)); } break; - case 2: - final TextSettingsCell settingsCell = (TextSettingsCell) holder.itemView; - if (position == featuredRow) { - final int count = MediaDataController.getInstance(currentAccount).getFeaturedStickerSets().size(); - settingsCell.setTextAndValue(LocaleController.getString("FeaturedStickers", R.string.FeaturedStickers), count > 0 ? Integer.toString(count) : "", true); - } else if (position == archivedRow) { - final int count = MediaDataController.getInstance(currentAccount).getArchivedStickersCount(currentType); - final String value = count > 0 ? Integer.toString(count) : ""; - if (currentType == MediaDataController.TYPE_IMAGE) { - settingsCell.setTextAndValue(LocaleController.getString("ArchivedStickers", R.string.ArchivedStickers), value, true); - } else { - settingsCell.setTextAndValue(LocaleController.getString("ArchivedMasks", R.string.ArchivedMasks), value, true); + case TYPE_TEXT_AND_VALUE: { + TextCell settingsCell = (TextCell) holder.itemView; + if (position == featuredStickersShowMoreRow) { + settingsCell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); + settingsCell.setTextAndIcon(LocaleController.getString(R.string.ShowMoreStickers), R.drawable.msg_trending, false); + } else { + settingsCell.setColors(Theme.key_windowBackgroundWhiteGrayIcon, Theme.key_windowBackgroundWhiteBlackText); + if (position == archivedRow) { + int count = MediaDataController.getInstance(currentAccount).getArchivedStickersCount(currentType); + String value = count > 0 ? Integer.toString(count) : ""; + if (currentType == MediaDataController.TYPE_IMAGE) { + settingsCell.setTextAndValueAndIcon(LocaleController.getString(R.string.ArchivedStickers), value, R.drawable.msg_archived_stickers, true); + } else { + settingsCell.setTextAndValue(LocaleController.getString("ArchivedMasks", R.string.ArchivedMasks), value, true); + } + } else if (position == masksRow) { + int type = MediaDataController.TYPE_MASK; + MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); + int count = MessagesController.getInstance(currentAccount).filterPremiumStickers(mediaDataController.getStickerSets(type)).size() + mediaDataController.getArchivedStickersCount(type); + settingsCell.setTextAndValueAndIcon(LocaleController.getString("Masks", R.string.Masks), count > 0 ? Integer.toString(count) : "", R.drawable.msg_mask, true); + } else if (position == suggestRow) { + String value; + switch (SharedConfig.suggestStickers) { + case 0: + value = LocaleController.getString("SuggestStickersAll", R.string.SuggestStickersAll); + break; + case 1: + value = LocaleController.getString("SuggestStickersInstalled", R.string.SuggestStickersInstalled); + break; + case 2: + default: + value = LocaleController.getString("SuggestStickersNone", R.string.SuggestStickersNone); + break; + } + settingsCell.setTextAndValue(LocaleController.getString("SuggestStickers", R.string.SuggestStickers), value, true); } - } else if (position == masksRow) { - final int type = MediaDataController.TYPE_MASK; - final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); - final int count = mediaDataController.getStickerSets(type).size() + mediaDataController.getArchivedStickersCount(type); - settingsCell.setTextAndValue(LocaleController.getString("Masks", R.string.Masks), count > 0 ? Integer.toString(count) : "", false); - } else if (position == suggestRow) { - String value; - switch (SharedConfig.suggestStickers) { - case 0: - value = LocaleController.getString("SuggestStickersAll", R.string.SuggestStickersAll); - break; - case 1: - value = LocaleController.getString("SuggestStickersInstalled", R.string.SuggestStickersInstalled); - break; - case 2: - default: - value = LocaleController.getString("SuggestStickersNone", R.string.SuggestStickersNone); - break; - } - settingsCell.setTextAndValue(LocaleController.getString("SuggestStickers", R.string.SuggestStickers), value, true); } break; - case 3: + } + case TYPE_SHADOW: if (position == stickersShadowRow) { - holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } break; - case 4: + case TYPE_SWITCH: + TextCheckCell cell = (TextCheckCell) holder.itemView; if (position == loopRow) { - TextCheckCell cell = (TextCheckCell) holder.itemView; - cell.setTextAndCheck(LocaleController.getString("LoopAnimatedStickers", R.string.LoopAnimatedStickers), SharedConfig.loopStickers, true); + cell.setTextAndCheck(LocaleController.getString(R.string.LoopAnimatedStickers), SharedConfig.loopStickers, true); + } else if (position == largeEmojiRow) { + cell.setTextAndCheck(LocaleController.getString(R.string.LargeEmoji), SharedConfig.allowBigEmoji, true); } break; + case TYPE_DOUBLE_TAP_REACTIONS: { + TextSettingsCell settingsCell = (TextSettingsCell) holder.itemView; + settingsCell.setText(LocaleController.getString(R.string.DoubleTapSetting), false); + settingsCell.setIcon(R.drawable.msg_reactions2); + String reaction = MediaDataController.getInstance(currentAccount).getDoubleTapReaction(); + if (reaction != null) { + TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction); + if (availableReaction != null) { + SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(availableReaction.static_icon.thumbs, Theme.key_windowBackgroundGray, 1.0f); + settingsCell.getValueBackupImageView().getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.center_icon), "100_100_lastframe", svgThumb, "webp", availableReaction, 1); + } + } + break; + } } } @@ -1098,9 +1311,9 @@ public class StickersActivity extends BaseFragment implements NotificationCenter onBindViewHolder(holder, position); } else { switch (holder.getItemViewType()) { - case 0: + case TYPE_STICKER_SET: if (position >= stickersStartRow && position < stickersEndRow) { - final StickerSetCell stickerSetCell = (StickerSetCell) holder.itemView; + StickerSetCell stickerSetCell = (StickerSetCell) holder.itemView; if (payloads.contains(UPDATE_SELECTION)) { stickerSetCell.setChecked(selectedItems.get(getItemId(position), false)); } @@ -1112,11 +1325,16 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } } break; - case 4: + case TYPE_SWITCH: if (payloads.contains(UPDATE_LOOP_STICKERS) && position == loopRow) { ((TextCheckCell) holder.itemView).setChecked(SharedConfig.loopStickers); } break; + case TYPE_FEATURED_STICKER_SET: + if (payloads.contains(UPDATE_FEATURED_ANIMATED) && position >= featuredStickersStartRow && position <= featuredStickersEndRow) { + ((FeaturedStickerSetCell2) holder.itemView).setStickersSet(featuredStickerSets.get(position - featuredStickersStartRow), true, false, false, true); + } + break; } } } @@ -1124,18 +1342,24 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); - return type == 0 || type == 2 || type == 4; + return type == TYPE_STICKER_SET || type == TYPE_FEATURED_STICKER_SET || type == TYPE_TEXT_AND_VALUE || type == TYPE_SWITCH || type == TYPE_DOUBLE_TAP_REACTIONS; } @Override @SuppressLint("ClickableViewAccessibility") - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + @NonNull + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; switch (viewType) { - case 0: + case TYPE_FEATURED_STICKER_SET: + view = new FeaturedStickerSetCell2(mContext, getResourceProvider()); + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + ((FeaturedStickerSetCell2) view).getTextView().setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + break; + case TYPE_STICKER_SET: view = new StickerSetCell(mContext, 1); - view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); - final StickerSetCell stickerSetCell = (StickerSetCell) view; + view.setBackgroundColor(getThemedColor(Theme.key_windowBackgroundWhite)); + StickerSetCell stickerSetCell = (StickerSetCell) view; stickerSetCell.setOnReorderButtonTouchListener((v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { itemTouchHelper.startDrag(listView.getChildViewHolder(stickerSetCell)); @@ -1144,12 +1368,12 @@ public class StickersActivity extends BaseFragment implements NotificationCenter }); stickerSetCell.setOnOptionsClick(v -> { StickerSetCell cell = (StickerSetCell) v.getParent(); - final TLRPC.TL_messages_stickerSet stickerSet = cell.getStickersSet(); + TLRPC.TL_messages_stickerSet stickerSet = cell.getStickersSet(); AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(stickerSet.set.title); - final int[] options; - final CharSequence[] items; - final int[] icons; + int[] options; + CharSequence[] items; + int[] icons; if (stickerSet.set.official) { options = new int[]{MENU_ARCHIVE, 4}; items = new CharSequence[]{ @@ -1198,7 +1422,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } builder.setItems(items, icons, (dialog, which) -> processSelectionOption(options[which], stickerSet)); - final AlertDialog dialog = builder.create(); + AlertDialog dialog = builder.create(); showDialog(dialog); if (options[options.length - 1] == MENU_DELETE) { @@ -1206,18 +1430,26 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } }); break; - case 1: + case TYPE_INFO: view = new TextInfoPrivacyCell(mContext); - view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + view.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); break; - case 2: + case TYPE_TEXT_AND_VALUE: + view = new TextCell(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); + break; + case TYPE_SHADOW: + view = new ShadowSectionCell(mContext); + break; + case TYPE_DOUBLE_TAP_REACTIONS: view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 3: - view = new ShadowSectionCell(mContext); + case TYPE_HEADER: + view = new HeaderCell(mContext); + view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 4: + case TYPE_SWITCH: default: view = new TextCheckCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); @@ -1229,18 +1461,24 @@ public class StickersActivity extends BaseFragment implements NotificationCenter @Override public int getItemViewType(int i) { - if (i >= stickersStartRow && i < stickersEndRow) { - return 0; + if (i >= featuredStickersStartRow && i < featuredStickersEndRow) { + return TYPE_FEATURED_STICKER_SET; + } else if (i >= stickersStartRow && i < stickersEndRow) { + return TYPE_STICKER_SET; } else if (i == stickersBotInfo || i == archivedInfoRow || i == loopInfoRow || i == masksInfoRow) { - return 1; - } else if (i == featuredRow || i == archivedRow || i == masksRow || i == suggestRow) { - return 2; - } else if (i == stickersShadowRow) { - return 3; - } else if (i == loopRow) { - return 4; + return TYPE_INFO; + } else if (i == archivedRow || i == masksRow || i == suggestRow || i == featuredStickersShowMoreRow) { + return TYPE_TEXT_AND_VALUE; + } else if (i == stickersShadowRow || i == featuredStickersShadowRow) { + return TYPE_SHADOW; + } else if (i == loopRow || i == largeEmojiRow) { + return TYPE_SWITCH; + } else if (i == reactionsDoubleTapRow) { + return TYPE_DOUBLE_TAP_REACTIONS; + } else if (i == featuredStickersHeaderRow || i == stickersHeaderRow) { + return TYPE_HEADER; } - return 0; + return TYPE_STICKER_SET; } public void swapElements(int fromIndex, int toIndex) { @@ -1248,10 +1486,10 @@ public class StickersActivity extends BaseFragment implements NotificationCenter needReorder = true; } - final MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); + MediaDataController mediaDataController = MediaDataController.getInstance(currentAccount); - final int index1 = fromIndex - stickersStartRow; - final int index2 = toIndex - stickersStartRow; + int index1 = fromIndex - stickersStartRow; + int index2 = toIndex - stickersStartRow; swapListElements(stickerSets, index1, index2); swapListElements(mediaDataController.getStickerSets(currentType), index1, index2); @@ -1291,13 +1529,13 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } private void swapListElements(List list, int index1, int index2) { - final TLRPC.TL_messages_stickerSet set1 = list.get(index1); + TLRPC.TL_messages_stickerSet set1 = list.get(index1); list.set(index1, list.get(index2)); list.set(index2, set1); } public void toggleSelected(int position) { - final long id = getItemId(position); + long id = getItemId(position); selectedItems.put(id, !selectedItems.get(id, false)); notifyItemChanged(position, UPDATE_SELECTION); checkActionMode(); @@ -1324,8 +1562,8 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } private void checkActionMode() { - final int selectedCount = listAdapter.getSelectedCount(); - final boolean actionModeShowed = actionBar.isActionModeShowed(); + int selectedCount = listAdapter.getSelectedCount(); + boolean actionModeShowed = actionBar.isActionModeShowed(); if (selectedCount > 0) { checkActionModeIcons(); selectedCountTextView.setNumber(selectedCount, actionModeShowed); @@ -1334,7 +1572,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter notifyStickersItemsChanged(UPDATE_REORDERABLE); if (!SharedConfig.stickersReorderingHintUsed) { SharedConfig.setStickersReorderingHintUsed(true); - final String stickersReorderHint = LocaleController.getString("StickersReorderHint", R.string.StickersReorderHint); + String stickersReorderHint = LocaleController.getString("StickersReorderHint", R.string.StickersReorderHint); Bulletin.make(parentLayout, new ReorderingBulletinLayout(mContext, stickersReorderHint, null), ReorderingHintDrawable.DURATION * 2 + 250).show(); } } @@ -1355,7 +1593,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } } } - final int visibility = canDelete ? View.VISIBLE : View.GONE; + int visibility = canDelete ? View.VISIBLE : View.GONE; if (deleteMenuItem.getVisibility() != visibility) { deleteMenuItem.setVisibility(visibility); } @@ -1367,8 +1605,8 @@ public class StickersActivity extends BaseFragment implements NotificationCenter } private CharSequence addStickersBotSpan(String text) { - final String botName = "@stickers"; - final int index = text.indexOf(botName); + String botName = "@stickers"; + int index = text.indexOf(botName); if (index != -1) { try { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(text); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java index 0431e6f6e..a1ee0bbd7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemeActivity.java @@ -41,6 +41,7 @@ import android.widget.FrameLayout; import android.widget.TextView; import androidx.annotation.Keep; +import androidx.annotation.NonNull; import androidx.core.content.FileProvider; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; @@ -49,20 +50,15 @@ import androidx.recyclerview.widget.RecyclerView; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.BuildConfig; -import org.telegram.messenger.DocumentObject; import org.telegram.messenger.FileLoader; import org.telegram.messenger.FileLog; -import org.telegram.messenger.ImageLocation; import org.telegram.messenger.LocaleController; -import org.telegram.messenger.MediaDataController; import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SharedConfig; -import org.telegram.messenger.SvgHelper; 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; @@ -71,6 +67,7 @@ import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.ActionBar.EmojiThemes; import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.ThemeDescription; +import org.telegram.ui.Cells.AppIconsSelectorCell; import org.telegram.ui.Cells.BrightnessControlCell; import org.telegram.ui.Cells.ChatListCell; import org.telegram.ui.Cells.ChatMessageCell; @@ -91,6 +88,7 @@ import org.telegram.ui.Components.RLottieDrawable; import org.telegram.ui.Components.RecyclerListView; 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.ThemeEditorView; @@ -135,17 +133,13 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int directShareRow; private int raiseToSpeakRow; private int sendByEnterRow; - private int saveToGalleryRow; private int saveToGalleryOption1Row; private int saveToGalleryOption2Row; private int saveToGallerySectionRow; private int distanceRow; private int enableAnimationsRow; private int settings2Row; - private int stickersRow; - private int stickersSection2Row; - private int emojiRow; private int contactsReimportRow; private int contactsSortRow; @@ -178,7 +172,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int themeListRow2; private int themeAccentListRow; private int themeInfoRow; - private int reactionsDoubleTapRow; private int chatBlurRow; private int swipeGestureHeaderRow; @@ -190,6 +183,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No private int editThemeRow; private int createNewThemeRow; + private int appIconHeaderRow; + private int appIconSelectorRow; + private int appIconShadowRow; + private int rowCount; private boolean updatingLocation; @@ -259,6 +256,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); +// sizeBar.setSeparatorsCount(endFontSize - startFontSize); sizeBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { @Override public void onSeekBarDrag(boolean stop, float progress) { @@ -342,6 +340,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No sizeBar = new SeekBarView(context); sizeBar.setReportChanges(true); +// sizeBar.setSeparatorsCount(endRadius - startRadius); sizeBar.setDelegate(new SeekBarView.SeekBarViewDelegate() { @Override public void onSeekBarDrag(boolean stop, float progress) { @@ -468,7 +467,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No int prevEditThemeRow = editThemeRow; rowCount = 0; - emojiRow = -1; contactsReimportRow = -1; contactsSortRow = -1; scheduleLocationRow = -1; @@ -501,7 +499,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No chatListHeaderRow = -1; chatListRow = -1; chatListInfoRow = -1; - reactionsDoubleTapRow = -1; chatBlurRow = -1; textSizeRow = -1; @@ -512,14 +509,11 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No enableAnimationsRow = -1; raiseToSpeakRow = -1; sendByEnterRow = -1; - saveToGalleryRow = -1; saveToGalleryOption1Row = -1; saveToGalleryOption2Row = -1; saveToGallerySectionRow = -1; distanceRow = -1; settings2Row = -1; - stickersRow = -1; - stickersSection2Row = -1; swipeGestureHeaderRow = -1; swipeGestureRow = -1; @@ -530,6 +524,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No editThemeRow = -1; createNewThemeRow = -1; + appIconHeaderRow = -1; + appIconSelectorRow = -1; + appIconShadowRow = -1; + defaultThemes.clear(); darkThemes.clear(); for (int a = 0, N = Theme.themes.size(); a < N; a++) { @@ -605,23 +603,22 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No swipeGestureRow = rowCount++; swipeGestureInfoRow = rowCount++; + appIconHeaderRow = rowCount++; + appIconSelectorRow = rowCount++; + appIconShadowRow = rowCount++; + settingsRow = rowCount++; nightThemeRow = rowCount++; customTabsRow = rowCount++; directShareRow = rowCount++; enableAnimationsRow = rowCount++; - emojiRow = rowCount++; raiseToSpeakRow = rowCount++; sendByEnterRow = rowCount++; - saveToGalleryRow = -1; if (SharedConfig.canBlurChat()) { chatBlurRow = rowCount++; } distanceRow = rowCount++; - reactionsDoubleTapRow = rowCount++; settings2Row = rowCount++; - stickersRow = rowCount++; - stickersSection2Row = rowCount++; } else { nightDisabledRow = rowCount++; nightScheduledRow = rowCount++; @@ -1014,11 +1011,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No if (view instanceof TextCheckCell) { ((TextCheckCell) view).setChecked(SharedConfig.raiseToSpeak); } - } else if (position == saveToGalleryRow) { - SharedConfig.toggleSaveToGallery(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.saveToGallery); - } } else if (position == distanceRow) { if (getParentActivity() == null) { return; @@ -1071,15 +1063,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); - } else if (position == stickersRow) { - presentFragment(new StickersActivity(MediaDataController.TYPE_IMAGE)); - } else if (position == reactionsDoubleTapRow) { - presentFragment(new ReactionsDoubleTapManageActivity()); - } else if (position == emojiRow) { - SharedConfig.toggleBigEmoji(); - if (view instanceof TextCheckCell) { - ((TextCheckCell) view).setChecked(SharedConfig.allowBigEmoji); - } } else if (position == chatBlurRow) { SharedConfig.toggleChatBlur(); if (view instanceof TextCheckCell) { @@ -1609,6 +1592,25 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } private class ListAdapter extends RecyclerListView.SelectionAdapter { + private final static int TYPE_TEXT_SETTING = 1; + private final static int TYPE_TEXT_INFO_PRIVACY = 2; + private final static int TYPE_SHADOW = 3; + private final static int TYPE_THEME_TYPE = 4; + private final static int TYPE_HEADER = 5; + private final static int TYPE_BRIGHTNESS = 6; + private final static int TYPE_TEXT_CHECK = 7; + private final static int TYPE_TEXT_SIZE = 8; + private final static int TYPE_CHAT_LIST = 9; + private final static int TYPE_NIGHT_THEME = 10; + private final static int TYPE_THEME_LIST = 11; + private final static int TYPE_THEME_ACCENT_LIST = 12; + private final static int TYPE_BUBBLE_RADIUS = 13; + private final static int TYPE_TEXT_PREFERENCE = 14; + private final static int TYPE_SWIPE_GESTURE = 15; + private final static int TYPE_THEME_PREVIEW = 16; + 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 Context mContext; private boolean first = true; @@ -1625,7 +1627,9 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override public boolean isEnabled(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); - return type == 0 || type == 1 || type == 4 || type == 7 || type == 10 || type == 11 || type == 12 || type == 14 || type == 18; + 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; } private void showOptionsForTheme(Theme.ThemeInfo themeInfo) { @@ -1766,30 +1770,31 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } } + @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view; switch (viewType) { - case 1: + case TYPE_TEXT_SETTING: view = new TextSettingsCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 2: + case TYPE_TEXT_INFO_PRIVACY: view = new TextInfoPrivacyCell(mContext); - view.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + view.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); break; - case 3: + case TYPE_SHADOW: view = new ShadowSectionCell(mContext); break; - case 4: + case TYPE_THEME_TYPE: view = new ThemeTypeCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 5: + case TYPE_HEADER: view = new HeaderCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 6: + case TYPE_BRIGHTNESS: view = new BrightnessControlCell(mContext) { @Override protected void didChangedValue(float value) { @@ -1808,15 +1813,15 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No }; view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 7: + case TYPE_TEXT_CHECK: view = new TextCheckCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 8: + case TYPE_TEXT_SIZE: view = new TextSizeCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 9: + case TYPE_CHAT_LIST: view = new ChatListCell(mContext) { @Override protected void didSelectChatType(boolean threeLines) { @@ -1825,11 +1830,11 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No }; view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 10: + case TYPE_NIGHT_THEME: view = new NotificationsCheckCell(mContext, 21, 64, false); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 11: + case TYPE_THEME_LIST: first = true; themesHorizontalListCell = new ThemesHorizontalListCell(mContext, currentType, defaultThemes, darkThemes) { @Override @@ -1852,7 +1857,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No view = themesHorizontalListCell; view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(148))); break; - case 12: { + case TYPE_THEME_ACCENT_LIST: { RecyclerListView accentsListView = new TintRecyclerListView(mContext) { @Override public boolean onInterceptTouchEvent(MotionEvent e) { @@ -1978,37 +1983,37 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, AndroidUtilities.dp(62))); break; } - case 13: + case TYPE_BUBBLE_RADIUS: view = new BubbleRadiusCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 14: + case TYPE_TEXT_PREFERENCE: default: view = new TextCell(mContext); view.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); break; - case 15: + case TYPE_SWIPE_GESTURE: view = new SwipeGestureSettingsView(mContext, currentAccount); break; - case 16: + case TYPE_THEME_PREVIEW: ThemePreviewMessagesCell messagesCell = new ThemePreviewMessagesCell(mContext, parentLayout, 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { messagesCell.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); } view = messagesCell; break; - case 17: + case TYPE_DEFAULT_THEMES_PREVIEW: DefaultThemesPreviewCell cell = new DefaultThemesPreviewCell(mContext, ThemeActivity.this, currentType); view = cell; cell.setFocusable(false); view.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); break; - case 18: - view = new TextSettingsCell(mContext); - break; - case 19: + case TYPE_SAVE_TO_GALLERY: view = new RadioButtonCell(mContext); break; + case TYPE_APP_ICON: + view = new AppIconsSelectorCell(mContext, ThemeActivity.this, currentAccount); + break; } return new RecyclerListView.Holder(view); } @@ -2016,7 +2021,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { switch (holder.getItemViewType()) { - case 1: { + case TYPE_TEXT_SETTING: { TextSettingsCell cell = (TextSettingsCell) holder.itemView; if (position == nightThemeRow) { if (Theme.selectedAutoNightType == Theme.AUTO_NIGHT_TYPE_NONE || Theme.getCurrentNightTheme() == null) { @@ -2048,8 +2053,6 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No cell.setTextAndValue(LocaleController.getString("SortBy", R.string.SortBy), value, true); } else if (position == contactsReimportRow) { cell.setText(LocaleController.getString("ImportContacts", R.string.ImportContacts), true); - } else if (position == stickersRow) { - cell.setText(LocaleController.getString("StickersAndMasks", R.string.StickersAndMasks), false); } else if (position == distanceRow) { String value; if (SharedConfig.distanceSystemType == 0) { @@ -2059,11 +2062,11 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } else { value = LocaleController.getString("DistanceUnitsMiles", R.string.DistanceUnitsMiles); } - cell.setTextAndValue(LocaleController.getString("DistanceUnits", R.string.DistanceUnits), value, true); + cell.setTextAndValue(LocaleController.getString("DistanceUnits", R.string.DistanceUnits), value, false); } break; } - case 2: { + case TYPE_TEXT_INFO_PRIVACY: { TextInfoPrivacyCell cell = (TextInfoPrivacyCell) holder.itemView; if (position == automaticBrightnessInfoRow) { cell.setText(LocaleController.formatString("AutoNightBrightnessInfo", R.string.AutoNightBrightnessInfo, (int) (100 * Theme.autoNightBrighnessThreshold))); @@ -2072,15 +2075,15 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } break; } - case 3: { - if (position == stickersSection2Row || position == nightTypeInfoRow && themeInfoRow == -1 || position == themeInfoRow && nightTypeInfoRow != -1 || position == saveToGallerySectionRow) { + case TYPE_SHADOW: { + if (position == nightTypeInfoRow && themeInfoRow == -1 || position == themeInfoRow && nightTypeInfoRow != -1 || position == saveToGallerySectionRow) { holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } else { holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } break; } - case 4: { + case TYPE_THEME_TYPE: { ThemeTypeCell typeCell = (ThemeTypeCell) holder.itemView; if (position == nightDisabledRow) { typeCell.setValue(LocaleController.getString("AutoNightDisabled", R.string.AutoNightDisabled), Theme.selectedAutoNightType == Theme.AUTO_NIGHT_TYPE_NONE, true); @@ -2093,7 +2096,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } break; } - case 5: { + case TYPE_HEADER: { HeaderCell headerCell = (HeaderCell) holder.itemView; if (position == scheduleHeaderRow) { headerCell.setText(LocaleController.getString("AutoNightSchedule", R.string.AutoNightSchedule)); @@ -2119,15 +2122,17 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No headerCell.setText(LocaleController.getString("ChatListSwipeGesture", R.string.ChatListSwipeGesture)); } else if (position == selectThemeHeaderRow) { headerCell.setText(LocaleController.getString("SelectTheme", R.string.SelectTheme)); + } else if (position == appIconHeaderRow) { + headerCell.setText(LocaleController.getString(R.string.AppIcon)); } break; } - case 6: { + case TYPE_BRIGHTNESS: { BrightnessControlCell cell = (BrightnessControlCell) holder.itemView; cell.setProgress(Theme.autoNightBrighnessThreshold); break; } - case 7: { + case TYPE_TEXT_CHECK: { TextCheckCell textCheckCell = (TextCheckCell) holder.itemView; if (position == scheduleLocationRow) { textCheckCell.setTextAndCheck(LocaleController.getString("AutoNightLocation", R.string.AutoNightLocation), Theme.autoNightScheduleByLocation, true); @@ -2137,22 +2142,18 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } else if (position == sendByEnterRow) { SharedPreferences preferences = MessagesController.getGlobalMainSettings(); textCheckCell.setTextAndCheck(LocaleController.getString("SendByEnter", R.string.SendByEnter), preferences.getBoolean("send_by_enter", false), true); - } else if (position == saveToGalleryRow) { - textCheckCell.setTextAndCheck(LocaleController.getString("SaveToGallerySettings", R.string.SaveToGallerySettings), SharedConfig.saveToGallery, true); } else if (position == raiseToSpeakRow) { textCheckCell.setTextAndCheck(LocaleController.getString("RaiseToSpeak", R.string.RaiseToSpeak), SharedConfig.raiseToSpeak, true); } else if (position == customTabsRow) { textCheckCell.setTextAndValueAndCheck(LocaleController.getString("ChromeCustomTabs", R.string.ChromeCustomTabs), LocaleController.getString("ChromeCustomTabsInfo", R.string.ChromeCustomTabsInfo), SharedConfig.customTabs, false, true); } else if (position == directShareRow) { textCheckCell.setTextAndValueAndCheck(LocaleController.getString("DirectShare", R.string.DirectShare), LocaleController.getString("DirectShareInfo", R.string.DirectShareInfo), SharedConfig.directShare, false, true); - } else if (position == emojiRow) { - textCheckCell.setTextAndCheck(LocaleController.getString("LargeEmoji", R.string.LargeEmoji), SharedConfig.allowBigEmoji, true); } else if (position == chatBlurRow) { textCheckCell.setTextAndCheck(LocaleController.getString("BlurInChat", R.string.BlurInChat), SharedConfig.chatBlurEnabled(), true); } break; } - case 10: { + case TYPE_NIGHT_THEME: { NotificationsCheckCell checkCell = (NotificationsCheckCell) holder.itemView; if (position == nightThemeRow) { boolean enabled = Theme.selectedAutoNightType != Theme.AUTO_NIGHT_TYPE_NONE; @@ -2172,14 +2173,14 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } break; } - case 11: { + case TYPE_THEME_LIST: { if (first) { themesHorizontalListCell.scrollToCurrentTheme(listView.getMeasuredWidth(), false); first = false; } break; } - case 12: { + case TYPE_THEME_ACCENT_LIST: { RecyclerListView accentsList = (RecyclerListView) holder.itemView; ThemeAccentsListAdapter adapter = (ThemeAccentsListAdapter) accentsList.getAdapter(); adapter.notifyDataSetChanged(); @@ -2192,7 +2193,7 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } break; } - case 14: { + case TYPE_TEXT_PREFERENCE: { TextCell cell = (TextCell) holder.itemView; cell.setColors(Theme.key_windowBackgroundWhiteBlueText4, Theme.key_windowBackgroundWhiteBlueText4); if (position == backgroundRow) { @@ -2204,25 +2205,12 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No } break; } - case 17: { + case TYPE_DEFAULT_THEMES_PREVIEW: { DefaultThemesPreviewCell cell = (DefaultThemesPreviewCell) holder.itemView; cell.updateDayNightMode(); break; } - case 18:{ - TextSettingsCell settingsCell = (TextSettingsCell) holder.itemView; - settingsCell.setText(LocaleController.getString("DoubleTapSetting", R.string.DoubleTapSetting), false); - String reaction = MediaDataController.getInstance(currentAccount).getDoubleTapReaction(); - if (reaction != null) { - TLRPC.TL_availableReaction availableReaction = MediaDataController.getInstance(currentAccount).getReactionsMap().get(reaction); - if (availableReaction != null) { - SvgHelper.SvgDrawable svgThumb = DocumentObject.getSvgThumb(availableReaction.static_icon.thumbs, Theme.key_windowBackgroundGray, 1.0f); - settingsCell.getValueBackupImageView().getImageReceiver().setImage(ImageLocation.getForDocument(availableReaction.static_icon), "100_100", svgThumb, "webp", availableReaction, 1); - } - } - break; - } - case 19:{ + case TYPE_SAVE_TO_GALLERY: { RadioButtonCell radioCell = (RadioButtonCell) holder.itemView; if (position == saveToGalleryOption1Row) { radioCell.setTextAndValueAndCheck("save media only from peer chats", "",true, false); @@ -2238,10 +2226,10 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { int type = holder.getItemViewType(); - if (type == 4) { + if (type == TYPE_THEME_TYPE) { ((ThemeTypeCell) holder.itemView).setTypeChecked(holder.getAdapterPosition() == Theme.selectedAutoNightType); } - if (type != 2 && type != 3) { + if (type != TYPE_TEXT_INFO_PRIVACY && type != TYPE_SHADOW) { holder.itemView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); } } @@ -2250,52 +2238,53 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No public int getItemViewType(int position) { if (position == scheduleFromRow || position == distanceRow || position == scheduleToRow || position == scheduleUpdateLocationRow || - position == contactsReimportRow || position == contactsSortRow || position == stickersRow) { - return 1; + position == contactsReimportRow || position == contactsSortRow) { + return TYPE_TEXT_SETTING; } else if (position == automaticBrightnessInfoRow || position == scheduleLocationInfoRow) { - return 2; + return TYPE_TEXT_INFO_PRIVACY; } else if (position == themeInfoRow || position == nightTypeInfoRow || position == scheduleFromToInfoRow || - position == stickersSection2Row || position == settings2Row || position == newThemeInfoRow || - position == chatListInfoRow || position == bubbleRadiusInfoRow || position == swipeGestureInfoRow || position == saveToGallerySectionRow) { - return 3; + position == settings2Row || position == newThemeInfoRow || position == chatListInfoRow || position == bubbleRadiusInfoRow || + position == swipeGestureInfoRow || position == saveToGallerySectionRow || position == appIconShadowRow) { + return TYPE_SHADOW; } else if (position == nightDisabledRow || position == nightScheduledRow || position == nightAutomaticRow || position == nightSystemDefaultRow) { - return 4; + return TYPE_THEME_TYPE; } else if (position == scheduleHeaderRow || position == automaticHeaderRow || position == preferedHeaderRow || position == settingsRow || position == themeHeaderRow || position == textSizeHeaderRow || - position == chatListHeaderRow || position == bubbleRadiusHeaderRow || position == swipeGestureHeaderRow || position == selectThemeHeaderRow) { - return 5; + position == chatListHeaderRow || position == bubbleRadiusHeaderRow || position == swipeGestureHeaderRow || + position == selectThemeHeaderRow || position == appIconHeaderRow) { + return TYPE_HEADER; } else if (position == automaticBrightnessRow) { - return 6; + return TYPE_BRIGHTNESS; } else if (position == scheduleLocationRow || position == enableAnimationsRow || position == sendByEnterRow || - position == saveToGalleryRow || position == raiseToSpeakRow || position == customTabsRow || - position == directShareRow || position == emojiRow || position == chatBlurRow) { - return 7; + position == raiseToSpeakRow || position == customTabsRow || + position == directShareRow || position == chatBlurRow) { + return TYPE_TEXT_CHECK; } else if (position == textSizeRow) { - return 8; + return TYPE_TEXT_SIZE; } else if (position == chatListRow) { - return 9; + return TYPE_CHAT_LIST; } else if (position == nightThemeRow) { - return 10; + return TYPE_NIGHT_THEME; } else if (position == themeListRow) { - return 11; + return TYPE_THEME_LIST; } else if (position == themeAccentListRow) { - return 12; + return TYPE_THEME_ACCENT_LIST; } else if (position == bubbleRadiusRow) { - return 13; + return TYPE_BUBBLE_RADIUS; } else if (position == backgroundRow || position == editThemeRow || position == createNewThemeRow) { - return 14; + return TYPE_TEXT_PREFERENCE; } else if (position == swipeGestureRow) { - return 15; + return TYPE_SWIPE_GESTURE; } else if (position == themePreviewRow) { - return 16; + return TYPE_THEME_PREVIEW; } else if (position == themeListRow2) { - return 17; - } else if (position == reactionsDoubleTapRow) { - return 18; + return TYPE_DEFAULT_THEMES_PREVIEW; } else if (position == saveToGalleryOption1Row || position == saveToGalleryOption2Row) { - return 19; + return TYPE_SAVE_TO_GALLERY; + } else if (position == appIconSelectorRow) { + return TYPE_APP_ICON; } - return 1; + return TYPE_TEXT_SETTING; } } @@ -2309,7 +2298,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}, 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, 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)); @@ -2394,6 +2383,37 @@ public class ThemeActivity extends BaseFragment implements NotificationCenter.No themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextSizeCell.class}, null, null, null, Theme.key_chat_inTimeSelectedText)); themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{TextSizeCell.class}, null, null, null, Theme.key_chat_outTimeSelectedText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhite)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhiteBlackText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhiteHintText)); + themeDescriptions.add(new ThemeDescription(listView, 0, new Class[]{AppIconsSelectorCell.class}, null, null, null, Theme.key_windowBackgroundWhiteValueText)); + themeDescriptions.addAll(SimpleThemeDescription.createThemeDescriptions(() -> { + for (int i = 0; i < listView.getChildCount(); i++) { + View ch = listView.getChildAt(i); + if (ch instanceof AppIconsSelectorCell) { + ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } + } + for (int i = 0; i < listView.getCachedChildCount(); i++) { + View ch = listView.getCachedChildAt(i); + if (ch instanceof AppIconsSelectorCell) { + ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } + } + for (int i = 0; i < listView.getHiddenChildCount(); i++) { + View ch = listView.getHiddenChildAt(i); + if (ch instanceof AppIconsSelectorCell) { + ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } + } + for (int i = 0; i < listView.getAttachedScrapChildCount(); i++) { + View ch = listView.getAttachedScrapChildAt(i); + if (ch instanceof AppIconsSelectorCell) { + ((AppIconsSelectorCell) ch).getAdapter().notifyDataSetChanged(); + } + } + }, Theme.key_windowBackgroundWhiteHintText, Theme.key_windowBackgroundWhiteBlackText, Theme.key_windowBackgroundWhiteValueText)); + return themeDescriptions; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index 84476a375..1226a8dd4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -75,7 +75,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.MessagesStorage; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; -import org.telegram.messenger.SharedConfig; import org.telegram.messenger.SvgHelper; import org.telegram.messenger.UserConfig; import org.telegram.messenger.Utilities; @@ -368,11 +367,6 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro isMotion = motion; } - @Override - public int getNavigationBarColor() { - return super.getNavigationBarColor(); - } - @SuppressLint("Recycle") @Override public View createView(Context context) { @@ -820,7 +814,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro if (applyingTheme.info != null && applyingTheme.info.installs_count > 0) { actionBar2.setSubtitle(LocaleController.formatPluralString("ThemeInstallCount", applyingTheme.info.installs_count)); } else { - actionBar2.setSubtitle(LocaleController.formatDateOnline(System.currentTimeMillis() / 1000 - 60 * 60)); + actionBar2.setSubtitle(LocaleController.formatDateOnline(System.currentTimeMillis() / 1000 - 60 * 60, null)); } } } @@ -1085,7 +1079,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro if (!done) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) currentWallpaper; - File f = FileLoader.getPathToAttach(wallPaper.document, true); + File f = FileLoader.getInstance(currentAccount).getPathToAttach(wallPaper.document, true); try { done = AndroidUtilities.copyFile(f, toFile); } catch (Exception e) { @@ -1152,7 +1146,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro File f; if (wallpaper.photo != null) { TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallpaper.photo.sizes, maxWallpaperSize, true); - f = FileLoader.getPathToAttach(image, true); + f = FileLoader.getInstance(currentAccount).getPathToAttach(image, true); } else { f = ImageLoader.getHttpFilePath(wallpaper.imageUrl, "jpg"); } @@ -1213,7 +1207,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro MediaController.SearchImage wallPaper = (MediaController.SearchImage) currentWallpaper; if (wallPaper.photo != null) { TLRPC.PhotoSize image = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); - path = FileLoader.getPathToAttach(image, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(image, true); } else { path = ImageLoader.getHttpFilePath(wallPaper.imageUrl, "jpg"); } @@ -2516,14 +2510,10 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro Theme.setChangingWallpaper(true); } if (screenType != SCREEN_TYPE_PREVIEW || accent != null) { - if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { - int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); - imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; - } else { - imageFilter = (int) (1080 / AndroidUtilities.density) + "_" + (int) (1920 / AndroidUtilities.density) + "_f"; - } - maxWallpaperSize = Math.min(1920, Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y)); + int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + int h = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); + imageFilter = (int) (w / AndroidUtilities.density) + "_" + (int) (h / AndroidUtilities.density) + "_f"; + maxWallpaperSize = Math.max(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersNeedReload); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.wallpapersDidLoad); @@ -3025,7 +3015,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro } boolean fileExists; File path; - int size; + long size; String fileName; if (object instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) object; @@ -3033,13 +3023,13 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro if (TextUtils.isEmpty(fileName)) { return; } - path = FileLoader.getPathToAttach(wallPaper.document, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(wallPaper.document, true); size = wallPaper.document.size; } else { MediaController.SearchImage wallPaper = (MediaController.SearchImage) object; if (wallPaper.photo != null) { TLRPC.PhotoSize photoSize = FileLoader.getClosestPhotoSizeWithSize(wallPaper.photo.sizes, maxWallpaperSize, true); - path = FileLoader.getPathToAttach(photoSize, true); + path = FileLoader.getInstance(currentAccount).getPathToAttach(photoSize, true); fileName = FileLoader.getAttachFileName(photoSize); size = photoSize.size; } else { @@ -3587,7 +3577,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro } if (!Theme.hasThemeKey(Theme.key_chat_serviceBackground) || backgroundImage.getBackground() instanceof MotionBackgroundDrawable) { Theme.applyChatServiceMessageColor(new int[]{checkColor, checkColor, checkColor, checkColor}, backgroundImage.getBackground()); - } else if (Theme.getCachedWallpaper() instanceof MotionBackgroundDrawable) { + } else if (Theme.getCachedWallpaperNonBlocking() instanceof MotionBackgroundDrawable) { int c = Theme.getColor(Theme.key_chat_serviceBackground); Theme.applyChatServiceMessageColor(new int[]{c, c, c, c}, backgroundImage.getBackground()); } @@ -3767,7 +3757,7 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro backgroundImage.setImage(ImageLocation.getForDocument(selectedPattern.document), imageFilter, null, null, "jpg", selectedPattern.document.size, 1, selectedPattern); } } else { - Drawable backgroundDrawable = Theme.getCachedWallpaper(); + Drawable backgroundDrawable = Theme.getCachedWallpaperNonBlocking(); if (backgroundDrawable != null) { if (backgroundDrawable instanceof MotionBackgroundDrawable) { ((MotionBackgroundDrawable) backgroundDrawable).setParentView(backgroundImage); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java index 06da6e1a6..042e2055a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TooManyCommunitiesActivity.java @@ -248,7 +248,7 @@ public class TooManyCommunitiesActivity extends BaseFragment { buttonTextView.setGravity(Gravity.CENTER); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); contentView.addView(buttonLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.BOTTOM)); buttonLayout.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); buttonLayout.addView(buttonTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, 0, 16, 12, 16, 12)); @@ -411,7 +411,6 @@ public class TooManyCommunitiesActivity extends BaseFragment { int inactiveChatsEndRow; int endPaddingPosition; - @Override public void notifyDataSetChanged() { updateRows(); @@ -671,7 +670,7 @@ public class TooManyCommunitiesActivity extends BaseFragment { } } - buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(4), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); progressBar.setProgressColor(Theme.getColor(Theme.key_progressCircle)); }; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationSetupActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationSetupActivity.java index cc4cfe0fd..8daff8d27 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationSetupActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationSetupActivity.java @@ -450,7 +450,7 @@ public class TwoStepVerificationSetupActivity extends BaseFragment { buttonTextView.setTextColor(Theme.getColor(Theme.key_featuredStickers_buttonText)); buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15); buttonTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); - buttonTextView.setBackground(Theme.createSimpleSelectorRoundRectDrawable(AndroidUtilities.dp(6), Theme.getColor(Theme.key_featuredStickers_addButton), Theme.getColor(Theme.key_featuredStickers_addButtonPressed))); + buttonTextView.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 6)); buttonTextView.setOnClickListener(v -> processNext()); switch (currentType) { @@ -1246,12 +1246,16 @@ public class TwoStepVerificationSetupActivity extends BaseFragment { @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - if (currentType == TYPE_ENTER_HINT && AndroidUtilities.isSmallScreen()) { - imageView.setVisibility(View.GONE); - } else if (!isIntro()) { - imageView.setVisibility(isLandscape() ? View.GONE : View.VISIBLE); + if (imageView != null) { + if (currentType == TYPE_ENTER_HINT && AndroidUtilities.isSmallScreen()) { + imageView.setVisibility(View.GONE); + } else if (!isIntro()) { + imageView.setVisibility(isLandscape() ? View.GONE : View.VISIBLE); + } + } + if (keyboardView != null) { + keyboardView.setVisibility(isCustomKeyboardVisible() ? View.VISIBLE : View.GONE); } - keyboardView.setVisibility(isCustomKeyboardVisible() ? View.VISIBLE : View.GONE); } private void animateSuccess(Runnable callback) { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/UnlockPremiumView.java b/TMessagesProj/src/main/java/org/telegram/ui/UnlockPremiumView.java new file mode 100644 index 000000000..d333d6552 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/UnlockPremiumView.java @@ -0,0 +1,63 @@ +package org.telegram.ui; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.ColorUtils; + +import org.telegram.messenger.LocaleController; +import org.telegram.messenger.R; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.ColoredImageSpan; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.Premium.PremiumButtonView; + +public class UnlockPremiumView extends FrameLayout { + + public static final int TYPE_STICKERS = 0; + public static final int TYPE_REACTIONS = 1; + public final PremiumButtonView premiumButtonView; + + public UnlockPremiumView(@NonNull Context context, int type, Theme.ResourcesProvider resourcesProvider) { + super(context); + LinearLayout linearLayout = new LinearLayout(context); + addView(linearLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); + linearLayout.setOrientation(LinearLayout.VERTICAL); + + + TextView descriptionTextView = new TextView(context); + descriptionTextView.setTextColor(ColorUtils.setAlphaComponent(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText, resourcesProvider), 100)); + descriptionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13); + descriptionTextView.setGravity(Gravity.CENTER); + if (type == TYPE_STICKERS) { + descriptionTextView.setText(LocaleController.getString("UnlockPremiumStickersDescription", R.string.UnlockPremiumStickersDescription)); + } else if (type == TYPE_REACTIONS) { + descriptionTextView.setText(LocaleController.getString("UnlockPremiumReactionsDescription", R.string.UnlockPremiumReactionsDescription)); + } + linearLayout.addView(descriptionTextView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 16, 17, 17, 16)); + + premiumButtonView = new PremiumButtonView(context, false); + + String text; + if (type == TYPE_STICKERS) { + text = LocaleController.getString("UnlockPremiumStickers", R.string.UnlockPremiumStickers); + } else { + text = LocaleController.getString("UnlockPremiumReactions", R.string.UnlockPremiumReactions); + } + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(); + spannableStringBuilder.append("d ").setSpan(new ColoredImageSpan(ContextCompat.getDrawable(context, R.drawable.msg_premium_normal)), 0, 1, 0); + spannableStringBuilder.append(text); + premiumButtonView.buttonTextView.setText(spannableStringBuilder); + linearLayout.addView(premiumButtonView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 0, 16, 0, 16, 16)); + + } + + +} diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VoiceMessageEnterTransition.java b/TMessagesProj/src/main/java/org/telegram/ui/VoiceMessageEnterTransition.java index 50c1b223f..f8802c7b6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/VoiceMessageEnterTransition.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/VoiceMessageEnterTransition.java @@ -82,6 +82,10 @@ public class VoiceMessageEnterTransition implements MessageEnterTransitionContai recordCircle.skipDraw = false; } }); + + if (messageView.getSeekBarWaveform() != null) { + messageView.getSeekBarWaveform().setSent(); + } } public void start() { diff --git a/TMessagesProj/src/main/java/org/telegram/ui/vibroslider.java b/TMessagesProj/src/main/java/org/telegram/ui/vibroslider.java new file mode 100644 index 000000000..b1fc1f8af --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/ui/vibroslider.java @@ -0,0 +1,103 @@ +package org.telegram.ui; + +import android.content.Context; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.telegram.messenger.AndroidUtilities; +import org.telegram.ui.ActionBar.BaseFragment; +import org.telegram.ui.ActionBar.Theme; +import org.telegram.ui.Components.LayoutHelper; +import org.telegram.ui.Components.PopupSwipeBackLayout; +import org.telegram.ui.Components.SeekBarView; +import org.telegram.ui.Components.Switch; + +public class vibroslider extends BaseFragment { + + + private long duration1 = 50, duration2 = 50, duration3 = 50; + private int amplitude1 = 50, amplitude2 = 50, amplitude3 = 50; + + @Override + public View createView(Context context) { + FrameLayout fragmentView = new FrameLayout(context); + LinearLayout ll = new LinearLayout(context); + ll.setOrientation(LinearLayout.VERTICAL); + fragmentView.addView(ll, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP, 16, 16, 16, 16)); + + ll.addView(new Slider(context, 0, 100, 50, a -> duration1 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + ll.addView(new Slider(context, 0, 100, 50, a -> duration2 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + ll.addView(new Slider(context, 0, 100, 50, a -> duration3 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + ll.addView(new Slider(context, 0, 255, 50, a -> amplitude1 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + ll.addView(new Slider(context, 0, 255, 50, a -> amplitude2 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + ll.addView(new Slider(context, 0, 255, 50, a -> amplitude3 = a), LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); + + FrameLayout button = new FrameLayout(context); + button.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 4)); + button.setOnClickListener(e -> { + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + final Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + VibrationEffect vibrationEffect = VibrationEffect.createWaveform( + new long[] { 100, 20, 10 }, + new int[] { 5, 0, 255 }, + -1 + ); + vibrator.cancel(); + vibrator.vibrate(vibrationEffect); + } + }); + ll.addView(button, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 48, 4, 80, 4, 4)); + + Switch switchView = new Switch(context); + switchView.setOnClickListener(e -> { + switchView.setChecked(!switchView.isChecked(), true); + }); + ll.addView(switchView); + + return fragmentView; + } + + public class Slider extends FrameLayout { + private int min; + private int max; + private int value; + private PopupSwipeBackLayout.IntCallback onChange; + public Slider(Context context, int min, int max, int initialValue, PopupSwipeBackLayout.IntCallback onChange) { + super(context); + this.min = min; + this.max = max; + this.value = initialValue; + this.onChange = onChange; + + TextView textView = new TextView(context); + textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf")); + textView.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); + addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL)); + + SeekBarView seekBarView = new SeekBarView(context); + seekBarView.setReportChanges(true); + seekBarView.setDelegate(new SeekBarView.SeekBarViewDelegate() { + @Override + public void onSeekBarDrag(boolean stop, float progress) { + value = AndroidUtilities.lerp(min, max, progress); + textView.setText(value + ""); + onChange.run(value); + } + + @Override + public void onSeekBarPressed(boolean pressed) { + + } + }); + textView.setText(value + ""); + seekBarView.setProgress((value - min) / (float) (max - min)); + addView(seekBarView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 38, Gravity.FILL_HORIZONTAL | Gravity.CENTER_VERTICAL, 24, 0, 0, 0)); + } + + } +} diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java index af36fe0d8..977e97581 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/NekoConfig.java @@ -156,7 +156,7 @@ public class NekoConfig { public static ConfigItem useChatAttachMediaMenu = addConfig("UseChatAttachEnterMenu", configTypeBool, true); public static ConfigItem disableLinkPreviewByDefault = addConfig("DisableLinkPreviewByDefault", configTypeBool, false); public static ConfigItem sendCommentAfterForward = addConfig("SendCommentAfterForward", configTypeBool, true); - public static ConfigItem increaseVoiceMessageQuality = addConfig("IncreaseVoiceMessageQuality", configTypeBool, true); +// public static ConfigItem increaseVoiceMessageQuality = addConfig("IncreaseVoiceMessageQuality", configTypeBool, true); public static ConfigItem disableTrending = addConfig("DisableTrending", configTypeBool, true); public static ConfigItem dontSendGreetingSticker = addConfig("DontSendGreetingSticker", configTypeBool, false); public static ConfigItem hideTimeForSticker = addConfig("HideTimeForSticker", configTypeBool, false); @@ -436,8 +436,8 @@ public class NekoConfig { disableLinkPreviewByDefault.setConfigBool(preferences.getBoolean("disableLinkPreviewByDefault", false)); if (preferences.contains("sendCommentAfterForward")) sendCommentAfterForward.setConfigBool(preferences.getBoolean("sendCommentAfterForward", true)); - if (preferences.contains("increaseVoiceMessageQuality")) - increaseVoiceMessageQuality.setConfigBool(preferences.getBoolean("increaseVoiceMessageQuality", true)); +// if (preferences.contains("increaseVoiceMessageQuality")) +// increaseVoiceMessageQuality.setConfigBool(preferences.getBoolean("increaseVoiceMessageQuality", true)); if (preferences.contains("disableTrending")) disableTrending.setConfigBool(preferences.getBoolean("disableTrending", true)); if (preferences.contains("dontSendGreetingSticker")) diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java index 8bf0c51fc..c6c9a0eff 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/settings/NekoExperimentalSettingsActivity.java @@ -75,7 +75,6 @@ public class NekoExperimentalSettingsActivity extends BaseFragment { private final AbstractConfigCell channelAliasRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.channelAlias)); private final AbstractConfigCell smoothKeyboardRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.smoothKeyboard)); - private final AbstractConfigCell increaseVoiceMessageQualityRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.increaseVoiceMessageQuality)); private final AbstractConfigCell mediaPreviewRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.mediaPreview)); private final AbstractConfigCell proxyAutoSwitchRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.proxyAutoSwitch)); private final AbstractConfigCell disableFilteringRow = cellGroup.appendCell(new ConfigCellCustom(CellGroup.ITEM_TYPE_TEXT_CHECK, true)); diff --git a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/ui/BottomBuilder.kt b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/ui/BottomBuilder.kt index 67bd53ad0..e0c59527c 100644 --- a/TMessagesProj/src/main/java/tw/nekomimi/nekogram/ui/BottomBuilder.kt +++ b/TMessagesProj/src/main/java/tw/nekomimi/nekogram/ui/BottomBuilder.kt @@ -334,9 +334,4 @@ class BottomBuilder(val ctx: Context) { return this } - fun fixNavigationBar() : BottomBuilder{ - builder.fixNavigationBar() - return this - } - } \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable-hdpi/emoji_tabs_premium.png b/TMessagesProj/src/main/res/drawable-hdpi/emoji_tabs_premium.png new file mode 100644 index 000000000..8aa3f1c3d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/emoji_tabs_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_2_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_2_background_sa.png new file mode 100644 index 000000000..575f2f148 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_2_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_3_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_3_background_sa.png new file mode 100644 index 000000000..4bfcec8ea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_3_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_4_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_4_background_sa.png new file mode 100644 index 000000000..4dc974db4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_4_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_5_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_5_background_sa.png new file mode 100644 index 000000000..eafaf8347 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_5_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_6_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_6_background_sa.png new file mode 100644 index 000000000..115a6d404 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_6_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip.png new file mode 100644 index 000000000..bbb217620 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip_round.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip_round.png new file mode 100644 index 000000000..bd3bcdc40 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/icon_background_clip_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_background_sa.png b/TMessagesProj/src/main/res/drawable-hdpi/icon_background_sa.png similarity index 100% rename from TMessagesProj/src/main/res/mipmap-hdpi/icon_background_sa.png rename to TMessagesProj/src/main/res/drawable-hdpi/icon_background_sa.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png index 95c025f09..8d02cdfcf 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_add.png new file mode 100644 index 000000000..d8129b132 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_all.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_all.png new file mode 100644 index 000000000..141d5b074 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_all.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_base.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_base.png new file mode 100644 index 000000000..acde0918d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_base.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_text.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_text.png new file mode 100644 index 000000000..c068bc520 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addaccount_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addbio.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbio.png index 67ab5fba8..a55912bc8 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_addbio.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbio.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png index 44bb78f6a..885958fbb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addfolder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addfolder.png index b6edc8122..84afef5ee 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_addfolder.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addfolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_addphoto.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_addphoto.png index 26556cc89..c0e090357 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_addphoto.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_addphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_admin_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_admin_add.png new file mode 100644 index 000000000..256ee3257 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_admin_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_admins.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_admins.png new file mode 100644 index 000000000..beaa00ac5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_admins.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_allowspeak.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_allowspeak.png index b413e57c0..5a62194e2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_allowspeak.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_allowspeak.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png index 8a166b183..c13e8d9f3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_archived_stickers.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_archived_stickers.png new file mode 100644 index 000000000..c3134dd97 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_archived_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_back.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_back.png index ef6d15a50..9814ae7ea 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_back.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_forward.png new file mode 100644 index 000000000..8f31a1027 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrow_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_arrowright.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrowright.png index 8faa67935..9395fb7a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_arrowright.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_arrowright.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_ask_question.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_ask_question.png new file mode 100644 index 000000000..b3480e379 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_ask_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_autodelete.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_autodelete.png index 33cb8df2c..d80d1e9f1 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_autodelete.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_autodelete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_background.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_background.png index 60c3dd194..815a9425d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_background.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_mute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_mute.png new file mode 100644 index 000000000..78c122d64 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_unmute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_unmute.png new file mode 100644 index 000000000..4142a6961 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_bell_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png index 07a7a945f..801d8becc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_block2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_block2.png index 395844e71..ac82c563e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_block2.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_block2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_bluetooth.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_bluetooth.png new file mode 100644 index 000000000..ae03d7121 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_bluetooth.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_blur_linear.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/blur_linear.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_blur_linear.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_blur_off.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/blur_off.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_blur_off.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_blur_radial.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/blur_radial.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_blur_radial.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_bots.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_bots.png new file mode 100644 index 000000000..9b631b865 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_high.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_high.png new file mode 100644 index 000000000..6b2a02261 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_high.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_low.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_low.png new file mode 100644 index 000000000..b438294a8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png index 2d9cf49b7..e386d1946 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png index 7c43b92b3..a8b6cbd03 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls.png new file mode 100644 index 000000000..a42b87fd1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_14.png new file mode 100644 index 000000000..ce6658ecf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_hw.png new file mode 100644 index 000000000..2011e6f07 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_minimize.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_minimize.png index 144563a28..cb6a6cb18 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_minimize.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_minimize.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_ny.png new file mode 100644 index 000000000..504e1bf9e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_pin.png index 324b74ba9..d00d0687a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_unpin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_unpin.png index 40e27cf9d..18e4e2c35 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_unpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_calls_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_camera.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_camera.png new file mode 100644 index 000000000..4c042bf6b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png index 6e3da3a1a..fe66e460d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_channel.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel.png index d10777ff6..8c404584a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_channel.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_14.png new file mode 100644 index 000000000..f2abdde5b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_hw.png new file mode 100644 index 000000000..9904740b6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_ny.png new file mode 100644 index 000000000..0cdc7b768 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_add.png new file mode 100644 index 000000000..74075395b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_remove.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_remove.png new file mode 100644 index 000000000..749314093 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_chats_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png index 7e17e7d38..64b204e26 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_check_thick.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_check_thick.png new file mode 100644 index 000000000..5698712e8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_check_thick.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png index 1c43863ea..18e3db88a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_input.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_input.png new file mode 100644 index 000000000..b9714f11a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_input.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_recent.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_recent.png new file mode 100644 index 000000000..924a1c5e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clear_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_clearcache.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_clearcache.png new file mode 100644 index 000000000..a20a7ab22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_close.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_close.png new file mode 100644 index 000000000..d4cf96e17 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_colors.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_colors.png index 0cb63dda5..4259bc98f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_colors.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contact_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contact_add.png new file mode 100644 index 000000000..2e5f1c748 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contact_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts.png new file mode 100644 index 000000000..4f5280679 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_14.png new file mode 100644 index 000000000..ca0cf5c54 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_hw.png new file mode 100644 index 000000000..7076969a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_name.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_name.png new file mode 100644 index 000000000..4a3ab5853 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_ny.png new file mode 100644 index 000000000..bb4cad11b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_time.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_time.png new file mode 100644 index 000000000..795043d4d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_contacts_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png index 3adb5299c..c8061c9d5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_current_location.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_current_location.png new file mode 100644 index 000000000..d87ad5bcb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_current_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_data.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_data.png new file mode 100644 index 000000000..b6339736a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png index 3b4e1f337..d9c67081d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_auto.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_auto.png index 6e4f315bf..1cd99d93d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_auto.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_old.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_old.png new file mode 100644 index 000000000..70dea031b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_delete_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_devices.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_devices.png new file mode 100644 index 000000000..f814a29fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_discussion.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_discussion.png index de907ba4c..90e2c8ef4 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_discussion.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_discussion.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png index e3f956203..6cc399581 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_arrow.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_arrow.png index a81a97a05..868e4a1fe 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_arrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_marker.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_marker.png index bf420efa5..88490329d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_marker.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_marker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_neon.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_neon.png index cf0df75ad..652a8bc1d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_neon.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_neon.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_pen.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_pen.png index 578a42fe6..994d12bbe 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_pen.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_draw_pen.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png index 4fdf49bd8..8c3e92fcb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_activities.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_activities.png new file mode 100644 index 000000000..6df944973 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_cat.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_cat.png new file mode 100644 index 000000000..7db4277cb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_flags.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_flags.png new file mode 100644 index 000000000..902dd07cf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_food.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_food.png new file mode 100644 index 000000000..bb46604e5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_objects.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_objects.png new file mode 100644 index 000000000..a977827ee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_other.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_other.png new file mode 100644 index 000000000..eca2c6513 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_premium.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_premium.png new file mode 100644 index 000000000..4e8f6e6ae Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_question.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_question.png new file mode 100644 index 000000000..7bc30ab13 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_recent.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_recent.png new file mode 100644 index 000000000..b1d44377f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_smiles.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_smiles.png new file mode 100644 index 000000000..9de845839 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_travel.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_travel.png new file mode 100644 index 000000000..defbfef02 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_emoji_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_endcall.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_endcall.png index 3981f2e91..bbb986f5f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_endcall.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_endcall.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_expand.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_expand.png new file mode 100644 index 000000000..af14cfab2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_expand.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png index e3cef5acf..d3ec39c06 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/abc_ic_menu_share_mtrl_alpha.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_filled_shareout.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/abc_ic_menu_share_mtrl_alpha.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_filled_shareout.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folder.png new file mode 100644 index 000000000..f653701f2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folder_reorder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folder_reorder.png new file mode 100644 index 000000000..e21abdf1b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folder_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_folders.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/menu_folders.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_folders.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_archive.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_archive.png new file mode 100644 index 000000000..3b960e7e1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_bots.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_bots.png new file mode 100644 index 000000000..626d598c9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_channels.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_channels.png new file mode 100644 index 000000000..3e9614f7e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_channels.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_groups.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_groups.png new file mode 100644 index 000000000..cb63e4184 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_muted.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_muted.png new file mode 100644 index 000000000..c7e8c7586 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_private.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_private.png new file mode 100644 index 000000000..eb1386aa9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_private.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_read.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_read.png new file mode 100644 index 000000000..4bfb24412 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_requests.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_requests.png new file mode 100644 index 000000000..6254455f1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_folders_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png index 20c2845fd..03afb190c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_check.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_check.png index 4b5ce7d5d..c33fff46d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_check.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_replace.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_replace.png index 947cd82c3..daf438674 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_replace.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_forward_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png index b5800378c..aa532930d 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png index 51d3731eb..62db427ee 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_gif_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif_add.png new file mode 100644 index 000000000..7ad13d8fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_gif_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png index ab0fc3303..38377f0d3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png index 447c642ec..0983c75b2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_groups.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups.png new file mode 100644 index 000000000..2f0102478 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_14.png new file mode 100644 index 000000000..9d844f697 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_create.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_create.png new file mode 100644 index 000000000..30eb68bdf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_create.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_hw.png new file mode 100644 index 000000000..d081bb9ff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_ny.png new file mode 100644 index 000000000..7001488e8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_handdown.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_handdown.png index d84d37e8e..c14054ba5 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_handdown.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_handdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_help.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_help.png new file mode 100644 index 000000000..17d6465e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_help_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_14.png new file mode 100644 index 000000000..796c512d0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_help_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_hw.png new file mode 100644 index 000000000..5cfe47752 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_help_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_ny.png new file mode 100644 index 000000000..bfb12be94 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png index 35cb62fa4..a5b331379 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png index 446507162..38a3424a3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_info.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_info.png new file mode 100644 index 000000000..326bbcda2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_inputarrow.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_inputarrow.png index ca6341c7b..cddd06958 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_inputarrow.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_inputarrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_instant_link.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_instant_link.png new file mode 100644 index 000000000..bd7ad4616 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_invite.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite.png new file mode 100644 index 000000000..e49823a3c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_14.png new file mode 100644 index 000000000..bd8997929 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_hw.png new file mode 100644 index 000000000..ed8c6e773 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_ny.png new file mode 100644 index 000000000..69a6ad5c7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_invited.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_invited.png index d249ab40d..354334d62 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_invited.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_invited.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_jobtitle.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_jobtitle.png new file mode 100644 index 000000000..04ac2787e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_jobtitle.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png index d1fdb97b1..355abdd7e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png index 9bcbe7316..3db891838 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_2x.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_2x.png new file mode 100644 index 000000000..59adc56db Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_accounts.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_accounts.png new file mode 100644 index 000000000..eb1386aa9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_accounts.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_chats.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_chats.png new file mode 100644 index 000000000..e8f8d01d7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_folder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_folder.png new file mode 100644 index 000000000..976af9ff6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_groups.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_groups.png new file mode 100644 index 000000000..46fe6e966 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_links.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_links.png new file mode 100644 index 000000000..867e18666 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_links.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_pin.png new file mode 100644 index 000000000..4f3dc847a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_limit_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png index 3edfc3275..3dbf03894 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_link2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_link2.png new file mode 100644 index 000000000..0f34b6ccb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_link2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_list.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_list.png index 2e316ae81..5aff80e7e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_list.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_list2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_list2.png new file mode 100644 index 000000000..41243afa5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_list2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png index 33aae1f7a..a24c3ab78 100755 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert.png index f5999728a..a4c4b9a31 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png index ff4f2155d..3743e1e11 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_location_alert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_log.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_log.png new file mode 100644 index 000000000..2f978ca11 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png index bb7d09e3a..d47516a60 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_map_type.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_map_type.png new file mode 100644 index 000000000..f21a2141d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_map_type.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png index 459c025cf..1260af6e0 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png index 3ebac7613..299328149 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png index dc55a00b9..23e61e569 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png index 52842da3f..2c63e7686 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mention.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mention.png index 6ffff5944..d83b746ef 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_mention.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mention.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png index 86b4adb4f..5b1ad3f2e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_customize.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_customize.png new file mode 100644 index 000000000..fe3699ba6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_customize.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_premiumlock.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_premiumlock.png new file mode 100644 index 000000000..44a9eac91 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_premiumlock.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_stickerstar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_stickerstar.png new file mode 100644 index 000000000..b2318b5bd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mini_stickerstar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_minvideo.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_minvideo.png index 9fa5cf9e9..4343be4bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_minvideo.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_minvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png index aca3c3dd0..68ec83336 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_msgbubble3.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png index b1d086283..56bb35b67 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_mute_period.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute_period.png index be0de9ad1..940b323dc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_mute_period.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_mute_period.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby.png new file mode 100644 index 000000000..b1209e201 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_14.png new file mode 100644 index 000000000..162827710 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_hw.png new file mode 100644 index 000000000..757a1f4ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_ny.png new file mode 100644 index 000000000..fd53f5d78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_off.png new file mode 100644 index 000000000..3d159a021 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nearby_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_newfilter.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_newfilter.png new file mode 100644 index 000000000..f7b92fc47 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_newfilter.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_newphone.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_newphone.png new file mode 100644 index 000000000..ca705b4bb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_nightmode_system.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_nightmode_system.png new file mode 100644 index 000000000..f2381caf3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_nightmode_system.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_off.png index 1732af939..88334c029 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_on.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_on.png index 827c22e48..7b5cd57b0 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_noise_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_notifications.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_notifications.png new file mode 100644 index 000000000..b36543c0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png index ed67c9eeb..6d119b9c6 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_openprofile.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_openprofile.png index 698550ff3..532489697 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_openprofile.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_openprofile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_palette.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-hdpi/menu_palette.png rename to TMessagesProj/src/main/res/drawable-hdpi/msg_palette.png diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_address.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_address.png new file mode 100644 index 000000000..4d60eb2b5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_address.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_card.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_card.png new file mode 100644 index 000000000..4e12ad8a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_card.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_delivery.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_delivery.png new file mode 100644 index 000000000..0c7cbb41c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_delivery.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_provider.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_provider.png new file mode 100644 index 000000000..53a2876a1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_payment_provider.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_permissions.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_permissions.png index 1375d0535..b2b173f9c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_permissions.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur.png new file mode 100644 index 000000000..4b27f99de Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_linear.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_linear.png new file mode 100644 index 000000000..5111f2e67 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_off.png new file mode 100644 index 000000000..6ff96b870 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_radial.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_radial.png new file mode 100644 index 000000000..df29f8eba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_brush.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_brush.png new file mode 100644 index 000000000..debc435fc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_crop.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_crop.png new file mode 100644 index 000000000..192ac1d13 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_cropfix.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_cropfix.png new file mode 100644 index 000000000..b417d54ab Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_curve.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_curve.png new file mode 100644 index 000000000..fa8476dd2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_draw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_draw.png new file mode 100644 index 000000000..948fdf9dd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_draw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_flip.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_flip.png new file mode 100644 index 000000000..bf8b41fe9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_flip.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_rotate.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_rotate.png new file mode 100644 index 000000000..55f9d0fee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_settings.png new file mode 100644 index 000000000..75c317a8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_text.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_text.png new file mode 100644 index 000000000..b78ee569b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photo_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_photos.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_photos.png new file mode 100644 index 000000000..12288d38e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png index 2b781babe..e19bcf5fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pinnedlist.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pinnedlist.png new file mode 100644 index 000000000..28a4b95eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_pinnedlist.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_played.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_played.png index ab5087f15..d0f145a0f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_played.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_played.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_policy.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_policy.png new file mode 100644 index 000000000..ce6f810a6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_policy.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png index e175ecf89..7122e82a2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_ads.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_ads.png new file mode 100644 index 000000000..d7f854b2b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_ads.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_avatar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_avatar.png new file mode 100644 index 000000000..ba61e60ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_badge.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_badge.png new file mode 100644 index 000000000..3e41a8a32 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_icons.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_icons.png new file mode 100644 index 000000000..2c669aae0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_icons.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_limits.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_limits.png new file mode 100644 index 000000000..c932a63fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_limits.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_liststar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_liststar.png new file mode 100644 index 000000000..bb47e46a4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_liststar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock.png new file mode 100644 index 000000000..261ef87a0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock2.png new file mode 100644 index 000000000..e52e78014 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_lock2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_normal.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_normal.png new file mode 100644 index 000000000..f9e36b481 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_normal.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_prolfilestar.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_prolfilestar.png new file mode 100644 index 000000000..9a55175cd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_prolfilestar.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_reactions.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_reactions.png new file mode 100644 index 000000000..f10c8ed36 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_speed.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_speed.png new file mode 100644 index 000000000..e3718cdb6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_stickers.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_stickers.png new file mode 100644 index 000000000..151ade623 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_tools.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_tools.png new file mode 100644 index 000000000..3e004f773 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_uploads.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_uploads.png new file mode 100644 index 000000000..88f3181bf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_uploads.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_voice.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_voice.png new file mode 100644 index 000000000..b78bd28c1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_premium_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_psa.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_psa.png index ada266bc1..a4c2c399a 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_psa.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_psa.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_down.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_down.png new file mode 100644 index 000000000..8866a70aa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_up.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_up.png new file mode 100644 index 000000000..b7ea84420 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_rate_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions.png index f54e98a27..b816d1c3f 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions2.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions2.png new file mode 100644 index 000000000..cb5231ee8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reactions2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_recent.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_recent.png new file mode 100644 index 000000000..0a4186fde Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_remove.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_remove.png new file mode 100644 index 000000000..a36891460 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_removefolder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_removefolder.png index 2948a7e80..dbe30e0fb 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_removefolder.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_removefolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reorder.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reorder.png index 2c07c2f3d..a8bd6082e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_reorder.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_replace.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_replace.png index 4ac9346dc..dbe0c5588 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_replace.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png index 62253a583..977794038 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_fake.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_fake.png index b736e4ac7..d94c395f2 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_fake.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_fake.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_violence.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_violence.png index 8359fe0fd..32a0ba8b9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_violence.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_violence.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_xxx.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_xxx.png index f6be5ec98..0e189821e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_report_xxx.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_report_xxx.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_requests.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_requests.png new file mode 100644 index 000000000..e4707dc0f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_reset.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_reset.png index 5dcf4fdf6..d3c26e7b3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_reset.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_reset.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png index 68a8de49f..3a858a2ab 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_saved.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved.png new file mode 100644 index 000000000..aa2f91328 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_14.png new file mode 100644 index 000000000..ad3454f11 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_hw.png new file mode 100644 index 000000000..482e02099 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_ny.png new file mode 100644 index 000000000..8504598a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_saved_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast.png index be4b41d9d..26cf0c552 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast_off.png index e4e497e79..81bd70176 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_screencast_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png index e76432671..13d5fe266 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_secret.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret.png new file mode 100644 index 000000000..a478e8019 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_14.png new file mode 100644 index 000000000..bced7a502 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_hw.png new file mode 100644 index 000000000..bfbc944b9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_ny.png new file mode 100644 index 000000000..b409f6df6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_seen.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_seen.png index 24ee4b7bc..7c517a389 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_seen.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_select.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_select.png index f36e5d9bc..64949fd07 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_select.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_send.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_send.png new file mode 100644 index 000000000..e806b9987 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_sendfile.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_sendfile.png index d04c56d8c..90962561c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_sendfile.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_sendfile.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings.png new file mode 100644 index 000000000..2be50ce58 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_14.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_14.png new file mode 100644 index 000000000..b60f71b66 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_hw.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_hw.png new file mode 100644 index 000000000..87e20c73d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_ny.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_ny.png new file mode 100644 index 000000000..c3382096b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_old.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_old.png new file mode 100644 index 000000000..816ad3877 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_premium.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_premium.png new file mode 100644 index 000000000..acde2ab03 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_settings_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png index 4ccfa6439..1e41c5a27 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png index 40d480a52..58faee9a3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_speed.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_speed.png index afdf4d02a..7a8eb9794 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_speed.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png index 32128c3be..a5d4e01fe 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png index aaa7dff43..e605f13b6 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_switch.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_switch.png new file mode 100644 index 000000000..be9a79d41 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_switch.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png index 87b6e9bf1..d4f6ce12e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png index bbb80a656..8913c6595 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_timer_1h.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer_1h.png new file mode 100644 index 000000000..c9089dc0c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_timer_1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_timeredit.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_timeredit.png index a0bbaad25..d159b9ac3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_timeredit.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_timeredit.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_add.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_add.png index 59b6dc57d..f3d77ea6e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_add.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_off.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_off.png index ef1be3615..9490dd8bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_off.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_on.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_on.png index 0deae5a62..73f20cef9 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_on.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_tone_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_trending.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_trending.png new file mode 100644 index 000000000..64e3a9816 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png index 52b3e5a33..f9f9e54c3 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png index 83bf9b1cc..b43f69f98 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png index 952ab798b..9f0fdec20 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png index cb984904a..c6764df7c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png index b2741e589..0048f025e 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_user_remove.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_user_remove.png new file mode 100644 index 000000000..d91305d22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_user_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_user_search.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_user_search.png new file mode 100644 index 000000000..f7db3ede1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_user_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_video.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_video.png index 6d46e0197..316f82c5b 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_video.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_viewreplies.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_viewreplies.png index 29df5bbda..58ba67974 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_viewreplies.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_viewreplies.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_voice_headphones.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_voice_headphones.png index b36c5e075..fd43a84dd 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_voice_headphones.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_voice_headphones.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_voicechat.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_voicechat.png index ce27764e1..46d7ca258 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_voicechat.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_voicechat.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_work.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_work.png new file mode 100644 index 000000000..ad17ef6ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_work.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png index 823e37fe3..13e16d752 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png index 3a5a0c5b7..ab970390c 100644 Binary files a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png and b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout_stats.png b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout_stats.png new file mode 100644 index 000000000..362823c7c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/msg_zoomout_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/other_2x_large.png b/TMessagesProj/src/main/res/drawable-hdpi/other_2x_large.png new file mode 100644 index 000000000..36d3d1c1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/other_2x_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders.png b/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders.png new file mode 100644 index 000000000..80b9b924f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders2.png b/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders2.png new file mode 100644 index 000000000..63801ce51 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/other_lockedfolders2.png differ diff --git a/TMessagesProj/src/main/res/drawable-hdpi/temp_starlarge.png b/TMessagesProj/src/main/res/drawable-hdpi/temp_starlarge.png new file mode 100644 index 000000000..e3a523f57 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/temp_starlarge.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/emoji_tabs_premium.png b/TMessagesProj/src/main/res/drawable-mdpi/emoji_tabs_premium.png new file mode 100644 index 000000000..87d1b2f27 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/emoji_tabs_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_2_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_2_background_sa.png new file mode 100644 index 000000000..8157bcab3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_2_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_3_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_3_background_sa.png new file mode 100644 index 000000000..1eb686bd4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_3_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_4_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_4_background_sa.png new file mode 100644 index 000000000..e5eebdada Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_4_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_5_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_5_background_sa.png new file mode 100644 index 000000000..3eb8317f4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_5_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_6_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_6_background_sa.png new file mode 100644 index 000000000..c1d455efc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_6_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip.png new file mode 100644 index 000000000..c598e12db Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip_round.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip_round.png new file mode 100644 index 000000000..1b8ff9b28 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/icon_background_clip_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_background_sa.png b/TMessagesProj/src/main/res/drawable-mdpi/icon_background_sa.png similarity index 100% rename from TMessagesProj/src/main/res/mipmap-mdpi/icon_background_sa.png rename to TMessagesProj/src/main/res/drawable-mdpi/icon_background_sa.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png index 96cab86ae..6dda25d24 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_add.png new file mode 100644 index 000000000..40963359e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_all.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_all.png new file mode 100644 index 000000000..ba80e881b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_all.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_base.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_base.png new file mode 100644 index 000000000..38d45c15e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_base.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_text.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_text.png new file mode 100644 index 000000000..e7b668b98 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addaccount_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addbio.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbio.png index 2040bc03d..a93307927 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_addbio.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbio.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png index e95c3b4c0..9d93367cf 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addfolder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addfolder.png index b1af01acb..7af3678bd 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_addfolder.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addfolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_addphoto.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_addphoto.png index 056b50141..d73fe1654 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_addphoto.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_addphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_admin_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_admin_add.png new file mode 100644 index 000000000..a05a756a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_admin_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_admins.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_admins.png new file mode 100644 index 000000000..37ac7952b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_admins.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_allowspeak.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_allowspeak.png index 30d0434cf..719315207 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_allowspeak.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_allowspeak.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png index 0f0243bc9..fe2f84768 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_archived_stickers.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_archived_stickers.png new file mode 100644 index 000000000..07f2d87af Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_archived_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_back.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_back.png index b83793877..683e02092 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_back.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_forward.png new file mode 100644 index 000000000..ae0315ace Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrow_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_arrowright.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrowright.png index 445ba02ef..5bcad55a5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_arrowright.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_arrowright.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_ask_question.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_ask_question.png new file mode 100644 index 000000000..21cf79fce Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_ask_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_autodelete.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_autodelete.png index d77fe2491..e5da19b86 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_autodelete.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_autodelete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_background.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_background.png index a276b53fb..700c85553 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_background.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_mute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_mute.png new file mode 100644 index 000000000..8effcfe00 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_unmute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_unmute.png new file mode 100644 index 000000000..c2870326e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_bell_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png index 8dde94d52..b3e24f1e8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_block2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_block2.png index c5aafb475..33b4c641a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_block2.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_block2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_bluetooth.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_bluetooth.png new file mode 100644 index 000000000..95da6af0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_bluetooth.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_blur_linear.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/blur_linear.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_blur_linear.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_blur_off.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/blur_off.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_blur_off.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_blur_radial.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/blur_radial.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_blur_radial.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_bots.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_bots.png new file mode 100644 index 000000000..68bdc04d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_high.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_high.png new file mode 100644 index 000000000..cf60dc79f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_high.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_low.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_low.png new file mode 100644 index 000000000..4c0541332 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png index 220627a80..667230535 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png index 8a208ec18..4d98650b3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls.png new file mode 100644 index 000000000..7e17192be Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_14.png new file mode 100644 index 000000000..3fd9a07db Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_hw.png new file mode 100644 index 000000000..11932f107 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_minimize.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_minimize.png index 31b6960b9..3093fde14 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_minimize.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_minimize.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_ny.png new file mode 100644 index 000000000..3116370f7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_pin.png index 6afc609fb..7367353dc 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_unpin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_unpin.png index b1c5f67ba..1a018544e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_unpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_calls_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_camera.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_camera.png new file mode 100644 index 000000000..158fddd8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png index cbb33253d..904c0f925 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_channel.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel.png index 4240d68db..0df25a1f2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_channel.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_14.png new file mode 100644 index 000000000..5e878867a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_hw.png new file mode 100644 index 000000000..6dc765274 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_ny.png new file mode 100644 index 000000000..4de64cd78 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_add.png new file mode 100644 index 000000000..72b38bf1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_remove.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_remove.png new file mode 100644 index 000000000..dec8fd51a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_chats_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png index 004713fd1..3fd562cf7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_check_thick.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_check_thick.png new file mode 100644 index 000000000..053ccebd5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_check_thick.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png index bf7a84683..528881811 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_input.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_input.png new file mode 100644 index 000000000..c575f7c90 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_input.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_recent.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_recent.png new file mode 100644 index 000000000..f3ac61824 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clear_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_clearcache.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_clearcache.png new file mode 100644 index 000000000..17737dacd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_close.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_close.png new file mode 100644 index 000000000..f2d0bc01d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_colors.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_colors.png index 3ac6db33a..ef7645b45 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_colors.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contact_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contact_add.png new file mode 100644 index 000000000..ce4c81574 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contact_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts.png new file mode 100644 index 000000000..66ef89221 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_14.png new file mode 100644 index 000000000..59d881127 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_hw.png new file mode 100644 index 000000000..f5f110734 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_name.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_name.png new file mode 100644 index 000000000..c45bf3f8a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_ny.png new file mode 100644 index 000000000..963bf11ce Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_time.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_time.png new file mode 100644 index 000000000..cbdd98e3c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_contacts_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png index 608f009e2..2509826a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_current_location.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_current_location.png new file mode 100644 index 000000000..4706cc612 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_current_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_data.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_data.png new file mode 100644 index 000000000..0fd6f38e2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png index 3b557e128..569da9309 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_auto.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_auto.png index d95af7c86..15070643b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_auto.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_old.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_old.png new file mode 100644 index 000000000..6c6eba380 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_delete_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_devices.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_devices.png new file mode 100644 index 000000000..f06476cd9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_discussion.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_discussion.png index 7c0ff6725..5cfe93e8a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_discussion.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_discussion.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png index dbaa9e9ad..e223f0d66 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_arrow.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_arrow.png index be8682a99..26888686f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_arrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_marker.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_marker.png index 585da1972..213dced87 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_marker.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_marker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_neon.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_neon.png index 6febda2c1..017c4a338 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_neon.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_neon.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_pen.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_pen.png index 6a92817d0..93b0dec96 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_pen.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_draw_pen.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png index 486dbd350..1b45d8cbe 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_activities.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_activities.png new file mode 100644 index 000000000..481d4e08d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_cat.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_cat.png new file mode 100644 index 000000000..47f2aa4fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_flags.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_flags.png new file mode 100644 index 000000000..bf5a5e34d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_food.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_food.png new file mode 100644 index 000000000..4c63c287f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_objects.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_objects.png new file mode 100644 index 000000000..bd8268739 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_other.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_other.png new file mode 100644 index 000000000..bb598d317 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_premium.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_premium.png new file mode 100644 index 000000000..13d72f50c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_question.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_question.png new file mode 100644 index 000000000..66685630d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_recent.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_recent.png new file mode 100644 index 000000000..63618f5c0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_smiles.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_smiles.png new file mode 100644 index 000000000..ec3e4985c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_travel.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_travel.png new file mode 100644 index 000000000..64bc43326 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_emoji_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_endcall.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_endcall.png index f7cca8409..52f55e026 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_endcall.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_endcall.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_expand.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_expand.png new file mode 100644 index 000000000..9e82c5b79 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_expand.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png index d4c6d083a..5b334ee50 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/abc_ic_menu_share_mtrl_alpha.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_filled_shareout.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/abc_ic_menu_share_mtrl_alpha.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_filled_shareout.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folder.png new file mode 100644 index 000000000..f05209ea8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folder_reorder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folder_reorder.png new file mode 100644 index 000000000..d8c7f26e1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folder_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_folders.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/menu_folders.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_folders.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_archive.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_archive.png new file mode 100644 index 000000000..586f4f385 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_bots.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_bots.png new file mode 100644 index 000000000..7225b288d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_channels.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_channels.png new file mode 100644 index 000000000..106a21fe3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_channels.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_groups.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_groups.png new file mode 100644 index 000000000..acb6cdd04 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_muted.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_muted.png new file mode 100644 index 000000000..73cbccf35 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_private.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_private.png new file mode 100644 index 000000000..660c678b4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_private.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_read.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_read.png new file mode 100644 index 000000000..e02aeb1a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_requests.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_requests.png new file mode 100644 index 000000000..bdf643d7e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_folders_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png index d46c19b9d..b1bede574 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_check.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_check.png index a1ba9ab42..3157161cf 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_check.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_replace.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_replace.png index 6387de321..888952ba7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_replace.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_forward_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png index 36c7c50e4..5afebfdc4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png index c988f096b..d3439c1e0 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_gif_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif_add.png new file mode 100644 index 000000000..c098fde5c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_gif_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png index f84a64969..ff04fa67b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png index 7b91fae01..8e5fb1a54 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_groups.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups.png new file mode 100644 index 000000000..f52e63a98 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_14.png new file mode 100644 index 000000000..1928557da Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_create.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_create.png new file mode 100644 index 000000000..5f3a0d349 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_create.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_hw.png new file mode 100644 index 000000000..f12041c19 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_ny.png new file mode 100644 index 000000000..02d401fe7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_handdown.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_handdown.png index e896528ee..055c3ef81 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_handdown.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_handdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_help.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_help.png new file mode 100644 index 000000000..2995931b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_help_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_14.png new file mode 100644 index 000000000..284623309 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_help_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_hw.png new file mode 100644 index 000000000..db6825f85 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_help_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_ny.png new file mode 100644 index 000000000..b926e87b0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png index 425389511..99ef999f7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png index af3989c15..a1272439f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_info.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_info.png new file mode 100644 index 000000000..99b1b458c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_inputarrow.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_inputarrow.png index 5fbcc6c2c..1ba9376cd 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_inputarrow.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_inputarrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_instant_link.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_instant_link.png new file mode 100644 index 000000000..c3247285c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_invite.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite.png new file mode 100644 index 000000000..3da8bb1fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_14.png new file mode 100644 index 000000000..6c5b79112 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_hw.png new file mode 100644 index 000000000..e81e59267 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_ny.png new file mode 100644 index 000000000..b6e3743c7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_invited.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_invited.png index 667fd89a0..707886bff 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_invited.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_invited.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_jobtitle.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_jobtitle.png new file mode 100644 index 000000000..913fb6f14 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_jobtitle.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png index ef26204bb..c20221cc5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png index 77c1cb482..24542b472 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_2x.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_2x.png new file mode 100644 index 000000000..c07216aea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_accounts.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_accounts.png new file mode 100644 index 000000000..660c678b4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_accounts.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_chats.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_chats.png new file mode 100644 index 000000000..296ffe919 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_folder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_folder.png new file mode 100644 index 000000000..4533dd4d3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_groups.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_groups.png new file mode 100644 index 000000000..de447a519 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_links.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_links.png new file mode 100644 index 000000000..433760a7a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_links.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_pin.png new file mode 100644 index 000000000..f9d760868 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_limit_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png index 3e3ba72ec..640edac80 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_link2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_link2.png new file mode 100644 index 000000000..d25db6eaa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_link2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_list.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_list.png index 0d7d1a7a4..1f42b7f7b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_list.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_list2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_list2.png new file mode 100644 index 000000000..d56b6725d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_list2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png index f60c06310..d65cbe22c 100755 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert.png index 1420d474f..fb743b034 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert2.png index 8b97c2d96..3942951ba 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert2.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_location_alert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_log.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_log.png new file mode 100644 index 000000000..33fb5c9ae Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png index fb9494b3d..caedc4d8a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_map_type.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_map_type.png new file mode 100644 index 000000000..c55827661 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_map_type.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png index 8fc3aeba3..08019c53d 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png index ff705bb09..c39fba228 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png index 4684b3b1d..bf2934aea 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png index c6a7a4c0d..b7d1abb2f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mention.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mention.png index bdfb662ef..4a3c7d882 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_mention.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mention.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png index aac6b3edf..5bd429956 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_customize.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_customize.png new file mode 100644 index 000000000..895a36c9f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_customize.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_premiumlock.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_premiumlock.png new file mode 100644 index 000000000..cb32e03ac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_premiumlock.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_stickerstar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_stickerstar.png new file mode 100644 index 000000000..6e5c81323 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mini_stickerstar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_minvideo.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_minvideo.png index 8219780cc..7ffaff9f5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_minvideo.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_minvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_msgbubble3.png index 565f3563a..8eca93723 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_msgbubble3.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_msgbubble3.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png index 250a9a7ee..ad16e80d6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_mute_period.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute_period.png index ae1b570ca..6d41cc809 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_mute_period.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_mute_period.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby.png new file mode 100644 index 000000000..c8c42b75d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_14.png new file mode 100644 index 000000000..33e863516 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_hw.png new file mode 100644 index 000000000..1fcf1cd77 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_ny.png new file mode 100644 index 000000000..8c1fefeda Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_off.png new file mode 100644 index 000000000..7356340c5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nearby_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_newfilter.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_newfilter.png new file mode 100644 index 000000000..5f39a1c2e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_newfilter.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_newphone.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_newphone.png new file mode 100644 index 000000000..176d646ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_nightmode_system.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_nightmode_system.png new file mode 100644 index 000000000..0a390d5fe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_nightmode_system.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_off.png index ba8373447..ff4cd89a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_on.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_on.png index d40136697..079de5423 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_noise_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_notifications.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_notifications.png new file mode 100644 index 000000000..d50b2bf7d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png index 470a21b43..b8b5698d7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_openprofile.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_openprofile.png index f0b5cbfa1..8ba236a82 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_openprofile.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_openprofile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_palette.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-mdpi/menu_palette.png rename to TMessagesProj/src/main/res/drawable-mdpi/msg_palette.png diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_address.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_address.png new file mode 100644 index 000000000..9a3cd95a6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_address.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_card.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_card.png new file mode 100644 index 000000000..700ee4817 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_card.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_delivery.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_delivery.png new file mode 100644 index 000000000..28baa8672 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_delivery.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_provider.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_provider.png new file mode 100644 index 000000000..92404b0f7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_payment_provider.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_permissions.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_permissions.png index 5231c81ef..f1742a9f8 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_permissions.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur.png new file mode 100644 index 000000000..d319a1d59 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_linear.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_linear.png new file mode 100644 index 000000000..40f849266 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_off.png new file mode 100644 index 000000000..f6d5cd5f0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_radial.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_radial.png new file mode 100644 index 000000000..0a49050c6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_brush.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_brush.png new file mode 100644 index 000000000..23271a129 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_crop.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_crop.png new file mode 100644 index 000000000..79177a1d9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_cropfix.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_cropfix.png new file mode 100644 index 000000000..080d74963 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_curve.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_curve.png new file mode 100644 index 000000000..5289df2ab Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_draw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_draw.png new file mode 100644 index 000000000..87c8f05f6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_draw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_flip.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_flip.png new file mode 100644 index 000000000..8cd308291 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_flip.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_rotate.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_rotate.png new file mode 100644 index 000000000..21a0c933b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_settings.png new file mode 100644 index 000000000..527c54663 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_text.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_text.png new file mode 100644 index 000000000..ba64b6c65 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photo_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_photos.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_photos.png new file mode 100644 index 000000000..81efac9a2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png index 7d7b9b312..628669457 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_pinnedlist.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_pinnedlist.png new file mode 100644 index 000000000..f0976ea91 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_pinnedlist.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_played.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_played.png index ac87b01ed..e24942bac 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_played.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_played.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_policy.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_policy.png new file mode 100644 index 000000000..073dd4a25 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_policy.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png index 569e6927c..39eb6c6b2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_ads.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_ads.png new file mode 100644 index 000000000..2ef411017 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_ads.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_avatar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_avatar.png new file mode 100644 index 000000000..8c6e52c68 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_badge.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_badge.png new file mode 100644 index 000000000..96ca2c01e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_icons.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_icons.png new file mode 100644 index 000000000..56af6a14b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_icons.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_limits.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_limits.png new file mode 100644 index 000000000..05f5c33d4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_limits.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_liststar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_liststar.png new file mode 100644 index 000000000..354f6fd22 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_liststar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock.png new file mode 100644 index 000000000..698baa0a9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock2.png new file mode 100644 index 000000000..f1ec031f1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_lock2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_normal.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_normal.png new file mode 100644 index 000000000..dc8791b35 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_normal.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_prolfilestar.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_prolfilestar.png new file mode 100644 index 000000000..20edf63dc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_prolfilestar.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_reactions.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_reactions.png new file mode 100644 index 000000000..d3dabb8a9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_speed.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_speed.png new file mode 100644 index 000000000..9ba628be0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_stickers.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_stickers.png new file mode 100644 index 000000000..ab1b00f87 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_tools.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_tools.png new file mode 100644 index 000000000..3a0beb2e7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_uploads.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_uploads.png new file mode 100644 index 000000000..d332d536b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_uploads.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_voice.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_voice.png new file mode 100644 index 000000000..81e4b7aef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_premium_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_psa.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_psa.png index eac7b1ffe..d74189336 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_psa.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_psa.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_down.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_down.png new file mode 100644 index 000000000..0327165e9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_up.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_up.png new file mode 100644 index 000000000..de9213a9d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_rate_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions.png index 79b2f2f26..265764110 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions2.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions2.png new file mode 100644 index 000000000..4501afa12 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reactions2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_recent.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_recent.png new file mode 100644 index 000000000..6d405a532 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_remove.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_remove.png new file mode 100644 index 000000000..7c46feb1c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_removefolder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_removefolder.png index 98627677c..92b7d538b 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_removefolder.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_removefolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reorder.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reorder.png index 56be782ed..78d6ee371 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_reorder.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_replace.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_replace.png index 0d97939e5..3bc01e713 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_replace.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png index e0d2252e7..4412963fc 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_drugs.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_drugs.png index 951808635..f40e482e0 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_drugs.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_drugs.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_fake.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_fake.png index f604c02fa..3522a2110 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_fake.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_fake.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_other.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_other.png index 4b62a7c9d..d0c12380e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_other.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_violence.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_violence.png index ce4342756..cfc54b43c 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_violence.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_violence.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_xxx.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_xxx.png index 5f6a52245..9e193a737 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_report_xxx.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_report_xxx.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_requests.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_requests.png new file mode 100644 index 000000000..14a8b61a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_reset.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_reset.png index c198dfabf..4eea7d15a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_reset.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_reset.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png index 6c3da8198..0d2226c8a 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_saved.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved.png new file mode 100644 index 000000000..16daa4e55 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_14.png new file mode 100644 index 000000000..cd7e345ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_hw.png new file mode 100644 index 000000000..5571c4c4c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_ny.png new file mode 100644 index 000000000..b9e58caa6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_saved_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast.png index acf7039f6..d816c8711 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast_off.png index acfad0d34..871e48aa4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_screencast_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png index b5fa27021..f6b2d88c3 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_secret.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret.png new file mode 100644 index 000000000..ca2b1fd36 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_14.png new file mode 100644 index 000000000..150997064 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_hw.png new file mode 100644 index 000000000..bb1ead59e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_ny.png new file mode 100644 index 000000000..f34448e32 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_seen.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_seen.png index 1ba2726ba..908618117 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_seen.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_select.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_select.png index 5d9d2a7c8..a4d3d13ae 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_select.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_send.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_send.png new file mode 100644 index 000000000..884fc8166 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_sendfile.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_sendfile.png index 60d059be8..44d54f7b4 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_sendfile.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_sendfile.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings.png new file mode 100644 index 000000000..359cac087 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_14.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_14.png new file mode 100644 index 000000000..1f2b0e83b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_hw.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_hw.png new file mode 100644 index 000000000..ac8985761 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_ny.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_ny.png new file mode 100644 index 000000000..ce12eaf3d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_old.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_old.png new file mode 100644 index 000000000..40ad03b71 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_premium.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_premium.png new file mode 100644 index 000000000..0d8b9e5e8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_settings_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png index 818a0edb7..fcb6d9ed5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png index 0a19abd51..75ca77204 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_speed.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_speed.png index 9b9b840b3..b063dd17f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_speed.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png index a684b8632..bb6d9d344 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png index 7bf88c334..e6f67444e 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_switch.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_switch.png new file mode 100644 index 000000000..4a8713db1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_switch.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png index 900656117..4497446cc 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png index 912381dc3..1d0716682 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_timer_1h.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer_1h.png new file mode 100644 index 000000000..1740efa5b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_timer_1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_timeredit.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_timeredit.png index fe9850122..b5b79dcca 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_timeredit.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_timeredit.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_add.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_add.png index e3d24a24f..d4db1a856 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_add.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_off.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_off.png index 1c346dc7f..8c655b087 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_off.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_on.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_on.png index b3e5d9b27..2e5121fb5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_on.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_tone_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_translate.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_translate.png index 420003382..9ae22ae74 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_translate.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_translate.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_trending.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_trending.png new file mode 100644 index 000000000..de8d8ff96 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png index 49618d07d..3f7f3cd4f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png index 83e95a8f8..08d307459 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png index 3e8644ac2..8a16c35f2 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png index b0fd8507d..7e6b753b7 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png index 0c108cbcb..cbef233c5 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_user_remove.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_user_remove.png new file mode 100644 index 000000000..cc001558e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_user_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_user_search.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_user_search.png new file mode 100644 index 000000000..dc5dd6da9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_user_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_video.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_video.png index 9de036654..95bc2fecc 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_video.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_viewreplies.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_viewreplies.png index bf27f9e06..0e1136371 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_viewreplies.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_viewreplies.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_voice_headphones.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_voice_headphones.png index 00d51d260..59d80f397 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_voice_headphones.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_voice_headphones.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_voicechat.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_voicechat.png index ee9796da2..0428350e6 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_voicechat.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_voicechat.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_work.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_work.png new file mode 100644 index 000000000..f1638a1c6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_work.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png index afd98f351..48bc6d90f 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png index 86231ecbe..96a2b6573 100644 Binary files a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png and b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout_stats.png b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout_stats.png new file mode 100644 index 000000000..bded3f809 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/msg_zoomout_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/other_2x_large.png b/TMessagesProj/src/main/res/drawable-mdpi/other_2x_large.png new file mode 100644 index 000000000..ba8a0e34e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/other_2x_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders.png b/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders.png new file mode 100644 index 000000000..0ed4533bf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders2.png b/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders2.png new file mode 100644 index 000000000..9b05b9368 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/other_lockedfolders2.png differ diff --git a/TMessagesProj/src/main/res/drawable-mdpi/temp_starlarge.png b/TMessagesProj/src/main/res/drawable-mdpi/temp_starlarge.png new file mode 100644 index 000000000..0e7a69f58 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/temp_starlarge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/emoji_tabs_premium.png b/TMessagesProj/src/main/res/drawable-xhdpi/emoji_tabs_premium.png new file mode 100644 index 000000000..039f764dc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/emoji_tabs_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_2_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_2_background_sa.png new file mode 100644 index 000000000..4b108a5d6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_2_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_3_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_3_background_sa.png new file mode 100644 index 000000000..bfb133c8d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_3_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_4_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_4_background_sa.png new file mode 100644 index 000000000..ff1655218 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_4_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_5_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_5_background_sa.png new file mode 100644 index 000000000..59f2baa5b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_5_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_6_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_6_background_sa.png new file mode 100644 index 000000000..a94eaaba5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_6_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip.png new file mode 100644 index 000000000..4d35e915b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip_round.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip_round.png new file mode 100644 index 000000000..347ab73ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_clip_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_background_sa.png b/TMessagesProj/src/main/res/drawable-xhdpi/icon_background_sa.png similarity index 100% rename from TMessagesProj/src/main/res/mipmap-xhdpi/icon_background_sa.png rename to TMessagesProj/src/main/res/drawable-xhdpi/icon_background_sa.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png index 6baec5634..8f20d3a99 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_add.png new file mode 100644 index 000000000..a45346d8a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_all.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_all.png new file mode 100644 index 000000000..6b174aec6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_all.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_base.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_base.png new file mode 100644 index 000000000..79dd789d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_base.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_text.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_text.png new file mode 100644 index 000000000..0c70608ca Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addaccount_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbio.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbio.png index fd37e12e3..39ae15d86 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbio.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png index 5f9afb426..6fdb01c03 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addfolder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addfolder.png index a1ac957f8..cb557d87f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addfolder.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addfolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addphoto.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addphoto.png index 2afc570aa..8233b876d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_addphoto.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_addphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_admin_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_admin_add.png new file mode 100644 index 000000000..e8f19fc05 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_admin_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_admins.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_admins.png new file mode 100644 index 000000000..08291300e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_admins.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_allowspeak.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_allowspeak.png index 1d840bde4..f165d1b4a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_allowspeak.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_allowspeak.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png index 96e0a5a7d..b6acc74b1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_archived_stickers.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archived_stickers.png new file mode 100644 index 000000000..f1a0007e5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_archived_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_back.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_back.png index 8b9659369..9eaff4e23 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_back.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_forward.png new file mode 100644 index 000000000..5b068f7d7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrow_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrowright.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrowright.png index ba06e5829..8bd5a0382 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrowright.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_arrowright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_ask_question.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_ask_question.png new file mode 100644 index 000000000..484a89cc3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_ask_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_autodelete.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_autodelete.png index 5eba29d6c..41b451a44 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_autodelete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_autodelete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_background.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_background.png index f00f713a2..f0566641e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_background.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_mute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_mute.png new file mode 100644 index 000000000..55a0d13d5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_unmute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_unmute.png new file mode 100644 index 000000000..d9f117711 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bell_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png index dfd3d7d9f..848bdaf89 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_block2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block2.png index c4408f21b..80c7299a4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_block2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_block2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_bluetooth.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bluetooth.png new file mode 100644 index 000000000..44d0ac9ed Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bluetooth.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_linear.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/blur_linear.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_linear.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_off.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/blur_off.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_off.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_radial.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/blur_radial.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_blur_radial.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_bots.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bots.png new file mode 100644 index 000000000..a95bf9bea Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_high.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_high.png new file mode 100644 index 000000000..6ddb51ddb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_high.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_low.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_low.png new file mode 100644 index 000000000..750e1104b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png index 1ba18b011..8e24c41f1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png index a8a76d000..f6ed76b78 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls.png new file mode 100644 index 000000000..a32738d84 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_14.png new file mode 100644 index 000000000..70ac7ca3c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_hw.png new file mode 100644 index 000000000..918b842fc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_minimize.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_minimize.png index a5e3e8b5b..67e9e8147 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_minimize.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_minimize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_ny.png new file mode 100644 index 000000000..8113c9a94 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_pin.png index e79778c78..39fd378f1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_unpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_unpin.png index 0217717b9..c2c7e3789 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_unpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_calls_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_camera.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_camera.png new file mode 100644 index 000000000..f594c73f5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png index eec3c61f9..e41b94ab0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel.png index 89c0095f3..b877a8f20 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_14.png new file mode 100644 index 000000000..88c4db4c1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_hw.png new file mode 100644 index 000000000..d7d982f9f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_ny.png new file mode 100644 index 000000000..b61fa6d95 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_add.png new file mode 100644 index 000000000..2b1352ae1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_remove.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_remove.png new file mode 100644 index 000000000..2edec1400 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_chats_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png index dc0830089..1df03d2ed 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_check_thick.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check_thick.png new file mode 100644 index 000000000..7bfd6bcdd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_check_thick.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png index 794464c60..eb0ec071a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_input.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_input.png new file mode 100644 index 000000000..6f6d641fb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_input.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_recent.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_recent.png new file mode 100644 index 000000000..d8a6f5321 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clear_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_clearcache.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clearcache.png new file mode 100644 index 000000000..ada3ce9ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_close.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_close.png new file mode 100644 index 000000000..bb809fc7f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_colors.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_colors.png index 8a7a63341..a3d2a6e57 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_colors.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact_add.png new file mode 100644 index 000000000..cf1024fef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contact_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts.png new file mode 100644 index 000000000..17acf05b6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_14.png new file mode 100644 index 000000000..b753e44da Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_hw.png new file mode 100644 index 000000000..6fb388e3f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_name.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_name.png new file mode 100644 index 000000000..bdcafccf4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_ny.png new file mode 100644 index 000000000..5c9cdb8eb Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_time.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_time.png new file mode 100644 index 000000000..38083e8ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_contacts_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png index 3e8019fea..366fa5280 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_current_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_current_location.png new file mode 100644 index 000000000..d8caf7e1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_current_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_customize.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_customize.png index d9522439c..d135532d5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_customize.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_customize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_data.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_data.png new file mode 100644 index 000000000..89dc6d345 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png index c61ad723e..6feea8c68 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_auto.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_auto.png index 3981f14aa..22431d8d3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_auto.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_old.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_old.png new file mode 100644 index 000000000..fe6156565 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_delete_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_devices.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_devices.png new file mode 100644 index 000000000..1dc97c95c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_discussion.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_discussion.png index fc472d169..c621d0103 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_discussion.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_discussion.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png index 01be76015..2f9f7e7c2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_arrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_arrow.png index 9a6ee6d4d..d0fd5fa3f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_arrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_marker.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_marker.png index 71280bcea..6f60bf53d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_marker.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_marker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_neon.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_neon.png index b6e7d3201..e7da87f55 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_neon.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_neon.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_pen.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_pen.png index c6a5e10c5..755aeff9a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_pen.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_draw_pen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png index e8499fd46..08d66c61c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_activities.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_activities.png new file mode 100644 index 000000000..898b395d1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_cat.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_cat.png new file mode 100644 index 000000000..835c0e446 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_flags.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_flags.png new file mode 100644 index 000000000..d7a98f26c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_food.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_food.png new file mode 100644 index 000000000..a95a9e3b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_objects.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_objects.png new file mode 100644 index 000000000..65de909fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_other.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_other.png new file mode 100644 index 000000000..14449416f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_premium.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_premium.png new file mode 100644 index 000000000..daba62401 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_question.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_question.png new file mode 100644 index 000000000..ac59fad10 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_recent.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_recent.png new file mode 100644 index 000000000..1dd9f5f53 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_smiles.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_smiles.png new file mode 100644 index 000000000..bb64c7d0e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_travel.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_travel.png new file mode 100644 index 000000000..e4685b932 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_emoji_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_endcall.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_endcall.png index 81cc06d2e..ee279e3a5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_endcall.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_endcall.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_expand.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_expand.png new file mode 100644 index 000000000..d75b69575 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_expand.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png index 5d667c129..946c4fc45 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_filled_shareout.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/abc_ic_menu_share_mtrl_alpha.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_filled_shareout.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder.png new file mode 100644 index 000000000..7dd2d616c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder_reorder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder_reorder.png new file mode 100644 index 000000000..b99fb4095 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folder_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_folders.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/menu_folders.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_folders.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_archive.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_archive.png new file mode 100644 index 000000000..037e56ac9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_bots.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_bots.png new file mode 100644 index 000000000..17d7fb77b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_channels.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_channels.png new file mode 100644 index 000000000..97fd4ee75 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_channels.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_groups.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_groups.png new file mode 100644 index 000000000..fc437bebd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_muted.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_muted.png new file mode 100644 index 000000000..ac6e8d77c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_private.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_private.png new file mode 100644 index 000000000..fbc50195a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_private.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_read.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_read.png new file mode 100644 index 000000000..e4e865b66 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_requests.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_requests.png new file mode 100644 index 000000000..76a5cd705 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_folders_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png index 2c8929993..010f26775 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_check.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_check.png index 830bc50b4..41df12a06 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_check.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_replace.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_replace.png index ba01ef4b5..ec7fd1ae5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_replace.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_forward_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png index b392961ec..e18e43da4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png index c9720b8f9..8d942e993 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif_add.png new file mode 100644 index 000000000..8ebe8078d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_gif_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png index 34888b613..813e06e9c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png index 3b7f39bea..14319392d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups.png new file mode 100644 index 000000000..93c34ca97 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_14.png new file mode 100644 index 000000000..4332be11c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_create.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_create.png new file mode 100644 index 000000000..71d138441 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_create.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_hw.png new file mode 100644 index 000000000..38ef33313 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_ny.png new file mode 100644 index 000000000..c9988ab24 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_handdown.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_handdown.png index a9f92fdfc..526b55547 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_handdown.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_handdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_help.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help.png new file mode 100644 index 000000000..0cbabde7c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_14.png new file mode 100644 index 000000000..aaf6d2244 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_hw.png new file mode 100644 index 000000000..1ef039b69 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_ny.png new file mode 100644 index 000000000..3cd633bf5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png index 42be54108..4da6672f1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png index 40c43c601..1140e9450 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_info.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_info.png new file mode 100644 index 000000000..3a9d6ffba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_inputarrow.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_inputarrow.png index 7bfde230f..6a6214fb7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_inputarrow.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_inputarrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant_link.png new file mode 100644 index 000000000..bc4206b1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite.png new file mode 100644 index 000000000..cffffe6d5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_14.png new file mode 100644 index 000000000..e25e36a03 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_hw.png new file mode 100644 index 000000000..234fc6300 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_ny.png new file mode 100644 index 000000000..f212c10aa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invited.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invited.png index d37f1d35b..b75aba243 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_invited.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_invited.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_jobtitle.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_jobtitle.png new file mode 100644 index 000000000..c43870c61 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_jobtitle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png index 99eaab7a5..de962626c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png index 65af266cb..b9b57c1d3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_2x.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_2x.png new file mode 100644 index 000000000..76f08db69 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_accounts.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_accounts.png new file mode 100644 index 000000000..fbc50195a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_accounts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_chats.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_chats.png new file mode 100644 index 000000000..b4fb00580 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_folder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_folder.png new file mode 100644 index 000000000..76d7f13a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_groups.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_groups.png new file mode 100644 index 000000000..b227731ed Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_links.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_links.png new file mode 100644 index 000000000..309290a9e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_links.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_pin.png new file mode 100644 index 000000000..82f432ad3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_limit_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png index 4c3724711..135cbdf5d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_link2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link2.png new file mode 100644 index 000000000..4e39a7765 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_link2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_list.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_list.png index 020aa7a2d..2c4d4a9a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_list.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_list2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_list2.png new file mode 100644 index 000000000..137f18efe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_list2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png index 3ccd38e27..1c4037a0c 100755 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert.png index 8f6181fac..d115d153a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png index 2c556f1b4..5024e7051 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_location_alert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_log.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_log.png new file mode 100644 index 000000000..138ed4af0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png index 64f3b7bc4..79b9f2268 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_map_type.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map_type.png new file mode 100644 index 000000000..c580bfdff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_map_type.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png index fb76ba61a..5db142b3f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png index 7669c6e9d..1e8e082bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png index 51b53f4f1..d4be58e71 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png index b512e340c..3a717a3c8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mention.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mention.png index 8a813cc72..376c68b7a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mention.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mention.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png index b97215aea..29a5fa84e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_customize.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_customize.png new file mode 100644 index 000000000..997e45324 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_customize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_premiumlock.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_premiumlock.png new file mode 100644 index 000000000..1f1c79418 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_premiumlock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_stickerstar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_stickerstar.png new file mode 100644 index 000000000..ec8c37e75 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mini_stickerstar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_minvideo.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_minvideo.png index 4c0aa646e..a190f25bd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_minvideo.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_minvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png index 582cb3812..414300b2b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_msgbubble3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png index d959f1e24..c5ccbddd1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute_period.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute_period.png index 61e5f32b2..5ac88f770 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute_period.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_mute_period.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby.png new file mode 100644 index 000000000..dd4b49a68 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_14.png new file mode 100644 index 000000000..dae8b5d37 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_hw.png new file mode 100644 index 000000000..1063ba1f8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_ny.png new file mode 100644 index 000000000..c10685cd8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_off.png new file mode 100644 index 000000000..9b3c3205d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nearby_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_newfilter.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_newfilter.png new file mode 100644 index 000000000..1046ae513 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_newfilter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_newphone.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_newphone.png new file mode 100644 index 000000000..0aa4c5fa9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_nightmode_system.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nightmode_system.png new file mode 100644 index 000000000..caab94110 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_nightmode_system.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_off.png index 112c073d8..fe961cb4a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_on.png index adef0e890..47afc35cc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_noise_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_notifications.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_notifications.png new file mode 100644 index 000000000..9824165de Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png index 5513e8be3..e0372af81 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_openprofile.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openprofile.png index 46b129062..37140f07f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_openprofile.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_openprofile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_palette.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xhdpi/menu_palette.png rename to TMessagesProj/src/main/res/drawable-xhdpi/msg_palette.png diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_address.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_address.png new file mode 100644 index 000000000..249a9f838 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_address.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_card.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_card.png new file mode 100644 index 000000000..7813ae714 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_card.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_delivery.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_delivery.png new file mode 100644 index 000000000..e3ff74a8b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_delivery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_provider.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_provider.png new file mode 100644 index 000000000..5cabbc43b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_payment_provider.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_permissions.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_permissions.png index 54615a900..c5f0e2acb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_permissions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur.png new file mode 100644 index 000000000..7c8ea7ec6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_linear.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_linear.png new file mode 100644 index 000000000..02ea70cd6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_off.png new file mode 100644 index 000000000..8901a0eb4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_radial.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_radial.png new file mode 100644 index 000000000..f0917f0cd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_brush.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_brush.png new file mode 100644 index 000000000..f1fc94f86 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_crop.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_crop.png new file mode 100644 index 000000000..16e5d4e58 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_cropfix.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_cropfix.png new file mode 100644 index 000000000..e877bce0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_curve.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_curve.png new file mode 100644 index 000000000..e79cd3e5a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_draw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_draw.png new file mode 100644 index 000000000..e159bd14b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_draw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_flip.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_flip.png new file mode 100644 index 000000000..eb0705bc2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_flip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_rotate.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_rotate.png new file mode 100644 index 000000000..295b3f1a3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_settings.png new file mode 100644 index 000000000..0a22ffd53 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_text.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_text.png new file mode 100644 index 000000000..0621d457d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photo_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_photos.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photos.png new file mode 100644 index 000000000..d49b2f845 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png index a7cc6fd52..8bbc67e92 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pinnedlist.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pinnedlist.png new file mode 100644 index 000000000..2875ec01b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pinnedlist.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_played.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_played.png index d85718dcf..b0a50abc4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_played.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_played.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_policy.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_policy.png new file mode 100644 index 000000000..d0d98524b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_policy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png index 76a62c35b..63189f049 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_ads.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_ads.png new file mode 100644 index 000000000..69090cce9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_ads.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_avatar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_avatar.png new file mode 100644 index 000000000..d973a6b29 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_badge.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_badge.png new file mode 100644 index 000000000..b92fd51e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_icons.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_icons.png new file mode 100644 index 000000000..8afab5397 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_icons.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_limits.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_limits.png new file mode 100644 index 000000000..7ee1c1ef3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_limits.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_liststar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_liststar.png new file mode 100644 index 000000000..414993c90 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_liststar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock.png new file mode 100644 index 000000000..f16668079 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock2.png new file mode 100644 index 000000000..466550d6b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_lock2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_normal.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_normal.png new file mode 100644 index 000000000..61cde4e1c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_normal.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_prolfilestar.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_prolfilestar.png new file mode 100644 index 000000000..ef6489aee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_prolfilestar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_reactions.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_reactions.png new file mode 100644 index 000000000..fa6a7ef73 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_speed.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_speed.png new file mode 100644 index 000000000..f5e6c8df9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_stickers.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_stickers.png new file mode 100644 index 000000000..f9e9266ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_tools.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_tools.png new file mode 100644 index 000000000..e31257eb5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_uploads.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_uploads.png new file mode 100644 index 000000000..e53cc2f61 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_uploads.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_voice.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_voice.png new file mode 100644 index 000000000..c99c3f2e8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_premium_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_psa.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_psa.png index 967ca6b68..ee0c2738f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_psa.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_psa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_qrcode.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_qrcode.png index 948fc8bc6..0aa996b4b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_qrcode.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_qrcode.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_down.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_down.png new file mode 100644 index 000000000..19db6029e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_up.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_up.png new file mode 100644 index 000000000..ded2a665c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_rate_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions.png index b3ed96c5e..0b2fc6dce 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions2.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions2.png new file mode 100644 index 000000000..ad6143c0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reactions2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_recent.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_recent.png new file mode 100644 index 000000000..87bdd4c0f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_remove.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_remove.png new file mode 100644 index 000000000..3ab5d7492 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_removefolder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_removefolder.png index b9855fc71..8cae8301c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_removefolder.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_removefolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reorder.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reorder.png index f2cd2628b..f903612c7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reorder.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_replace.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_replace.png index 09ace2a39..ea38d468f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_replace.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png index 9f41c7b87..9f5999dfb 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_drugs.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_drugs.png index 240c3df7b..eedfa3e17 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_drugs.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_drugs.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_fake.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_fake.png index 81066b316..6cac6da06 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_fake.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_fake.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_other.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_other.png index c1206a47d..9499540aa 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_other.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_personal.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_personal.png index 7f3098c0c..d48987725 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_personal.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_personal.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_violence.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_violence.png index b889dc6d5..3bfeee8aa 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_violence.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_violence.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_xxx.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_xxx.png index 105099f38..758e97a26 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_xxx.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_report_xxx.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_requests.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_requests.png new file mode 100644 index 000000000..2752acd1d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reset.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reset.png index 2442830a6..a305b6244 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_reset.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_reset.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png index bcc7340a6..5d0574e17 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved.png new file mode 100644 index 000000000..b383a20f0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_14.png new file mode 100644 index 000000000..d3587d73a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_hw.png new file mode 100644 index 000000000..4130f7d1a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_ny.png new file mode 100644 index 000000000..c9966edc0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_saved_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast.png index d1cfbb249..a0734e675 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast_off.png index 137e6c217..01c434f78 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_screencast_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png index 2bf287b43..641f58115 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret.png new file mode 100644 index 000000000..fc340aed0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_14.png new file mode 100644 index 000000000..83df3ace1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_hw.png new file mode 100644 index 000000000..582025548 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_ny.png new file mode 100644 index 000000000..f165ef073 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_seen.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_seen.png index bc15e499f..27973ad7a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_seen.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_select.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_select.png index c25d5ce12..5b1b41a34 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_select.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_send.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_send.png new file mode 100644 index 000000000..5fb416a14 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_sendfile.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sendfile.png index 15937deba..9ab102387 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_sendfile.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sendfile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings.png new file mode 100644 index 000000000..59a620f0b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_14.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_14.png new file mode 100644 index 000000000..0a40ac17b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_hw.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_hw.png new file mode 100644 index 000000000..b2c725480 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_ny.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_ny.png new file mode 100644 index 000000000..e5eb1f039 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_old.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_old.png new file mode 100644 index 000000000..6eebcb251 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_premium.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_premium.png new file mode 100644 index 000000000..3d70c7282 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_settings_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png index a475b29d4..cdb2af393 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png index 70a2a7b59..5772567f5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_silent.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_silent.png index fa9801652..f8e91f148 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_silent.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_silent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_speed.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_speed.png index d51cb331e..2bb05cd53 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_speed.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png index 2f230ea39..be8a2f035 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png index d585ed923..3db081722 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_switch.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_switch.png new file mode 100644 index 000000000..a949bef59 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_switch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png index 7942e4dc5..4f629591d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png index 455e059be..456e7f644 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer_1h.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer_1h.png new file mode 100644 index 000000000..1df4aab4b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timer_1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timeredit.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timeredit.png index 4a6b4ba2f..331236a99 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_timeredit.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_timeredit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_add.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_add.png index 9b480b167..b046e2fa1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_add.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_off.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_off.png index 6efdc2dd8..c9df03bd1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_off.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_on.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_on.png index 97be3b6d5..966d7a7ff 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_on.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_tone_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_translate.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_translate.png index 6e1b2ed09..dbf378621 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_translate.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_translate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_trending.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_trending.png new file mode 100644 index 000000000..abbf104d7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png index b0fa8bc88..f8d89d711 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png index b36f8b4eb..e4af79bff 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png index 29ee3be36..88b012a68 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png index 35cc9ff9c..e19ec7d9d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png index 1526eb4e6..122cf53f0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_remove.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_remove.png new file mode 100644 index 000000000..1b46219c7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_search.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_search.png new file mode 100644 index 000000000..4969ea719 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_user_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_video.png index 95c97e5b3..e6a1e9cf2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_video.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_videocall.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_videocall.png index 53877643c..0bb7de73b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_videocall.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_videocall.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_viewreplies.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_viewreplies.png index e62cd6906..956306e81 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_viewreplies.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_viewreplies.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_voice_headphones.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_voice_headphones.png index b648fee77..74c05002f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_voice_headphones.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_voice_headphones.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_voicechat.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_voicechat.png index f50cdaa8d..ccbc396a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_voicechat.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_voicechat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_work.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_work.png new file mode 100644 index 000000000..f0620f394 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_work.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png index ecf15e471..ae2a2b442 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png index f16659154..6f9a199a8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout_stats.png b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout_stats.png new file mode 100644 index 000000000..18879ec08 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/msg_zoomout_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/other_2x_large.png b/TMessagesProj/src/main/res/drawable-xhdpi/other_2x_large.png new file mode 100644 index 000000000..c6b0366e3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/other_2x_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders.png b/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders.png new file mode 100644 index 000000000..21b31ceb0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders2.png b/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders2.png new file mode 100644 index 000000000..61c59bd92 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/other_lockedfolders2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/temp_starlarge.png b/TMessagesProj/src/main/res/drawable-xhdpi/temp_starlarge.png new file mode 100644 index 000000000..32824733a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/temp_starlarge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/emoji_tabs_premium.png b/TMessagesProj/src/main/res/drawable-xxhdpi/emoji_tabs_premium.png new file mode 100644 index 000000000..3f2acbf87 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/emoji_tabs_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_2_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_2_background_sa.png new file mode 100644 index 000000000..3d782f465 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_2_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_3_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_3_background_sa.png new file mode 100644 index 000000000..4f98481b2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_3_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_4_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_4_background_sa.png new file mode 100644 index 000000000..b2eddb6b4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_4_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_5_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_5_background_sa.png new file mode 100644 index 000000000..8a375a169 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_5_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_6_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_6_background_sa.png new file mode 100644 index 000000000..1274cdb62 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_6_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip.png new file mode 100644 index 000000000..878c53435 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip_round.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip_round.png new file mode 100644 index 000000000..837660051 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_clip_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background_sa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_sa.png similarity index 100% rename from TMessagesProj/src/main/res/mipmap-xxhdpi/icon_background_sa.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/icon_background_sa.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png index b50b233b2..164825b4f 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_actions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_add.png new file mode 100644 index 000000000..ee38a0ff9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_all.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_all.png new file mode 100644 index 000000000..d646fb9c4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_all.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_base.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_base.png new file mode 100644 index 000000000..278336862 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_base.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_text.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_text.png new file mode 100644 index 000000000..d0580ed86 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addaccount_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbio.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbio.png index aaf83b51a..19028341b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbio.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbio.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png index 6d62bf618..54efa8714 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addbot.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addfolder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addfolder.png index 01810a96b..22dc7ee69 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addfolder.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addfolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addphoto.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addphoto.png index f9edb8978..0f883b361 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addphoto.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_addphoto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admin_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admin_add.png new file mode 100644 index 000000000..10b63c4e5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admin_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admins.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admins.png new file mode 100644 index 000000000..c2dfe4d8c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_admins.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_allowspeak.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_allowspeak.png index a1806e57a..9e50c92a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_allowspeak.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_allowspeak.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png index f81ca5f62..513412710 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archived_stickers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archived_stickers.png new file mode 100644 index 000000000..c1051a07d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_archived_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_back.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_back.png index 39862c8ba..d17711d9b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_back.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_back.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_forward.png new file mode 100644 index 000000000..773311988 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrow_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrowright.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrowright.png index 003fc03d7..0bdb7bff1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrowright.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_arrowright.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_ask_question.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_ask_question.png new file mode 100644 index 000000000..1338187d3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_ask_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_autodelete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_autodelete.png index d26b6a3e0..58d9c4841 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_autodelete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_autodelete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_background.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_background.png index 70eb44b84..51a760802 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_background.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_background.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_mute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_mute.png new file mode 100644 index 000000000..6afd63970 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_unmute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_unmute.png new file mode 100644 index 000000000..122abae39 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bell_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png index 5223dd43f..47363d84c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block2.png index d332865c9..051a5ab4c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_block2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bluetooth.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bluetooth.png new file mode 100644 index 000000000..70f2b163b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bluetooth.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_linear.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/blur_linear.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_linear.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_off.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/blur_off.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_off.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_radial.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/blur_radial.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_blur_radial.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bots.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bots.png new file mode 100644 index 000000000..1fd1d9181 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_high.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_high.png new file mode 100644 index 000000000..2b88aa468 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_high.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_low.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_low.png new file mode 100644 index 000000000..5b3b46b5d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_brightness_low.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png index 005d52e22..7fdc3bab1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png index 965ac9719..9877f8dee 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calendar2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls.png new file mode 100644 index 000000000..9df76cd14 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_14.png new file mode 100644 index 000000000..146f1da65 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_hw.png new file mode 100644 index 000000000..c733cc3f8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_minimize.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_minimize.png index 866a0f854..684902965 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_minimize.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_minimize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_ny.png new file mode 100644 index 000000000..3bd559633 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_pin.png index 9bfc2da50..0d8309ae6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_unpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_unpin.png index bbed5a697..dfe91e203 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_unpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_calls_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_camera.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_camera.png new file mode 100644 index 000000000..5c5b1374a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_camera.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png index 316f40e02..018b5b30e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_cancel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel.png index 8d8f0325b..087c0f556 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_14.png new file mode 100644 index 000000000..f0c17ef95 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_hw.png new file mode 100644 index 000000000..264d71754 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_ny.png new file mode 100644 index 000000000..970aab5b8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_channel_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_add.png new file mode 100644 index 000000000..7ffe0606d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_remove.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_remove.png new file mode 100644 index 000000000..64af2496f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_chats_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png index aef869985..5a266d8bc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check_thick.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check_thick.png new file mode 100644 index 000000000..1ba5ab03f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_check_thick.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png index ea78fb3f8..c1905483e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_input.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_input.png new file mode 100644 index 000000000..21f972df3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_input.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_recent.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_recent.png new file mode 100644 index 000000000..60e43ee8a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clear_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clearcache.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clearcache.png new file mode 100644 index 000000000..09e77fde7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_clearcache.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_close.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_close.png new file mode 100644 index 000000000..fda207295 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_close.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_colors.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_colors.png index e3a0d0538..0ba09cd20 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_colors.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_colors.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact_add.png new file mode 100644 index 000000000..544686261 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contact_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts.png new file mode 100644 index 000000000..17ac5bc57 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_14.png new file mode 100644 index 000000000..3d24d45e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_hw.png new file mode 100644 index 000000000..e3683ac9c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_name.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_name.png new file mode 100644 index 000000000..70c1925a6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_name.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_ny.png new file mode 100644 index 000000000..7628cebe8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_time.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_time.png new file mode 100644 index 000000000..af5c690d2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_contacts_time.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png index 87ed4473f..928e19042 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_copy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_current_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_current_location.png new file mode 100644 index 000000000..9ec8b9936 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_current_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_data.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_data.png new file mode 100644 index 000000000..dbbd4bba9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_data.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png index 4b87ebc01..932dbc475 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_auto.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_auto.png index cee6d944e..52bd6cd66 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_auto.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_auto.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_old.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_old.png new file mode 100644 index 000000000..f61d350a5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_delete_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_devices.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_devices.png new file mode 100644 index 000000000..d1167ad21 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_devices.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_discussion.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_discussion.png index 74975993e..e68c9da06 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_discussion.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_discussion.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png index 9a7fd7739..8a5ca1e1d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_download.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_arrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_arrow.png index 7cd0bdd30..abe2962b3 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_arrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_arrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_marker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_marker.png index 00f465683..a7ef8dc15 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_marker.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_marker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_neon.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_neon.png index 69cd6be5e..8ce7b4492 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_neon.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_neon.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_pen.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_pen.png index b7d2ac6b3..db96c2c6a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_pen.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_draw_pen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png index 23c63c725..d0059fd31 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_edit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_activities.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_activities.png new file mode 100644 index 000000000..e8ee8cc00 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_activities.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_cat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_cat.png new file mode 100644 index 000000000..41b3a2f9a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_cat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_flags.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_flags.png new file mode 100644 index 000000000..70d29652d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_flags.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_food.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_food.png new file mode 100644 index 000000000..ef4160eb1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_food.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_objects.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_objects.png new file mode 100644 index 000000000..8a6b5d331 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_objects.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_other.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_other.png new file mode 100644 index 000000000..f855cf296 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_other.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_premium.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_premium.png new file mode 100644 index 000000000..209f29776 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_question.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_question.png new file mode 100644 index 000000000..a84dfb844 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_question.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_recent.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_recent.png new file mode 100644 index 000000000..f81433017 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_smiles.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_smiles.png new file mode 100644 index 000000000..3fa9cbafc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_smiles.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_travel.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_travel.png new file mode 100644 index 000000000..3289e5230 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_emoji_travel.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_endcall.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_endcall.png index 833167f28..9187a66ef 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_endcall.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_endcall.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_expand.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_expand.png new file mode 100644 index 000000000..73f4ae4fd Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_expand.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png index d30ab499c..b56509577 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_fave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/abc_ic_menu_share_mtrl_alpha.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_filled_shareout.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/abc_ic_menu_share_mtrl_alpha.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_filled_shareout.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder.png new file mode 100644 index 000000000..0683d22ad Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder_reorder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder_reorder.png new file mode 100644 index 000000000..45ccc9676 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folder_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_folders.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/menu_folders.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_archive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_archive.png new file mode 100644 index 000000000..436d4f219 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_archive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_bots.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_bots.png new file mode 100644 index 000000000..92b5bd47c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_bots.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_channels.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_channels.png new file mode 100644 index 000000000..ef9ba933e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_channels.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_groups.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_groups.png new file mode 100644 index 000000000..e9afcb6fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_muted.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_muted.png new file mode 100644 index 000000000..822de94d8 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_muted.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_private.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_private.png new file mode 100644 index 000000000..c5ac142e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_private.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_read.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_read.png new file mode 100644 index 000000000..2cd5e1ad9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_read.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_requests.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_requests.png new file mode 100644 index 000000000..180616c09 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_folders_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png index f4318e2c9..b337f2ebc 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_check.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_check.png index 2ba7ff0e3..4767a768d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_check.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_check.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_replace.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_replace.png index ec846f3a4..7d429c1d1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_replace.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_forward_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png index a21ffce4f..9d104b20d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gallery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png index 49d7d77e9..40ee4c188 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif_add.png new file mode 100644 index 000000000..d3457be27 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_gif_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png index 208648826..be7d0769d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png index 4ea67a15f..1c45300e6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_go_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups.png new file mode 100644 index 000000000..5c43438aa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_14.png new file mode 100644 index 000000000..3203d5dd7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_create.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_create.png new file mode 100644 index 000000000..c257933d5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_create.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_hw.png new file mode 100644 index 000000000..e97468de4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_ny.png new file mode 100644 index 000000000..635cd5e4c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_groups_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_handdown.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_handdown.png index ca1110672..f6b3a67ec 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_handdown.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_handdown.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help.png new file mode 100644 index 000000000..7646b0534 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_14.png new file mode 100644 index 000000000..95bbeb308 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_hw.png new file mode 100644 index 000000000..0b3595fe4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_ny.png new file mode 100644 index 000000000..02f223d63 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_help_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png index 507440762..c8bc10422 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_home.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png index 308a343ac..84fe767ae 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_hybrid.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_info.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_info.png new file mode 100644 index 000000000..57cb52bf3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_info.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_inputarrow.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_inputarrow.png index 72f0c953a..7454e2efd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_inputarrow.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_inputarrow.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant_link.png new file mode 100644 index 000000000..906768464 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_instant_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite.png new file mode 100644 index 000000000..985834b61 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_14.png new file mode 100644 index 000000000..f1298c360 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_hw.png new file mode 100644 index 000000000..b6435a7c5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_ny.png new file mode 100644 index 000000000..25986343a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invite_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invited.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invited.png index 85a240de7..e0438a556 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invited.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_invited.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_jobtitle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_jobtitle.png new file mode 100644 index 000000000..cac7bb01e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_jobtitle.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png index 34dabdabc..183d3009c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_language.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png index 4767b2b81..8c6883ea1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_leave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_2x.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_2x.png new file mode 100644 index 000000000..57c701959 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_2x.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_accounts.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_accounts.png new file mode 100644 index 000000000..c5ac142e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_accounts.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_chats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_chats.png new file mode 100644 index 000000000..c8af6d94c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_chats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_folder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_folder.png new file mode 100644 index 000000000..0823b3c5b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_folder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_groups.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_groups.png new file mode 100644 index 000000000..f3f323a26 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_groups.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_links.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_links.png new file mode 100644 index 000000000..f4b3eb5ee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_links.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_pin.png new file mode 100644 index 000000000..40ed635bc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_limit_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png index 48298e408..fef4b84a5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link2.png new file mode 100644 index 000000000..dbfad952b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_link2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list.png index 384d17714..3d4a79fd5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list2.png new file mode 100644 index 000000000..80c9108b7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_list2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png index 611c78c4c..1375e98df 100755 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png index 2678d0d75..4b83b9202 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert2.png index f72a6e1d6..836f50bd9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert2.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_location_alert2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_log.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_log.png new file mode 100644 index 000000000..575b95da3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_log.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png index 82b2f7f58..0bff5cbf7 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map_type.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map_type.png new file mode 100644 index 000000000..27dc80485 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_map_type.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png index 719fc2f16..1adab64d4 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png index 43f206d65..f06defe76 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_markunread.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png index bc0645af6..7af0df762 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mask.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png index 4f331f9fd..86d339e26 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_media.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mention.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mention.png index 662eaf096..2e3b18c34 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mention.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mention.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png index a13e9514f..3763f0577 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_message.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_customize.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_customize.png new file mode 100644 index 000000000..0a6367cfc Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_customize.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_premiumlock.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_premiumlock.png new file mode 100644 index 000000000..e5c6136b9 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_premiumlock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_stickerstar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_stickerstar.png new file mode 100644 index 000000000..7ec074743 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mini_stickerstar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_minvideo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_minvideo.png index 904f97812..496f5d58c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_minvideo.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_minvideo.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_msgbubble3.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_msgbubble3.png index b47398882..73e488d88 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_msgbubble3.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_msgbubble3.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png index a02e81b8d..d243f8b78 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute_period.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute_period.png index 3f04018f4..85202494e 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute_period.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_mute_period.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby.png new file mode 100644 index 000000000..5d5822e74 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_14.png new file mode 100644 index 000000000..5d5c6b103 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_hw.png new file mode 100644 index 000000000..9b74cf00e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_ny.png new file mode 100644 index 000000000..d4445a8ec Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_off.png new file mode 100644 index 000000000..4ed949dda Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nearby_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newfilter.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newfilter.png new file mode 100644 index 000000000..2dd26fb6d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newfilter.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newphone.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newphone.png new file mode 100644 index 000000000..2a734b1b5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_newphone.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nightmode_system.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nightmode_system.png new file mode 100644 index 000000000..7e7bd4571 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_nightmode_system.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_off.png index fa67d6680..0c6b5367b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_on.png index cdcf732f8..5a6edb95b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_noise_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_notifications.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_notifications.png new file mode 100644 index 000000000..49b0dc54d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_notifications.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png index 904ef8078..dd4487118 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openprofile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openprofile.png index bc98ebe16..d204c9c41 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openprofile.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_openprofile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_palette.png similarity index 100% rename from TMessagesProj/src/main/res/drawable-xxhdpi/menu_palette.png rename to TMessagesProj/src/main/res/drawable-xxhdpi/msg_palette.png diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_address.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_address.png new file mode 100644 index 000000000..7d274b387 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_address.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_card.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_card.png new file mode 100644 index 000000000..36b8c7049 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_card.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_delivery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_delivery.png new file mode 100644 index 000000000..9e6610404 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_delivery.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_provider.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_provider.png new file mode 100644 index 000000000..a47c598e4 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_payment_provider.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_permissions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_permissions.png index 2cb7cf34a..82d3fae6f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_permissions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_permissions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur.png new file mode 100644 index 000000000..75cdfe01c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_linear.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_linear.png new file mode 100644 index 000000000..9cf18a85b Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_linear.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_off.png new file mode 100644 index 000000000..079f4d554 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_radial.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_radial.png new file mode 100644 index 000000000..9840a2810 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_blur_radial.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_brush.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_brush.png new file mode 100644 index 000000000..96f7c4268 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_brush.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_crop.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_crop.png new file mode 100644 index 000000000..55fdaa0aa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_crop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_cropfix.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_cropfix.png new file mode 100644 index 000000000..c76982e63 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_cropfix.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_curve.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_curve.png new file mode 100644 index 000000000..e0ffe00e0 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_curve.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_draw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_draw.png new file mode 100644 index 000000000..2a52e1158 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_draw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_flip.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_flip.png new file mode 100644 index 000000000..0e612006e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_flip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_rotate.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_rotate.png new file mode 100644 index 000000000..b18afdf90 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_rotate.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_settings.png new file mode 100644 index 000000000..79d60a1e7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_text.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_text.png new file mode 100644 index 000000000..234138a3a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photo_text.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photos.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photos.png new file mode 100644 index 000000000..620ef2e0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_photos.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png index 855d195fa..32eb8065b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pinnedlist.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pinnedlist.png new file mode 100644 index 000000000..615faee3f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pinnedlist.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_played.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_played.png index d61a99502..0b68de355 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_played.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_played.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_policy.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_policy.png new file mode 100644 index 000000000..d0459094e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_policy.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png index 524c3d5b6..5587960e2 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_pollstop.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_ads.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_ads.png new file mode 100644 index 000000000..ac8d7bec2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_ads.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_avatar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_avatar.png new file mode 100644 index 000000000..f843e00ef Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_avatar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_badge.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_badge.png new file mode 100644 index 000000000..5d3639f00 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_badge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_icons.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_icons.png new file mode 100644 index 000000000..b3565e877 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_icons.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_limits.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_limits.png new file mode 100644 index 000000000..5393df3fe Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_limits.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_liststar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_liststar.png new file mode 100644 index 000000000..ae84e58ba Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_liststar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock.png new file mode 100644 index 000000000..e2f117071 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock2.png new file mode 100644 index 000000000..645997c17 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_lock2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_normal.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_normal.png new file mode 100644 index 000000000..2fb554919 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_normal.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_prolfilestar.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_prolfilestar.png new file mode 100644 index 000000000..88b3009d1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_prolfilestar.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_reactions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_reactions.png new file mode 100644 index 000000000..544c14d31 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_speed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_speed.png new file mode 100644 index 000000000..e497a6983 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_stickers.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_stickers.png new file mode 100644 index 000000000..77c1746fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_stickers.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_tools.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_tools.png new file mode 100644 index 000000000..75966dad5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_tools.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_uploads.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_uploads.png new file mode 100644 index 000000000..8b1eaa3fa Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_uploads.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_voice.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_voice.png new file mode 100644 index 000000000..6a5718f38 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_premium_voice.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_psa.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_psa.png index d8b034c52..f6eb7acd8 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_psa.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_psa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_down.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_down.png new file mode 100644 index 000000000..094d58043 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_down.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_up.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_up.png new file mode 100644 index 000000000..334f4a8a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_rate_up.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions.png index 9f8a363af..f085b0f99 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions2.png new file mode 100644 index 000000000..253d90dd1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reactions2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_recent.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_recent.png new file mode 100644 index 000000000..8e4b4ac6e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_recent.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_remove.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_remove.png new file mode 100644 index 000000000..251c4056e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_removefolder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_removefolder.png index 48b46e67c..eecf3ca3d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_removefolder.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_removefolder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reorder.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reorder.png index 54ee6aa30..9ac9280c0 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reorder.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reorder.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_replace.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_replace.png index 722c9155a..c52611317 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_replace.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_replace.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png index e7dea2c06..d8c676ae9 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reply.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_fake.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_fake.png index df2f194e6..230c46b84 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_fake.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_fake.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_violence.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_violence.png index f05e30e46..c03fb3f55 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_violence.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_report_violence.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_requests.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_requests.png new file mode 100644 index 000000000..38862aa5c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_requests.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reset.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reset.png index 4d24aaf73..b1b04a441 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reset.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_reset.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png index 978f49233..e3b9586be 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_satellite.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved.png new file mode 100644 index 000000000..a45df260f Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_14.png new file mode 100644 index 000000000..f3ddeaeee Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_hw.png new file mode 100644 index 000000000..805b008b3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_ny.png new file mode 100644 index 000000000..70b3bdf67 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_saved_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast.png index 87a776d30..df43fec72 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast_off.png index a1ba164ab..4be8b9745 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_screencast_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png index 6e74cbee4..681613f20 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret.png new file mode 100644 index 000000000..eafb1728c Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_14.png new file mode 100644 index 000000000..2dc5967f3 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_hw.png new file mode 100644 index 000000000..cd645e611 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_ny.png new file mode 100644 index 000000000..2c5690e0d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_secret_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_seen.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_seen.png index 0f9626a17..b7fcc535a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_seen.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_seen.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_select.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_select.png index b4f5db3c3..ee6af1fc1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_select.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_select.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_send.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_send.png new file mode 100644 index 000000000..9e460a9ed Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_send.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sendfile.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sendfile.png index 47146a079..dfc7c38c6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sendfile.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sendfile.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings.png new file mode 100644 index 000000000..6b8563d88 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_14.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_14.png new file mode 100644 index 000000000..87e65292d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_14.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_hw.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_hw.png new file mode 100644 index 000000000..74a11e527 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_hw.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_ny.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_ny.png new file mode 100644 index 000000000..cf18ee1e1 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_ny.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_old.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_old.png new file mode 100644 index 000000000..63098d5ff Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_old.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_premium.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_premium.png new file mode 100644 index 000000000..50e3b653a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_settings_premium.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png index 5b54ca176..535a8a101 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_share.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png index 55664d519..b7cec636b 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_shareout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_speed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_speed.png index bd31f7f66..e66256f22 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_speed.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_speed.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png index 6b9a52a8c..2223545f6 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png index e8f12dfd5..761614717 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_sticker.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_switch.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_switch.png new file mode 100644 index 000000000..6c1dd645e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_switch.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png index e2ba113b3..af0ae0035 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_theme.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png index 36fb2fdf9..14b0682aa 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer_1h.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer_1h.png new file mode 100644 index 000000000..8325c20be Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timer_1h.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timeredit.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timeredit.png index 21b2ff7b5..61e3b84b5 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timeredit.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_timeredit.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_add.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_add.png index 56d9d307f..76a49f2fd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_add.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_add.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_off.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_off.png index 0e7a5173c..4502bd883 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_off.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_off.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_on.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_on.png index f8d0bed82..78ad4a40a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_on.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_tone_on.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_trending.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_trending.png new file mode 100644 index 000000000..9917d22d5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_trending.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png index 1538baa05..5d2c6a1bf 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unarchive.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png index 9f9d24443..e5d150547 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unfave.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png index bfab737e7..cb7dc121d 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unmute.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png index 0933b4a05..5e372f1a1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unpin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png index 9128a67c9..9fe6d35bd 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_unvote.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_remove.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_remove.png new file mode 100644 index 000000000..18391f36e Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_remove.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_search.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_search.png new file mode 100644 index 000000000..79d4bc88a Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_user_search.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_video.png index 9d4b0e6de..a5f8e3d8c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_video.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_video.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_viewreplies.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_viewreplies.png index ca2aeb6f3..e74523d1a 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_viewreplies.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_viewreplies.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voice_headphones.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voice_headphones.png index f1c2f2c78..2a440103f 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voice_headphones.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voice_headphones.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voicechat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voicechat.png index 91691c984..2e5e9eeb1 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voicechat.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_voicechat.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_work.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_work.png new file mode 100644 index 000000000..d669cc116 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_work.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png index b8863b8eb..f4a292e2c 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomin.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png index 03459cb52..a8b5a9c09 100644 Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout_stats.png b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout_stats.png new file mode 100644 index 000000000..1324968b6 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/msg_zoomout_stats.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/other_2x_large.png b/TMessagesProj/src/main/res/drawable-xxhdpi/other_2x_large.png new file mode 100644 index 000000000..2aee493ac Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/other_2x_large.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders.png b/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders.png new file mode 100644 index 000000000..b6e638398 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders2.png new file mode 100644 index 000000000..a7847ec09 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/other_lockedfolders2.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/temp_starlarge.png b/TMessagesProj/src/main/res/drawable-xxhdpi/temp_starlarge.png new file mode 100644 index 000000000..428b529a7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/temp_starlarge.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_2_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_2_background_sa.png new file mode 100644 index 000000000..1fb160d52 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_2_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_3_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_3_background_sa.png new file mode 100644 index 000000000..db569c7d2 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_3_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_4_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_4_background_sa.png new file mode 100644 index 000000000..87ec9b7c7 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_4_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_5_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_5_background_sa.png new file mode 100644 index 000000000..a9daefadf Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_5_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_6_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_6_background_sa.png new file mode 100644 index 000000000..7b7c8dd6d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_6_background_sa.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip.png new file mode 100644 index 000000000..5e92dd50d Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip.png differ diff --git a/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip_round.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip_round.png new file mode 100644 index 000000000..80e66ebd5 Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_clip_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background_sa.png b/TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_sa.png similarity index 100% rename from TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_background_sa.png rename to TMessagesProj/src/main/res/drawable-xxxhdpi/icon_background_sa.png diff --git a/TMessagesProj/src/main/res/drawable/icon_2_background.xml b/TMessagesProj/src/main/res/drawable/icon_2_background.xml new file mode 100644 index 000000000..d1440713e --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_2_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_2_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_2_background_round.xml new file mode 100644 index 000000000..5a8cc155f --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_2_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_3_background.xml b/TMessagesProj/src/main/res/drawable/icon_3_background.xml new file mode 100644 index 000000000..d00445b9d --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_3_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_3_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_3_background_round.xml new file mode 100644 index 000000000..3e2c38cff --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_3_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_4_background.xml b/TMessagesProj/src/main/res/drawable/icon_4_background.xml new file mode 100644 index 000000000..b65238aa6 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_4_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_4_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_4_background_round.xml new file mode 100644 index 000000000..b2ccb6d31 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_4_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_5_background.xml b/TMessagesProj/src/main/res/drawable/icon_5_background.xml new file mode 100644 index 000000000..9df3154c3 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_5_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_5_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_5_background_round.xml new file mode 100644 index 000000000..7c2df592b --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_5_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_6_background.xml b/TMessagesProj/src/main/res/drawable/icon_6_background.xml new file mode 100644 index 000000000..2630ccb36 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_6_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_6_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_6_background_round.xml new file mode 100644 index 000000000..deab3c4cb --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_6_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_background.xml b/TMessagesProj/src/main/res/drawable/icon_background.xml new file mode 100644 index 000000000..27feec428 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/drawable/icon_background_round.xml b/TMessagesProj/src/main/res/drawable/icon_background_round.xml new file mode 100644 index 000000000..444b6f188 --- /dev/null +++ b/TMessagesProj/src/main/res/drawable/icon_background_round.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_sa.xml index bd195b5c4..7d4db32b6 100644 --- a/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_sa.xml +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/ic_launcher_sa.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher.xml new file mode 100644 index 000000000..9f6262518 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_round.xml new file mode 100644 index 000000000..f2f3cdbe1 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_sa.xml new file mode 100644 index 000000000..d8044115b --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_2_launcher_sa.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher.xml new file mode 100644 index 000000000..1e6219cb3 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_round.xml new file mode 100644 index 000000000..1b1050a68 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_sa.xml new file mode 100644 index 000000000..2c880e784 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_3_launcher_sa.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher.xml new file mode 100644 index 000000000..996130674 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_round.xml new file mode 100644 index 000000000..8088534f5 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_sa.xml new file mode 100644 index 000000000..4974cb43c --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_4_launcher_sa.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher.xml new file mode 100644 index 000000000..536bd3f8b --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_round.xml new file mode 100644 index 000000000..617ba1708 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_sa.xml new file mode 100644 index 000000000..d1031fb67 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_5_launcher_sa.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher.xml new file mode 100644 index 000000000..38eda1b31 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_round.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_round.xml new file mode 100644 index 000000000..509ff470d --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_sa.xml b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_sa.xml new file mode 100644 index 000000000..9ef459fa3 --- /dev/null +++ b/TMessagesProj/src/main/res/mipmap-anydpi-v26/icon_6_launcher_sa.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher.png new file mode 100644 index 000000000..bb5802800 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_round.png new file mode 100644 index 000000000..bb5802800 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_sa.png new file mode 100644 index 000000000..0798d4900 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_2_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground.png new file mode 100644 index 000000000..bbd11247c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_round.png new file mode 100644 index 000000000..4b14e5264 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_sa.png new file mode 100644 index 000000000..2474f0e30 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher.png new file mode 100644 index 000000000..b8b31b914 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_round.png new file mode 100644 index 000000000..faeb4eeef Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_sa.png new file mode 100644 index 000000000..60f76574e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_3_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher.png new file mode 100644 index 000000000..e426ae8ab Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_round.png new file mode 100644 index 000000000..e426ae8ab Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_sa.png new file mode 100644 index 000000000..06bc1e648 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_4_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground.png new file mode 100644 index 000000000..9a7768a67 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_round.png new file mode 100644 index 000000000..4c3935b72 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_sa.png new file mode 100644 index 000000000..4c3935b72 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher.png new file mode 100644 index 000000000..e97a34bc8 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_round.png new file mode 100644 index 000000000..0cd282901 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_sa.png new file mode 100644 index 000000000..a843de42a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_5_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground.png new file mode 100644 index 000000000..c5d911719 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_round.png new file mode 100644 index 000000000..c18ac2e63 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_sa.png new file mode 100644 index 000000000..ca91a39e6 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher.png new file mode 100644 index 000000000..741f9c3e6 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_round.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_round.png new file mode 100644 index 000000000..741f9c3e6 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_sa.png new file mode 100644 index 000000000..3167bbbcf Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-hdpi/icon_6_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher.png new file mode 100644 index 000000000..ffdb4e0e0 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_round.png new file mode 100644 index 000000000..ffdb4e0e0 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_sa.png new file mode 100644 index 000000000..86aa47f14 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_2_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground.png new file mode 100644 index 000000000..7f722ba4c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_round.png new file mode 100644 index 000000000..f98bec433 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_sa.png new file mode 100644 index 000000000..1b57c5af7 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher.png new file mode 100644 index 000000000..bd81646e1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_round.png new file mode 100644 index 000000000..13511cb4c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_sa.png new file mode 100644 index 000000000..ea53f5819 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_3_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher.png new file mode 100644 index 000000000..5b5e6a2d4 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_round.png new file mode 100644 index 000000000..5b5e6a2d4 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_sa.png new file mode 100644 index 000000000..c8d66d3ca Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_4_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground.png new file mode 100644 index 000000000..879615702 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_round.png new file mode 100644 index 000000000..b4d601262 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_sa.png new file mode 100644 index 000000000..b4d601262 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher.png new file mode 100644 index 000000000..a09410a09 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_round.png new file mode 100644 index 000000000..cb19e8889 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_sa.png new file mode 100644 index 000000000..8593c9ad1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_5_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground.png new file mode 100644 index 000000000..6abe2a439 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_round.png new file mode 100644 index 000000000..68cb022f2 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_sa.png new file mode 100644 index 000000000..6bbdb3bbd Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher.png new file mode 100644 index 000000000..2626b3d0c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_round.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_round.png new file mode 100644 index 000000000..2626b3d0c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_sa.png new file mode 100644 index 000000000..a801a206f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-mdpi/icon_6_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher.png new file mode 100644 index 000000000..b88b7b508 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_round.png new file mode 100644 index 000000000..b88b7b508 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_sa.png new file mode 100644 index 000000000..a63b7edab Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_2_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground.png new file mode 100644 index 000000000..820f495ef Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_round.png new file mode 100644 index 000000000..3cc064a3f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_sa.png new file mode 100644 index 000000000..15ae585da Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher.png new file mode 100644 index 000000000..9113f1b61 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_round.png new file mode 100644 index 000000000..ea6701760 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_sa.png new file mode 100644 index 000000000..18fba2e99 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_3_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher.png new file mode 100644 index 000000000..2d0d4d565 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_round.png new file mode 100644 index 000000000..2d0d4d565 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_sa.png new file mode 100644 index 000000000..89272479c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_4_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground.png new file mode 100644 index 000000000..9881807e3 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_round.png new file mode 100644 index 000000000..58208bc4a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_sa.png new file mode 100644 index 000000000..58208bc4a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher.png new file mode 100644 index 000000000..b7b966b5a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_round.png new file mode 100644 index 000000000..76243ec39 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_sa.png new file mode 100644 index 000000000..69a1f0c39 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_5_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground.png new file mode 100644 index 000000000..7e38f4505 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_round.png new file mode 100644 index 000000000..b9420281a Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_sa.png new file mode 100644 index 000000000..82b68ca06 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher.png new file mode 100644 index 000000000..10a5ecbf8 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_round.png new file mode 100644 index 000000000..10a5ecbf8 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_sa.png new file mode 100644 index 000000000..c227c29ae Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xhdpi/icon_6_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher.png new file mode 100644 index 000000000..fac63dbe9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_round.png new file mode 100644 index 000000000..fac63dbe9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_sa.png new file mode 100644 index 000000000..00ec4714c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_2_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground.png new file mode 100644 index 000000000..7a00e5204 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_round.png new file mode 100644 index 000000000..478eae3ee Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_sa.png new file mode 100644 index 000000000..6af96e162 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher.png new file mode 100644 index 000000000..033000f85 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_round.png new file mode 100644 index 000000000..05510c72c Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_sa.png new file mode 100644 index 000000000..941db6791 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_3_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher.png new file mode 100644 index 000000000..85d680bfb Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_round.png new file mode 100644 index 000000000..85d680bfb Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_sa.png new file mode 100644 index 000000000..724b1deb2 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_4_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground.png new file mode 100644 index 000000000..d33e89be5 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_round.png new file mode 100644 index 000000000..0ed490fc3 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_sa.png new file mode 100644 index 000000000..0ed490fc3 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher.png new file mode 100644 index 000000000..8ea03705f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_round.png new file mode 100644 index 000000000..864234c9e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_sa.png new file mode 100644 index 000000000..6d180ea1e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_5_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground.png new file mode 100644 index 000000000..71845f28e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_round.png new file mode 100644 index 000000000..5e47b28e2 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_sa.png new file mode 100644 index 000000000..498e55ba1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher.png new file mode 100644 index 000000000..c3ef8c871 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_round.png new file mode 100644 index 000000000..c3ef8c871 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_sa.png new file mode 100644 index 000000000..fbd6b5fd2 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxhdpi/icon_6_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher.png new file mode 100644 index 000000000..8ea8b260f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_round.png new file mode 100644 index 000000000..8ea8b260f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_sa.png new file mode 100644 index 000000000..40af15585 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_2_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground.png new file mode 100644 index 000000000..a94b0236b Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_round.png new file mode 100644 index 000000000..8ab407167 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_sa.png new file mode 100644 index 000000000..1d898cce6 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher.png new file mode 100644 index 000000000..4c6da9fbc Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_round.png new file mode 100644 index 000000000..31e00d73e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_sa.png new file mode 100644 index 000000000..470554ba0 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_3_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher.png new file mode 100644 index 000000000..2be4d4ad9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_round.png new file mode 100644 index 000000000..2be4d4ad9 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_sa.png new file mode 100644 index 000000000..6fe44e352 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_4_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground.png new file mode 100644 index 000000000..9c9070f0e Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_round.png new file mode 100644 index 000000000..0bcabb4d7 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_sa.png new file mode 100644 index 000000000..0bcabb4d7 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher.png new file mode 100644 index 000000000..e4781717f Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_round.png new file mode 100644 index 000000000..5dca77061 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_sa.png new file mode 100644 index 000000000..547df65e7 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_5_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground.png new file mode 100644 index 000000000..a21db4190 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_round.png new file mode 100644 index 000000000..3cf1754d0 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_sa.png new file mode 100644 index 000000000..7069339ae Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_foreground_sa.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher.png new file mode 100644 index 000000000..cc1049bd1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_round.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_round.png new file mode 100644 index 000000000..cc1049bd1 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_round.png differ diff --git a/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_sa.png b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_sa.png new file mode 100644 index 000000000..b1e36f349 Binary files /dev/null and b/TMessagesProj/src/main/res/mipmap-xxxhdpi/icon_6_launcher_sa.png differ diff --git a/TMessagesProj/src/main/res/raw/addone_icon.json b/TMessagesProj/src/main/res/raw/addone_icon.json new file mode 100644 index 000000000..2c0230da5 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/addone_icon.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":120,"w":30,"h":30,"nm":"addone","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"+1","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-24,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,0]],"o":[[0,0],[0,0]],"v":[[3,0],[-3,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 76","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3,0],[-3,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":16,"s":[100]}],"ix":1},"e":{"a":0,"k":0,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-90,"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":"Vector 80","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[1,4],[1,-4],[-1,-2]],"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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[100]},{"t":24,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[48,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 78","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2,0],[-2,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":24,"s":[100]},{"t":30,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[54,24],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 79","np":3,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":124,"st":4,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"block","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[3,15,0],"ix":2,"l":2},"a":{"a":0,"k":[-72,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"t":30,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-2.209],[0,0],[2.209,0],[0,0],[0,2.209],[0,0],[-2.209,0],[0,0]],"o":[[0,0],[0,2.209],[0,0],[-2.209,0],[0,0],[0,-2.209],[0,0],[2.209,0]],"v":[[12,-5],[12,5],[8,9],[-8,9],[-12,5],[-12,-5],[-8,-9],[8,-9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 111","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"+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":[42,0,0],"ix":2,"l":2},"a":{"a":0,"k":[66,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,1]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0]},"t":0,"s":[100,100,100]},{"t":20,"s":[0,0,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":[[3,0],[-3,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 76","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3,0],[-3,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":100,"ix":1},"e":{"a":0,"k":0,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":-90,"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":"Vector 80","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[1,4],[1,-4],[-1,-2]],"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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[48,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 78","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2,0],[-2,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":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[54,24],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 79","np":3,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":124,"st":4,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"block 2","tt":2,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"t":12,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[27,15,0],"ix":2,"l":2},"a":{"a":0,"k":[72,0,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,17.667]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,-16.667]},"t":0,"s":[16.667,16.667,100]},{"t":12,"s":[0,0,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-2.209],[0,0],[2.209,0],[0,0],[0,2.209],[0,0],[-2.209,0],[0,0]],"o":[[0,0],[0,2.209],[0,0],[-2.209,0],[0,0],[0,-2.209],[0,0],[2.209,0]],"v":[[12,-5],[12,5],[8,9],[-8,9],[-12,5],[-12,-5],[-8,-9],[8,-9]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 111","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/dots_loading.json b/TMessagesProj/src/main/res/raw/dots_loading.json new file mode 100644 index 000000000..63e9f971a --- /dev/null +++ b/TMessagesProj/src/main/res/raw/dots_loading.json @@ -0,0 +1,848 @@ +{ + "v": "5.8.1", + "fr": 60, + "ip": 0, + "op": 60, + "w": 48, + "h": 60, + "nm": "ccaDots", + "ddd": 0, + "assets": [ + { + "id": "comp_0", + "nm": "Comp 1", + "fr": 60, + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Point 1", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.7, + "y": 1 + }, + "o": { + "x": 0.7, + "y": 0 + }, + "t": 12, + "s": [ + 118.6, + 256, + 0 + ], + "to": [ + -0.6, + -119, + 0 + ], + "ti": [ + -1.438, + -92.469, + 0 + ] + }, + { + "i": { + "x": 0.4, + "y": 1 + }, + "o": { + "x": 0.32, + "y": 0 + }, + "t": 32, + "s": [ + 255.938, + 275.469, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "t": 42, + "s": [ + 255.938, + 255.969, + 0 + ] + } + ], + "ix": 2, + "l": 2 + }, + "a": { + "a": 0, + "k": [ + -102.4, + 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": [ + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ], + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ] + ], + "o": [ + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ], + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ] + ], + "v": [ + [ + -102.4, + -32 + ], + [ + -70.4, + 0 + ], + [ + -102.4, + 32 + ], + [ + -134.4, + 0 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 180, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "Point 2", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.7, + "y": 1 + }, + "o": { + "x": 0.7, + "y": 0 + }, + "t": 0, + "s": [ + 256, + 256, + 0 + ], + "to": [ + 1.75, + -110, + 0 + ], + "ti": [ + -5.25, + -93.219, + 0 + ] + }, + { + "i": { + "x": 0.42, + "y": 1 + }, + "o": { + "x": 0.3, + "y": 0 + }, + "t": 20, + "s": [ + 393.25, + 276.969, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "t": 30, + "s": [ + 393.25, + 255.969, + 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": [ + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ], + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ] + ], + "o": [ + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ], + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ] + ], + "v": [ + [ + 0, + -32 + ], + [ + 32, + 0 + ], + [ + 0, + 32 + ], + [ + -32, + 0 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 180, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "Point 3", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 1, + "k": [ + { + "i": { + "x": 0.4, + "y": 1 + }, + "o": { + "x": 0.3, + "y": 0 + }, + "t": 0, + "s": [ + 393.4, + 256, + 0 + ], + "to": [ + 0, + 0, + 0 + ], + "ti": [ + 0, + 0, + 0 + ] + }, + { + "t": 40, + "s": [ + 118.562, + 255.969, + 0 + ] + } + ], + "ix": 2, + "l": 2 + }, + "a": { + "a": 0, + "k": [ + 102.4, + 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": [ + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ], + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ] + ], + "o": [ + [ + 17.673, + 0 + ], + [ + 0, + 17.673 + ], + [ + -17.673, + 0 + ], + [ + 0, + -17.673 + ] + ], + "v": [ + [ + 102.4, + -32 + ], + [ + 134.4, + 0 + ], + [ + 102.4, + 32 + ], + [ + 70.4, + 0 + ] + ], + "c": true + }, + "ix": 2 + }, + "nm": "Path 1", + "mn": "ADBE Vector Shape - Group", + "hd": false + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ], + "ix": 4 + }, + "o": { + "a": 0, + "k": 100, + "ix": 5 + }, + "r": 1, + "bm": 0, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill", + "hd": false + }, + { + "ty": "tr", + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "nm": "Transform" + } + ], + "nm": "Group 1", + "np": 2, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 180, + "st": 0, + "bm": 0 + } + ] + } + ], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 0, + "nm": "Comp 1", + "refId": "comp_0", + "sr": 1, + "ks": { + "o": { + "a": 0, + "k": 100, + "ix": 11 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "p": { + "a": 0, + "k": [ + 24, + 43, + 0 + ], + "ix": 2, + "l": 2 + }, + "a": { + "a": 0, + "k": [ + 256, + 256, + 0 + ], + "ix": 1, + "l": 2 + }, + "s": { + "a": 0, + "k": [ + 9.5, + 9.5, + 100 + ], + "ix": 6, + "l": 2 + } + }, + "ao": 0, + "w": 512, + "h": 512, + "ip": 0, + "op": 180, + "st": 0, + "bm": 0 + } + ], + "markers": [] +} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/double_icon.json b/TMessagesProj/src/main/res/raw/double_icon.json new file mode 100644 index 000000000..55fd5e2ed --- /dev/null +++ b/TMessagesProj/src/main/res/raw/double_icon.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":120,"w":30,"h":30,"nm":"double","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"x2move","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.593},"o":{"x":1,"y":0},"t":0,"s":[15,15,0],"to":[2.667,0,0],"ti":[2.667,0,0]},{"i":{"x":0.833,"y":0.963},"o":{"x":0.167,"y":0.042},"t":5,"s":[31,15,0],"to":[-2.667,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.704},"o":{"x":0.167,"y":0.296},"t":6,"s":[-1,15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.957},"o":{"x":0.167,"y":0.037},"t":14,"s":[31,15,0],"to":[0,0,0],"ti":[2.528,0,0]},{"i":{"x":0.833,"y":0.935},"o":{"x":0.167,"y":0.395},"t":15,"s":[-1,15,0],"to":[-2.528,0,0],"ti":[-2.667,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.78},"t":20,"s":[15.833,15,0],"to":[2.667,0,0],"ti":[0.139,0,0]},{"t":30,"s":[15,15,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":[1,1,0.333],"y":[0,0,0]},"t":0,"s":[16.667,16.667,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":5,"s":[8.333,8.333,100]},{"i":{"x":[0,0,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":15,"s":[8.333,8.333,100]},{"t":20,"s":[16.667,16.667,100]}],"ix":6,"l":2}},"ao":0,"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"x2","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-24,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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3,4],[-3,-4]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3,4],[-1.333,-4]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3,4],[-3,-4]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.909803921569,0.470588235294,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"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":[600,600],"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":"Vector 73","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"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":20,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3,4],[3,-4]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3,4],[4.667,-4]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-3,4],[3,-4]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.909803921569,0.470588235294,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"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":[600,600],"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":"Vector 74","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"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":20,"s":[{"i":[[0,0],[0,0],[-0.828,0],[0,0],[0,-1.195],[0.733,-0.366],[0,0],[0,-0.758],[0,0],[0,0]],"o":[[0,0],[0,-0.828],[0,0],[1.195,0],[0,0.819],[0,0],[-0.678,0.339],[0,0],[0,0],[0,0]],"v":[[-2.5,-2],[-2.5,-2.5],[-1,-4],[0.337,-4],[2.5,-1.837],[1.304,0.098],[-1.394,1.447],[-2.5,3.236],[-2.5,4],[2.5,4]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[-0.828,0],[0,0],[0,-1.195],[0.733,-0.366],[0,0],[0,-0.758],[0,0],[0,0]],"o":[[0,0],[0,-0.828],[0,0],[1.195,0],[0,0.819],[0,0],[-0.678,0.339],[0,0],[0,0],[0,0]],"v":[[-0.833,-2],[-0.833,-2.5],[0.667,-4],[2.004,-4],[4.167,-1.837],[1.304,0.098],[-1.394,1.447],[-2.5,3.236],[-2.5,4],[2.5,4]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0],[-0.828,0],[0,0],[0,-1.195],[0.733,-0.366],[0,0],[0,-0.758],[0,0],[0,0]],"o":[[0,0],[0,-0.828],[0,0],[1.195,0],[0,0.819],[0,0],[-0.678,0.339],[0,0],[0,0],[0,0]],"v":[[-2.5,-2],[-2.5,-2.5],[-1,-4],[0.337,-4],[2.5,-1.837],[1.304,0.098],[-1.394,1.447],[-2.5,3.236],[-2.5,4],[2.5,4]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.909803921569,0.470588235294,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.66,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[51,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"Vector 75","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"block","tt":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[15,15,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,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":15,"s":[{"i":[[0,-2.209],[0,0],[2.209,0],[0,0],[0,2.209],[0,0],[-2.209,0],[0,0]],"o":[[0,0],[0,2.209],[0,0],[-2.209,0],[0,0],[0,-2.209],[0,0],[2.209,0]],"v":[[12,-5],[12,5],[8,9],[-8,9],[-12,5],[-12,-5],[-8,-9],[8,-9]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,-2.209],[0,0],[2.209,0],[0,0],[0,2.209],[0,0],[-2.209,0],[0,0]],"o":[[0,0],[0,2.209],[0,0],[-2.209,0],[0,0],[0,-2.209],[0,0],[2.209,0]],"v":[[14.792,-5],[13.125,5],[9.125,9],[-8,9],[-12,5],[-10.333,-5],[-6.333,-9],[10.792,-9]],"c":true}]},{"t":30,"s":[{"i":[[0,-2.209],[0,0],[2.209,0],[0,0],[0,2.209],[0,0],[-2.209,0],[0,0]],"o":[[0,0],[0,2.209],[0,0],[-2.209,0],[0,0],[0,-2.209],[0,0],[2.209,0]],"v":[[12,-5],[12,5],[8,9],[-8,9],[-12,5],[-12,-5],[-8,-9],[8,-9]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 111","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_adsbubble.svg b/TMessagesProj/src/main/res/raw/premium_object_adsbubble.svg new file mode 100644 index 000000000..6f485a51c --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_adsbubble.svg @@ -0,0 +1,7 @@ + + + premium_object_adsbubble + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_bubble.svg b/TMessagesProj/src/main/res/raw/premium_object_bubble.svg new file mode 100644 index 000000000..54e9706c3 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_bubble.svg @@ -0,0 +1,7 @@ + + + premium_object_bubble + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_folder.svg b/TMessagesProj/src/main/res/raw/premium_object_folder.svg new file mode 100644 index 000000000..7510a7b1a --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_folder.svg @@ -0,0 +1,7 @@ + + + premium_object_folder + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_like.svg b/TMessagesProj/src/main/res/raw/premium_object_like.svg new file mode 100644 index 000000000..3360558dc --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_like.svg @@ -0,0 +1,7 @@ + + + premium_object_like + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_noads.svg b/TMessagesProj/src/main/res/raw/premium_object_noads.svg new file mode 100644 index 000000000..4b150334d --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_noads.svg @@ -0,0 +1,7 @@ + + + premium_object_noads + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_settings.svg b/TMessagesProj/src/main/res/raw/premium_object_settings.svg new file mode 100644 index 000000000..80d1f3611 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_settings.svg @@ -0,0 +1,7 @@ + + + premium_object_settings + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_user.svg b/TMessagesProj/src/main/res/raw/premium_object_user.svg new file mode 100644 index 000000000..9ef1bc349 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_user.svg @@ -0,0 +1,7 @@ + + + premium_object_user + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_video.svg b/TMessagesProj/src/main/res/raw/premium_object_video.svg new file mode 100644 index 000000000..a542c2539 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_video.svg @@ -0,0 +1,7 @@ + + + premium_object_video + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/premium_object_video2.svg b/TMessagesProj/src/main/res/raw/premium_object_video2.svg new file mode 100644 index 000000000..7f314d28e --- /dev/null +++ b/TMessagesProj/src/main/res/raw/premium_object_video2.svg @@ -0,0 +1,7 @@ + + + premium_object_video2 + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/star_loader.svg b/TMessagesProj/src/main/res/raw/star_loader.svg new file mode 100644 index 000000000..398f8ede7 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/star_loader.svg @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/transcribe_in.json b/TMessagesProj/src/main/res/raw/transcribe_in.json new file mode 100644 index 000000000..f3371c880 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/transcribe_in.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":20,"w":240,"h":240,"nm":"a_voice_to_text","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":2,"ty":4,"nm":"Artboard Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[120,120,0],"ix":2,"l":2},"a":{"a":0,"k":[12,12,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,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],[0.051,-0.056],[0,0]],"o":[[0,0],[0.051,0.056],[0,0],[0,0]],"v":[[-1.647,-3.666],[1.597,-0.098],[1.597,0.098],[-1.647,3.666]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[50]},{"t":19,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[50]},{"t":19,"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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":19,"s":[1.567]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[2.644,12.097],"to":[1,0],"ti":[-1,0]},{"t":19,"s":[8.644,12.097]}],"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":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.33,12.097],[9.33,12.097]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[100]},{"t":19,"s":[0]}],"ix":1},"e":{"a":0,"k":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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":19,"s":[1.567]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[-5,0],"to":[0.833,0],"ti":[-0.833,0]},{"t":19,"s":[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":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.663,13.43],[18.996,13.43]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[50]},{"t":19,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[50]},{"t":19,"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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.567,"ix":5},"lc":2,"lj":1,"ml":10,"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":"Group 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-10.662,3.248],[-4.673,-2.752],[-4.662,-2.752],[1.338,3.248]],"c":false}]},{"t":19,"s":[{"i":[[0,0],[0,0],[-0.264,-0.532],[0,0]],"o":[[0,0],[0.19,-0.497],[0,0],[0,0]],"v":[[-3.333,4.012],[-0.566,-3.482],[0.558,-3.48],[3.333,4.012]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[1.67]},{"t":19,"s":[1.567]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[16.662,11.752],"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":"Group 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/transcribe_out.json b/TMessagesProj/src/main/res/raw/transcribe_out.json new file mode 100644 index 000000000..23716e6fa --- /dev/null +++ b/TMessagesProj/src/main/res/raw/transcribe_out.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":20,"w":240,"h":240,"nm":"a_text_to_voice","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Artboard Outlines","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":19,"s":[-90]}],"ix":10},"p":{"a":0,"k":[120,120,0],"ix":2,"l":2},"a":{"a":0,"k":[12,12,0],"ix":1,"l":2},"s":{"a":0,"k":[1000,1000,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0.051,-0.056],[0,0]],"o":[[0,0],[0.051,0.056],[0,0],[0,0]],"v":[[-1.647,-3.666],[1.597,-0.098],[1.597,0.098],[-1.647,3.666]],"c":false}]},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[0.356,-6.097],[6.356,-0.107],[6.356,-0.097],[0.356,5.903]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[1.567]},{"t":19,"s":[1.67]}],"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[8.644,12.097],"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":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":0,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[3.33,12.097],[9.33,12.097]],"c":false}]},{"t":19,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[9.33,12.097],[15.33,12.097]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":10,"s":[100]}],"ix":1},"e":{"a":0,"k":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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.567,"ix":5},"lc":2,"lj":1,"ml":10,"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":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[14.663,13.43],[18.996,13.43]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":12,"s":[100]}],"ix":1},"e":{"a":0,"k":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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1.567,"ix":5},"lc":2,"lj":1,"ml":10,"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":"Group 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.264,-0.532],[0,0]],"o":[[0,0],[0.19,-0.497],[0,0],[0,0]],"v":[[-3.333,4.012],[-0.566,-3.482],[0.558,-3.48],[3.333,4.012]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":0,"s":[0]},{"t":16,"s":[100]}],"ix":1},"e":{"a":0,"k":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},{"ty":"st","c":{"a":0,"k":[0.270588235294,0.639215686275,0.960784373564,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":10,"s":[1.567]},{"t":14,"s":[0]}],"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[16.662,11.752],"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":"Group 4","np":3,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":20,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/raw/unlock_icon.json b/TMessagesProj/src/main/res/raw/unlock_icon.json new file mode 100644 index 000000000..b199523eb --- /dev/null +++ b/TMessagesProj/src/main/res/raw/unlock_icon.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":120,"w":30,"h":30,"nm":"unlock","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"lock2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[0.805]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[-0.195]},"t":20,"s":[7.407]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[15]},{"t":40,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[19,14,0],"to":[0,-0.139,0],"ti":[0,0,0]},{"i":{"x":0.903,"y":0},"o":{"x":0.333,"y":0},"t":10,"s":[19,13.167,0],"to":[0,0,0],"ti":[0,-0.124,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.152,"y":1},"t":20,"s":[19,13.383,0],"to":[0,0.216,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[19,13.167,0],"to":[0,0,0],"ti":[0,-0.088,0]},{"t":40,"s":[19,14,0]}],"ix":2,"l":2},"a":{"a":0,"k":[4,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],[-2.209,0],[0,-2.209],[0,0]],"o":[[0,0],[0,-2.209],[2.209,0],[0,0],[0,0]],"v":[[-4,-1],[-4,-4],[0,-8],[4,-4],[4,8]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"rd","nm":"Round Corners 1","r":{"a":0,"k":4,"ix":1},"ix":2,"mn":"ADBE Vector Filter - RC","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"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":"lock2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"lock1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[0.805]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[-15]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[-0.195]},"t":20,"s":[-7.407]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[-15]},{"t":40,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[19,16,0],"to":[0,0.139,0],"ti":[0,0,0]},{"i":{"x":0.903,"y":0},"o":{"x":0.333,"y":0},"t":10,"s":[19,16.833,0],"to":[0,0,0],"ti":[0,0.124,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.152,"y":1},"t":20,"s":[19,16.617,0],"to":[0,-0.216,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[19,16.833,0],"to":[0,0,0],"ti":[0,0.088,0]},{"t":40,"s":[19,16,0]}],"ix":2,"l":2},"a":{"a":0,"k":[24,-12,0],"ix":1,"l":2},"s":{"a":0,"k":[16.667,16.667,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[14,12],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":4,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[600,600],"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":"lock1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":120,"st":0,"bm":0}],"markers":[]} diff --git a/TMessagesProj/src/main/res/raw/utyan_saved_messages.tgs b/TMessagesProj/src/main/res/raw/utyan_saved_messages.tgs new file mode 100644 index 000000000..d9d24ce14 --- /dev/null +++ b/TMessagesProj/src/main/res/raw/utyan_saved_messages.tgs @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2","fr":60,"ip":0,"op":180,"w":512,"h":512,"nm":"_054_CLOUDY_UPLOAD_OUT","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"wing_bl","parent":3,"sr":1,"ks":{"p":{"a":0,"k":[-3.342,8.073,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":78,"s":[{"i":[[0,0],[-7.642,3.157]],"o":[[11.403,-0.59],[0,0]],"v":[[-16.161,3.318],[11.03,-1.641]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[11.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[11.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":124,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":138,"s":[{"i":[[0,0],[-7.642,3.157]],"o":[[11.403,-0.59],[0,0]],"v":[[-16.161,3.318],[15.822,-2.353]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[0,0],[-7.642,3.157]],"o":[[11.403,-0.59],[0,0]],"v":[[-16.161,3.318],[15.822,-2.353]],"c":false}]},{"t":212,"s":[{"i":[[0,0],[-5.051,6.133]],"o":[[9.38,5.051],[0,0]],"v":[[-16.161,3.318],[16.161,-5.015]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.988235294819,0.933333337307,0.129411771894,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"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":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":96,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[5]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[0]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":96,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[100]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[95]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"NULL CONTROL","parent":25,"sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[60.406,-23.23,0],"to":[-2.373,18.584,0],"ti":[0,0,0]},{"t":74,"s":[31.56,-7.605,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[31.56,-7.605,0],"to":[0,0,0],"ti":[-2.373,18.584,0]},{"t":120,"s":[60.406,-23.23,0]}]},"a":{"a":0,"k":[60,60,0]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"wing","parent":2,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":74,"s":[10.549]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":88,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":134,"s":[10.549]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":148,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":194,"s":[10.549]},{"t":208,"s":[0]}]},"p":{"a":0,"k":[18.897,81.268,0]},"a":{"a":0,"k":[-32,-0.5,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":78,"s":[{"i":[[0,0],[0.54,-13.293],[49.178,7.296]],"o":[[30.901,11.686],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[27.067,-6.803],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":92,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[25.683,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":106,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[25.683,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":124,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":138,"s":[{"i":[[0,0],[0.54,-13.293],[49.178,7.296]],"o":[[30.901,11.686],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[39.047,-8.584],[-38.19,21.997]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":152,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[0,0],[0.54,-13.293],[49.178,7.296]],"o":[[30.901,11.686],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[39.047,-8.584],[-38.19,21.997]],"c":false}]},{"t":212,"s":[{"i":[[0,0],[0.54,-13.293],[50.756,14.899]],"o":[[29.04,22.474],[-0.54,13.293],[0,0]],"v":[[-21.776,-25.224],[38.183,-17.165],[-38.19,21.997]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,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":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Layer 6","parent":2,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[3.236]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":74,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[0]},{"t":120,"s":[3.236]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[108.932,54.523,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":0.667},"o":{"x":0.333,"y":0.333},"t":74,"s":[105.642,72.944,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[105.642,72.944,0],"to":[0,0,0],"ti":[0,0,0]},{"t":120,"s":[108.932,54.523,0]}]},"a":{"a":0,"k":[241.426,390.515,0]},"s":{"a":0,"k":[84.345,91.374,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0.333,-1.762],[0,0]],"o":[[0,0],[-0.335,1.769]],"v":[[12.4,-10.925],[6.821,18.575]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0.413,-1.473],[0,0]],"o":[[0,0],[-0.415,1.48]],"v":[[2.016,-12.335],[-4.906,12.335]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[0.413,-1.59],[0,0]],"o":[[0,0],[-0.415,1.597]],"v":[[2.016,-15.086],[-4.906,11.536]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0.413,-1.59],[0,0]],"o":[[0,0],[-0.415,1.597]],"v":[[2.016,-15.086],[-4.906,11.536]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0.333,-1.762],[0,0]],"o":[[0,0],[-0.335,1.769]],"v":[[12.4,-10.925],[6.821,18.575]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0.483,-1.735],[0,0]],"o":[[0,0],[-0.485,1.743]],"v":[[14.309,-15.08],[6.22,13.978]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.333,-1.762],[0,0]],"o":[[0,0],[-0.335,1.769]],"v":[[12.4,-10.925],[6.821,18.575]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.333,-1.762],[0,0]],"o":[[0,0],[-0.335,1.769]],"v":[[12.4,-10.925],[6.821,18.575]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[0.483,-1.735],[0,0]],"o":[[0,0],[-0.485,1.743]],"v":[[14.309,-15.08],[6.22,13.978]],"c":false}]},{"t":212,"s":[{"i":[[0.333,-1.762],[0,0]],"o":[[0,0],[-0.335,1.769]],"v":[[12.4,-10.925],[6.821,18.575]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.560784339905,0.792156875134,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[208.261,368.097]},"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":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[12.233,-3.905],[5.637,4.126],[1.747,-2.402],[8.343,-10.434]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0.927,-3.364],[3.593,0],[-0.927,3.364],[-3.593,0]],"o":[[-0.927,3.364],[-3.593,0],[0.927,-3.364],[3.593,0]],"v":[[7.814,0],[-0.37,6.091],[-5.196,0],[2.988,-6.091]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[7.814,-2.63],[-0.37,3.943],[-5.196,-2.63],[2.988,-9.204]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[7.814,-2.63],[-0.37,3.943],[-5.196,-2.63],[2.988,-9.204]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[12.233,-3.905],[5.637,4.126],[1.747,-2.402],[8.343,-10.434]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[16.089,-2.774],[8.46,4.795],[4.774,-1.981],[12.403,-9.55]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[12.233,-3.905],[5.637,4.126],[1.747,-2.402],[8.343,-10.434]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[12.233,-3.905],[5.637,4.126],[1.747,-2.402],[8.343,-10.434]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[16.089,-2.774],[8.46,4.795],[4.774,-1.981],[12.403,-9.55]],"c":true}]},{"t":212,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[12.233,-3.905],[5.637,4.126],[1.747,-2.402],[8.343,-10.434]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[248.761,357.29]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[14.457,-0.622],[7.861,7.409],[3.971,0.881],[10.567,-7.151]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0.927,-3.364],[3.593,0],[-0.927,3.364],[-3.593,0]],"o":[[-0.927,3.364],[-3.593,0],[0.927,-3.364],[3.593,0]],"v":[[6.728,0],[-1.457,6.091],[-6.283,0],[1.902,-6.091]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[6.728,-1.995],[-1.457,4.578],[-6.283,-1.995],[1.902,-8.568]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[6.728,-1.995],[-1.457,4.578],[-6.283,-1.995],[1.902,-8.568]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[14.457,-0.622],[7.861,7.409],[3.971,0.881],[10.567,-7.151]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[16.553,-0.443],[8.924,7.126],[5.239,0.351],[12.867,-7.219]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[14.457,-0.622],[7.861,7.409],[3.971,0.881],[10.567,-7.151]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[14.457,-0.622],[7.861,7.409],[3.971,0.881],[10.567,-7.151]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[16.553,-0.443],[8.924,7.126],[5.239,0.351],[12.867,-7.219]],"c":true}]},{"t":212,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[14.457,-0.622],[7.861,7.409],[3.971,0.881],[10.567,-7.151]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[232.782,365.318]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[13.88,-3.757],[7.284,4.274],[3.394,-2.254],[9.99,-10.286]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0.927,-3.364],[3.593,0],[-0.927,3.364],[-3.593,0]],"o":[[-0.927,3.364],[-3.593,0],[0.927,-3.364],[3.593,0]],"v":[[7.009,0],[-1.175,6.091],[-6.001,0],[2.183,-6.091]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[7.009,-3.266],[-1.175,3.307],[-6.001,-3.266],[2.183,-9.839]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0.927,-3.63],[3.593,0],[-0.927,3.63],[-3.593,0]],"o":[[-0.927,3.63],[-3.593,0],[0.927,-3.63],[3.593,0]],"v":[[7.009,-3.266],[-1.175,3.307],[-6.001,-3.266],[2.183,-9.839]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[13.88,-3.757],[7.284,4.274],[3.394,-2.254],[9.99,-10.286]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[17.605,-3.294],[9.977,4.275],[6.291,-2.501],[13.919,-10.07]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[13.88,-3.757],[7.284,4.274],[3.394,-2.254],[9.99,-10.286]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[13.88,-3.757],[7.284,4.274],[3.394,-2.254],[9.99,-10.286]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[1.089,-3.961],[3.124,-0.219],[-1.089,3.961],[-3.124,0.219]],"o":[[-1.089,3.961],[-3.124,0.219],[1.089,-3.961],[3.124,-0.219]],"v":[[17.605,-3.294],[9.977,4.275],[6.291,-2.501],[13.919,-10.07]],"c":true}]},{"t":212,"s":[{"i":[[0.747,-4.021],[2.896,-0.415],[-0.747,4.021],[-2.896,0.415]],"o":[[-0.747,4.021],[-2.896,0.415],[0.747,-4.021],[2.896,-0.415]],"v":[[13.88,-3.757],[7.284,4.274],[3.394,-2.254],[9.99,-10.286]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[236.927,349.261]},"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":"tr","p":{"a":0,"k":[236.927,349.261]},"a":{"a":0,"k":[236.927,349.261]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[0.969,1.552],[-0.456,2.448],[0,0],[-3.337,0.478],[0,0],[-0.969,-1.552],[0.456,-2.448],[0,0],[3.337,-0.478]],"o":[[-1.725,0.247],[-0.999,-1.6],[0,0],[0.857,-4.603],[0,0],[1.725,-0.247],[0.999,1.6],[0,0],[-0.857,4.603],[0,0]],"v":[[-5.369,20.908],[-9.608,18.855],[-10.463,12.486],[-5.632,-13.5],[1.846,-22.56],[21.434,-25.367],[25.673,-23.315],[26.528,-16.946],[21.698,9.04],[14.219,18.1]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0,0],[1.202,1.453],[-0.565,2.048],[0,0],[-4.141,0],[0,0],[-1.202,-1.453],[0.565,-2.048],[0,0],[4.141,0]],"o":[[-2.14,0],[-1.239,-1.498],[0,0],[1.063,-3.851],[0,0],[2.14,0],[1.239,1.498],[0,0],[-1.063,3.851],[0,0]],"v":[[-15.828,18.237],[-21.086,15.951],[-22.147,10.371],[-16.154,-11.371],[-6.876,-18.237],[17.427,-18.237],[22.686,-15.951],[23.746,-10.371],[17.754,11.371],[8.475,18.237]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[0,0],[1.202,1.568],[-0.565,2.21],[0,0],[-4.141,0],[0,0],[-1.202,-1.568],[0.565,-2.21],[0,0],[4.141,0]],"o":[[-2.14,0],[-1.239,-1.617],[0,0],[1.063,-4.155],[0,0],[2.14,0],[1.239,1.617],[0,0],[-1.063,4.155],[0,0]],"v":[[-15.828,17.05],[-21.086,14.583],[-22.147,8.561],[-16.154,-14.901],[-6.876,-22.311],[17.427,-22.311],[22.686,-19.844],[23.746,-13.822],[17.754,9.64],[8.475,17.05]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0,0],[1.202,1.568],[-0.565,2.21],[0,0],[-4.141,0],[0,0],[-1.202,-1.568],[0.565,-2.21],[0,0],[4.141,0]],"o":[[-2.14,0],[-1.239,-1.617],[0,0],[1.063,-4.155],[0,0],[2.14,0],[1.239,1.617],[0,0],[-1.063,4.155],[0,0]],"v":[[-15.828,17.05],[-21.086,14.583],[-22.147,8.561],[-16.154,-14.901],[-6.876,-22.311],[17.427,-22.311],[22.686,-19.844],[23.746,-13.822],[17.754,9.64],[8.475,17.05]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[0,0],[0.969,1.552],[-0.456,2.448],[0,0],[-3.337,0.478],[0,0],[-0.969,-1.552],[0.456,-2.448],[0,0],[3.337,-0.478]],"o":[[-1.725,0.247],[-0.999,-1.6],[0,0],[0.857,-4.603],[0,0],[1.725,-0.247],[0.999,1.6],[0,0],[-0.857,4.603],[0,0]],"v":[[-5.369,20.908],[-9.608,18.855],[-10.463,12.486],[-5.632,-13.5],[1.846,-22.56],[21.434,-25.367],[25.673,-23.315],[26.528,-16.946],[21.698,9.04],[14.219,18.1]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[0,0],[0.923,1.613],[-0.663,2.412],[0,0],[-3.601,0.253],[0,0],[-0.923,-1.613],[0.663,-2.412],[0,0],[3.601,-0.253]],"o":[[-1.861,0.131],[-0.952,-1.663],[0,0],[1.247,-4.534],[0,0],[1.861,-0.131],[0.952,1.663],[0,0],[-1.247,4.534],[0,0]],"v":[[-5.025,20.293],[-9.407,17.96],[-9.861,11.547],[-2.825,-14.054],[5.82,-22.59],[26.955,-24.072],[31.337,-21.739],[31.791,-15.327],[24.755,10.275],[16.11,18.811]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0,0],[0.969,1.552],[-0.456,2.448],[0,0],[-3.337,0.478],[0,0],[-0.969,-1.552],[0.456,-2.448],[0,0],[3.337,-0.478]],"o":[[-1.725,0.247],[-0.999,-1.6],[0,0],[0.857,-4.603],[0,0],[1.725,-0.247],[0.999,1.6],[0,0],[-0.857,4.603],[0,0]],"v":[[-5.369,20.908],[-9.608,18.855],[-10.463,12.486],[-5.632,-13.5],[1.846,-22.56],[21.434,-25.367],[25.673,-23.315],[26.528,-16.946],[21.698,9.04],[14.219,18.1]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[0,0],[0.969,1.552],[-0.456,2.448],[0,0],[-3.337,0.478],[0,0],[-0.969,-1.552],[0.456,-2.448],[0,0],[3.337,-0.478]],"o":[[-1.725,0.247],[-0.999,-1.6],[0,0],[0.857,-4.603],[0,0],[1.725,-0.247],[0.999,1.6],[0,0],[-0.857,4.603],[0,0]],"v":[[-5.369,20.908],[-9.608,18.855],[-10.463,12.486],[-5.632,-13.5],[1.846,-22.56],[21.434,-25.367],[25.673,-23.315],[26.528,-16.946],[21.698,9.04],[14.219,18.1]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[0,0],[0.923,1.613],[-0.663,2.412],[0,0],[-3.601,0.253],[0,0],[-0.923,-1.613],[0.663,-2.412],[0,0],[3.601,-0.253]],"o":[[-1.861,0.131],[-0.952,-1.663],[0,0],[1.247,-4.534],[0,0],[1.861,-0.131],[0.952,1.663],[0,0],[-1.247,4.534],[0,0]],"v":[[-5.025,20.293],[-9.407,17.96],[-9.861,11.547],[-2.825,-14.054],[5.82,-22.59],[26.955,-24.072],[31.337,-21.739],[31.791,-15.327],[24.755,10.275],[16.11,18.811]],"c":true}]},{"t":212,"s":[{"i":[[0,0],[0.969,1.552],[-0.456,2.448],[0,0],[-3.337,0.478],[0,0],[-0.969,-1.552],[0.456,-2.448],[0,0],[3.337,-0.478]],"o":[[-1.725,0.247],[-0.999,-1.6],[0,0],[0.857,-4.603],[0,0],[1.725,-0.247],[0.999,1.6],[0,0],[-0.857,4.603],[0,0]],"v":[[-5.369,20.908],[-9.608,18.855],[-10.463,12.486],[-5.632,-13.5],[1.846,-22.56],[21.434,-25.367],[25.673,-23.315],[26.528,-16.946],[21.698,9.04],[14.219,18.1]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.35686275363,0.556862771511,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":4},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[241.27,357.29]},"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":"tr","p":{"a":0,"k":[241.27,357.29]},"a":{"a":0,"k":[241.27,357.29]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[4.985,-0.714],[0,0],[1.261,-6.669],[0,0],[-4.985,0.714],[0,0],[-1.261,6.669],[0,0]],"o":[[0,0],[-4.963,0.711],[0,0],[-1.267,6.698],[0,0],[4.963,-0.711],[0,0],[1.267,-6.698]],"v":[[38.102,-69.567],[-1.981,-63.822],[-12.545,-51.297],[-33.662,60.37],[-26.307,72.206],[13.776,66.461],[24.34,53.936],[45.458,-57.731]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[6.185,0],[0,0],[1.565,-5.577],[0,0],[-6.185,0],[0,0],[-1.565,5.577],[0,0]],"o":[[0,0],[-6.158,0],[0,0],[-1.571,5.601],[0,0],[6.158,0],[0,0],[1.571,-5.601]],"v":[[40.852,-56.963],[-8.878,-56.963],[-21.984,-47.499],[-48.184,45.884],[-39.059,56.963],[10.672,56.963],[23.778,47.499],[49.978,-45.884]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[6.185,0],[0,0],[1.565,-6.018],[0,0],[-6.185,0],[0,0],[-1.565,6.018],[0,0]],"o":[[0,0],[-6.158,0],[0,0],[-1.571,6.044],[0,0],[6.158,0],[0,0],[1.571,-6.044]],"v":[[40.852,-61.365],[-8.878,-61.365],[-21.984,-51.151],[-48.184,49.625],[-39.059,61.581],[10.672,61.581],[23.778,51.367],[49.978,-49.408]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[6.185,0],[0,0],[1.565,-6.018],[0,0],[-6.185,0],[0,0],[-1.565,6.018],[0,0]],"o":[[0,0],[-6.158,0],[0,0],[-1.571,6.044],[0,0],[6.158,0],[0,0],[1.571,-6.044]],"v":[[40.852,-61.365],[-8.878,-61.365],[-21.984,-51.151],[-48.184,49.625],[-39.059,61.581],[10.672,61.581],[23.778,51.367],[49.978,-49.408]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[4.985,-0.714],[0,0],[1.261,-6.669],[0,0],[-4.985,0.714],[0,0],[-1.261,6.669],[0,0]],"o":[[0,0],[-4.963,0.711],[0,0],[-1.267,6.698],[0,0],[4.963,-0.711],[0,0],[1.267,-6.698]],"v":[[38.102,-69.567],[-1.981,-63.822],[-12.545,-51.297],[-33.662,60.37],[-26.307,72.206],[13.776,66.461],[24.34,53.936],[45.458,-57.731]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[5.379,-0.377],[0,0],[1.829,-6.569],[0,0],[-5.379,0.377],[0,0],[-1.829,6.569],[0,0]],"o":[[0,0],[-5.355,0.376],[0,0],[-1.837,6.597],[0,0],[5.355,-0.376],[0,0],[1.837,-6.597]],"v":[[45.558,-67.031],[2.31,-63.999],[-9.883,-52.214],[-40.503,57.779],[-33.496,70.082],[9.752,67.05],[21.944,55.265],[52.565,-54.727]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[4.985,-0.714],[0,0],[1.261,-6.669],[0,0],[-4.985,0.714],[0,0],[-1.261,6.669],[0,0]],"o":[[0,0],[-4.963,0.711],[0,0],[-1.267,6.698],[0,0],[4.963,-0.711],[0,0],[1.267,-6.698]],"v":[[38.102,-69.567],[-1.981,-63.822],[-12.545,-51.297],[-33.662,60.37],[-26.307,72.206],[13.776,66.461],[24.34,53.936],[45.458,-57.731]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[4.985,-0.714],[0,0],[1.261,-6.669],[0,0],[-4.985,0.714],[0,0],[-1.261,6.669],[0,0]],"o":[[0,0],[-4.963,0.711],[0,0],[-1.267,6.698],[0,0],[4.963,-0.711],[0,0],[1.267,-6.698]],"v":[[38.102,-69.567],[-1.981,-63.822],[-12.545,-51.297],[-33.662,60.37],[-26.307,72.206],[13.776,66.461],[24.34,53.936],[45.458,-57.731]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[5.379,-0.377],[0,0],[1.829,-6.569],[0,0],[-5.379,0.377],[0,0],[-1.829,6.569],[0,0]],"o":[[0,0],[-5.355,0.376],[0,0],[-1.837,6.597],[0,0],[5.355,-0.376],[0,0],[1.837,-6.597]],"v":[[45.558,-67.031],[2.31,-63.999],[-9.883,-52.214],[-40.503,57.779],[-33.496,70.082],[9.752,67.05],[21.944,55.265],[52.565,-54.727]],"c":true}]},{"t":212,"s":[{"i":[[4.985,-0.714],[0,0],[1.261,-6.669],[0,0],[-4.985,0.714],[0,0],[-1.261,6.669],[0,0]],"o":[[0,0],[-4.963,0.711],[0,0],[-1.267,6.698],[0,0],[4.963,-0.711],[0,0],[1.267,-6.698]],"v":[[38.102,-69.567],[-1.981,-63.822],[-12.545,-51.297],[-33.662,60.37],[-26.307,72.206],[13.776,66.461],[24.34,53.936],[45.458,-57.731]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.560784339905,0.792156875134,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[242.701,391.881]},"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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[2.605,1.088],[2.09,-0.299],[0,0],[1.496,-5.807],[0,0],[-1.491,-1.641],[-2.581,-1.529],[-2.445,0.35],[0,0],[-1.261,6.669],[0,0],[1.125,2.058]],"o":[[-1.974,-0.824],[0,0],[-4.963,0.711],[0,0],[-0.289,3.63],[2.088,2.297],[2.696,1.597],[0,0],[4.963,-0.711],[0,0],[0.56,-2.961],[-1.544,-2.826]],"v":[[38.697,-69.505],[32.711,-70.732],[-7.373,-64.988],[-18.171,-53.324],[-39.288,58.344],[-38.358,66.667],[-31.122,71.679],[-24.936,73.916],[15.148,68.171],[25.711,55.646],[46.829,-56.021],[45.937,-63.907]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[2.238,2.384],[2.593,0],[0,0],[1.856,-4.807],[0,0],[-1.245,-1.823],[-1.95,-2.39],[-3.034,0],[0,0],[-1.565,5.577],[0,0],[1.395,1.908]],"o":[[-1.547,-1.648],[0,0],[-6.158,0],[0,0],[-0.358,3.084],[1.73,2.534],[1.662,2.037],[0,0],[6.158,0],[0,0],[0.695,-2.476],[-1.915,-2.619]],"v":[[46.071,-55.83],[39.51,-58.329],[-10.22,-58.329],[-23.618,-49.634],[-49.818,43.749],[-48.663,51.017],[-45.146,55.001],[-37.784,58.329],[11.946,58.329],[25.053,48.864],[51.253,-44.518],[50.146,-51.406]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":88,"s":[{"i":[[1.422,1.19],[2.593,0],[0,0],[1.856,-5.188],[0,0],[-1.239,-1.971],[-1.952,-1.769],[-3.034,0],[0,0],[-1.565,6.018],[0,0],[1.395,2.059]],"o":[[-1.583,-1.071],[0,0],[-6.158,0],[0,0],[-0.358,3.329],[1.043,1.603],[2.194,1.878],[0,0],[6.158,0],[0,0],[0.695,-2.672],[-1.915,-2.826]],"v":[[45.835,-59.595],[39.51,-61.491],[-10.22,-61.491],[-23.618,-52.108],[-49.818,48.668],[-48.663,56.512],[-44.791,60.119],[-37.784,62.947],[11.946,62.947],[25.053,52.733],[51.253,-48.042],[50.146,-55.476]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[1.422,1.19],[2.593,0],[0,0],[1.856,-5.188],[0,0],[-1.239,-1.971],[-1.952,-1.769],[-3.034,0],[0,0],[-1.565,6.018],[0,0],[1.395,2.059]],"o":[[-1.583,-1.071],[0,0],[-6.158,0],[0,0],[-0.358,3.328],[1.043,1.603],[2.194,1.878],[0,0],[6.158,0],[0,0],[0.695,-2.672],[-1.915,-2.826]],"v":[[45.835,-59.595],[39.51,-61.491],[-10.22,-61.491],[-23.618,-52.108],[-49.818,48.668],[-48.663,56.512],[-44.791,60.119],[-37.784,62.947],[11.946,62.947],[25.053,52.733],[51.253,-48.042],[50.146,-55.476]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[2.605,1.088],[2.09,-0.299],[0,0],[1.496,-5.807],[0,0],[-1.491,-1.641],[-2.581,-1.529],[-2.445,0.35],[0,0],[-1.261,6.669],[0,0],[1.125,2.058]],"o":[[-1.974,-0.824],[0,0],[-4.963,0.711],[0,0],[-0.289,3.63],[2.088,2.297],[2.696,1.597],[0,0],[4.963,-0.711],[0,0],[0.56,-2.961],[-1.544,-2.826]],"v":[[38.697,-69.505],[32.711,-70.732],[-7.373,-64.988],[-18.171,-53.324],[-39.288,58.344],[-38.358,66.667],[-31.122,71.679],[-24.936,73.916],[15.148,68.171],[25.711,55.646],[46.829,-56.021],[45.937,-63.907]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":134,"s":[{"i":[[2.705,1.261],[2.255,-0.158],[0,0],[2.017,-5.693],[0,0],[-1.475,-1.738],[-2.648,-1.699],[-2.638,0.185],[0,0],[-1.829,6.569],[0,0],[1.053,2.129]],"o":[[-2.05,-0.955],[0,0],[-5.355,0.376],[0,0],[-0.57,3.602],[2.066,2.432],[2.766,1.775],[0,0],[5.355,-0.376],[0,0],[0.812,-2.916],[-1.446,-2.923]],"v":[[47.296,-69.573],[40.987,-71.201],[-2.262,-68.168],[-14.643,-57.258],[-45.263,52.734],[-44.869,61.1],[-38.593,69.15],[-32.143,71.798],[11.105,68.766],[23.297,56.981],[53.918,-53.011],[53.533,-60.939]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[2.605,1.088],[2.09,-0.299],[0,0],[1.496,-5.807],[0,0],[-1.491,-1.641],[-2.581,-1.529],[-2.445,0.35],[0,0],[-1.261,6.669],[0,0],[1.125,2.058]],"o":[[-1.974,-0.824],[0,0],[-4.963,0.711],[0,0],[-0.289,3.63],[2.088,2.297],[2.696,1.597],[0,0],[4.963,-0.711],[0,0],[0.56,-2.961],[-1.544,-2.826]],"v":[[38.697,-69.505],[32.711,-70.732],[-7.373,-64.988],[-18.171,-53.324],[-39.288,58.344],[-38.358,66.667],[-31.122,71.679],[-24.936,73.916],[15.148,68.171],[25.711,55.646],[46.829,-56.021],[45.937,-63.907]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":184,"s":[{"i":[[2.605,1.088],[2.09,-0.299],[0,0],[1.496,-5.807],[0,0],[-1.491,-1.641],[-2.581,-1.529],[-2.445,0.35],[0,0],[-1.261,6.669],[0,0],[1.125,2.058]],"o":[[-1.974,-0.824],[0,0],[-4.963,0.711],[0,0],[-0.289,3.63],[2.088,2.297],[2.696,1.597],[0,0],[4.963,-0.711],[0,0],[0.56,-2.961],[-1.544,-2.826]],"v":[[38.697,-69.505],[32.711,-70.732],[-7.373,-64.988],[-18.171,-53.324],[-39.288,58.344],[-38.358,66.667],[-31.122,71.679],[-24.936,73.916],[15.148,68.171],[25.711,55.646],[46.829,-56.021],[45.937,-63.907]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[2.705,1.261],[2.255,-0.158],[0,0],[2.017,-5.693],[0,0],[-1.475,-1.738],[-2.648,-1.699],[-2.638,0.185],[0,0],[-1.829,6.569],[0,0],[1.053,2.129]],"o":[[-2.05,-0.955],[0,0],[-5.355,0.376],[0,0],[-0.57,3.602],[2.066,2.432],[2.766,1.775],[0,0],[5.355,-0.376],[0,0],[0.812,-2.916],[-1.446,-2.923]],"v":[[47.296,-69.573],[40.987,-71.201],[-2.262,-68.168],[-14.643,-57.258],[-45.263,52.734],[-44.869,61.1],[-38.593,69.15],[-32.143,71.798],[11.105,68.766],[23.297,56.981],[53.918,-53.011],[53.533,-60.939]],"c":true}]},{"t":212,"s":[{"i":[[2.605,1.088],[2.09,-0.299],[0,0],[1.496,-5.807],[0,0],[-1.491,-1.641],[-2.581,-1.529],[-2.445,0.35],[0,0],[-1.261,6.669],[0,0],[1.125,2.058]],"o":[[-1.974,-0.824],[0,0],[-4.963,0.711],[0,0],[-0.289,3.63],[2.088,2.297],[2.696,1.597],[0,0],[4.963,-0.711],[0,0],[0.56,-2.961],[-1.544,-2.826]],"v":[[38.697,-69.505],[32.711,-70.732],[-7.373,-64.988],[-18.171,-53.324],[-39.288,58.344],[-38.358,66.667],[-31.122,71.679],[-24.936,73.916],[15.148,68.171],[25.711,55.646],[46.829,-56.021],[45.937,-63.907]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0.35686275363,0.556862771511,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":16},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.35686275363,0.556862771511,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[241.426,390.515]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Layer 31 copy 3","parent":8,"sr":1,"ks":{"p":{"a":0,"k":[393.747,389.827,0]},"a":{"a":0,"k":[384.389,390.413,0]},"s":{"a":0,"k":[100.017,100.017,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-5.256,0]],"o":[[0,-5.256],[0,0]],"v":[[-4.758,4.758],[4.758,-4.758]],"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":4},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[385.027,376.374]},"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,8.513],[0,0],[-8.726,0]],"o":[[0,0],[0,-8.726],[0,0]],"v":[[-7.9,14.518],[-7.9,1.282],[7.9,-14.518]],"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":4},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[376.375,352.89]},"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,5.256],[0,0],[-5.256,0],[0,0],[0,-5.256],[0,0],[0,0],[8.513,0],[0,0],[0,8.513],[0,0],[-8.726,0],[0,0],[0,-8.726]],"o":[[0,0],[0,-5.256],[0,0],[5.256,0],[0,0],[0,0],[0,8.513],[0,0],[-8.513,0],[0,0],[0,-8.726],[0,0],[8.726,0],[0,0]],"v":[[-4.006,21.249],[-4.006,-8.78],[5.511,-18.297],[5.511,-18.297],[15.028,-8.78],[15.028,14.129],[15.028,36.127],[-0.386,51.541],[-0.386,51.541],[-15.799,36.127],[-15.799,-35.742],[0,-51.541],[0,-51.541],[15.799,-35.742]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.68235296011,0.729411780834,0.721568644047,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":4},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[384.275,389.913]},"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":"tr","p":{"a":0,"k":[384.275,389.913]},"a":{"a":0,"k":[384.275,389.913]},"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,5.256],[0,0],[-5.256,0],[0,0],[0,-5.256],[0,0],[0,0],[8.513,0],[0,0],[0,8.513],[0,0]],"o":[[0,0],[0,-5.256],[0,0],[5.256,0],[0,0],[0,0],[0,8.513],[0,0],[-8.513,0],[0,0],[0,0]],"v":[[-3.62,13.349],[-3.62,-16.68],[5.897,-26.197],[5.897,-26.197],[15.414,-16.68],[15.414,6.23],[15.414,28.228],[0,43.641],[0,43.641],[-15.414,28.228],[-15.414,-43.641]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.478431373835,0.537254929543,0.529411792755,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":9},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[384.889,398.812]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Layer 5","parent":5,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[390.7,409.983,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,5.256],[0,0],[-5.256,0],[0,0],[0,-5.256],[0,0],[0,0],[8.513,0],[0,0],[0,8.513],[0,0]],"o":[[0,0],[0,-5.256],[0,0],[5.256,0],[0,0],[0,0],[0,8.513],[0,0],[-8.513,0],[0,0],[0,0]],"v":[[-3.62,8.62],[-3.62,-21.409],[5.897,-30.926],[5.897,-30.926],[15.414,-21.409],[15.414,1.501],[15.414,23.499],[0,38.912],[0,38.912],[-15.414,23.499],[-15.414,-38.912]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":9},"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":300,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Layer 31 copy 2","parent":8,"sr":1,"ks":{"p":{"a":0,"k":[433.308,426.356,0]},"a":{"a":0,"k":[416.693,427.185,0]},"s":{"a":0,"k":[100.017,100.017,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[2.719,-2.719],[0,0],[0,0],[2.719,-2.719],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[-2.719,-2.719],[0,0],[0,0],[0,0],[0,0],[-2.719,-2.719]],"v":[[5.265,-18.1],[-14.305,1.469],[-19.616,-3.842],[-29.464,-3.842],[-53.353,20.047],[-53.353,20.14],[53.353,20.14],[15.112,-18.1]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.301960796118,0.352941185236,0.435294121504,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[416.69,447.371]},"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,-5.95],[5.95,0],[0,5.95],[-5.95,0]],"o":[[0,5.95],[-5.95,0],[0,-5.95],[5.95,0]],"v":[[10.773,0],[0,10.773],[-10.773,0],[0,-10.773]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333337307,0.780392169952,0.51372551918,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[444.369,408.674]},"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],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[53.356,-40.326],[53.356,40.326],[-53.356,40.326],[-53.356,-40.326]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.454901963472,0.674509823322,0.803921580315,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[416.693,427.185]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"fr3","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[10]},{"t":152,"s":[-10]}]},"p":{"a":1,"k":[{"i":{"x":0.189,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[241.593,389.067,0],"to":[40.407,-10.067,0],"ti":[2.407,177.933,0]},{"t":150,"s":[340.593,137.067,0],"h":1}]},"a":{"a":0,"k":[443.032,410.108,0]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":105,"s":[150,150,100]},{"t":150,"s":[0,0,100],"h":1}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-6.53],[0,0],[-6.53,0],[0,0],[0,6.53],[0,0],[0,0],[0,0],[0,0],[6.53,0],[0,0]],"o":[[0,0],[0,6.53],[0,0],[6.53,0],[0,0],[0,0],[0,0],[0,0],[0,-6.53],[0,0],[-6.53,0]],"v":[[-77.159,-41.835],[-77.159,41.835],[-65.335,53.658],[45.791,53.658],[57.615,41.835],[57.615,7.107],[77.159,-12.438],[57.615,-12.438],[57.615,-41.835],[45.791,-53.658],[-65.335,-53.658]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":106,"s":[5]},{"t":150,"s":[6],"h":1}]},"lc":2,"lj":2,"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":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":106,"s":[10]},{"t":150,"s":[14],"h":1}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 2","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":"tr","p":{"a":0,"k":[443.032,427.185]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Layer 4","parent":5,"sr":1,"ks":{"p":{"a":0,"k":[385.275,366.704,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-8.726,0],[0,0],[0,-8.726],[0,0]],"o":[[0,-8.726],[0,0],[8.726,0],[0,0],[0,0]],"v":[[-15.799,-11.533],[0,-27.332],[0,-27.332],[15.799,-11.533],[15.799,27.332]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.478431373835,0.537254929543,0.529411792755,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":9},"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":300,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"grl","parent":11,"sr":1,"ks":{"p":{"a":0,"k":[-2.69,-10.125,0]},"a":{"a":0,"k":[623.274,533.285,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,2.418],[-0.081,2.996],[-2.977,2.519],[0.081,1.942]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,2.418],[-0.081,2.996],[-2.977,2.519],[0.081,1.942]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,2.418],[-0.081,2.996],[-2.977,2.519],[0.081,1.942]],"c":true}]},{"t":204,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"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":"Group 1","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[326.847,240.985]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,1.937],[-0.081,2.515],[-2.977,2.038],[0.081,1.461]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,1.937],[-0.081,2.515],[-2.977,2.038],[0.081,1.461]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[0.045,-0.291],[1.644,-0.028],[-0.045,0.291],[-1.644,0.028]],"o":[[-0.045,0.291],[-1.644,0.028],[0.045,-0.291],[1.644,-0.028]],"v":[[2.977,1.937],[-0.081,2.515],[-2.977,2.038],[0.081,1.461]],"c":true}]},{"t":204,"s":[{"i":[[0.045,-1.334],[1.644,-0.127],[-0.045,1.334],[-1.644,0.127]],"o":[[-0.045,1.334],[-1.644,0.127],[0.045,-1.334],[1.644,-0.127]],"v":[[2.977,-0.231],[-0.081,2.415],[-2.977,0.231],[0.081,-2.415]],"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":"Group 1","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[298.654,241.6]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.765,0],[0.048,0.005],[0,0],[0.144,0.631],[-0.555,0.334],[0,0],[-0.428,-0.71],[0.71,-0.428],[0,0],[0,0],[0.078,-0.824]],"o":[[-0.048,0],[0,0],[-0.645,-0.062],[-0.144,-0.631],[0,0],[0.707,-0.429],[0.428,0.709],[0,0],[0,0],[0.825,0.078],[-0.074,0.776]],"v":[[3.852,3.953],[3.708,3.946],[-3.991,3.214],[-5.312,2.053],[-4.624,0.436],[2.297,-3.737],[4.356,-3.227],[3.846,-1.168],[0.819,0.658],[3.991,0.96],[5.343,2.594]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[0.758,-0.098],[0.048,-0.001],[0,0],[0.223,0.607],[-0.507,0.402],[0,0],[-0.515,-0.649],[0.649,-0.515],[0,0],[0,0],[-0.028,-0.827]],"o":[[-0.047,0.006],[0,0],[-0.647,0.022],[-0.223,-0.607],[0,0],[0.646,-0.516],[0.515,0.648],[0,0],[0,0],[0.828,-0.028],[0.026,0.779]],"v":[[4.333,3.292],[4.189,3.304],[-3.54,3.566],[-4.999,2.585],[-4.524,0.893],[1.804,-4.134],[3.911,-3.893],[3.67,-1.786],[0.902,0.414],[4.087,0.306],[5.637,1.754]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[0.765,0],[0.048,0.005],[0,0],[0.144,0.631],[-0.555,0.334],[0,0],[-0.428,-0.71],[0.71,-0.428],[0,0],[0,0],[0.078,-0.824]],"o":[[-0.048,0],[0,0],[-0.645,-0.062],[-0.144,-0.631],[0,0],[0.707,-0.429],[0.428,0.709],[0,0],[0,0],[0.825,0.078],[-0.074,0.776]],"v":[[3.852,3.953],[3.708,3.946],[-3.991,3.214],[-5.312,2.053],[-4.624,0.436],[2.297,-3.737],[4.356,-3.227],[3.846,-1.168],[0.819,0.658],[3.991,0.96],[5.343,2.594]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[0.758,-0.098],[0.048,-0.001],[0,0],[0.223,0.607],[-0.507,0.402],[0,0],[-0.515,-0.649],[0.649,-0.515],[0,0],[0,0],[-0.028,-0.827]],"o":[[-0.047,0.006],[0,0],[-0.647,0.022],[-0.223,-0.607],[0,0],[0.646,-0.516],[0.515,0.648],[0,0],[0,0],[0.828,-0.028],[0.026,0.779]],"v":[[4.333,3.292],[4.189,3.304],[-3.54,3.566],[-4.999,2.585],[-4.524,0.893],[1.804,-4.134],[3.911,-3.893],[3.67,-1.786],[0.902,0.414],[4.087,0.306],[5.637,1.754]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[0.765,0],[0.048,0.005],[0,0],[0.144,0.631],[-0.555,0.334],[0,0],[-0.428,-0.71],[0.71,-0.428],[0,0],[0,0],[0.078,-0.824]],"o":[[-0.048,0],[0,0],[-0.645,-0.062],[-0.144,-0.631],[0,0],[0.707,-0.429],[0.428,0.709],[0,0],[0,0],[0.825,0.078],[-0.074,0.776]],"v":[[3.852,3.953],[3.708,3.946],[-3.991,3.214],[-5.312,2.053],[-4.624,0.436],[2.297,-3.737],[4.356,-3.227],[3.846,-1.168],[0.819,0.658],[3.991,0.96],[5.343,2.594]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[0.765,0],[0.048,0.005],[0,0],[0.144,0.631],[-0.555,0.334],[0,0],[-0.428,-0.71],[0.71,-0.428],[0,0],[0,0],[0.078,-0.824]],"o":[[-0.048,0],[0,0],[-0.645,-0.062],[-0.144,-0.631],[0,0],[0.707,-0.429],[0.428,0.709],[0,0],[0,0],[0.825,0.078],[-0.074,0.776]],"v":[[3.852,3.953],[3.708,3.946],[-3.991,3.214],[-5.312,2.053],[-4.624,0.436],[2.297,-3.737],[4.356,-3.227],[3.846,-1.168],[0.819,0.658],[3.991,0.96],[5.343,2.594]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[0.758,-0.098],[0.048,-0.001],[0,0],[0.223,0.607],[-0.507,0.402],[0,0],[-0.515,-0.649],[0.649,-0.515],[0,0],[0,0],[-0.028,-0.827]],"o":[[-0.047,0.006],[0,0],[-0.647,0.022],[-0.223,-0.607],[0,0],[0.646,-0.516],[0.515,0.648],[0,0],[0,0],[0.828,-0.028],[0.026,0.779]],"v":[[4.333,3.292],[4.189,3.304],[-3.54,3.566],[-4.999,2.585],[-4.524,0.893],[1.804,-4.134],[3.911,-3.893],[3.67,-1.786],[0.902,0.414],[4.087,0.306],[5.637,1.754]],"c":true}]},{"t":204,"s":[{"i":[[0.765,0],[0.048,0.005],[0,0],[0.144,0.631],[-0.555,0.334],[0,0],[-0.428,-0.71],[0.71,-0.428],[0,0],[0,0],[0.078,-0.824]],"o":[[-0.048,0],[0,0],[-0.645,-0.062],[-0.144,-0.631],[0,0],[0.707,-0.429],[0.428,0.709],[0,0],[0,0],[0.825,0.078],[-0.074,0.776]],"v":[[3.852,3.953],[3.708,3.946],[-3.991,3.214],[-5.312,2.053],[-4.624,0.436],[2.297,-3.737],[4.356,-3.227],[3.846,-1.168],[0.819,0.658],[3.991,0.96],[5.343,2.594]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[335.385,243.182]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[0.126,0],[0.177,0.674],[-0.801,0.21],[0,0],[0,0],[-0.319,0.765],[-0.768,-0.32],[0,0],[0.045,-0.642],[0.622,-0.163],[0,0]],"o":[[-0.666,0],[-0.21,-0.802],[0,0],[0,0],[-0.765,-0.318],[0.319,-0.763],[0,0],[0.594,0.247],[-0.045,0.642],[0,0],[-0.127,0.033]],"v":[[-3.576,3.835],[-5.027,2.715],[-3.955,0.884],[-1.101,0.137],[-3.707,-0.951],[-4.513,-2.913],[-2.551,-3.719],[4.154,-0.92],[5.072,0.569],[3.956,1.915],[-3.195,3.786]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[0.12,0.038],[-0.033,0.696],[-0.827,-0.039],[0,0],[0,0],[-0.534,0.634],[-0.637,-0.535],[0,0],[0.235,-0.599],[0.642,0.031],[0,0]],"o":[[-0.635,-0.199],[0.04,-0.828],[0,0],[0,0],[-0.634,-0.533],[0.533,-0.632],[0,0],[0.493,0.414],[-0.235,0.599],[0,0],[-0.131,-0.006]],"v":[[-4.594,2.602],[-5.642,1.099],[-4.072,-0.327],[-1.125,-0.186],[-3.286,-2.004],[-3.467,-4.117],[-1.354,-4.298],[4.206,0.379],[4.636,2.074],[3.168,3.025],[-4.216,2.669]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[0.126,0],[0.177,0.674],[-0.801,0.21],[0,0],[0,0],[-0.319,0.765],[-0.768,-0.32],[0,0],[0.045,-0.642],[0.622,-0.163],[0,0]],"o":[[-0.666,0],[-0.21,-0.802],[0,0],[0,0],[-0.765,-0.318],[0.319,-0.763],[0,0],[0.594,0.247],[-0.045,0.642],[0,0],[-0.127,0.033]],"v":[[-3.576,3.835],[-5.027,2.715],[-3.955,0.884],[-1.101,0.137],[-3.707,-0.951],[-4.513,-2.913],[-2.551,-3.719],[4.154,-0.92],[5.072,0.569],[3.956,1.915],[-3.195,3.786]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[0.12,0.038],[-0.033,0.696],[-0.827,-0.039],[0,0],[0,0],[-0.534,0.634],[-0.637,-0.535],[0,0],[0.235,-0.599],[0.642,0.031],[0,0]],"o":[[-0.635,-0.199],[0.04,-0.828],[0,0],[0,0],[-0.634,-0.533],[0.533,-0.632],[0,0],[0.493,0.414],[-0.235,0.599],[0,0],[-0.131,-0.006]],"v":[[-4.594,2.602],[-5.642,1.099],[-4.072,-0.327],[-1.125,-0.186],[-3.286,-2.004],[-3.467,-4.117],[-1.354,-4.298],[4.206,0.379],[4.636,2.074],[3.168,3.025],[-4.216,2.669]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[0.126,0],[0.177,0.674],[-0.801,0.21],[0,0],[0,0],[-0.319,0.765],[-0.768,-0.32],[0,0],[0.045,-0.642],[0.622,-0.163],[0,0]],"o":[[-0.666,0],[-0.21,-0.802],[0,0],[0,0],[-0.765,-0.318],[0.319,-0.763],[0,0],[0.594,0.247],[-0.045,0.642],[0,0],[-0.127,0.033]],"v":[[-3.576,3.835],[-5.027,2.715],[-3.955,0.884],[-1.101,0.137],[-3.707,-0.951],[-4.513,-2.913],[-2.551,-3.719],[4.154,-0.92],[5.072,0.569],[3.956,1.915],[-3.195,3.786]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[0.126,0],[0.177,0.674],[-0.801,0.21],[0,0],[0,0],[-0.319,0.765],[-0.768,-0.32],[0,0],[0.045,-0.642],[0.622,-0.163],[0,0]],"o":[[-0.666,0],[-0.21,-0.802],[0,0],[0,0],[-0.765,-0.318],[0.319,-0.763],[0,0],[0.594,0.247],[-0.045,0.642],[0,0],[-0.127,0.033]],"v":[[-3.576,3.835],[-5.027,2.715],[-3.955,0.884],[-1.101,0.137],[-3.707,-0.951],[-4.513,-2.913],[-2.551,-3.719],[4.154,-0.92],[5.072,0.569],[3.956,1.915],[-3.195,3.786]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[0.12,0.038],[-0.033,0.696],[-0.827,-0.039],[0,0],[0,0],[-0.534,0.634],[-0.637,-0.535],[0,0],[0.235,-0.599],[0.642,0.031],[0,0]],"o":[[-0.635,-0.199],[0.04,-0.828],[0,0],[0,0],[-0.634,-0.533],[0.533,-0.632],[0,0],[0.493,0.414],[-0.235,0.599],[0,0],[-0.131,-0.006]],"v":[[-4.594,2.602],[-5.642,1.099],[-4.072,-0.327],[-1.125,-0.186],[-3.286,-2.004],[-3.467,-4.117],[-1.354,-4.298],[4.206,0.379],[4.636,2.074],[3.168,3.025],[-4.216,2.669]],"c":true}]},{"t":204,"s":[{"i":[[0.126,0],[0.177,0.674],[-0.801,0.21],[0,0],[0,0],[-0.319,0.765],[-0.768,-0.32],[0,0],[0.045,-0.642],[0.622,-0.163],[0,0]],"o":[[-0.666,0],[-0.21,-0.802],[0,0],[0,0],[-0.765,-0.318],[0.319,-0.763],[0,0],[0.594,0.247],[-0.045,0.642],[0,0],[-0.127,0.033]],"v":[[-3.576,3.835],[-5.027,2.715],[-3.955,0.884],[-1.101,0.137],[-3.707,-0.951],[-4.513,-2.913],[-2.551,-3.719],[4.154,-0.92],[5.072,0.569],[3.956,1.915],[-3.195,3.786]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[291.714,243.462]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.969,-0.687],[0,0],[-1.02,-0.671],[0,0],[-0.969,0.687],[0,0],[1.02,0.671],[0,0]],"o":[[0,0],[-0.969,0.687],[0,0],[1.02,0.671],[0,0],[0.969,-0.687],[0,0],[-1.02,-0.671]],"v":[[-1.966,-4.464],[-6.608,-1.177],[-6.517,1.281],[-1.636,4.493],[1.966,4.464],[6.608,1.177],[6.517,-1.281],[1.636,-4.493]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.945098042488,0.352941185236,0.141176477075,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},{"ty":"tr","p":{"a":0,"k":[312.565,254.105]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[-0.161,-1.465],[3.579,-0.01],[0.161,1.465],[-3.579,0.01]],"o":[[0.161,1.465],[-3.579,0.01],[-0.161,-1.465],[3.579,-0.01]],"v":[[6.48,-0.017],[0.291,2.653],[-6.48,0.017],[-0.291,-2.653]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[-0.161,-1.465],[3.579,-0.01],[0.161,1.465],[-3.579,0.01]],"o":[[0.161,1.465],[-3.579,0.01],[-0.161,-1.465],[3.579,-0.01]],"v":[[6.48,-0.017],[0.291,2.653],[-6.48,0.017],[-0.291,-2.653]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[-0.161,-1.465],[3.579,-0.01],[0.161,1.465],[-3.579,0.01]],"o":[[0.161,1.465],[-3.579,0.01],[-0.161,-1.465],[3.579,-0.01]],"v":[[6.48,-0.017],[0.291,2.653],[-6.48,0.017],[-0.291,-2.653]],"c":true}]},{"t":204,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[327.422,244.328]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":148,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153.834,"s":[{"i":[[-0.161,-1.321],[3.579,-0.009],[0.161,1.321],[-3.579,0.009]],"o":[[0.161,1.321],[-3.579,0.009],[-0.161,-1.321],[3.579,-0.009]],"v":[[6.48,-0.016],[0.291,2.392],[-6.48,0.016],[-0.291,-2.392]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":159.666,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":165.5,"s":[{"i":[[-0.161,-1.321],[3.579,-0.009],[0.161,1.321],[-3.579,0.009]],"o":[[0.161,1.321],[-3.579,0.009],[-0.161,-1.321],[3.579,-0.009]],"v":[[6.48,-0.016],[0.291,2.392],[-6.48,0.016],[-0.291,-2.392]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":171.334,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":192.334,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":198.166,"s":[{"i":[[-0.161,-1.321],[3.579,-0.009],[0.161,1.321],[-3.579,0.009]],"o":[[0.161,1.321],[-3.579,0.009],[-0.161,-1.321],[3.579,-0.009]],"v":[[6.48,-0.016],[0.291,2.392],[-6.48,0.016],[-0.291,-2.392]],"c":true}]},{"t":204,"s":[{"i":[[-0.161,-4.36],[3.579,-0.028],[0.161,4.36],[-3.579,0.028]],"o":[[0.161,4.36],[-3.579,0.028],[-0.161,-4.36],[3.579,-0.028]],"v":[[6.48,-0.052],[0.291,7.895],[-6.48,0.052],[-0.291,-7.895]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[299.162,244.553]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[3.997,1.037],[-0.474,-1.675],[0,0],[-1.289,0.925],[0,0],[0,0],[0.229,1.664],[0,0],[1.413,-0.814]],"o":[[-5.167,-2.07],[-1.702,-0.441],[0,0],[0.439,1.551],[0,0],[0,0],[1.61,0.567],[0,0],[-0.224,-1.631],[0,0]],"v":[[-0.115,-2.287],[-15.723,-7.197],[-18.444,-4.455],[-14.737,8.638],[-11.14,9.941],[1.207,1.082],[15.527,6.123],[18.511,3.753],[16.851,-8.326],[13.372,-10.059]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0.607843160629,0.878431379795,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},{"ty":"tr","p":{"a":0,"k":[310.287,221.893]},"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},{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-2.958,-15.455],[15.825,-2.01],[2.958,15.455],[-15.825,2.01]],"o":[[2.958,15.455],[-15.825,2.01],[-2.958,-15.455],[15.825,-2.01]],"v":[[28.683,-0.671],[3.59,24.817],[-28.625,6.61],[-5.327,-25.014]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.831372559071,0,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},{"ty":"tr","p":{"a":0,"k":[313.041,245.801]},"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":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[13.463,0.304],[3.569,-16.175],[8.726,22.117]],"o":[[-16.412,-0.371],[-4.698,21.292],[-5.826,-14.767]],"v":[[-0.627,-20.184],[-30.938,5.342],[30.441,2.378]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.831372559071,0,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},{"ty":"tr","p":{"a":0,"k":[312.87,279.194]},"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":"tr","p":{"a":0,"k":[312.87,279.194]},"a":{"a":0,"k":[312.87,279.194]},"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":"tr","p":{"a":0,"k":[312.87,279.194]},"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":"tr","p":{"a":0,"k":[312.87,279.194]},"a":{"a":0,"k":[312.87,279.194]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-38.659,52.387],[-38.659,-52.387],[38.659,-52.387],[38.659,52.387]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.831372559071,0.078431375325,0.352941185236,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},{"ty":"tr","p":{"a":0,"k":[625.524,533.285]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"fr2","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":158,"s":[5]},{"t":220,"s":[-10]}]},"p":{"a":1,"k":[{"i":{"x":0.189,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[241.593,389.067,0],"to":[40.407,-10.067,0],"ti":[2.407,177.933,0]},{"t":210,"s":[340.593,137.067,0],"h":1}]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":120,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":166,"s":[150,150,100]},{"t":210,"s":[0,0,100],"h":1}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[6.53,0],[0,0],[0,-6.53],[0,0],[-6.53,0],[0,0],[0,0],[0,0],[0,0],[0,6.53],[0,0]],"o":[[0,0],[-6.53,0],[0,0],[0,6.53],[0,0],[0,0],[0,0],[0,0],[6.53,0],[0,0],[0,-6.53]],"v":[[41.835,-77.159],[-41.835,-77.159],[-53.658,-65.335],[-53.658,45.791],[-41.835,57.615],[-7.107,57.615],[12.438,77.159],[12.438,57.615],[41.835,57.615],[53.658,45.791],[53.658,-65.335]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":166,"s":[5]},{"t":210,"s":[6],"h":1}]},"lc":2,"lj":2,"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":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":166,"s":[10]},{"t":210,"s":[14],"h":1}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 2","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":300,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"psi","parent":13,"sr":1,"ks":{"p":{"a":0,"k":[-8.477,0.779,0]},"a":{"a":0,"k":[240.555,427.964,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[{"i":[[0.755,0.64],[0,0],[0,0]],"o":[[-1.851,-1.57],[0,0],[0,0]],"v":[[5.227,-7.486],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0.988,-0.063],[0,0],[0,0]],"o":[[-2.423,0.154],[0,0],[0,0]],"v":[[-2.143,-12.157],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[{"i":[[-0.052,0.989],[0,0],[0,0]],"o":[[0.128,-2.424],[0,0],[0,0]],"v":[[8.44,1.204],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[{"i":[[0.988,-0.063],[0,0],[0,0]],"o":[[-2.423,0.154],[0,0],[0,0]],"v":[[-2.143,-12.157],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":56,"s":[{"i":[[0.755,0.64],[0,0],[0,0]],"o":[[-1.851,-1.57],[0,0],[0,0]],"v":[[5.227,-7.486],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":210,"s":[{"i":[[0.755,0.64],[0,0],[0,0]],"o":[[-1.851,-1.57],[0,0],[0,0]],"v":[[5.227,-7.486],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":216,"s":[{"i":[[0.988,-0.063],[0,0],[0,0]],"o":[[-2.423,0.154],[0,0],[0,0]],"v":[[-2.143,-12.157],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":222,"s":[{"i":[[-0.052,0.989],[0,0],[0,0]],"o":[[0.128,-2.424],[0,0],[0,0]],"v":[[8.44,1.204],[-5.398,0.646],[3.989,7.658]],"c":true}]},{"t":230,"s":[{"i":[[0.755,0.64],[0,0],[0,0]],"o":[[-1.851,-1.57],[0,0],[0,0]],"v":[[5.227,-7.486],[-5.398,0.646],[3.989,7.658]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.741176486015,0.858823537827,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},{"ty":"tr","p":{"a":0,"k":[259.56,412.034]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.67,0.729],[0,0],[0,0]],"o":[[1.643,-1.787],[0,0],[0,0]],"v":[[-5.734,-7.314],[5.814,-0.557],[-2.635,7.56]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.741176486015,0.858823537827,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},{"ty":"tr","p":{"a":0,"k":[211.546,415.518]},"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":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.074,0],[0.925,1.278],[-0.672,0.485],[-0.487,-0.672],[-0.344,0.041],[-0.293,0.533],[-0.725,-0.397],[0.399,-0.727],[1.386,-0.086]],"o":[[-1.308,0],[-0.485,-0.671],[0.67,-0.484],[0.356,0.492],[0.333,-0.021],[0.398,-0.728],[0.726,0.398],[-0.803,1.46],[-0.073,0.005]],"v":[[-0.035,2.331],[-3.53,0.335],[-3.193,-1.76],[-1.099,-1.423],[0.001,-0.67],[1,-1.554],[3.037,-2.146],[3.629,-0.108],[0.186,2.324]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[238.665,436.122]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0.074,0],[0.924,1.278],[-0.672,0.485],[-0.486,-0.673],[-0.332,0.007],[-0.293,0.532],[-0.726,-0.397],[0.399,-0.727],[1.386,-0.086]],"o":[[-1.308,0],[-0.486,-0.671],[0.67,-0.486],[0.356,0.492],[0.333,-0.021],[0.398,-0.727],[0.726,0.398],[-0.802,1.46],[-0.074,0.004]],"v":[[-0.035,2.331],[-3.53,0.335],[-3.194,-1.759],[-1.1,-1.423],[0.001,-0.67],[1,-1.554],[3.038,-2.146],[3.629,-0.109],[0.187,2.324]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[234.036,436.409]},"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":"tr","p":{"a":0,"k":[234.036,436.409]},"a":{"a":0,"k":[234.036,436.409]},"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":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.214,-3.446],[3.253,-0.202],[0.214,3.446],[-3.253,0.202]],"o":[[0.214,3.446],[-3.253,0.202],[-0.214,-3.446],[3.253,-0.202]],"v":[[5.889,-0.365],[0.387,6.239],[-5.889,0.365],[-0.387,-6.239]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[252.365,432.395]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.214,-3.446],[3.253,-0.202],[0.214,3.446],[-3.253,0.202]],"o":[[0.214,3.446],[-3.253,0.202],[-0.214,-3.446],[3.253,-0.202]],"v":[[5.889,-0.365],[0.387,6.239],[-5.889,0.365],[-0.387,-6.239]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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},{"ty":"tr","p":{"a":0,"k":[221.548,434.305]},"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":"tr","p":{"a":0,"k":[221.548,434.305]},"a":{"a":0,"k":[221.548,434.305]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[17.097,-1.06],[-0.963,-15.534],[-0.8,-2.242],[-6.573,11.764],[-19.074,-4.386],[0.208,3.352]],"o":[[-17.097,1.06],[0.153,2.471],[13.656,-3.072],[4.316,6.667],[0.999,-3.054],[-0.963,-15.534]],"v":[[-1.743,-18.533],[-30.956,11.513],[-29.501,18.599],[-1.004,-6.604],[29.716,17.336],[30.956,7.676]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.737254917622,0.78823530674,0.784313738346,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},{"ty":"tr","p":{"a":0,"k":[236.911,423.017]},"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":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":24,"s":[{"i":[[0,0],[0.003,4.107],[2.613,-0.828],[2.616,-1.444]],"o":[[1.435,-10.171],[-0.002,-2.741],[-6.047,1.915],[0,0]],"v":[[8.828,13.248],[10.626,-9.199],[5.324,-13.056],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0,0],[2.852,2.956],[1.308,-2.409],[2.616,-1.444]],"o":[[1.435,-10.171],[-1.903,-1.973],[-3.026,5.575],[0,0]],"v":[[8.828,13.248],[-0.117,-14.939],[-6.61,-14.037],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[{"i":[[0,0],[-3.267,2.49],[2.241,1.578],[2.616,-1.444]],"o":[[1.435,-10.171],[2.18,-1.662],[-5.187,-3.652],[0,0]],"v":[[8.828,13.248],[15.552,3.322],[15.41,-3.232],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":44,"s":[{"i":[[0,0],[2.852,2.956],[1.308,-2.409],[2.616,-1.444]],"o":[[1.435,-10.171],[-1.903,-1.973],[-3.026,5.575],[0,0]],"v":[[8.828,13.248],[-0.117,-14.939],[-6.61,-14.037],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":56,"s":[{"i":[[0,0],[0.003,4.107],[2.613,-0.828],[2.616,-1.444]],"o":[[1.435,-10.171],[-0.002,-2.741],[-6.047,1.915],[0,0]],"v":[[8.828,13.248],[10.626,-9.199],[5.324,-13.056],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":210,"s":[{"i":[[0,0],[0.003,4.107],[2.613,-0.828],[2.616,-1.444]],"o":[[1.435,-10.171],[-0.002,-2.741],[-6.047,1.915],[0,0]],"v":[[8.828,13.248],[10.626,-9.199],[5.324,-13.056],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":216,"s":[{"i":[[0,0],[2.852,2.956],[1.308,-2.409],[2.616,-1.444]],"o":[[1.435,-10.171],[-1.903,-1.973],[-3.026,5.575],[0,0]],"v":[[8.828,13.248],[-0.117,-14.939],[-6.61,-14.037],[-10.626,-4.284]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":222,"s":[{"i":[[0,0],[-3.267,2.49],[2.241,1.578],[2.616,-1.444]],"o":[[1.435,-10.171],[2.18,-1.662],[-5.187,-3.652],[0,0]],"v":[[8.828,13.248],[15.552,3.322],[15.41,-3.232],[-10.626,-4.284]],"c":false}]},{"t":230,"s":[{"i":[[0,0],[0.003,4.107],[2.613,-0.828],[2.616,-1.444]],"o":[[1.435,-10.171],[-0.002,-2.741],[-6.047,1.915],[0,0]],"v":[[8.828,13.248],[10.626,-9.199],[5.324,-13.056],[-10.626,-4.284]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.737254917622,0.78823530674,0.784313738346,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},{"ty":"tr","p":{"a":0,"k":[257.171,410.103]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0.504,4.076],[-2.696,-0.499],[-2.774,-1.109]],"o":[[-2.68,-9.916],[-0.337,-2.721],[6.238,1.154],[0,0]],"v":[[-6.276,13.302],[-10.832,-8.751],[-6.047,-13.233],[10.863,-6.498]],"c":false}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.737254917622,0.78823530674,0.784313738346,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},{"ty":"tr","p":{"a":0,"k":[213.178,413.712]},"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":"tr","p":{"a":0,"k":[213.178,413.712]},"a":{"a":0,"k":[213.178,413.712]},"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":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.963,-15.534],[17.097,-1.06],[0.963,15.534],[-17.097,1.06]],"o":[[0.963,15.534],[-17.097,1.06],[-0.963,-15.534],[17.097,-1.06]],"v":[[30.956,-1.919],[1.743,28.128],[-30.956,1.919],[-1.743,-28.128]],"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":"Group 1","bm":0,"hd":false},{"ty":"tr","p":{"a":0,"k":[236.911,432.611]},"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":"tr","p":{"a":0,"k":[236.911,432.611]},"a":{"a":0,"k":[236.911,432.611]},"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],[13.16,-11.456],[-6.064,-9.208],[0,0]],"o":[[-11.976,-13.117],[-1.773,7.775],[0,0],[0,0]],"v":[[23.565,-6.254],[-22.749,-11.691],[-17.601,18.507],[23.565,18.507]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.737254917622,0.78823530674,0.784313738346,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[268.749,447.337]},"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],[9.248,-20.638],[1.215,-5.838],[0,0]],"o":[[-16.591,-18.256],[-1.315,2.935],[0,0],[0,0]],"v":[[38.711,-4.521],[-32.813,-1.291],[-38.711,17.531],[38.711,17.531]],"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":[254.859,449.87]},"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],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-52.387,-38.659],[52.387,-38.659],[52.387,38.659],[-52.387,38.659]],"c":true}},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.109803922474,0.57647061348,0.552941203117,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[239.927,427.185]},"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":300,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"fr1","sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":46,"s":[-5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":226,"s":[-5]},{"t":288,"s":[10]}]},"p":{"a":1,"k":[{"i":{"x":0.189,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[241.593,389.067,0],"to":[40.407,-10.067,0],"ti":[2.407,177.933,0]},{"t":90,"s":[340.593,137.067,0],"h":1},{"i":{"x":0.189,"y":1},"o":{"x":0.333,"y":0},"t":180,"s":[241.593,389.067,0],"to":[40.407,-10.067,0],"ti":[2.407,177.933,0]},{"t":270,"s":[340.593,137.067,0],"h":1}]},"s":{"a":1,"k":[{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":0,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":45,"s":[150,150,100]},{"t":90,"s":[0,0,100],"h":1},{"i":{"x":[0,0,0],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":180,"s":[0,0,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,1],"y":[0,0,0]},"t":225,"s":[150,150,100]},{"t":270,"s":[0,0,100],"h":1}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,-6.53],[0,0],[-6.53,0],[0,0],[0,6.53],[0,0],[0,0],[0,0],[0,0],[6.53,0],[0,0]],"o":[[0,0],[0,6.53],[0,0],[6.53,0],[0,0],[0,0],[0,0],[0,0],[0,-6.53],[0,0],[-6.53,0]],"v":[[-77.159,-41.835],[-77.159,41.835],[-65.335,53.658],[45.791,53.658],[57.615,41.835],[57.615,7.107],[77.159,-12.438],[57.615,-12.438],[57.615,-41.835],[45.791,-53.658],[-65.335,-53.658]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":46,"s":[5]},{"t":90,"s":[6],"h":1},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[6]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":226,"s":[5]},{"t":270,"s":[6],"h":1}]},"lc":2,"lj":2,"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":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":46,"s":[10]},{"t":90,"s":[14],"h":1},{"i":{"x":[0],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[14]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[1],"y":[0]},"t":226,"s":[10]},{"t":270,"s":[14],"h":1}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 2","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":300,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"bl","parent":15,"sr":1,"ks":{"p":{"a":0,"k":[2.497,-9.912,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":66,"s":[{"i":[[0.868,0.806],[1.563,-0.392],[-0.868,-0.806],[-1.563,0.392]],"o":[[-0.868,-0.806],[-1.563,0.392],[0.868,0.806],[1.563,-0.392]],"v":[[2.042,12.871],[-2.36,12.121],[-3.618,14.29],[0.784,15.039]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":116,"s":[{"i":[[0.868,0.806],[1.563,-0.392],[-0.868,-0.806],[-1.563,0.392]],"o":[[-0.868,-0.806],[-1.563,0.392],[0.868,0.806],[1.563,-0.392]],"v":[[2.042,12.871],[-2.36,12.121],[-3.618,14.29],[0.784,15.039]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":168,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[{"i":[[0.868,0.806],[1.563,-0.392],[-0.868,-0.806],[-1.563,0.392]],"o":[[-0.868,-0.806],[-1.563,0.392],[0.868,0.806],[1.563,-0.392]],"v":[[2.042,12.871],[-2.36,12.121],[-3.618,14.29],[0.784,15.039]],"c":true}]},{"t":180,"s":[{"i":[[0.745,3.588],[1.603,-0.644],[-0.745,-3.588],[-1.603,0.644]],"o":[[-0.745,-3.588],[-1.603,0.644],[0.745,3.588],[1.603,-0.644]],"v":[[2.902,-1.166],[-1.348,-6.497],[-2.902,1.166],[1.348,6.497]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":60,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":66,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":72,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":110,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":116,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":122,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":168,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":174,"s":[0,0,0,1]},{"t":180,"s":[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":300,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"eye","parent":21,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":60,"s":[29.102,-39.909,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[43.176,-40.09,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[43.176,-40.09,0],"to":[0,0,0],"ti":[0,0,0]},{"t":120,"s":[29.102,-39.909,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[100,100,100]},{"t":74,"s":[170,100,100],"h":1},{"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":106,"s":[170,100,100]},{"t":120,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":66,"s":[{"i":[[-5.746,0.037],[-0.346,-4.338],[5.746,-0.037],[-3,3.035]],"o":[[5.746,-0.037],[0.171,2.14],[-5.746,0.037],[1.584,-1.602]],"v":[[0.501,2.973],[9.148,3.728],[-0.457,8.139],[-9.368,0.899]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":116,"s":[{"i":[[-5.746,0.037],[-0.346,-4.338],[5.746,-0.037],[-3,3.035]],"o":[[5.746,-0.037],[0.171,2.14],[-5.746,0.037],[1.584,-1.602]],"v":[[0.501,2.973],[9.148,3.728],[-0.457,8.139],[-9.368,0.899]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":168,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[{"i":[[-5.746,0.037],[-0.346,-4.338],[5.746,-0.037],[-3,3.035]],"o":[[5.746,-0.037],[0.171,2.14],[-5.746,0.037],[1.584,-1.602]],"v":[[0.501,2.973],[9.148,3.728],[-0.457,8.139],[-9.368,0.899]],"c":true}]},{"t":180,"s":[{"i":[[-5.329,2.149],[-1.333,-11.884],[5.329,-2.149],[1.333,11.884]],"o":[[5.329,-2.149],[1.333,11.884],[-5.329,2.149],[-1.333,-11.884]],"v":[[-2.415,-21.518],[9.65,-3.892],[2.414,21.518],[-9.65,3.892]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":66,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":110,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":116,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":174,"s":[5]},{"t":180,"s":[0]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":300,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"wing 2","parent":25,"sr":1,"ks":{"p":{"a":0,"k":[104.076,-54.491,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.423],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-25.804,13.181],[-27.588,69.626]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":70,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.423],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-55.628,21.515],[-27.588,69.626]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.423],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-16.465,-45.243],[-27.588,69.626]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.423],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-55.628,21.515],[-27.588,69.626]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":132,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.422],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-31.405,16.983],[-27.588,69.626]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":146,"s":[{"i":[[0,0],[19.367,1.721],[-4.381,-42.07]],"o":[[-8.631,-14.492],[-15.358,-1.365],[0,0]],"v":[[30.62,13.31],[29.08,-64.363],[-7.136,20.552]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":156,"s":[{"i":[[0,0],[19.367,1.721],[-4.381,-42.07]],"o":[[-8.631,-14.492],[-15.358,-1.365],[0,0]],"v":[[30.62,13.31],[29.08,-64.363],[-7.136,20.552]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":176,"s":[{"i":[[0,0],[10.371,-16.446],[30.958,-10.917]],"o":[[9.508,-0.422],[-8.67,13.749],[0,0]],"v":[[11.474,19.5],[-20.879,27.948],[-27.588,69.626]],"c":false}]},{"i":{"x":0.07,"y":1},"o":{"x":0.333,"y":0},"t":190,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[22.817,-24.271],[-1.449,26.399]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.93,"y":0},"t":204,"s":[{"i":[[0,0],[-9.329,13.311],[37.618,-36.066]],"o":[[12.528,-21.492],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[30.269,-80],[-1.449,26.399]],"c":false}]},{"t":218,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-48.175,12.921],[-7.996,2.643],[-22.063,48.329]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,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":178,"st":0,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"bl","parent":18,"sr":1,"ks":{"p":{"a":0,"k":[7.318,-9.613,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":66,"s":[{"i":[[-0.871,-0.963],[2.903,-0.176],[0.871,0.963],[-2.903,0.176]],"o":[[0.871,0.963],[-2.903,0.176],[-0.871,-0.963],[2.903,-0.176]],"v":[[4.247,9.202],[0.568,11.264],[-6.265,9.838],[-2.586,7.776]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":116,"s":[{"i":[[-0.871,-0.963],[2.903,-0.176],[0.871,0.963],[-2.903,0.176]],"o":[[0.871,0.963],[-2.903,0.176],[-0.871,-0.963],[2.903,-0.176]],"v":[[4.247,9.202],[0.568,11.264],[-6.265,9.838],[-2.586,7.776]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":168,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[{"i":[[-0.871,-0.963],[2.903,-0.176],[0.871,0.963],[-2.903,0.176]],"o":[[0.871,0.963],[-2.903,0.176],[-0.871,-0.963],[2.903,-0.176]],"v":[[4.247,9.202],[0.568,11.264],[-6.265,9.838],[-2.586,7.776]],"c":true}]},{"t":180,"s":[{"i":[[-0.871,-3.609],[2.903,-0.658],[0.871,3.609],[-2.903,0.658]],"o":[[0.871,3.609],[-2.903,0.658],[-0.871,-3.609],[2.903,-0.658]],"v":[[5.256,-1.192],[1.577,6.534],[-5.256,1.192],[-1.577,-6.534]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":60,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":66,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":72,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":110,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":116,"s":[0,0,0,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":122,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":168,"s":[1,1,1,1]},{"i":{"x":[0],"y":[1]},"o":{"x":[1],"y":[0]},"t":174,"s":[0,0,0,1]},{"t":180,"s":[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":300,"st":0,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":"eye","parent":21,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":60,"s":[-43.236,-37.669,0],"to":[0,0,0],"ti":[0,0,0]},{"t":74,"s":[-48.207,-37.13,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[-48.207,-37.13,0],"to":[0,0,0],"ti":[0,0,0]},{"t":120,"s":[-43.236,-37.669,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":60,"s":[100,100,100]},{"t":74,"s":[100,100,100],"h":1},{"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":106,"s":[100,100,100]},{"t":120,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":66,"s":[{"i":[[10.448,2.012],[1.578,-1.407],[-10.448,-2.012],[1.414,4.375]],"o":[[-10.448,-2.012],[-3.477,3.099],[10.448,2.012],[-1.161,-3.591]],"v":[[-0.145,-3.172],[-17.835,-6.762],[-1.135,4.61],[19.37,-2.921]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":116,"s":[{"i":[[10.448,2.012],[1.578,-1.407],[-10.448,-2.012],[1.414,4.375]],"o":[[-10.448,-2.012],[-3.477,3.099],[10.448,2.012],[-1.161,-3.591]],"v":[[-0.145,-3.172],[-17.835,-6.762],[-1.135,4.61],[19.37,-2.921]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":168,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[{"i":[[10.448,2.012],[1.578,-1.407],[-10.448,-2.012],[1.414,4.375]],"o":[[-10.448,-2.012],[-3.477,3.099],[10.448,2.012],[-1.161,-3.591]],"v":[[-0.145,-3.172],[-17.835,-6.762],[-1.135,4.61],[19.37,-2.921]],"c":true}]},{"t":180,"s":[{"i":[[10.448,2.012],[2.294,-11.916],[-10.448,-2.012],[-2.294,11.916]],"o":[[-10.448,-2.012],[-2.294,11.916],[10.448,2.012],[2.294,-11.916]],"v":[[4.154,-21.576],[-18.917,-3.642],[-4.154,21.576],[18.917,3.642]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0,0,0,1]},"o":{"a":0,"k":100},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":66,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":110,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":116,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":122,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":174,"s":[5]},{"t":180,"s":[0]}]},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,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":300,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"mouth","parent":21,"sr":1,"ks":{"p":{"a":0,"k":[3.922,12.448,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":64,"s":[{"i":[[0,0],[23.484,7.114],[-6.691,1.491]],"o":[[-11.53,4.212],[7.115,6.044],[6.691,-1.491]],"v":[[26.438,-3.428],[-26.438,0.287],[7.667,3.014]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0,0],[23.484,7.114],[-6.691,1.491]],"o":[[-11.53,4.212],[7.115,6.044],[6.691,-1.491]],"v":[[26.438,-3.428],[-26.438,0.287],[6.76,10.287]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":156,"s":[{"i":[[0,0],[23.484,7.114],[-6.691,1.491]],"o":[[-11.53,4.212],[7.115,6.044],[6.691,-1.491]],"v":[[26.438,-3.428],[-26.438,0.287],[6.76,10.287]],"c":true}]},{"t":166,"s":[{"i":[[0,0],[23.484,7.114],[-6.691,1.491]],"o":[[-11.53,4.212],[7.115,6.044],[6.691,-1.491]],"v":[[26.438,-3.428],[-26.438,0.287],[7.667,3.014]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.490196079016,0.035294119269,0.035294119269,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":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}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"beak_bl","parent":21,"sr":1,"ks":{"o":{"a":0,"k":33},"p":{"a":0,"k":[-3.932,-5.725,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-1.255,4.047]],"o":[[3.344,-4.352],[0,0]],"v":[[-3.876,7.53],[3.876,-7.53]],"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":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}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"beak","parent":23,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[-26.602]},{"t":74,"s":[6.185],"h":1},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[6.185]},{"t":120,"s":[-26.602]}]},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":60,"s":[75.575,9.259,0],"to":[0,0,0],"ti":[21.31,-1.698,0]},{"t":74,"s":[30.623,51.968,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[30.623,51.968,0],"to":[21.31,-1.698,0],"ti":[0,0,0]},{"t":120,"s":[75.575,9.259,0]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[10.117,0.332],[6.289,-0.442],[13.575,-2.377],[-12.443,-3.229],[-7.925,4.546],[0.765,4.154]],"o":[[-18.721,-0.615],[-6.899,0.485],[-14.368,2.516],[24.622,6.389],[7.048,-4.043],[10.405,-0.023]],"v":[[30.395,-4.093],[-0.58,-29.159],[-27.045,0.215],[-26.963,25.076],[20.053,24.984],[28.209,10.679]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[10.122,0.134],[6.289,-0.442],[13.575,-2.377],[-11.871,-4.932],[-11.396,2.056],[-5.971,7.718]],"o":[[-26.852,-0.356],[-6.899,0.485],[-14.368,2.516],[13.169,5.472],[12.793,-2.308],[10.405,-0.023]],"v":[[38.254,-5.207],[2.555,-29.237],[-27.045,0.215],[-26.963,25.076],[11.391,35.411],[40.101,13.319]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[10.122,0.134],[6.289,-0.442],[13.575,-2.377],[-11.871,-4.932],[-11.396,2.056],[-5.971,7.718]],"o":[[-26.852,-0.356],[-6.899,0.485],[-14.368,2.516],[13.169,5.472],[12.793,-2.308],[10.405,-0.023]],"v":[[38.254,-5.207],[2.555,-29.237],[-27.045,0.215],[-26.963,25.076],[11.391,35.411],[40.101,13.319]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[{"i":[[10.117,0.332],[6.289,-0.442],[13.575,-2.377],[-11.958,-4.719],[-7.925,4.546],[0.765,4.154]],"o":[[-18.721,-0.615],[-6.899,0.485],[-14.368,2.516],[24.074,9.5],[7.048,-4.043],[10.405,-0.023]],"v":[[30.395,-4.093],[-0.58,-29.159],[-27.045,0.215],[-26.963,25.076],[13.676,32.694],[28.209,10.679]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":156,"s":[{"i":[[10.117,0.332],[6.289,-0.442],[13.575,-2.377],[-11.958,-4.719],[-7.925,4.546],[0.765,4.154]],"o":[[-18.721,-0.615],[-6.899,0.485],[-14.368,2.516],[24.074,9.5],[7.048,-4.043],[10.405,-0.023]],"v":[[30.395,-4.093],[-0.58,-29.159],[-27.045,0.215],[-26.963,25.076],[13.676,32.694],[28.209,10.679]],"c":true}]},{"t":166,"s":[{"i":[[10.117,0.332],[6.289,-0.442],[13.575,-2.377],[-12.443,-3.229],[-7.925,4.546],[0.765,4.154]],"o":[[-18.721,-0.615],[-6.899,0.485],[-14.368,2.516],[24.622,6.389],[7.048,-4.043],[10.405,-0.023]],"v":[[30.395,-4.093],[-0.58,-29.159],[-27.045,0.215],[-26.963,25.076],[20.053,24.984],[28.209,10.679]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.811764717102,0.207843139768,0.007843137719,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":1,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.364705890417,0.121568627656,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":300,"st":0,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"head_bl","parent":23,"sr":1,"ks":{"p":{"a":0,"k":[-54.395,-36.749,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-16.703,11.436],[-8.863,2.813]],"o":[[6.46,-17.994],[7.466,-5.111],[0,0]],"v":[[-30.23,28.947],[5.637,-16.907],[30.23,-28.947]],"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":10},"lc":2,"lj":2,"bm":0,"d":[{"n":"d","nm":"dash","v":{"a":0,"k":50}},{"n":"g","nm":"gap","v":{"a":0,"k":20}},{"n":"o","nm":"offset","v":{"a":0,"k":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":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[5]},{"t":240,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":60,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":72,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":132,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":156,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":168,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":216,"s":[95]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":228,"s":[100]},{"t":240,"s":[100]}]},"o":{"a":0,"k":0},"m":1,"nm":"Trim Paths 1","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":"head","parent":25,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.298],"y":[0]},"t":74,"s":[-4.573]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[-4.573]},{"t":120,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[-0.871,-31.973,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[-3.756,-31.973,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[-3.756,-31.973,0],"to":[0,0,0],"ti":[0,0,0]},{"t":120,"s":[-0.871,-31.973,0]}]},"a":{"a":0,"k":[0,87.265,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[1.469,25.441],[60.458,-3.491],[-3.121,-54.046],[-19.474,-14.322]],"o":[[17.925,-16.604],[-3.121,-54.046],[-60.457,3.491],[1.473,25.51],[0,0]],"v":[[83.336,78.198],[109.469,13.834],[-6.191,-87.094],[-109.465,26.476],[-76.286,87.265]],"c":false}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,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":300,"st":0,"bm":0},{"ddd":0,"ind":24,"ty":3,"nm":"NULL CONTROL","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":0,"k":[147.145,504.021,0]},"a":{"a":0,"k":[60,60,0]},"s":{"a":0,"k":[114,114,100]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"body","parent":24,"sr":1,"ks":{"p":{"a":0,"k":[60,60,0]},"a":{"a":0,"k":[0,67.25,0]},"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":60,"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":74,"s":[104,96,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":88,"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":120,"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":134,"s":[104,96,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":148,"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":180,"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":194,"s":[104,96,100]},{"t":208,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[4.471,-22.92],[-13.036,-8.849],[-4.695,51.815],[25.492,12.62]],"o":[[-36.71,11.379],[-21.049,11.071],[39.352,26.711],[3.908,-43.129],[0,0]],"v":[[-53.963,-48.458],[-103.547,8.731],[-103.095,48.658],[115.961,25.945],[65.153,-67.25]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":74,"s":[{"i":[[0,0],[4.471,-22.92],[-13.036,-8.849],[-4.695,51.815],[25.492,12.62]],"o":[[-23.581,22.457],[-5.247,20.477],[39.352,26.711],[3.908,-43.129],[0,0]],"v":[[-78.001,-53.145],[-110.278,7.168],[-104.537,48.837],[113.557,25.841],[62.749,-67.355]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":106,"s":[{"i":[[0,0],[4.471,-22.92],[-13.036,-8.849],[-4.695,51.815],[25.492,12.62]],"o":[[-23.581,22.457],[-5.247,20.477],[39.352,26.711],[3.908,-43.129],[0,0]],"v":[[-78.001,-53.145],[-110.278,7.168],[-104.537,48.837],[113.557,25.841],[62.749,-67.355]],"c":false}]},{"t":120,"s":[{"i":[[0,0],[4.471,-22.92],[-13.036,-8.849],[-4.695,51.815],[25.492,12.62]],"o":[[-36.71,11.379],[-21.049,11.071],[39.352,26.711],[3.908,-43.129],[0,0]],"v":[[-53.963,-48.458],[-103.547,8.731],[-103.095,48.658],[115.961,25.945],[65.153,-67.25]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,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":300,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"wing","parent":25,"sr":1,"ks":{"p":{"a":0,"k":[104.076,-54.491,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.07,"y":1},"o":{"x":0.333,"y":0},"t":70,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-48.175,12.921],[-7.996,2.643],[-22.063,48.329]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.93,"y":0},"t":84,"s":[{"i":[[0,0],[-16.971,3.715],[33.447,-30.233]],"o":[[31.71,-21.793],[3.469,-0.76],[0,0]],"v":[[-37.134,22.38],[21.131,-26.948],[-11.023,57.788]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":98,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-48.175,12.921],[2.203,-2.341],[-22.063,48.329]],"c":false}]},{"i":{"x":0.07,"y":1},"o":{"x":0.333,"y":0},"t":130,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-48.175,12.921],[2.203,-2.341],[-22.063,48.329]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.93,"y":0},"t":144,"s":[{"i":[[0,0],[-9.329,13.311],[37.618,-36.066]],"o":[[12.528,-21.492],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[30.269,-80],[-1.449,26.399]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":158,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[22.817,-24.271],[-1.449,26.399]],"c":false}]},{"i":{"x":0.46,"y":1},"o":{"x":0.333,"y":0},"t":198,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[22.817,-24.271],[-1.449,26.399]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.93,"y":0},"t":214,"s":[{"i":[[0,0],[-9.329,13.311],[37.618,-36.066]],"o":[[12.528,-21.492],[9.329,-13.311],[0,0]],"v":[[-27.561,-9.009],[30.269,-80],[-1.449,26.399]],"c":false}]},{"t":238,"s":[{"i":[[0,0],[-9.329,13.311],[30.958,-10.917]],"o":[[9.508,-0.423],[9.329,-13.311],[0,0]],"v":[[-48.175,12.921],[-7.996,2.643],[-22.063,48.329]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.980392158031,0.564705908298,0.086274512112,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.835294127464,0.152941182256,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":178,"op":300,"st":0,"bm":0},{"ddd":0,"ind":27,"ty":4,"nm":"CLOUD","sr":1,"ks":{"p":{"a":0,"k":[322.393,112.298,0]},"a":{"a":0,"k":[322.393,108.298,0]},"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":66,"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":88,"s":[103,103,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":106,"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":126,"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":148,"s":[103,103,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":166,"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":186,"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":208,"s":[103,103,100]},{"t":226,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76.363,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-25.773,-83.517],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92.729,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.417,-69.153],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109.09,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":125.453,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-25.773,-83.517],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":141.818,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.417,-69.153],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":158.182,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174.545,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-25.773,-83.517],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":190.908,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.417,-69.153],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":207.271,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-25.773,-83.517],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":223.637,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.417,-69.153],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"t":240,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[322.393,108.298]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[10.251,-83.234],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-94.893,-9.622],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76.363,"s":[{"i":[[0,0],[-66.455,-10.102],[-8.244,-86.04],[-11.946,0],[78.5,0]],"o":[[-53.792,0.363],[10.731,-87.13],[8.722,-6.843],[67.947,0],[0,0]],"v":[[-115.743,75.255],[-95.625,-15.366],[54.383,-12.541],[86.034,-23.476],[86.034,79.187]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92.729,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[18.024,-66.353],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-93.855,-16.885],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109.09,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[10.251,-83.234],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-94.893,-9.622],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":125.453,"s":[{"i":[[0,0],[-66.455,-10.102],[-8.244,-86.04],[-11.946,0],[78.5,0]],"o":[[-53.792,0.363],[10.731,-87.13],[8.722,-6.843],[67.947,0],[0,0]],"v":[[-115.743,75.255],[-95.625,-15.366],[54.383,-12.541],[86.034,-23.476],[86.034,79.187]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":141.818,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[18.024,-66.353],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-93.855,-16.885],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":158.182,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[10.251,-83.234],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-94.893,-9.622],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174.545,"s":[{"i":[[0,0],[-66.455,-10.102],[-8.244,-86.04],[-11.946,0],[78.5,0]],"o":[[-53.792,0.363],[10.731,-87.13],[8.722,-6.843],[67.947,0],[0,0]],"v":[[-115.743,75.255],[-95.625,-15.366],[54.383,-12.541],[86.034,-23.476],[86.034,79.187]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":190.908,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[18.024,-66.353],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-93.855,-16.885],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":207.271,"s":[{"i":[[0,0],[-66.455,-10.102],[-8.244,-86.04],[-11.946,0],[78.5,0]],"o":[[-53.792,0.363],[10.731,-87.13],[8.722,-6.843],[67.947,0],[0,0]],"v":[[-115.743,75.255],[-95.625,-15.366],[54.383,-12.541],[86.034,-23.476],[86.034,79.187]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":223.637,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[18.024,-66.353],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-93.855,-16.885],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"c":true}]},{"t":240,"s":[{"i":[[0,0],[-63.484,-9.65],[-22.506,-80.734],[-12.735,0],[83.688,0]],"o":[[-51.386,0.347],[10.251,-83.234],[9.298,-7.295],[72.437,0],[0,0]],"v":[[-114.111,76.947],[-94.893,-9.622],[55.779,-20.843],[89.521,-32.501],[89.521,76.947]],"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":[314.298,94.739]},"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.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76.363,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-24.295,-81.053],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92.729,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.935,-70.191],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109.09,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":125.453,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-24.295,-81.053],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":141.818,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.935,-70.191],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":158.182,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174.545,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-24.295,-81.053],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":190.908,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.935,-70.191],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":207.271,"s":[{"i":[[0,0],[0,36.011],[-36.011,0],[-0.003,0],[-24.295,-81.053],[0,-48.038],[39.514,0]],"o":[[-36.011,0],[0,-36.011],[0.003,0],[23.185,-89.634],[45.97,-14.045],[0,39.514],[0,0]],"v":[[-110.538,99.527],[-175.742,34.323],[-110.538,-30.881],[-110.53,-30.881],[70.223,-40.448],[162.701,27.98],[91.154,99.527]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":223.637,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[21.935,-70.191],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-177.496,37.038],[-108.464,-32.312],[-108.455,-32.312],[72.681,-54.368],[171.79,23.252],[95.514,99.527]],"c":true}]},{"t":240,"s":[{"i":[[0,0],[0,34.401],[-34.401,0],[-0.003,0],[-44.712,-77.529],[0,-51.213],[42.126,0]],"o":[[-34.401,0],[0,-34.401],[0.003,0],[22.148,-85.626],[49.008,-14.973],[0,42.126],[0,0]],"v":[[-109.501,99.527],[-171.79,37.239],[-109.501,-25.05],[-109.493,-25.05],[73.2,-49.699],[171.79,23.252],[95.514,99.527]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.533333361149,0.72549021244,0.886274516582,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":10},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.86274510622,0.992156863213,1,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[322.393,108.298]},"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":300,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"_054_CLOUDY_UPLOAD","refId":"comp_0","sr":1,"ks":{"p":{"a":0,"k":[256,256,0]},"a":{"a":0,"k":[256,256,0]}},"ao":0,"w":512,"h":512,"ip":0,"op":180,"st":-60,"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 12cb75597..c2d1b4f34 100644 --- a/TMessagesProj/src/main/res/values-ar/strings.xml +++ b/TMessagesProj/src/main/res/values-ar/strings.xml @@ -2493,7 +2493,6 @@ تمت إزالة **%1$s** من **%2$s** تمت إزالة **%1$s** من **%2$s** وصلت الحد الأقصى - عذرًا، لايمكنك إضافة أكثر من 100 محادثة إلى مجلد. عذرًا، لايمكنك استثناء أكثر من 100 محادثة من مجلد. رمز القفل diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml index 6ccc9a72b..a0e907222 100644 --- a/TMessagesProj/src/main/res/values-de/strings.xml +++ b/TMessagesProj/src/main/res/values-de/strings.xml @@ -2494,7 +2494,6 @@ **%1$s** wurde aus **%2$s** entfernt **%1$s** wurde aus **%2$s** entfernt Limt erreicht - Mehr als 100 Chats kann man leider nicht einem Ordner hinzufügen. Mehr als 100 Chats kann man leider nicht aus einem Ordner ausschließen. Pincode-Sperre diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml index 59a18f013..b41963379 100644 --- a/TMessagesProj/src/main/res/values-es/strings.xml +++ b/TMessagesProj/src/main/res/values-es/strings.xml @@ -2494,7 +2494,6 @@ Quitaste **%1$s** de **%2$s** Quitaste **%1$s** de **%2$s** Límite alcanzado - No puedes añadir más de 100 chats a una carpeta. No puedes excluir más de 100 chats de una carpeta. Código de bloqueo diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml index c7d92b4d8..edbecaa82 100644 --- a/TMessagesProj/src/main/res/values-it/strings.xml +++ b/TMessagesProj/src/main/res/values-it/strings.xml @@ -2494,7 +2494,6 @@ **%1$s** rimossa da **%2$s** **%1$s** rimosse da **%2$s** Limite raggiunto - Spiacenti, non puoi aggiungere più di 100 chat a una cartella. Spiacenti, non puoi escludere più di 100 chat da una cartella. Codice di blocco diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml index 8f1ed42c8..5d3c3a7f7 100644 --- a/TMessagesProj/src/main/res/values-ko/strings.xml +++ b/TMessagesProj/src/main/res/values-ko/strings.xml @@ -2494,7 +2494,6 @@ **%2$s** 폴더에서 **%1$s** 대화가 삭제됨 **%2$s** 폴더에서 **%1$s** 대화가 삭제됨 한계 도달 - 죄송합니다, 폴더에 100 개 이상의 대화를 추가 할 수 없습니다. 죄송합니다, 폴더에서 100개 이상의 대화를 제외할 수 없습니다. 암호 잠금 diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml index 4bf807df2..68271c906 100644 --- a/TMessagesProj/src/main/res/values-nl/strings.xml +++ b/TMessagesProj/src/main/res/values-nl/strings.xml @@ -2494,7 +2494,6 @@ **%1$s** verwijderd van **%2$s** **%1$s** verwijderd van **%2$s** Limiet bereikt - Sorry, je kunt niet meer dan 100 chats aan een map toevoegen. Sorry, je kunt niet meer dan 100 chats uitsluiten van een map Toegangscode-vergrendeling diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml index 1d743a5bd..9d056ce5e 100644 --- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml +++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml @@ -2494,7 +2494,6 @@ **%1$s** removido de **%2$s** **%1$s** removido de **%2$s** Limite atingido - Desculpe, você não pode adicionar mais que 100 chats numa pasta. Desculpe, você não pode ignorar mais que 100 chats numa pasta. Senha de Bloqueio diff --git a/TMessagesProj/src/main/res/values/ids.xml b/TMessagesProj/src/main/res/values/ids.xml index 8c9605ea9..9c79c24dc 100644 --- a/TMessagesProj/src/main/res/values/ids.xml +++ b/TMessagesProj/src/main/res/values/ids.xml @@ -21,10 +21,13 @@ + + + diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index f2cbbe3d6..8c21cd8fb 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -77,6 +77,8 @@ You have just successfully transferred %1$s to %2$s for %3$s You have just successfully transferred %1$s to %2$s + You successfully transferred %1$s to %2$s for %3$s and allowed future recurrent payments + You successfully transferred %1$s to %2$s and allowed future recurrent payments Checkout Shipping methods Sorry, it is not possible to deliver to your address. @@ -109,6 +111,7 @@ Transaction Review Transfer **%1$s** to the %2$s bot for **%3$s**? Total + Invalid invoice INVOICE TEST INVOICE PAY %1$s @@ -147,6 +150,7 @@ New Group yesterday No results + No results found for \"%s\". Welcome to Telegram Recently viewed HIDE @@ -428,6 +432,7 @@ Leave channel Settings JOIN + APPLY TO JOIN GROUP Broadcast Silent Broadcast What is a Channel? @@ -494,6 +499,7 @@ You can add administrators to help you manage your channel. Tap and hold to remove admins. Do you want to join the channel \'%1$s\'? Sorry, this channel is private, so you can’t view its content. + Sorry, this channel is private. Sorry, you can\'t access this chat because you were banned by an admin. Unfortunately, you were banned from participating in public groups. Sorry, this chat is no longer accessible. @@ -917,10 +923,15 @@ Choose from your stickers You can choose a sticker set that will be available to all group members when they are chatting in this group. CHOOSE STICKER SET + Choose sticker set stickerset You can create your own custom sticker sets using the @stickers bot. No such sticker set found Try again or choose from the list below + Set as Group Sticker Set + Remove Group Sticker Set + No results found for \"%1$s\" + My sticker sets invisible support @@ -1286,6 +1297,8 @@ Sender names removed %s: %s From %s + No words recognized. + Rate transcription %1$s set the self-destruct timer to %2$s You set the self-destruct timer to %1$s @@ -1337,6 +1350,7 @@ %1$s sent an audio file to the group %2$s %1$s sent a sticker to the group %2$s %1$s sent a %3$s sticker to the group %2$s + %1$s were charged %2$s %1$s invited you to the group %2$s %1$s renamed the group %2$s %1$s changed the group photo for %2$s @@ -1645,6 +1659,7 @@ More Stickers Delete from Favorites Delete from Recent + Clear recent stickers Add to Masks Stickers not found Stickers removed. @@ -1677,6 +1692,7 @@ You can add masks to photos you send. To do this, open the photo editor before sending a photo. Trending Stickers Trending GIFs + Show More Stickers Suggest stickers by emoji All Sets My Sets @@ -1837,6 +1853,9 @@ All notification settings reset to default Reset all notifications Are you sure you want to reset all notification settings to default? + Reset to default settings + Reset notifications + Are you sure you want to reset notification settings to default? Message text size Ask a Question Add an explanation @@ -2152,7 +2171,9 @@ Disable forced RTMP Stream Flag Clear WebView cache Enable WebView debug + Disable WebView debug Debug enabled! + Debug disabled! You can change your language later in Settings. Choose your language Other @@ -2220,6 +2241,7 @@ Free up disk space on your device; your media will stay in the cloud. Change Phone Number Move your account, chats and media to a new number. + Your phone number has been successfully changed. Contact Support Tell us about any issues; logging out doesn\'t usually help. Log Out @@ -2609,7 +2631,6 @@ **%1$s** removed from **%2$s** **%1$s** removed from **%2$s** Limit reached - Sorry, you can\'t add more than 100 chats to a folder. Sorry, you can\'t exlude more than 100 chats from a folder. Passcode Lock @@ -2853,7 +2874,13 @@ Are you sure you want to discard all changes? Clear search history? Are you sure you want to clear your search history? + Do you want to remove this chat from your search history? + Do you want to remove these %1$d chats from your search history? + Do you want to remove these %1$d chats from your search history? + Do you want to remove these %1$d chats from your search history? + Do you want to remove these %1$d chats from your search history? Clear search history + Remove from search history Search history Are you sure you want to remove \"%1$s\" from search history? Are you sure you want to remove \"%1$s\" from search history? @@ -3152,6 +3179,13 @@ Change who can add you to groups and channels. Sorry, you can\'t add this user to groups because of user\'s privacy settings. Sorry, you can\'t add this user to channels because of user\'s privacy settings. + Can\'t add this user + Can\'t add some users + Can\'t add these users + Sorry, you can\'t add **%1$s** to groups because of **%1$s**\'s privacy settings. + Sorry, you can\'t add **%1$s** and **%2$s** to groups because of their privacy settings. + Sorry, you can\'t add some of these users to groups because of their privacy settings. + Sorry, you can\'t add these users to groups because of their privacy settings. Sorry, you can\'t create a group with these users because of their privacy settings. Disabling peer-to-peer will relay all calls through Telegram servers to avoid revealing your IP address, but may slightly decrease audio quality. Delete Synced Contacts @@ -3183,12 +3217,15 @@ Open page **%1$s** would like to open its web app to proceed.\n\nIt will be able to access your **IP address** and basic device info. Add to Menu + This bot can\'t be opened in chats with bots. + This bot can\'t be opened in chats with users. This bot can\'t be opened in groups. This bot can\'t be opened in channels. This link does not lead to a bot. Remove bot Message Preview Choose a file + Settings Open bot Reload page Delete bot @@ -3349,6 +3386,7 @@ This phone number is banned. Code expired, please retry login. Wrong code + For security reasons, you can\'t change phone number from a device that you\'ve just connected. Please use an earlier connection or wait for a few hours. Too many attempts, please try again later Too many attempts, please try again in %1$s Invalid code @@ -3433,6 +3471,7 @@ Do you want to share this game to **%1$s**? Do you want to send this contact to **%1$s**? There is no Telegram account with this username. + There is no Telegram account with this phone number. This bot can\'t join groups. Would you like to enable extended link previews in Secret Chats? Note that link previews are generated on Telegram servers. Please note that inline bots are provided by third-party developers. For the bot to work, the symbols you type after the bot\'s username are sent to the respective developer. @@ -3572,7 +3611,7 @@ Cloud-Based The world\'s **fastest** messaging app.\nIt is **free** and **secure**. **Telegram** delivers messages faster than\nany other application. - **Telegram** is free forever. No ads.\nNo subscription fees. + **Telegram** provides free unlimited cloud storage for chats and media. **Telegram** keeps your messages safe\nfrom hacker attacks. **Telegram** has no limits on\nthe size of your media and chats. **Telegram** lets you access your messages\nfrom multiple devices. @@ -3671,6 +3710,7 @@ Include technical information Doesn\'t reveal chat contents and helps us fix the issue sooner. Thank you for helping make Telegram calls better. + Thank you for your feedback. answering as %s Respond with Text These quick responses will be available when you respond to an incoming call with a Telegram message. Change them to say anything you like. @@ -3989,6 +4029,20 @@ Voice call %1$s Video call %1$s + Revoke %d links + Revoke link + Revoke %d links + Revoke %d links + Revoke %d links + Revoke %d links + + Leave %d communities + Leave community + Leave %d communities + Leave %d communities + Leave %d communities + Leave %d communities + Do you want remove these **%d documents** from Downloads? Do you want remove this document from Downloads? Do you want remove these **%d documents** from Downloads? @@ -4673,6 +4727,16 @@ %1$d Dialogs unpinned %1$d Dialogs unpinned %1$d Dialogs unpinned + Forward media + Would you like to forward... + This photo + This media + All %1$d photos + All %1$d photos + All %1$d photos + All %1$d media + All %1$d media + All %1$d media %1$d Seen Seen @@ -4709,7 +4773,11 @@ Cancel download Open file Message options + Forwarded origin Enter selection mode + Chat Preview + Open Voice Transcription + Close Transcription Emoji, stickers, and GIFs Attach media Send silently @@ -4757,6 +4825,9 @@ User options Rotate Mirror + Brush type + Paint + Place text Photo editor Adjustments Photo viewer @@ -4775,6 +4846,7 @@ Not seen Sending Sending error + Played Not played Next search result Previous search result @@ -4793,6 +4865,19 @@ Viewed %1$d times Viewed %1$d times Viewed %1$d times + Has %1$d reply + Has %1$d replies + Has %1$d replies + Has %1$d replies + Has %1$d replies + %1$s has seen + %1$s reacted with %2$s + You reacted with %1$s + %1$d person reacted with %2$s + %1$d people reacted with %2$s + %1$d people reacted with %2$s + %1$d people reacted with %2$s + %1$d people reacted with %2$s Send %1$d photo Send %1$d photos Send %1$d photos @@ -4814,6 +4899,7 @@ Share in %1$d chats Share in %1$d chats Correct answer + Incorrect answer Explanation Picture-in-Picture mode Microphone is on @@ -4825,6 +4911,20 @@ Pinned messages list Switch to fullscreen Exit fullscreen + Send as %1$s + Bot menu + Verified + %1$d mention + %1$d mentions + %1$d mentions + %1$d mentions + %1$d mentions + %1$d unread chat + %1$d unread chats + %1$d unread chats + %1$d unread chats + %1$d unread chats + With new reaction MMM yyyy MMM dd yyyy, h:mm a @@ -4955,6 +5055,7 @@ Add to Group Add to Channel Add to Group or Channel + This bot is able to manage a group or channel. Dismiss Dismiss request requested to join %1$s @@ -4965,6 +5066,7 @@ Your request to join the group was approved Your request to join the channel was approved un1 joined via invite link un2, approved by un3 + un1 joined, approved by un2 No join requests There are no pending requests\nto join this channel. M @@ -4990,6 +5092,11 @@ Restrict saving content Members won\'t be able to forward messages from this group or save media files. Subscribers won\'t be able to forward messages from this group or save media files. + Who can send new messages? + Only members + Turn this on if you expect users to join your group before being able to send messages. + Approve new members + Turn this on if you want users to join the group only after they are approved by an admin. Please allow **Telegram** to manage all files to open in-app file browser Telegram needs permission to manage all files to migrate old cache files to Scoped Storage Allow @@ -5213,4 +5320,134 @@ Clear for all Clear for me WebView not available. Please update it to use WebView bots. + Private Chats + Groups + Channels + Unlock Premium Stickers + Unlock Premium Reactions + Unlock additional reactions by subscribing to Telegram Premium. + y + Increase Limit + You have reserved too many public links. Try revoking the link from an older group or channel, or upgrade to **Telegram Premium** to double the limit to **%2$d** public links. + You have reserved too many public links. Try revoking the link from an older group or channel. + You have reserved too many public links. Try revoking the link from an older group or channel. We are working to let you increase this limit in the future. + Your public communities + You have reached the limit of **%1$d** folders. You can double the limit to **%2$d** folders by subscribing to **Telegram Premium**. + You have reached the limit of **%1$d** folders for this account. + You have reached the limit of **%1$d** folders for this account. We are working to let you increase this limit in the future. + Sorry, you can\'t add more than **%1$d** chats to a folder. You can increase this limit to **%2$d** by upgrading to **Telegram Premium**. + Sorry, you can\'t add more than **%1$d** chats to a folder. Please create a new one. + Sorry, you can\'t add more than **%1$d** chats to a folder. Please create a new one. We are working to let you increase this limit in the future. + You are a member of **%1$d** groups and channels. Please leave some before joining a new one — or upgrade to **Telegram Premium** to double the limit to **%2$d** groups and channels. + You are a member of **%1$d** groups and channels. Please leave some before joining a new one. + You are a member of **%1$d** groups and channels. Please leave some before joining a new one. We are working to let you increase this limit in the future. + Premium account + Free + Premium + Doubled limits + Up to %1$d channels, %2$d folders, %3$d pins, %4$d public links, %5$d accounts and more. + 4Gb Upload Size + Increased upload size from 2Gb to 4Gb per document, unlimited storage overall. + Faster Download Speed + No more limits on the speed with which media and documents are downloaded. + No Ads + No more ads in public channels where Telegram sometimes shows ads. + Unique Reactions + Premium Stickers + Exclusive enlarged stickers featuring additional effects, updated monthly. + Profile Badge + A badge next to your name showing that you are helping support Telegram. + Animated Profile Pictures + Video avatars animated in chat lists and chats to allow for additional self-expression. + Subscribe for %s per month + Subscribe + Subscription not available + **Official app needed** + You need an official Telegram app to subscribe to **Telegram Premium**.\n\nOnce subscribed, you will be able to use the benefits of Telegram Premium in any apps that support it, including unofficial ones. + Install official app + Telegram Premium + Go **beyond the limits**, get exclusive features and support us by subscribing to **Telegram Premium**. + You are all set! + Thank you for subscribing to **Telegram Premium**.\nHere’s what is now unlocked. + Limit of %d Stickers Reached + An older sticker was replaced with this one. You can **increase the limit** to %d stickers + Limit of %d GIFs Reached + An older GIF was replaced with this one. You can **increase the limit** to %d GIFs + The document cant’t be sent, because it is larger than **%1$s**. You can double this limit to **%2$s** per document by subscribing to **Telegram Premium**. + The document cant’t be sent, because it is larger than **%1$s**. + The document cant’t be sent, because it is larger than **%1$s**. We are working to let you increase this limit in the future. + About Telegram Premium + While the free version of Telegram already gives its users more than any other messaging application, **Telegram Premium** pushes its capabilities even further. + **Telegram Premium** is a paid option, because most Premium Features require additional expenses from Telegram to third parties such as data center providers and server manufacturers. Contributions from **Telegram Premium** users allow us to cover such costs and also help Telegram stay free for everyone. + Groups and Channels + Join up to %d channels and large groups + Pinned Chats + Pin up to %d chats in your main chat list + Public Links + Reserve up to %d t.me/name links + Saved GIFs + Save up to %d GIFs in your Favorite GIFs + Favorite Stickers + Save up to %d stickers in your Favorite stickers + Folders + Organize your chats into %d folders + Chats per Folder + Add up to %d chats into each of your folders + Connected Accounts + Connect %d accounts with different mobile numbers + Doubled Limits + Sorry, you can\'t add more than **%1$d** accounts. You can increase this limit to **%2$d** by upgrading to **Telegram Premium**. + Sorry, you can\'t add more than **%1$d** accounts. + Voice-to-Text Conversion + Ability to read the transcript of any incoming voice message. + Advanced Chat Management + Premium + Premuim Stickers + Captions + Use longer descriptions for your photos and videos + An older sticker was replaced with this one. + An older GIF was replaced with this one. + This pack contains premium stickers like this one. + View + **%s** is a subscriber of Telegram Premium. + Hide + Bio + Add more symbols and use links in your bio. + App Icon + Default + Vintage + Aqua + Premium + Turbo + Nox + App icon has been changed to %1$s + File Too Large + Premium App Icon + Choose from a selection of Telegram app icons for your homescreen. + Unlock Premium Icons + About Telegram Premium + Additional Reactions + Unlock a wider range of reactions on messages by subscribing to Telegram Premium. + Additional App Icons + Unlock a wider range of app icons by subscribing to Telegram Premium. + I accept the *Terms of Service* of %1$s. + JOIN REQUEST SENT + Are you sure you want to revoke these links?\n\nThe groups will become private. + Are you sure you want to revoke these links?\n\nThe channels will become private. + Do you want to clear all your recent stickers? + All other sessions terminated. + All websites disconnected. + Can\'t add user + This bot can\'t be opened in the chat with itself. + Unlock this sticker and many more by subscribing to Telegram Premium. + Sorry, you can\'t pin more than %1$d chats to the top. Unpin some that are currently pinned or subscribe to **Telegram Premium** to double the limit to **%2$d** chats. + Sorry, you can\'t pin more than %1$d chats to the top. Unpin some that are currently pinned. + Sorry, you can\'t pin more than %1$d chats to the top. Unpin some that are currently pinned. We are working to let you increase this limit in the future. + Recently active communities + Are you sure you want to leave the selected chats?]]> + Additional animated reactions on messages, available only to Premium subscribers. + Tools to set the default folder, auto-archive and hide new chats from non-contacts. + Owners of **Telegram Premium** accounts have exclusive acces to multiple additional features. + Remove ads such as this one by subscribing to Telegram Premium. + Trending Premium Stickers