diff --git a/TMessagesProj/jni/TgNetWrapper.cpp b/TMessagesProj/jni/TgNetWrapper.cpp index 3558c4939..6fa879eb5 100644 --- a/TMessagesProj/jni/TgNetWrapper.cpp +++ b/TMessagesProj/jni/TgNetWrapper.cpp @@ -5,6 +5,7 @@ #include "tgnet/ConnectionsManager.h" #include "tgnet/MTProtoScheme.h" #include "tgnet/ConnectionSocket.h" +#include "tgnet/FileLog.h" JavaVM *java; jclass jclass_RequestDelegateInternal; @@ -96,12 +97,15 @@ void sendRequest(JNIEnv *env, jclass c, jint instanceNum, jlong object, jobject TL_api_request *request = new TL_api_request(); request->request = (NativeByteBuffer *) (intptr_t) object; if (onComplete != nullptr) { + DEBUG_REF("sendRequest onComplete"); onComplete = env->NewGlobalRef(onComplete); } if (onQuickAck != nullptr) { + DEBUG_REF("sendRequest onQuickAck"); onQuickAck = env->NewGlobalRef(onQuickAck); } if (onWriteToSocket != nullptr) { + DEBUG_REF("sendRequest onWriteToSocket"); onWriteToSocket = env->NewGlobalRef(onWriteToSocket); } ConnectionsManager::getInstance(instanceNum).sendRequest(request, ([onComplete, instanceNum](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) { @@ -238,6 +242,7 @@ jlong checkProxy(JNIEnv *env, jclass c, jint instanceNum, jstring address, jint const char *secretStr = env->GetStringUTFChars(secret, 0); if (requestTimeFunc != nullptr) { + DEBUG_REF("sendRequest requestTimeFunc"); requestTimeFunc = env->NewGlobalRef(requestTimeFunc); } @@ -483,7 +488,8 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (!registerNativeMethods(env, ConnectionsManagerClassPathName, ConnectionsManagerMethods, sizeof(ConnectionsManagerMethods) / sizeof(ConnectionsManagerMethods[0]))) { return JNI_FALSE; } - + + DEBUG_REF("RequestDelegateInternal class"); jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal")); if (jclass_RequestDelegateInternal == 0) { return JNI_FALSE; @@ -493,6 +499,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { return JNI_FALSE; } + DEBUG_REF("RequestTimeDelegate class"); jclass_RequestTimeDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestTimeDelegate")); if (jclass_RequestTimeDelegate == 0) { return JNI_FALSE; @@ -502,6 +509,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { return JNI_FALSE; } + DEBUG_REF("QuickAckDelegate class"); jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate")); if (jclass_RequestDelegateInternal == 0) { return JNI_FALSE; @@ -511,6 +519,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { return JNI_FALSE; } + DEBUG_REF("WriteToSocketDelegate class"); jclass_WriteToSocketDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/WriteToSocketDelegate")); if (jclass_WriteToSocketDelegate == 0) { return JNI_FALSE; @@ -519,6 +528,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) { if (jclass_WriteToSocketDelegate_run == 0) { return JNI_FALSE; } + DEBUG_REF("ConnectionsManager class"); jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager")); if (jclass_ConnectionsManager == 0) { return JNI_FALSE; diff --git a/TMessagesProj/jni/gifvideo.cpp b/TMessagesProj/jni/gifvideo.cpp index 09a42bf87..5de5d4c34 100644 --- a/TMessagesProj/jni/gifvideo.cpp +++ b/TMessagesProj/jni/gifvideo.cpp @@ -121,6 +121,7 @@ typedef struct VideoInfo { } else { attached = false; } + DEBUG_DELREF("gifvideocpp stream"); jniEnv->DeleteGlobalRef(stream); if (attached) { javaVm->DetachCurrentThread(); @@ -955,6 +956,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_telegram_ui_Components_AnimatedFileD int ret; if (streamFileSize != 0) { info->file_size = streamFileSize; + DEBUG_REF("gifvideo.cpp new stream"); info->stream = env->NewGlobalRef(stream); info->account = account; info->fd = open(info->src, O_RDONLY, S_IRUSR); @@ -1381,6 +1383,7 @@ extern "C" JNIEXPORT jint JNICALL Java_org_telegram_ui_Components_AnimatedFileDr extern "C" jint videoOnJNILoad(JavaVM *vm, JNIEnv *env) { //av_log_set_callback(custom_log); + DEBUG_REF("gifvideo.cpp AnimatedFileDrawableStream ref"); jclass_AnimatedFileDrawableStream = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/AnimatedFileDrawableStream")); if (jclass_AnimatedFileDrawableStream == 0) { return JNI_FALSE; diff --git a/TMessagesProj/jni/image.cpp b/TMessagesProj/jni/image.cpp index 7171bafe5..6169b000a 100644 --- a/TMessagesProj/jni/image.cpp +++ b/TMessagesProj/jni/image.cpp @@ -27,14 +27,17 @@ jfieldID jclass_Options_outHeight; jfieldID jclass_Options_outWidth; jint imageOnJNILoad(JavaVM *vm, JNIEnv *env) { + DEBUG_REF("image.cpp nullpointerexception class"); jclass_NullPointerException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/NullPointerException")); if (jclass_NullPointerException == 0) { return JNI_FALSE; } + DEBUG_REF("image.cpp runtimeexception class"); jclass_RuntimeException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/RuntimeException")); if (jclass_RuntimeException == 0) { return JNI_FALSE; } + DEBUG_REF("image.cpp bitmapfactoryoptions class"); jclass_Options = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/BitmapFactory$Options")); if (jclass_Options == 0) { return JNI_FALSE; diff --git a/TMessagesProj/jni/jni.c b/TMessagesProj/jni/jni.c index 5b3b2c115..62f31ccc4 100644 --- a/TMessagesProj/jni/jni.c +++ b/TMessagesProj/jni/jni.c @@ -274,7 +274,7 @@ JNIEXPORT jlong Java_org_telegram_messenger_Utilities_getLastUsageFileTime(JNIEn struct stat attrib; stat(fileName, &attrib); jlong value; - if (attrib.st_atim.tv_sec != 0) { + if (attrib.st_atim.tv_sec > 316000000) { value = attrib.st_atim.tv_sec; } else { value = attrib.st_mtim.tv_sec; diff --git a/TMessagesProj/jni/rlottie/src/lottie/lottiemodel.h b/TMessagesProj/jni/rlottie/src/lottie/lottiemodel.h index 9eabf1fac..b482b58e9 100755 --- a/TMessagesProj/jni/rlottie/src/lottie/lottiemodel.h +++ b/TMessagesProj/jni/rlottie/src/lottie/lottiemodel.h @@ -98,9 +98,9 @@ public: inline void getColorReplacement(std::map *colorMap, const LottieColor &c, float &r, float &g, float &b) { if (colorMap != nullptr && !colorMap->empty()) { - int32_t rr = (int32_t) (c.r * 255); - int32_t gg = (int32_t) (c.g * 255); - int32_t bb = (int32_t) (c.b * 255); + int32_t rr = (int32_t) round(c.r * 255); + int32_t gg = (int32_t) round(c.g * 255); + int32_t bb = (int32_t) round(c.b * 255); int32_t cc = (int32_t) (((bb & 0xff) << 16) | ((gg & 0xff) << 8) | (rr & 0xff)); std::map::iterator iter = colorMap->find(cc); if (iter != colorMap->end()) { diff --git a/TMessagesProj/jni/tgnet/ApiScheme.cpp b/TMessagesProj/jni/tgnet/ApiScheme.cpp index 98a69b5a8..2c0881e04 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.cpp +++ b/TMessagesProj/jni/tgnet/ApiScheme.cpp @@ -56,6 +56,7 @@ void TL_dcOption::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool cdn = (flags & 8) != 0; isStatic = (flags & 16) != 0; thisPortOnly = (flags & 32) != 0; + force_try_ipv6 = (flags & 16384) != 0; id = stream->readInt32(&error); ip_address = stream->readString(&error); port = stream->readInt32(&error); @@ -72,6 +73,7 @@ void TL_dcOption::serializeToStream(NativeByteBuffer *stream) { flags = cdn ? (flags | 8) : (flags &~ 8); flags = isStatic ? (flags | 16) : (flags &~ 16); flags = thisPortOnly ? (flags | 32) : (flags &~ 32); + flags = force_try_ipv6 ? (flags | 16384) : (flags &~ 16384); 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 60a9bf309..fe1e9cfd9 100644 --- a/TMessagesProj/jni/tgnet/ApiScheme.h +++ b/TMessagesProj/jni/tgnet/ApiScheme.h @@ -50,6 +50,7 @@ public: bool cdn; bool isStatic; bool thisPortOnly; + bool force_try_ipv6; int32_t id; std::string ip_address; int32_t port; diff --git a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp index b89089616..fc10b8e1e 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -1899,14 +1899,17 @@ void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete exit(1); } if (ptr1 != nullptr) { + DEBUG_DELREF("connectionsmanager ptr1"); env->DeleteGlobalRef(ptr1); ptr1 = nullptr; } if (ptr2 != nullptr) { + DEBUG_DELREF("connectionsmanager ptr2"); env->DeleteGlobalRef(ptr2); ptr2 = nullptr; } if (ptr3 != nullptr) { + DEBUG_DELREF("connectionsmanager ptr3"); env->DeleteGlobalRef(ptr3); ptr3 = nullptr; } @@ -3103,12 +3106,14 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) { std::vector addressesIpv4Download; std::vector addressesIpv6Download; bool isCdn = false; + bool forceTryIpV6; void addAddressAndPort(TL_dcOption *dcOption) { std::vector *addresses; if (!isCdn) { isCdn = dcOption->cdn; } + forceTryIpV6 = dcOption->force_try_ipv6; if (dcOption->media_only) { if (dcOption->ipv6) { addresses = &addressesIpv6Download; @@ -3131,7 +3136,7 @@ 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], 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 (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has_secret = %d[%d], try_this_port_only = %d, force_try_ipv6 = %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, dcOption->force_try_ipv6 ? 1 : 0); if (dcOption->thisPortOnly) { addresses->insert(addresses->begin(), TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret)); } else { @@ -3681,6 +3686,7 @@ void ConnectionsManager::useJavaVM(JavaVM *vm, bool useJavaByteBuffers) { if (LOGS_ENABLED) DEBUG_E("can't get jnienv"); exit(1); } + DEBUG_REF("connectionsmanager byte buffer"); jclass_ByteBuffer = (jclass) env->NewGlobalRef(env->FindClass("java/nio/ByteBuffer")); if (jclass_ByteBuffer == nullptr) { if (LOGS_ENABLED) DEBUG_E("can't find java ByteBuffer class"); diff --git a/TMessagesProj/jni/tgnet/FileLog.cpp b/TMessagesProj/jni/tgnet/FileLog.cpp index 8f9fc22ae..d81cfb49e 100644 --- a/TMessagesProj/jni/tgnet/FileLog.cpp +++ b/TMessagesProj/jni/tgnet/FileLog.cpp @@ -22,6 +22,8 @@ bool LOGS_ENABLED = true; bool LOGS_ENABLED = false; #endif +bool REF_LOGS_ENABLED = false; + FileLog &FileLog::getInstance() { static FileLog instance; return instance; @@ -166,3 +168,43 @@ void FileLog::d(const char *message, ...) { va_end(argptr); } + +static int refsCount = 0; + +void FileLog::ref(const char *message, ...) { + if (!REF_LOGS_ENABLED) { + return; + } + va_list argptr; + va_start(argptr, message); + time_t t = time(0); + struct tm *now = localtime(&t); + refsCount++; +#ifdef ANDROID + std::ostringstream s; + s << refsCount << " refs (+ref): " << message; + __android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr); + va_end(argptr); + va_start(argptr, message); +#endif + va_end(argptr); +} + +void FileLog::delref(const char *message, ...) { + if (!REF_LOGS_ENABLED) { + return; + } + va_list argptr; + va_start(argptr, message); + time_t t = time(0); + struct tm *now = localtime(&t); + refsCount--; +#ifdef ANDROID + std::ostringstream s; + s << refsCount << " refs (-ref): " << message; + __android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr); + va_end(argptr); + va_start(argptr, message); +#endif + va_end(argptr); +} \ No newline at end of file diff --git a/TMessagesProj/jni/tgnet/FileLog.h b/TMessagesProj/jni/tgnet/FileLog.h index 79945e72d..0569d6a0b 100644 --- a/TMessagesProj/jni/tgnet/FileLog.h +++ b/TMessagesProj/jni/tgnet/FileLog.h @@ -19,6 +19,8 @@ public: static void e(const char *message, ...) __attribute__((format (printf, 1, 2))); static void w(const char *message, ...) __attribute__((format (printf, 1, 2))); static void d(const char *message, ...) __attribute__((format (printf, 1, 2))); + static void ref(const char *message, ...) __attribute__((format (printf, 1, 2))); + static void delref(const char *message, ...) __attribute__((format (printf, 1, 2))); static FileLog &getInstance(); @@ -34,4 +36,7 @@ extern bool LOGS_ENABLED; #define DEBUG_W FileLog::getInstance().w #define DEBUG_D FileLog::getInstance().d +#define DEBUG_REF FileLog::getInstance().ref +#define DEBUG_DELREF FileLog::getInstance().delref + #endif diff --git a/TMessagesProj/jni/tgnet/NativeByteBuffer.cpp b/TMessagesProj/jni/tgnet/NativeByteBuffer.cpp index afbc4cbbe..b7e1d6960 100644 --- a/TMessagesProj/jni/tgnet/NativeByteBuffer.cpp +++ b/TMessagesProj/jni/tgnet/NativeByteBuffer.cpp @@ -14,6 +14,8 @@ #include "ConnectionsManager.h" #include "BuffersStorage.h" +static int buffersCount = 0; + NativeByteBuffer::NativeByteBuffer(uint32_t size) { #ifdef ANDROID if (jclass_ByteBuffer != nullptr) { @@ -27,6 +29,7 @@ NativeByteBuffer::NativeByteBuffer(uint32_t size) { if (LOGS_ENABLED) DEBUG_E("can't create javaByteBuffer"); exit(1); } + DEBUG_REF("nativebytebuffer"); jobject globalRef = env->NewGlobalRef(javaByteBuffer); env->DeleteLocalRef(javaByteBuffer); javaByteBuffer = globalRef; @@ -43,6 +46,7 @@ NativeByteBuffer::NativeByteBuffer(uint32_t size) { if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer"); exit(1); } + _limit = _capacity = size; } @@ -64,6 +68,7 @@ NativeByteBuffer::~NativeByteBuffer() { if (LOGS_ENABLED) DEBUG_E("can't get jnienv"); exit(1); } + DEBUG_DELREF("nativebytebuffer"); env->DeleteGlobalRef(javaByteBuffer); javaByteBuffer = nullptr; } @@ -694,6 +699,7 @@ jobject NativeByteBuffer::getJavaByteBuffer() { if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer"); exit(1); } + DEBUG_REF("nativebytebuffer"); jobject globalRef = env->NewGlobalRef(javaByteBuffer); env->DeleteLocalRef(javaByteBuffer); javaByteBuffer = globalRef; diff --git a/TMessagesProj/jni/tgnet/ProxyCheckInfo.cpp b/TMessagesProj/jni/tgnet/ProxyCheckInfo.cpp index c6835b970..73c84c55d 100644 --- a/TMessagesProj/jni/tgnet/ProxyCheckInfo.cpp +++ b/TMessagesProj/jni/tgnet/ProxyCheckInfo.cpp @@ -8,10 +8,12 @@ #include "ProxyCheckInfo.h" #include "ConnectionsManager.h" +#include "FileLog.h" ProxyCheckInfo::~ProxyCheckInfo() { #ifdef ANDROID if (ptr1 != nullptr) { + DEBUG_DELREF("tgnet (2) request ptr1"); jniEnv[instanceNum]->DeleteGlobalRef(ptr1); ptr1 = nullptr; } diff --git a/TMessagesProj/jni/tgnet/Request.cpp b/TMessagesProj/jni/tgnet/Request.cpp index c041e253a..14667314b 100644 --- a/TMessagesProj/jni/tgnet/Request.cpp +++ b/TMessagesProj/jni/tgnet/Request.cpp @@ -13,6 +13,7 @@ #include "ConnectionsManager.h" #include "Datacenter.h" #include "Connection.h" +#include "FileLog.h" Request::Request(int32_t instance, int32_t token, ConnectionType type, uint32_t flags, uint32_t datacenter, onCompleteFunc completeFunc, onQuickAckFunc quickAckFunc, onWriteToSocketFunc writeToSocketFunc) { requestToken = token; @@ -29,14 +30,17 @@ Request::Request(int32_t instance, int32_t token, ConnectionType type, uint32_t Request::~Request() { #ifdef ANDROID if (ptr1 != nullptr) { + DEBUG_DELREF("tgnet request ptr1"); jniEnv[instanceNum]->DeleteGlobalRef(ptr1); ptr1 = nullptr; } if (ptr2 != nullptr) { + DEBUG_DELREF("tgnet request ptr2"); jniEnv[instanceNum]->DeleteGlobalRef(ptr2); ptr2 = nullptr; } if (ptr3 != nullptr) { + DEBUG_DELREF("tgnet request ptr3"); jniEnv[instanceNum]->DeleteGlobalRef(ptr3); ptr3 = nullptr; } diff --git a/TMessagesProj/jni/voip/libtgvoip/os/android/AudioInputAndroid.cpp b/TMessagesProj/jni/voip/libtgvoip/os/android/AudioInputAndroid.cpp index 313a24452..536e14966 100644 --- a/TMessagesProj/jni/voip/libtgvoip/os/android/AudioInputAndroid.cpp +++ b/TMessagesProj/jni/voip/libtgvoip/os/android/AudioInputAndroid.cpp @@ -8,6 +8,7 @@ #include #include "../../logging.h" #include "JNIUtilities.h" +#include "tgnet/FileLog.h" extern JavaVM* sharedJVM; @@ -25,6 +26,7 @@ AudioInputAndroid::AudioInputAndroid(){ jni::DoWithJNI([this](JNIEnv* env){ jmethodID ctor=env->GetMethodID(jniClass, "", "(J)V"); jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this); + DEBUG_REF("AudioInputAndroid"); javaObject=env->NewGlobalRef(obj); env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2); @@ -38,6 +40,7 @@ AudioInputAndroid::~AudioInputAndroid(){ MutexGuard guard(mutex); jni::DoWithJNI([this](JNIEnv* env){ env->CallVoidMethod(javaObject, releaseMethod); + DEBUG_DELREF("AudioInputAndroid"); env->DeleteGlobalRef(javaObject); javaObject=NULL; }); diff --git a/TMessagesProj/jni/voip/libtgvoip/os/android/AudioOutputAndroid.cpp b/TMessagesProj/jni/voip/libtgvoip/os/android/AudioOutputAndroid.cpp index c1dc2d5df..96702f034 100644 --- a/TMessagesProj/jni/voip/libtgvoip/os/android/AudioOutputAndroid.cpp +++ b/TMessagesProj/jni/voip/libtgvoip/os/android/AudioOutputAndroid.cpp @@ -7,6 +7,7 @@ #include "AudioOutputAndroid.h" #include #include "../../logging.h" +#include "tgnet/FileLog.h" extern JavaVM* sharedJVM; @@ -30,6 +31,7 @@ AudioOutputAndroid::AudioOutputAndroid(){ jmethodID ctor=env->GetMethodID(jniClass, "", "(J)V"); jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this); + DEBUG_REF("AudioOutputAndroid"); javaObject=env->NewGlobalRef(obj); env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2); @@ -50,6 +52,7 @@ AudioOutputAndroid::~AudioOutputAndroid(){ } env->CallVoidMethod(javaObject, releaseMethod); + DEBUG_DELREF("AudioOutputAndroid"); env->DeleteGlobalRef(javaObject); javaObject=NULL; diff --git a/TMessagesProj/jni/voip/libtgvoip/os/android/VideoSourceAndroid.cpp b/TMessagesProj/jni/voip/libtgvoip/os/android/VideoSourceAndroid.cpp index 8431f5005..5b297f770 100644 --- a/TMessagesProj/jni/voip/libtgvoip/os/android/VideoSourceAndroid.cpp +++ b/TMessagesProj/jni/voip/libtgvoip/os/android/VideoSourceAndroid.cpp @@ -6,6 +6,7 @@ #include "JNIUtilities.h" #include "../../logging.h" #include "../../PrivateDefines.h" +#include "tgnet/FileLog.h" using namespace tgvoip; using namespace tgvoip::video; @@ -27,6 +28,7 @@ VideoSourceAndroid::VideoSourceAndroid(jobject jobj) : javaObject(jobj){ VideoSourceAndroid::~VideoSourceAndroid(){ jni::DoWithJNI([this](JNIEnv* env){ + DEBUG_DELREF("VideoSourceAndroid"); env->DeleteGlobalRef(javaObject); }); } diff --git a/TMessagesProj/jni/voip/org_telegram_messenger_voip_Instance.cpp b/TMessagesProj/jni/voip/org_telegram_messenger_voip_Instance.cpp index 311a2ce00..b2bb47369 100644 --- a/TMessagesProj/jni/voip/org_telegram_messenger_voip_Instance.cpp +++ b/TMessagesProj/jni/voip/org_telegram_messenger_voip_Instance.cpp @@ -381,9 +381,13 @@ void initWebRTC(JNIEnv *env) { rtc::InitializeSSL(); webrtcLoaded = true; + DEBUG_REF("NativeInstanceClass"); NativeInstanceClass = static_cast(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/NativeInstance"))); + DEBUG_REF("TrafficStatsClass"); TrafficStatsClass = static_cast(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$TrafficStats"))); + DEBUG_REF("FingerprintClass"); FingerprintClass = static_cast(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$Fingerprint"))); + DEBUG_REF("FinalStateClass"); FinalStateClass = static_cast(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$FinalState"))); FinalStateInitMethod = env->GetMethodID(FinalStateClass, "", "([BLjava/lang/String;Lorg/telegram/messenger/voip/Instance$TrafficStats;Z)V"); } diff --git a/TMessagesProj/jni/voip/tg_voip_jni.cpp b/TMessagesProj/jni/voip/tg_voip_jni.cpp index 05f021873..5b3725957 100644 --- a/TMessagesProj/jni/voip/tg_voip_jni.cpp +++ b/TMessagesProj/jni/voip/tg_voip_jni.cpp @@ -20,6 +20,7 @@ #include "libtgvoip/PrivateDefines.h" #include "libtgvoip/logging.h" #include "../c_utils.h" +#include "tgnet/FileLog.h" #ifdef TGVOIP_HAS_CONFIG #include @@ -63,6 +64,7 @@ namespace tgvoip { jlong VoIPController_nativeInit(JNIEnv *env, jobject thiz, jstring persistentStateFile) { ImplDataAndroid *impl = new ImplDataAndroid(); + DEBUG_REF("VoIPController_nativeInit"); impl->javaObject = env->NewGlobalRef(thiz); if (persistentStateFile) { impl->persistentStateFile = jni::JavaStringToStdString(env, persistentStateFile); @@ -123,6 +125,7 @@ namespace tgvoip { ctlr->Stop(); std::vector state = ctlr->GetPersistentState(); delete ctlr; + DEBUG_DELREF("VoIPController_nativeRelease"); env->DeleteGlobalRef(impl->javaObject); if (!impl->persistentStateFile.empty()) { FILE *f = fopen(impl->persistentStateFile.c_str(), "w"); @@ -294,6 +297,7 @@ int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env) { env->GetJavaVM(&sharedJVM); if (!AudioInputAndroid::jniClass) { jclass cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioRecordJNI"); + DEBUG_REF("AudioRecordJNI"); AudioInputAndroid::jniClass = (jclass) env->NewGlobalRef(cls); AudioInputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V"); AudioInputAndroid::releaseMethod = env->GetMethodID(cls, "release", "()V"); @@ -302,6 +306,7 @@ int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env) { AudioInputAndroid::getEnabledEffectsMaskMethod = env->GetMethodID(cls, "getEnabledEffectsMask", "()I"); cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioTrackJNI"); + DEBUG_REF("AudioTrackJNI"); AudioOutputAndroid::jniClass = (jclass) env->NewGlobalRef(cls); AudioOutputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V"); AudioOutputAndroid::releaseMethod = env->GetMethodID(cls, "release", "()V"); @@ -313,6 +318,7 @@ int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env) { setSignalBarsMethod = env->GetMethodID(controller, "handleSignalBarsChange", "(I)V"); if (!jniUtilitiesClass) { + DEBUG_REF("JNIUtilities"); jniUtilitiesClass = (jclass) env->NewGlobalRef(env->FindClass(TGVOIP_PACKAGE_PATH "/JNIUtilities")); } diff --git a/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp b/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp index 7cf031dc8..3feb47ee7 100644 --- a/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp +++ b/TMessagesProj/jni/voip/tgcalls/platform/android/AndroidContext.cpp @@ -6,9 +6,12 @@ namespace tgcalls { AndroidContext::AndroidContext(JNIEnv *env, jobject instance, bool screencast) { + DEBUG_REF("VideoCapturerDevice"); VideoCapturerDeviceClass = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/VideoCapturerDevice")); jmethodID initMethodId = env->GetMethodID(VideoCapturerDeviceClass, "", "(Z)V"); + DEBUG_REF("VideoCapturerDevice javaCapturer"); javaCapturer = env->NewGlobalRef(env->NewObject(VideoCapturerDeviceClass, initMethodId, screencast)); + DEBUG_REF("VideoCapturerDevice javaInstance"); javaInstance = env->NewGlobalRef(instance); } @@ -17,17 +20,21 @@ AndroidContext::~AndroidContext() { jmethodID onDestroyMethodId = env->GetMethodID(VideoCapturerDeviceClass, "onDestroy", "()V"); env->CallVoidMethod(javaCapturer, onDestroyMethodId); + DEBUG_DELREF("javaCapturer"); env->DeleteGlobalRef(javaCapturer); javaCapturer = nullptr; + DEBUG_DELREF("VideoCapturerDeviceClass"); env->DeleteGlobalRef(VideoCapturerDeviceClass); if (javaInstance) { + DEBUG_DELREF("javaInstance"); env->DeleteGlobalRef(javaInstance); } } void AndroidContext::setJavaInstance(JNIEnv *env, jobject instance) { + DEBUG_REF("setJavaInstance"); javaInstance = env->NewGlobalRef(instance); } diff --git a/TMessagesProj/jni/voip/webrtc/base/android/scoped_java_ref.cc b/TMessagesProj/jni/voip/webrtc/base/android/scoped_java_ref.cc index 7d31a75bc..d0d71f3ea 100644 --- a/TMessagesProj/jni/voip/webrtc/base/android/scoped_java_ref.cc +++ b/TMessagesProj/jni/voip/webrtc/base/android/scoped_java_ref.cc @@ -7,6 +7,8 @@ #include "base/android/jni_android.h" #include "base/logging.h" +#include + namespace base { namespace android { namespace { @@ -60,10 +62,14 @@ void JavaRef::SetNewGlobalRef(JNIEnv* env, jobject obj) { } else { DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread. } - if (obj) + if (obj) { + DEBUG_REF("scoped_java_ref.cc"); obj = env->NewGlobalRef(obj); - if (obj_) + } + if (obj_) { + DEBUG_DELREF("scoped_java_ref.cc"); env->DeleteGlobalRef(obj_); + } obj_ = obj; } @@ -77,6 +83,7 @@ void JavaRef::ResetLocalRef(JNIEnv* env) { void JavaRef::ResetGlobalRef() { if (obj_) { + DEBUG_DELREF("webrtc ResetGlobalRef"); AttachCurrentThread()->DeleteGlobalRef(obj_); obj_ = nullptr; } diff --git a/TMessagesProj/jni/voip/webrtc/modules/utility/source/helpers_android.cc b/TMessagesProj/jni/voip/webrtc/modules/utility/source/helpers_android.cc index 9cfee8a2a..0e04817bc 100644 --- a/TMessagesProj/jni/voip/webrtc/modules/utility/source/helpers_android.cc +++ b/TMessagesProj/jni/voip/webrtc/modules/utility/source/helpers_android.cc @@ -17,6 +17,7 @@ #include "rtc_base/checks.h" #include "rtc_base/platform_thread.h" +#include "tgnet/FileLog.h" #define TAG "HelpersAndroid" #define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) @@ -76,6 +77,7 @@ jclass FindClass(JNIEnv* jni, const char* name) { } jobject NewGlobalRef(JNIEnv* jni, jobject o) { + DEBUG_REF("webrtc new global ref"); jobject ret = jni->NewGlobalRef(o); CHECK_EXCEPTION(jni) << "Error during NewGlobalRef"; RTC_CHECK(ret); @@ -83,6 +85,7 @@ jobject NewGlobalRef(JNIEnv* jni, jobject o) { } void DeleteGlobalRef(JNIEnv* jni, jobject o) { + DEBUG_DELREF("webrtc remove global ref"); jni->DeleteGlobalRef(o); CHECK_EXCEPTION(jni) << "Error during DeleteGlobalRef"; } diff --git a/TMessagesProj/jni/voip/webrtc/modules/utility/source/jvm_android.cc b/TMessagesProj/jni/voip/webrtc/modules/utility/source/jvm_android.cc index 96ec46806..69bfdc9d1 100644 --- a/TMessagesProj/jni/voip/webrtc/modules/utility/source/jvm_android.cc +++ b/TMessagesProj/jni/voip/webrtc/modules/utility/source/jvm_android.cc @@ -17,6 +17,7 @@ #include "rtc_base/checks.h" #include "rtc_base/logging.h" #include "rtc_base/platform_thread.h" +#include "tgnet/FileLog.h" namespace webrtc { @@ -44,6 +45,7 @@ void LoadClasses(JNIEnv* jni) { RTC_LOG(LS_INFO) << "name: " << c.name; CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name; RTC_CHECK(localRef) << c.name; + DEBUG_REF("webrtc 4 globalref"); jclass globalRef = reinterpret_cast(jni->NewGlobalRef(localRef)); CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name; RTC_CHECK(globalRef) << c.name; @@ -53,6 +55,7 @@ void LoadClasses(JNIEnv* jni) { void FreeClassReferences(JNIEnv* jni) { for (auto& c : loaded_classes) { + DEBUG_DELREF("FreeClassReferences"); jni->DeleteGlobalRef(c.clazz); c.clazz = nullptr; } @@ -94,11 +97,13 @@ JvmThreadConnector::~JvmThreadConnector() { // GlobalRef implementation. GlobalRef::GlobalRef(JNIEnv* jni, jobject object) : jni_(jni), j_object_(NewGlobalRef(jni, object)) { + DEBUG_REF("webrtc jvm globalref"); RTC_LOG(LS_INFO) << "GlobalRef::ctor"; } GlobalRef::~GlobalRef() { RTC_LOG(LS_INFO) << "GlobalRef::dtor"; + DEBUG_DELREF("webrtc jvm globalref"); DeleteGlobalRef(jni_, j_object_); } diff --git a/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/class_loader.cc b/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/class_loader.cc index 1789d78c8..2b93f41a8 100644 --- a/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/class_loader.cc +++ b/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/class_loader.cc @@ -33,6 +33,7 @@ class ClassLoader { public: explicit ClassLoader(JNIEnv* env) : class_loader_(jni::Java_WebRtcClassLoader_getClassLoader(env)) { + DEBUG_REF("webrtc class_loader"); class_loader_class_ = reinterpret_cast( env->NewGlobalRef(env->FindClass("java/lang/ClassLoader"))); CHECK_EXCEPTION(env); diff --git a/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/scoped_java_ref.h b/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/scoped_java_ref.h index a2be447de..ca11cdec6 100644 --- a/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/scoped_java_ref.h +++ b/TMessagesProj/jni/voip/webrtc/sdk/android/native_api/jni/scoped_java_ref.h @@ -19,6 +19,7 @@ #include #include "sdk/android/native_api/jni/jvm.h" +#include "tgnet/FileLog.h" namespace webrtc { @@ -182,8 +183,10 @@ class ScopedJavaGlobalRef : public JavaRef { : JavaRef(other.Release()) {} ~ScopedJavaGlobalRef() { - if (obj_ != nullptr) + if (obj_ != nullptr) { + DEBUG_DELREF("ScopedJavaGlobalRef"); AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_); + } } ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete; @@ -192,13 +195,20 @@ class ScopedJavaGlobalRef : public JavaRef { void operator=(const JavaRef& other) { JNIEnv* env = AttachCurrentThreadIfNeeded(); if (obj_ != nullptr) { + DEBUG_DELREF("webrtc 3 delete global ref"); env->DeleteGlobalRef(obj_); } - obj_ = other.is_null() ? nullptr : env->NewGlobalRef(other.obj()); + if (other.is_null()) { + obj_ = nullptr; + } else { + DEBUG_REF("webrtc 3 new global ref"); + obj_ = env->NewGlobalRef(other.obj()); + } } void operator=(std::nullptr_t) { if (obj_ != nullptr) { + DEBUG_DELREF("webrtc 3 delete global ref"); AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_); } obj_ = nullptr; diff --git a/TMessagesProj/jni/voip/webrtc/sdk/android/src/jni/jni_helpers.cc b/TMessagesProj/jni/voip/webrtc/sdk/android/src/jni/jni_helpers.cc index 53399abab..1098dfb23 100644 --- a/TMessagesProj/jni/voip/webrtc/sdk/android/src/jni/jni_helpers.cc +++ b/TMessagesProj/jni/voip/webrtc/sdk/android/src/jni/jni_helpers.cc @@ -12,6 +12,7 @@ #include #include "sdk/android/native_api/jni/java_types.h" +#include "tgnet/FileLog.h" namespace webrtc { namespace jni { @@ -26,6 +27,7 @@ ScopedJavaLocalRef NewDirectByteBuffer(JNIEnv* env, } jobject NewGlobalRef(JNIEnv* jni, jobject o) { + DEBUG_REF("webrtc 2 new global ref"); jobject ret = jni->NewGlobalRef(o); CHECK_EXCEPTION(jni) << "error during NewGlobalRef"; RTC_CHECK(ret); @@ -33,6 +35,7 @@ jobject NewGlobalRef(JNIEnv* jni, jobject o) { } void DeleteGlobalRef(JNIEnv* jni, jobject o) { + DEBUG_DELREF("webrtc 2 delete global ref"); jni->DeleteGlobalRef(o); CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef"; } diff --git a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java index 0ac4c5194..876c5d76e 100644 --- a/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java +++ b/TMessagesProj/src/main/java/androidx/recyclerview/widget/LinearLayoutManager.java @@ -802,6 +802,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements mLayoutState.mScrapList = null; } + protected int firstPosition() { + return 0; + } + private void updateAnchorInfoForLayout(RecyclerView.Recycler recycler, RecyclerView.State state, AnchorInfo anchorInfo) { if (updateAnchorFromPendingData(state, anchorInfo)) { @@ -821,7 +825,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements Log.d(TAG, "deciding anchor info for fresh state"); } anchorInfo.assignCoordinateFromPadding(); - anchorInfo.mPosition = mStackFromEnd ? state.getItemCount() - 1 : 0; + anchorInfo.mPosition = mStackFromEnd ? state.getItemCount() - 1 : firstPosition(); } /** diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java index 86c9bce6a..278701fbd 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AndroidUtilities.java @@ -493,6 +493,16 @@ public class AndroidUtilities { } public static void recycleBitmaps(List bitmapToRecycle) { + if (Build.VERSION.SDK_INT <= 23) { + // cause to crash: + // /system/lib/libskia.so (SkPixelRef::unlockPixels()+3) + // /system/lib/libskia.so (SkBitmap::freePixels()+14) + // /system/lib/libskia.so (SkBitmap::setPixelRef(SkPixelRef*, int, int)+50) + // /system/lib/libhwui.so (android::uirenderer::ResourceCache::recycleLocked(SkBitmap*)+30) + // /system/lib/libhwui.so (android::uirenderer::ResourceCache::recycle(SkBitmap*)+20) + // gc recycle it automatically + return; + } if (bitmapToRecycle != null && !bitmapToRecycle.isEmpty()) { AndroidUtilities.runOnUIThread(() -> Utilities.globalQueue.postRunnable(() -> { for (int i = 0; i < bitmapToRecycle.size(); i++) { @@ -505,7 +515,7 @@ public class AndroidUtilities { } } } - }), Build.VERSION.SDK_INT <= 23 ? 100 : 36); + }), 36); } } @@ -628,6 +638,11 @@ public class AndroidUtilities { if (TextUtils.indexOf(s, '─') >= 0) { s = new SpannableStringBuilder(s.toString().replace('─', ' ')); } + if (!TextUtils.isEmpty(s) && TextUtils.lastIndexOf(s, '_') == s.length() - 1) { + //fix infinity loop regex + SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(s.toString()); + s = spannableStringBuilder.replace(s.length() - 1, s.length(), "a"); + } Matcher m = pattern.matcher(s); while (m.find()) { int start = m.start(); @@ -1934,20 +1949,18 @@ public class AndroidUtilities { FileLog.d("external dir mounted"); try { File file; - if (Build.VERSION.SDK_INT >= 19) { - File[] dirs = ApplicationLoader.applicationContext.getExternalCacheDirs(); - file = dirs[0]; - if (!TextUtils.isEmpty(SharedConfig.storageCacheDir)) { - for (int a = 0; a < dirs.length; a++) { - if (dirs[a] != null && dirs[a].getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) { - file = dirs[a]; - break; - } + + File[] dirs = ApplicationLoader.applicationContext.getExternalCacheDirs(); + file = dirs[0]; + if (!TextUtils.isEmpty(SharedConfig.storageCacheDir)) { + for (int a = 0; a < dirs.length; a++) { + if (dirs[a] != null && dirs[a].getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) { + file = dirs[a]; + break; } } - } else { - file = ApplicationLoader.applicationContext.getExternalCacheDir(); } + FileLog.d("check dir " + (file == null ? null : file.getPath()) + " "); if (file != null && (file.exists() || file.mkdirs()) && file.canWrite()) { // boolean canWrite = true; @@ -4782,6 +4795,13 @@ public class AndroidUtilities { ); } + public static boolean isEROFS(Exception e) { + return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && e instanceof IOException && + (e.getCause() instanceof ErrnoException && ((ErrnoException) e.getCause()).errno == OsConstants.EROFS) || + (e.getMessage() != null && e.getMessage().toLowerCase().contains("read-only file system")) + ); + } + public static CharSequence replaceCharSequence(String what, CharSequence from, CharSequence obj) { SpannableStringBuilder spannableStringBuilder; if (from instanceof SpannableStringBuilder) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java b/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java index ec678d6c1..52d1cb45e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java @@ -14,7 +14,7 @@ public class AutoDeleteMediaTask { public static void run() { int time = (int) (System.currentTimeMillis() / 1000); - if (!BuildVars.DEBUG_PRIVATE_VERSION && Math.abs(time - SharedConfig.lastKeepMediaCheckTime) < 24 * 60 * 60) { + if (Math.abs(time - SharedConfig.lastKeepMediaCheckTime) < 24 * 60 * 60) { return; } SharedConfig.lastKeepMediaCheckTime = time; @@ -103,13 +103,16 @@ public class AutoDeleteMediaTask { } long lastUsageTime = Utilities.getLastUsageFileTime(file.file.getAbsolutePath()); long timeLocal = time - seconds; - boolean needDelete = lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath()); + boolean needDelete = lastUsageTime > 316000000 && lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath()); if (needDelete) { try { if (BuildVars.LOGS_ENABLED) { autoDeletedFiles++; autoDeletedFilesSize += file.file.length(); } + if (BuildVars.DEBUG_PRIVATE_VERSION) { + FileLog.d("delete file " + file.file.getPath() + " last_usage_time=" + lastUsageTime + " time_local=" + timeLocal); + } file.file.delete(); } catch (Exception exception) { FileLog.e(exception); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java index 1a568b401..a36f0b825 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BillingController.java @@ -315,6 +315,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien @Override public void onBillingSetupFinished(@NonNull BillingResult setupBillingResult) { + FileLog.d("Billing setup finished with result " + setupBillingResult); if (setupBillingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { queryProductDetails(Collections.singletonList(PREMIUM_PRODUCT), (billingResult, list) -> { if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 563b55530..e9e2c0b32 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java @@ -24,8 +24,8 @@ public class BuildVars { public static boolean USE_CLOUD_STRINGS = true; public static boolean CHECK_UPDATES = true; public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29; - public static int BUILD_VERSION = 3227; - public static String BUILD_VERSION_STRING = "9.5.4"; + public static int BUILD_VERSION = 3249; + public static String BUILD_VERSION_STRING = "9.5.7"; public static int APP_ID = 12652123; // set you own APP_ID public static String APP_HASH = "bb81fa5b3c3f80706ac142c9b72ce9ef"; // set you own APP_HASH diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java index be43aa674..b62dc24b8 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ContactsController.java @@ -23,13 +23,13 @@ import android.net.Uri; import android.os.Build; import android.provider.BaseColumns; import android.provider.ContactsContract; -import android.telephony.PhoneNumberUtils; import android.text.TextUtils; -import android.util.Log; import android.util.SparseArray; import androidx.collection.LongSparseArray; +import com.google.android.exoplayer2.util.Log; + import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.fakepasscode.FakePasscode; import org.telegram.messenger.fakepasscode.FakePasscodeUtils; @@ -641,6 +641,7 @@ public class ContactsController extends BaseController { ArrayList idsArr = new ArrayList<>(); pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null); + long time = System.currentTimeMillis(); int lastContactId = 1; if (pCur != null) { int count = pCur.getCount(); @@ -809,68 +810,96 @@ public class ContactsController extends BaseController { } pCur = null; } + FileLog.d("loading contacts 1 query time = " + (System.currentTimeMillis() - time) + " contactsSize = " + (contactsMap == null ? 0 : contactsMap.size())); + time = System.currentTimeMillis(); + + HashMap phoneBookContactHashMap = new HashMap<>(); + ArrayList phonebookContactsId = new ArrayList<>(); + + Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, new String[]{ + ContactsContract.Contacts._ID, + ContactsContract.Contacts.LOOKUP_KEY, + ContactsContract.Contacts.DISPLAY_NAME + }, ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?", new String[]{"0"}, null); - Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?", new String[]{"0"}, null); if (cur != null) { - String[] metadata = new String[5]; - Pattern phonePattern = Pattern.compile(".*(\\+[0-9 \\-]+).*"); while (cur.moveToNext()) { - String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID)); - String lookup_key = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)); - String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); - String phone = null; - if ((contactsMap != null && contactsMap.get(lookup_key) != null) || TextUtils.isEmpty(name)) { + PhoneBookContact phoneBookContact = new PhoneBookContact(); + phoneBookContact.id = cur.getString(0); + phoneBookContact.lookup_key = cur.getString(1); + phoneBookContact.name = cur.getString(2); + if ((contactsMap != null && contactsMap.get(phoneBookContact.lookup_key) != null) || TextUtils.isEmpty(phoneBookContact.name)) { continue; } - pCur = cr.query( - ContactsContract.Data.CONTENT_URI, - null, - ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", - new String[]{id}, null); - loop : while (pCur.moveToNext()) { - metadata[0] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA1)); - metadata[1] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA2)); - metadata[2] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA3)); - metadata[3] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA4)); - metadata[4] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA5)); - for (int i = 0; i < metadata.length; i++) { - if (metadata[i] == null) { - continue; - } - Matcher matcher = phonePattern.matcher(metadata[i]); - if (matcher.matches()) { - phone = matcher.group(1).replace(" ", "").replace("-", ""); - break loop; - } - } - } - - pCur.close(); - - if (phone != null) { - - String shortNumber = phone; - if (phone.startsWith("+")) { - shortNumber = phone.substring(1); - } - - Contact contact = new Contact(); - contact.first_name = name; - contact.last_name = ""; - contact.contact_id = lastContactId++; - contact.key = lookup_key; - contact.phones.add(phone); - contact.shortPhones.add(shortNumber); - contact.phoneDeleted.add(0); - contact.phoneTypes.add(LocaleController.getString("PhoneOther", R.string.PhoneOther)); - -// contact.provider = accountType; -// contact.isGoodProvider = isGoodAccountType; - contactsMap.put(lookup_key, contact); - } + phoneBookContactHashMap.put(phoneBookContact.id, phoneBookContact); + phonebookContactsId.add(phoneBookContact.id); } cur.close(); } + FileLog.d("loading contacts 2 query time = " + (System.currentTimeMillis() - time) + " phoneBookConacts size = " + phonebookContactsId.size()); + time = System.currentTimeMillis(); + + if (!phonebookContactsId.isEmpty()) { + String[] metadata = new String[4]; + Pattern phonePattern = Pattern.compile(".*(\\+[0-9 \\-]+).*"); + pCur = cr.query( + ContactsContract.Data.CONTENT_URI, + new String[]{ + ContactsContract.CommonDataKinds.Phone.CONTACT_ID, + ContactsContract.Data.DATA1, + ContactsContract.Data.DATA2, + ContactsContract.Data.DATA3, + ContactsContract.Data.DATA4, + }, + ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " IN (" + TextUtils.join(", ", phonebookContactsId) + ")", + null, null); + if (pCur != null) { + while (pCur.moveToNext()) { + String id = pCur.getString(0); + PhoneBookContact phoneBookContact = phoneBookContactHashMap.get(id); + if (phoneBookContact != null) { + metadata[0] = pCur.getString(1); + metadata[1] = pCur.getString(2); + metadata[2] = pCur.getString(3); + metadata[3] = pCur.getString(4); + for (int i = 0; i < metadata.length; i++) { + if (metadata[i] == null) { + continue; + } + Matcher matcher = phonePattern.matcher(metadata[i]); + if (matcher.matches()) { + phoneBookContact.phone = matcher.group(1).replace(" ", "").replace("-", ""); + } + + if (phoneBookContact.phone != null) { + String shortNumber = phoneBookContact.phone; + if (phoneBookContact.phone.startsWith("+")) { + shortNumber = phoneBookContact.phone.substring(1); + } + + Contact contact = new Contact(); + contact.first_name = phoneBookContact.name; + contact.last_name = ""; + contact.contact_id = lastContactId++; + contact.key = phoneBookContact.lookup_key; + contact.phones.add(phoneBookContact.phone); + contact.shortPhones.add(shortNumber); + contact.phoneDeleted.add(0); + contact.phoneTypes.add(LocaleController.getString("PhoneOther", R.string.PhoneOther)); + if (contactsMap == null) { + contactsMap = new HashMap<>(); + } + contactsMap.put(phoneBookContact.lookup_key, contact); + break; + } + } + } + } + pCur.close(); + } + } + + FileLog.d("loading contacts 3 query time = " + (System.currentTimeMillis() - time)); } catch (Throwable e) { FileLog.e(e); @@ -1955,6 +1984,7 @@ public class ContactsController extends BaseController { private void performWriteContactsToPhoneBookInternal(ArrayList contactsArray) { Cursor cursor = null; + long time = System.currentTimeMillis(); try { Account account = systemAccount; if (!hasContactsPermission() || account == null) { @@ -1966,7 +1996,7 @@ public class ContactsController extends BaseController { settings.edit().putBoolean("contacts_updated_v7", true).commit(); } final ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver(); - Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type).build(); + Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI; cursor = contentResolver.query(rawContactUri, new String[]{BaseColumns._ID, ContactsContract.RawContacts.SYNC2}, null, null, null); LongSparseArray bookContacts = new LongSparseArray<>(); if (cursor != null) { @@ -1976,12 +2006,26 @@ public class ContactsController extends BaseController { cursor.close(); cursor = null; + FileLog.d("performWriteContactsToPhoneBookInternal contacts array " + contactsArray.size() + " " + forceUpdate + " bookContactsSize=" + bookContacts.size() + " currentAccount=" + currentAccount); + ArrayList query = null; for (int a = 0; a < contactsArray.size(); a++) { TLRPC.TL_contact u = contactsArray.get(a); if (forceUpdate || bookContacts.indexOfKey(u.user_id) < 0) { - addContactToPhoneBook(getMessagesController().getUser(u.user_id), forceUpdate); + if (query == null) { + query = new ArrayList<>(); + } + applyContactToPhoneBook(query, getMessagesController().getUser(u.user_id)); + if (query.size() > 450) { + contentResolver.applyBatch(ContactsContract.AUTHORITY, query); + query.clear(); + } } } + if (query != null && !query.isEmpty()) { + contentResolver.applyBatch(ContactsContract.AUTHORITY, query); + query.clear(); + } + } } catch (Exception e) { FileLog.e(e); @@ -1990,6 +2034,8 @@ public class ContactsController extends BaseController { cursor.close(); } } + + FileLog.d("performWriteContactsToPhoneBookInternal " + (System.currentTimeMillis() - time)) ; } private void performWriteContactsToPhoneBook() { @@ -2180,56 +2226,7 @@ public class ContactsController extends BaseController { } ArrayList query = new ArrayList<>(); - - ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI); - builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name); - builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type); - builder.withValue(ContactsContract.RawContacts.SYNC1, TextUtils.isEmpty(user.phone) ? "" : user.phone); - builder.withValue(ContactsContract.RawContacts.SYNC2, user.id); - query.add(builder.build()); - - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0); - builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name); - builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name); - query.add(builder.build()); - -// builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); -// builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0); -// builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); -// builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+" + user.phone); -// builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); -// query.add(builder.build()); - - final String phoneOrName = TextUtils.isEmpty(user.phone) ? ContactsController.formatName(user.first_name, user.last_name) : "+" + user.phone; - - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0); - builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile"); - builder.withValue(ContactsContract.Data.DATA1, user.id); - builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile"); - builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutMessage", R.string.ContactShortcutMessage, phoneOrName)); - builder.withValue(ContactsContract.Data.DATA4, user.id); - query.add(builder.build()); - - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0); - builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call"); - builder.withValue(ContactsContract.Data.DATA1, user.id); - builder.withValue(ContactsContract.Data.DATA2, "Telegram Voice Call"); - builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVoiceCall", R.string.ContactShortcutVoiceCall, phoneOrName)); - builder.withValue(ContactsContract.Data.DATA4, user.id); - query.add(builder.build()); - - builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); - builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0); - builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video"); - builder.withValue(ContactsContract.Data.DATA1, user.id); - builder.withValue(ContactsContract.Data.DATA2, "Telegram Video Call"); - builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVideoCall", R.string.ContactShortcutVideoCall, phoneOrName)); - builder.withValue(ContactsContract.Data.DATA4, user.id); - query.add(builder.build()); + applyContactToPhoneBook(query, user); try { ContentProviderResult[] result = contentResolver.applyBatch(ContactsContract.AUTHORITY, query); @@ -2245,6 +2242,55 @@ public class ContactsController extends BaseController { return res; } + private void applyContactToPhoneBook(ArrayList query, TLRPC.User user) { + if (user == null) { + return; + } + int rawContactId = query.size(); + ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI); + builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name); + builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type); + builder.withValue(ContactsContract.RawContacts.SYNC1, TextUtils.isEmpty(user.phone) ? "" : user.phone); + builder.withValue(ContactsContract.RawContacts.SYNC2, user.id); + query.add(builder.build()); + + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactId); + builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name); + builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name); + query.add(builder.build()); + + final String phoneOrName = TextUtils.isEmpty(user.phone) ? ContactsController.formatName(user.first_name, user.last_name) : "+" + user.phone; + + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); + builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile"); + builder.withValue(ContactsContract.Data.DATA1, user.id); + builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile"); + builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutMessage", R.string.ContactShortcutMessage, phoneOrName)); + builder.withValue(ContactsContract.Data.DATA4, user.id); + query.add(builder.build()); + + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); + builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call"); + builder.withValue(ContactsContract.Data.DATA1, user.id); + builder.withValue(ContactsContract.Data.DATA2, "Telegram Voice Call"); + builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVoiceCall", R.string.ContactShortcutVoiceCall, phoneOrName)); + builder.withValue(ContactsContract.Data.DATA4, user.id); + query.add(builder.build()); + + builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); + builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId); + builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video"); + builder.withValue(ContactsContract.Data.DATA1, user.id); + builder.withValue(ContactsContract.Data.DATA2, "Telegram Video Call"); + builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVideoCall", R.string.ContactShortcutVideoCall, phoneOrName)); + builder.withValue(ContactsContract.Data.DATA4, user.id); + query.add(builder.build()); + } + private void deleteContactFromPhoneBook(long uid) { if (!hasContactsPermission()) { return; @@ -2854,4 +2900,11 @@ public class ContactsController extends BaseController { } return result.toString(); } + + private class PhoneBookContact { + String id; + String lookup_key; + String name; + String phone; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java index 0a577a01a..88f48947b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/DatabaseMigrationHelper.java @@ -1247,6 +1247,13 @@ public class DatabaseMigrationHelper { database.executeFast("PRAGMA user_version = 115").stepThis().dispose(); version = 115; } + if (version == 115) { + database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_v2 ON messages_v2(reply_to_message_id, mid);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_scheduled_messages_v2 ON scheduled_messages_v2(reply_to_message_id, mid);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_topics ON messages_topics(reply_to_message_id, mid);").stepThis().dispose(); + database.executeFast("PRAGMA user_version = 116").stepThis().dispose(); + version = 116; + } return version; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java index d3a1a737b..cfb1c958a 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java @@ -33,6 +33,7 @@ public class FileLoadOperation { private final static int FINISH_CODE_DEFAULT = 0; private final static int FINISH_CODE_FILE_ALREADY_EXIST = 1; + public boolean preFinished; FileLoadOperationStream stream; boolean streamPriority; @@ -41,6 +42,7 @@ public class FileLoadOperation { public static volatile DispatchQueue filesQueue = new DispatchQueue("writeFileQueue"); public static ImmutableByteArrayOutputStream filesQueueByteBuffer; private boolean forceSmallChunk; + private Runnable fileWriteRunnable; public void setStream(FileLoadOperationStream stream, boolean streamPriority, long streamOffset) { this.stream = stream; @@ -48,6 +50,10 @@ public class FileLoadOperation { this.streamPriority = streamPriority; } + public int getPositionInQueue() { + return getQueue().getPosition(this); + } + protected static class RequestInfo { public long requestStartTime; private int requestToken; @@ -205,6 +211,7 @@ public class FileLoadOperation { private FileLoaderPriorityQueue priorityQueue; public interface FileLoadOperationDelegate { + void didPreFinishLoading(FileLoadOperation operation, File finalFile); void didFinishLoadingFile(FileLoadOperation operation, File finalFile); void didFailedLoadingFile(FileLoadOperation operation, int state); void didChangedLoadProgress(FileLoadOperation operation, long uploadedSize, long totalSize); @@ -521,7 +528,10 @@ public class FileLoadOperation { if (save) { if (modified) { ArrayList rangesFinal = new ArrayList<>(ranges); - filesQueue.postRunnable(() -> { + if (fileWriteRunnable != null) { + filesQueue.cancelRunnable(fileWriteRunnable); + } + filesQueue.postRunnable(fileWriteRunnable = () -> { long time = System.currentTimeMillis(); try { if (filePartsStream == null) { @@ -551,6 +561,8 @@ public class FileLoadOperation { FileLog.e(e, false); if (AndroidUtilities.isENOSPC(e)) { LaunchActivity.checkFreeDiscSpaceStatic(1); + } else if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); } } totalTime += System.currentTimeMillis() - time; @@ -715,7 +727,7 @@ public class FileLoadOperation { requestedBytesCount -= currentDownloadChunkSize; removePart(notRequestedBytesRanges, priorityRequestInfo.offset, priorityRequestInfo.offset + currentDownloadChunkSize); if (priorityRequestInfo.requestToken != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(priorityRequestInfo.requestToken, true); + ConnectionsManager.getInstance(currentAccount).cancelRequest(priorityRequestInfo.requestToken, false); requestsCount--; } if (BuildVars.DEBUG_VERSION) { @@ -884,6 +896,9 @@ public class FileLoadOperation { if (AndroidUtilities.isENOSPC(e)) { LaunchActivity.checkFreeDiscSpaceStatic(1); FileLog.e(e, false); + } else if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); + FileLog.e(e, false); } else { FileLog.e(e); } @@ -1048,6 +1063,9 @@ public class FileLoadOperation { if (AndroidUtilities.isENOSPC(e)) { LaunchActivity.checkFreeDiscSpaceStatic(1); FileLog.e(e, false); + } else if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); + FileLog.e(e, false); } else { FileLog.e(e); } @@ -1068,6 +1086,11 @@ public class FileLoadOperation { LaunchActivity.checkFreeDiscSpaceStatic(1); onFail(true, -1); return false; + } else if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); + FileLog.e(e, false); + onFail(true, -1); + return false; } } if (fileOutputStream == null) { @@ -1091,13 +1114,17 @@ public class FileLoadOperation { try { onFinishLoadingFile(false, FINISH_CODE_FILE_ALREADY_EXIST); if (pathSaveData != null) { - delegate.saveFilePath(pathSaveData, null); + delegate.saveFilePath(pathSaveData, cacheFileFinal); } } catch (Exception e) { FileLog.e(e, false); if (AndroidUtilities.isENOSPC(e)) { LaunchActivity.checkFreeDiscSpaceStatic(1); onFail(true, -1); + } if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); + onFail(true, -1); + return false; } else { onFail(true, 0); } @@ -1153,7 +1180,7 @@ public class FileLoadOperation { cancel(false); } - public void cancel(boolean deleteFiles) { + private void cancel(boolean deleteFiles) { Utilities.stageQueue.postRunnable(() -> { if (state != stateFinished && state != stateFailed) { cancelRequests(); @@ -1214,7 +1241,7 @@ public class FileLoadOperation { for (int a = 0; a < requestInfos.size(); a++) { RequestInfo requestInfo = requestInfos.get(a); if (requestInfo.requestToken != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(requestInfo.requestToken, true); + ConnectionsManager.getInstance(currentAccount).cancelRequest(requestInfo.requestToken, false); } } } @@ -1332,7 +1359,7 @@ public class FileLoadOperation { final File cacheFilePartsFinal = cacheFileParts; final File cacheFilePreloadFinal = cacheFilePreload; final File cacheFileTempFinal = cacheFileTemp; - Utilities.globalQueue.postRunnable(() -> { + filesQueue.postRunnable(() -> { if (cacheIvTempFinal != null) { cacheIvTempFinal.delete(); } @@ -1449,6 +1476,7 @@ public class FileLoadOperation { cacheIvTemp = null; cacheFileParts = null; cacheFilePreload = null; + delegate.didPreFinishLoading(FileLoadOperation.this, cacheFileFinal); } } @@ -1782,6 +1810,9 @@ public class FileLoadOperation { FileLog.e(e, !AndroidUtilities.isFilNotFoundException(e) && !AndroidUtilities.isENOSPC(e)); if (AndroidUtilities.isENOSPC(e)) { onFail(false, -1); + } else if (AndroidUtilities.isEROFS(e)) { + SharedConfig.checkSdCard(cacheFileFinal); + onFail(true, -1); } else { onFail(false, 0); } @@ -1844,7 +1875,11 @@ public class FileLoadOperation { if (delegate != null) { if (BuildVars.LOGS_ENABLED) { long time = startTime == 0 ? 0 : (System.currentTimeMillis() - startTime); - FileLog.d("failed downloading file to " + cacheFileFinal + " reason = " + reason + " time = " + (System.currentTimeMillis() - startTime) + " dc = " + datacenterId + " size = " + AndroidUtilities.formatFileSize(totalBytesCount)); + if (reason == 1) { + FileLog.d("cancel downloading file to " + cacheFileFinal + " time = " + time + " dc = " + datacenterId + " size = " + AndroidUtilities.formatFileSize(totalBytesCount)); + } else { + FileLog.d("failed downloading file to " + cacheFileFinal + " reason = " + reason + " time = " + time + " dc = " + datacenterId + " size = " + AndroidUtilities.formatFileSize(totalBytesCount)); + } } if (thread) { Utilities.stageQueue.postRunnable(() -> delegate.didFailedLoadingFile(FileLoadOperation.this, reason)); @@ -1868,7 +1903,7 @@ public class FileLoadOperation { continue; } if (info.requestToken != 0) { - ConnectionsManager.getInstance(currentAccount).cancelRequest(info.requestToken, true); + ConnectionsManager.getInstance(currentAccount).cancelRequest(info.requestToken, false); } } requestInfos.clear(); @@ -1904,7 +1939,7 @@ public class FileLoadOperation { if (requestingReference) { return; } - clearOperaion(requestInfo, false); + clearOperaion(null, false); requestingReference = true; if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; @@ -1912,12 +1947,19 @@ public class FileLoadOperation { parentObject = messageObject.messageOwner.media.webpage; } } + if (BuildVars.LOGS_ENABLED) { + FileLog.d("debug_loading: " + cacheFileFinal.getName() + " file reference expired "); + } FileRefController.getInstance(currentAccount).requestReference(parentObject, location, this, requestInfo); } protected void startDownloadRequest() { - if (paused || reuploadingCdn || - state != stateDownloading || + if (BuildVars.DEBUG_PRIVATE_VERSION) { + if (Utilities.stageQueue != null && Utilities.stageQueue.getHandler() != null && Thread.currentThread() != Utilities.stageQueue.getHandler().getLooper().getThread()) { + throw new RuntimeException("Wrong thread!!!"); + } + } + if (paused || reuploadingCdn || state != stateDownloading || requestingReference || streamPriorityStartOffset == 0 && ( !nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) || isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0))) { @@ -2085,7 +2127,7 @@ public class FileLoadOperation { return; } if (BuildVars.LOGS_ENABLED) { - FileLog.d("debug_loading: " + request.getClass().getSimpleName() + " time=" + (System.currentTimeMillis() - requestInfo.requestStartTime) + " dcId=" + datacenterId + " cdn=" + isCdn + " connectionType=" + connectionType + " " + isLast); + FileLog.d("debug_loading: " + cacheFileFinal.getName() + " time=" + (System.currentTimeMillis() - requestInfo.requestStartTime) + " dcId=" + datacenterId + " cdn=" + isCdn + " conType=" + connectionType + " reqId" + requestInfo.requestToken); } if (requestInfo == priorityRequestInfo) { if (BuildVars.DEBUG_VERSION) { @@ -2197,6 +2239,9 @@ public class FileLoadOperation { processRequestResult(requestInfo, error); } }, null, null, flags, datacenterId, connectionType, isLast); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("debug_loading: " + cacheFileFinal.getName() + " send reqId " + requestInfo.requestToken); + } requestsCount++; } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java index fae182e79..2ebf1bcd2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java @@ -204,7 +204,7 @@ public class FileLoader extends BaseController { filePathDatabase = new FilePathDatabase(instance); for (int i = 0; i < smallFilesQueue.length; i++) { smallFilesQueue[i] = new FileLoaderPriorityQueue("smallFilesQueue dc" + (i + 1), 5); - largeFilesQueue[i] = new FileLoaderPriorityQueue("largeFilesQueue dc" + (i + 1), 2); + largeFilesQueue[i] = new FileLoaderPriorityQueue("largeFilesQueue dc" + (i + 1), 1); } dumpFilesQueue(); } @@ -667,11 +667,9 @@ public class FileLoader extends BaseController { getDownloadController().startDownloadFile(document, (MessageObject) parentObject); } - FileLoadOperation operation = loadOperationPaths.get(fileName); + final String finalFileName = fileName; + FileLoadOperation operation = loadOperationPaths.get(finalFileName); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("checkFile operation fileName=" + fileName + " documentName=" + getDocumentFileName(document) + " operation=" + operation + " priority=" + priority + " account=" + currentAccount); - } priority = getPriorityValue(priority); if (operation != null) { @@ -684,6 +682,7 @@ public class FileLoader extends BaseController { operation.getQueue().add(operation); operation.updateProgress(); operation.getQueue().checkLoadingOperations(); + FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); return operation; } @@ -734,18 +733,11 @@ public class FileLoader extends BaseController { } FileLoaderPriorityQueue loaderQueue; int index = Utilities.clamp(operation.getDatacenterId() - 1, 4, 0); - if (operation.totalBytesCount > 20 * 1024 * 1024) { + if (operation.totalBytesCount > 20 * 1024 * 1024) {//20mb loaderQueue = largeFilesQueue[index]; } else { loaderQueue = smallFilesQueue[index]; } -// if (type == MEDIA_DIR_AUDIO) { -// loaderQueue = audioQueue; -// } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument) || MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) { -// loaderQueue = imagesQueue; -// } else { - -// } String storeFileName = fileName; @@ -804,6 +796,20 @@ public class FileLoader extends BaseController { final int finalType = type; FileLoadOperation.FileLoadOperationDelegate fileLoadOperationDelegate = new FileLoadOperation.FileLoadOperationDelegate() { + + @Override + public void didPreFinishLoading(FileLoadOperation operation, File finalFile) { + FileLoaderPriorityQueue queue = operation.getQueue(); + fileLoaderQueue.postRunnable(() -> { + FileLoadOperation currentOperation = loadOperationPaths.get(fileName); + if (currentOperation != null) { + currentOperation.preFinished = true; + queue.checkLoadingOperations(); + } + }); + checkDownloadQueue(operation.getQueue(), fileName); + } + @Override public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) { if (!operation.isPreloadVideoOperation() && operation.isPreloadFinished()) { @@ -864,16 +870,16 @@ public class FileLoader extends BaseController { }; operation.setDelegate(fileLoadOperationDelegate); - loadOperationPaths.put(fileName, operation); + loadOperationPaths.put(finalFileName, operation); operation.setPriority(priority); operation.setStream(stream, streamPriority, streamOffset); - if (BuildVars.LOGS_ENABLED) { - FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document)); - } - loaderQueue.add(operation); loaderQueue.checkLoadingOperations(); + + if (BuildVars.LOGS_ENABLED) { + FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount); + } return operation; } @@ -1681,8 +1687,8 @@ public class FileLoader extends BaseController { Runnable dumpFilesQueueRunnable = () -> { for (int i = 0; i < smallFilesQueue.length; i++) { - if (smallFilesQueue[i].allOperations.size() > 0 || largeFilesQueue[i].allOperations.size() > 0) { - FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].allOperations.size() + " large_operations=" + largeFilesQueue[i].allOperations.size()); + if (smallFilesQueue[i].getCount() > 0 || largeFilesQueue[i].getCount() > 0) { + FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].getCount() + " large_operations=" + largeFilesQueue[i].getCount()); } } dumpFilesQueue(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java index d83429089..5cacee6a2 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java @@ -1,16 +1,13 @@ package org.telegram.messenger; -import org.telegram.tgnet.ConnectionsManager; - import java.util.ArrayList; -import java.util.Objects; public class FileLoaderPriorityQueue { private final int maxActiveOperationsCount; String name; - ArrayList allOperations = new ArrayList<>(); + private ArrayList allOperations = new ArrayList<>(); private int PRIORITY_VALUE_MAX = (1 << 20); private int PRIORITY_VALUE_NORMAL = (1 << 16); @@ -27,7 +24,7 @@ public class FileLoaderPriorityQueue { } int index = -1; for (int i = 0; i < allOperations.size(); i++) { - if (allOperations.get(i) == operation || Objects.equals(allOperations.get(i).getFileName(), (operation.getFileName()))) { + if (allOperations.get(i) == operation) { allOperations.remove(i); i--; } @@ -49,14 +46,16 @@ public class FileLoaderPriorityQueue { if (operation == null) { return; } - allOperations.remove(operation); - operation.cancel(); + if (allOperations.remove(operation)) { + operation.cancel(); + } } public void checkLoadingOperations() { int activeCount = 0; int lastPriority = 0; boolean pauseAllNextOperations = false; + int max = maxActiveOperationsCount; for (int i = 0; i < allOperations.size(); i++) { FileLoadOperation operation = allOperations.get(i); if (i > 0 && !pauseAllNextOperations) { @@ -64,7 +63,11 @@ public class FileLoaderPriorityQueue { pauseAllNextOperations = true; } } - if (!pauseAllNextOperations && i < maxActiveOperationsCount) { + if (operation.preFinished) { + //operation will not use connections + //just skip + max++; + } else if (!pauseAllNextOperations && i < max) { operation.start(); activeCount++; } else { @@ -80,11 +83,14 @@ public class FileLoaderPriorityQueue { if (operation == null) { return; } - ConnectionsManager connectionsManager = ConnectionsManager.getInstance(operation.currentAccount); - if (connectionsManager != null && connectionsManager.getConnectionState() == ConnectionsManager.ConnectionStateWaitingForNetwork) { - operation.cancel(); - } allOperations.remove(operation); } + public int getCount() { + return allOperations.size(); + } + + public int getPosition(FileLoadOperation fileLoadOperation) { + return allOperations.indexOf(fileLoadOperation); + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java index 6644f9b48..235eb82b0 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLog.java @@ -8,6 +8,8 @@ package org.telegram.messenger; +import android.content.Context; +import android.content.res.ColorStateList; import android.util.Log; import com.google.gson.ExclusionStrategy; @@ -116,7 +118,7 @@ public class FileLog { } public static void dumpUnparsedMessage(TLObject message, long messageId) { - if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null) { + if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null || SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { return; } try { @@ -160,6 +162,7 @@ public class FileLog { privateFields.add("networkType"); privateFields.add("disableFree"); + privateFields.add("mContext"); //exclude file loading excludeRequests = new HashSet<>(); @@ -178,6 +181,9 @@ public class FileLog { @Override public boolean shouldSkipClass(Class clazz) { + if (clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class)) { + return true; + } return false; } }).create(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java index d4f1b621a..56fbd728d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FilePathDatabase.java @@ -170,7 +170,7 @@ public class FilePathDatabase { FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]); } } - } catch (SQLiteException e) { + } catch (Throwable e) { FileLog.e(e); } finally { if (cursor != null) { @@ -287,10 +287,11 @@ public class FilePathDatabase { MessageObject messageObject = arrayListFinal.get(i); messageObject.checkMediaExistance(false); } - } catch (Exception e) { - e.printStackTrace(); + } catch (Throwable e) { + FileLog.e(e); + } finally { + syncLatch.countDown(); } - syncLatch.countDown(); }); try { @@ -332,8 +333,9 @@ public class FilePathDatabase { } } catch (Exception e) { FileLog.e(e); + } finally { + syncLatch.countDown(); } - syncLatch.countDown(); }); try { @@ -344,7 +346,7 @@ public class FilePathDatabase { return res[0]; } - public void saveFileDialogId(File file,FileMeta fileMeta) { + public void saveFileDialogId(File file, FileMeta fileMeta) { if (file == null || fileMeta == null) { return; } @@ -417,7 +419,7 @@ public class FilePathDatabase { for (int i = 0; i < filesToRemove.size(); i++) { database.executeFast("DELETE FROM paths_by_dialog_id WHERE path = '" + shield(filesToRemove.get(i).file.getPath()) + "'").stepThis().dispose(); } - } catch (Exception e) { + } catch (Throwable e) { FileLog.e(e); } finally { database.commitTransaction(); @@ -443,10 +445,11 @@ public class FilePathDatabase { list.add(keepMediaFiles.get(i)); } } - } catch (Exception e) { + } catch (Throwable e) { FileLog.e(e); + } finally { + syncLatch.countDown(); } - syncLatch.countDown(); }); try { syncLatch.await(); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java index d4b1ff985..d02956e36 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileRefController.java @@ -22,7 +22,6 @@ public class FileRefController extends BaseController { private static class CachedResult { private TLObject response; - private long lastQueryTime; private long firstQueryTime; } @@ -124,7 +123,7 @@ public class FileRefController extends BaseController { String locationKey; TLRPC.InputFileLocation location; if (BuildVars.LOGS_ENABLED) { - FileLog.d("start loading request reference for parent = " + parentObject + " args = " + args[0]); + FileLog.d("start loading request reference parent " + getObjectString(parentObject) + " args = " + args[0]); } if (args[0] instanceof TLRPC.TL_inputSingleMedia) { TLRPC.TL_inputSingleMedia req = (TLRPC.TL_inputSingleMedia) args[0]; @@ -291,7 +290,7 @@ public class FileRefController extends BaseController { cleanupCache(); CachedResult cachedResult = getCachedResponse(cacheKey); if (cachedResult != null) { - if (!onRequestComplete(locationKey, parentKey, cachedResult.response, false, true)) { + if (!onRequestComplete(locationKey, parentKey, cachedResult.response, null,false, true)) { responseCache.remove(locationKey); } else { return; @@ -299,21 +298,34 @@ public class FileRefController extends BaseController { } else { cachedResult = getCachedResponse(parentKey); if (cachedResult != null) { - if (!onRequestComplete(locationKey, parentKey, cachedResult.response, false, true)) { + if (!onRequestComplete(locationKey, parentKey, cachedResult.response, null, false, true)) { responseCache.remove(parentKey); } else { return; } } } - requestReferenceFromServer(parentObject, locationKey, parentKey, args); } - private void broadcastWaitersData(ArrayList waiters, TLObject response) { + private String getObjectString(Object parentObject) { + if (parentObject instanceof String) { + return (String) parentObject; + } + if (parentObject instanceof MessageObject) { + MessageObject messageObject = (MessageObject) parentObject; + return "message(dialogId=" + messageObject.getDialogId() + "messageId" + messageObject.getId() + ")"; + } + if (parentObject == null) { + return null; + } + return parentObject.getClass().getSimpleName(); + } + + private void broadcastWaitersData(ArrayList waiters, TLObject response, TLRPC.TL_error error) { for (int a = 0, N = waiters.size(); a < N; a++) { Waiter waiter = waiters.get(a); - onRequestComplete(waiter.locationKey, waiter.parentKey, response, a == N - 1, false); + onRequestComplete(waiter.locationKey, waiter.parentKey, response, error, a == N - 1, false); } waiters.clear(); } @@ -328,22 +340,22 @@ public class FileRefController extends BaseController { getMediaDataController().processLoadedPremiumPromo(r, date, false); } - onRequestComplete(locationKey, parentKey, response, true, false); + onRequestComplete(locationKey, parentKey, response, error, true, false); }); } else 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)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, 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)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, 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)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof MessageObject) { MessageObject messageObject = (MessageObject) parentObject; long channelId = messageObject.getChannelId(); @@ -351,16 +363,16 @@ public class FileRefController extends BaseController { TLRPC.TL_messages_getScheduledMessages req = new TLRPC.TL_messages_getScheduledMessages(); req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); req.id.add(messageObject.getRealId()); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (channelId != 0) { TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); req.id.add(messageObject.getRealId()); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else { TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); req.id.add(messageObject.getRealId()); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } } else if (parentObject instanceof TLRPC.TL_wallPaper) { TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) parentObject; @@ -369,7 +381,7 @@ public class FileRefController extends BaseController { inputWallPaper.id = wallPaper.id; inputWallPaper.access_hash = wallPaper.access_hash; req.wallpaper = inputWallPaper; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.TL_theme) { TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject; TLRPC.TL_account_getTheme req = new TLRPC.TL_account_getTheme(); @@ -378,53 +390,53 @@ public class FileRefController extends BaseController { inputTheme.access_hash = theme.access_hash; req.theme = inputTheme; req.format = "android"; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.WebPage) { TLRPC.WebPage webPage = (TLRPC.WebPage) parentObject; TLRPC.TL_messages_getWebPage req = new TLRPC.TL_messages_getWebPage(); req.url = webPage.url; req.hash = 0; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.User) { TLRPC.User user = (TLRPC.User) parentObject; TLRPC.TL_users_getUsers req = new TLRPC.TL_users_getUsers(); req.id.add(getMessagesController().getInputUser(user)); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.Chat) { TLRPC.Chat chat = (TLRPC.Chat) parentObject; if (chat instanceof TLRPC.TL_chat) { TLRPC.TL_messages_getChats req = new TLRPC.TL_messages_getChats(); req.id.add(chat.id); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (chat instanceof TLRPC.TL_channel) { TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels(); req.id.add(MessagesController.getInputChannel(chat)); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } } else if (parentObject instanceof String) { String string = (String) parentObject; if ("wallpaper".equals(string)) { if (wallpaperWaiters.isEmpty()) { TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); - getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(wallpaperWaiters, response)); + getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(wallpaperWaiters, response, error)); } wallpaperWaiters.add(new Waiter(locationKey, parentKey)); } else if (string.startsWith("gif")) { if (savedGifsWaiters.isEmpty()) { TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs(); - getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(savedGifsWaiters, response)); + getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(savedGifsWaiters, response, error)); } savedGifsWaiters.add(new Waiter(locationKey, parentKey)); } else if ("recent".equals(string)) { if (recentStickersWaiter.isEmpty()) { TLRPC.TL_messages_getRecentStickers req = new TLRPC.TL_messages_getRecentStickers(); - getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(recentStickersWaiter, response)); + getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(recentStickersWaiter, response, error)); } recentStickersWaiter.add(new Waiter(locationKey, parentKey)); } else if ("fav".equals(string)) { if (favStickersWaiter.isEmpty()) { TLRPC.TL_messages_getFavedStickers req = new TLRPC.TL_messages_getFavedStickers(); - getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(favStickersWaiter, response)); + getConnectionsManager().sendRequest(req, (response, error) -> broadcastWaitersData(favStickersWaiter, response, error)); } favStickersWaiter.add(new Waiter(locationKey, parentKey)); } else if ("update".equals(string)) { @@ -437,7 +449,7 @@ public class FileRefController extends BaseController { if (req.source == null) { req.source = ""; } - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (string.startsWith("avatar_")) { long id = Utilities.parseLong(string); if (id > 0) { @@ -446,7 +458,7 @@ public class FileRefController extends BaseController { req.offset = 0; req.max_id = 0; req.user_id = getMessagesController().getInputUser(id); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else { TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); req.filter = new TLRPC.TL_inputMessagesFilterChatPhotos(); @@ -454,7 +466,7 @@ public class FileRefController extends BaseController { req.offset_id = 0; req.q = ""; req.peer = getMessagesController().getInputPeer(id); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } } else if (string.startsWith("sent_")) { String[] params = string.split("_"); @@ -464,11 +476,11 @@ public class FileRefController extends BaseController { TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); req.channel = getMessagesController().getInputChannel(channelId); req.id.add(Utilities.parseInt(params[2])); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, false, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, false, false)); } else { TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); req.id.add(Utilities.parseInt(params[2])); - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, false, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, false, false)); } } else { sendErrorToObject(args, 0); @@ -482,18 +494,18 @@ public class FileRefController extends BaseController { req.stickerset = new TLRPC.TL_inputStickerSetID(); req.stickerset.id = stickerSet.set.id; req.stickerset.access_hash = stickerSet.set.access_hash; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.StickerSetCovered) { TLRPC.StickerSetCovered stickerSet = (TLRPC.StickerSetCovered) parentObject; TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); req.stickerset = new TLRPC.TL_inputStickerSetID(); req.stickerset.id = stickerSet.set.id; req.stickerset.access_hash = stickerSet.set.access_hash; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else if (parentObject instanceof TLRPC.InputStickerSet) { TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); req.stickerset = (TLRPC.InputStickerSet) parentObject; - getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, true, false)); + getConnectionsManager().sendRequest(req, (response, error) -> onRequestComplete(locationKey, parentKey, response, error, true, false)); } else { sendErrorToObject(args, 0); } @@ -624,18 +636,35 @@ public class FileRefController extends BaseController { getConnectionsManager().sendRequest(req, (RequestDelegate) requester.args[1]); } else if (requester.args[1] instanceof FileLoadOperation) { FileLoadOperation fileLoadOperation = (FileLoadOperation) requester.args[1]; + String oldRef = null; + String newRef = null; if (locationReplacement != null) { if (fromCache && isSameReference(fileLoadOperation.location.file_reference, locationReplacement.file_reference)) { return false; } + if (BuildVars.LOGS_ENABLED) { + oldRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference); + } fileLoadOperation.location = locationReplacement; + if (BuildVars.LOGS_ENABLED) { + newRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference); + } } else { if (fromCache && isSameReference(requester.location.file_reference, file_reference)) { return false; } - requester.location.file_reference = file_reference; + if (BuildVars.LOGS_ENABLED) { + oldRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference); + } + fileLoadOperation.location.file_reference = requester.location.file_reference = file_reference; + if (BuildVars.LOGS_ENABLED) { + newRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference); + } } fileLoadOperation.requestingReference = false; + if (BuildVars.LOGS_ENABLED) { + FileLog.d("debug_loading: " + fileLoadOperation.getCacheFileFinal().getName() + " " + oldRef + " " + newRef + " reference updated resume download"); + } fileLoadOperation.startDownloadRequest(); } return true; @@ -665,26 +694,16 @@ public class FileRefController extends BaseController { TLRPC.TL_messages_getAttachedStickers req = (TLRPC.TL_messages_getAttachedStickers) args[0]; getConnectionsManager().sendRequest(req, (RequestDelegate) args[1]); } else { - if (reason == 0) { - TLRPC.TL_error error = new TLRPC.TL_error(); - error.text = "not found parent object to request reference"; - error.code = 400; - if (args[1] instanceof FileLoadOperation) { - FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1]; - fileLoadOperation.requestingReference = false; - fileLoadOperation.processRequestResult((FileLoadOperation.RequestInfo) args[2], error); - } - } else if (reason == 1) { - if (args[1] instanceof FileLoadOperation) { - FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1]; - fileLoadOperation.requestingReference = false; - fileLoadOperation.onFail(false, 0); - } + if (args[1] instanceof FileLoadOperation) { + FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1]; + fileLoadOperation.requestingReference = false; + FileLog.e("debug_loading: " + fileLoadOperation.getCacheFileFinal().getName() + "reference can't update: fail operation "); + fileLoadOperation.onFail(false, 0); } } } - private boolean onRequestComplete(String locationKey, String parentKey, TLObject response, boolean cache, boolean fromCache) { + private boolean onRequestComplete(String locationKey, String parentKey, TLObject response, TLRPC.TL_error error, boolean cache, boolean fromCache) { boolean found = false; String cacheKey = parentKey; if (response instanceof TLRPC.TL_help_premiumPromo) { @@ -706,7 +725,7 @@ public class FileRefController extends BaseController { if (requester.completed) { continue; } - if (onRequestComplete(requester.locationKey, null, response, cache && !found, fromCache)) { + if (onRequestComplete(requester.locationKey, null, response, error, cache && !found, fromCache)) { found = true; } } @@ -729,6 +748,13 @@ public class FileRefController extends BaseController { if (requester.completed) { continue; } + if (error != null && BuildVars.LOGS_ENABLED) { + if (requester.args[1] instanceof FileLoadOperation) { + FileLoadOperation operation = (FileLoadOperation) requester.args[1]; + FileLog.e("debug_loading: " + operation.getCacheFileFinal().getName() + " can't update file reference: " + error.code + " " + error.text); + } + + } if (requester.location instanceof TLRPC.TL_inputFileLocation || requester.location instanceof TLRPC.TL_inputPeerPhotoFileLocation) { locationReplacement = new TLRPC.InputFileLocation[1]; needReplacement = new boolean[1]; @@ -768,6 +794,10 @@ public class FileRefController extends BaseController { FileLog.d("file ref not found in messages, replacing message"); } } + } else { + if (BuildVars.DEBUG_VERSION) { + FileLog.d("empty messages, file ref not found"); + } } } else if (response instanceof TLRPC.TL_help_premiumPromo) { TLRPC.TL_help_premiumPromo premiumPromo = (TLRPC.TL_help_premiumPromo) response; @@ -1007,7 +1037,7 @@ public class FileRefController extends BaseController { ArrayList keysToDelete = null; for (HashMap.Entry entry : responseCache.entrySet()) { CachedResult cachedResult = entry.getValue(); - if (Math.abs(SystemClock.elapsedRealtime() - cachedResult.firstQueryTime) >= 60 * 10 * 1000) { + if (Math.abs(System.currentTimeMillis() - cachedResult.firstQueryTime) >= 60 * 1000) { if (keysToDelete == null) { keysToDelete = new ArrayList<>(); } @@ -1023,7 +1053,7 @@ public class FileRefController extends BaseController { private CachedResult getCachedResponse(String key) { CachedResult cachedResult = responseCache.get(key); - if (cachedResult != null && Math.abs(SystemClock.elapsedRealtime() - cachedResult.firstQueryTime) >= 60 * 10 * 1000) { + if (cachedResult != null && Math.abs(System.currentTimeMillis() - cachedResult.firstQueryTime) >= 60 * 1000) { responseCache.remove(key); cachedResult = null; } @@ -1035,10 +1065,9 @@ public class FileRefController extends BaseController { if (cachedResult == null) { cachedResult = new CachedResult(); cachedResult.response = response; - cachedResult.firstQueryTime = SystemClock.uptimeMillis(); + cachedResult.firstQueryTime = System.currentTimeMillis(); responseCache.put(key, cachedResult); } - cachedResult.lastQueryTime = SystemClock.uptimeMillis(); } private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java index fefb5bdee..c0adf1938 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -582,7 +582,7 @@ public class ImageLoader { } } } catch (Exception e) { - FileLog.e(e); + FileLog.e(e, false); } if (imageSize == 0 && httpConnection != null) { try { @@ -1433,52 +1433,8 @@ public class ImageLoader { Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable); file.close(); } else { - String DEBUG_TAG = "secured_document_image"; - try { - if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { - FileLog.d( DEBUG_TAG + " try get image from secured document " + secureDocumentKey + " encryption path " + cacheImage.encryptionKeyPath); - } - RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r"); - int len = (int) f.length(); - int offset = 0; - byte[] bytes = bytesLocal.get(); - byte[] data = bytes != null && bytes.length >= len ? bytes : null; - if (data == null) { - bytes = data = new byte[len]; - bytesLocal.set(bytes); - } - f.readFully(data, 0, len); - f.close(); - boolean error = false; - if (secureDocumentKey != null) { - EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey); - byte[] hash = Utilities.computeSHA256(data, 0, len); - if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) { - error = true; - } - offset = (data[0] & 0xff); - len -= offset; - } else if (inEncryptedFile) { - EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath); - } - if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { - FileLog.d(DEBUG_TAG + " check error " + error); - } - if (!error) { - image = BitmapFactory.decodeByteArray(data, offset, len, opts); - if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { - FileLog.d( DEBUG_TAG + " image " + image); - } - } - } catch (Throwable e) { - FileLog.e(e); - } - if (image == null) { FileInputStream is; - if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { - FileLog.d(DEBUG_TAG + " try get image from stream "); - } if (secureDocumentKey != null) { is = new EncryptedFileInputStream(cacheFileFinal, secureDocumentKey); } else if (inEncryptedFile) { @@ -1517,9 +1473,38 @@ public class ImageLoader { } image = BitmapFactory.decodeStream(is, null, opts); is.close(); + } - if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { - FileLog.d(DEBUG_TAG + " image2 " + image); + if (image == null) { + try { + RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r"); + int len = (int) f.length(); + int offset = 0; + byte[] bytes = bytesLocal.get(); + byte[] data = bytes != null && bytes.length >= len ? bytes : null; + if (data == null) { + bytes = data = new byte[len]; + bytesLocal.set(bytes); + } + f.readFully(data, 0, len); + f.close(); + boolean error = false; + if (secureDocumentKey != null) { + EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey); + byte[] hash = Utilities.computeSHA256(data, 0, len); + if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) { + error = true; + } + offset = (data[0] & 0xff); + len -= offset; + } else if (inEncryptedFile) { + EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath); + } + if (!error) { + image = BitmapFactory.decodeByteArray(data, offset, len, opts); + } + } catch (Throwable e) { + FileLog.e(e); } } } @@ -2245,6 +2230,8 @@ public class ImageLoader { FileLog.d("cache path = " + cachePath); } + FileLog.d("selected SD card = " + SharedConfig.storageCacheDir); + try { if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { File path = Environment.getExternalStorageDirectory(); @@ -2253,14 +2240,28 @@ public class ImageLoader { if (dirs != null) { for (int a = 0, N = dirs.size(); a < N; a++) { File dir = dirs.get(a); + FileLog.d("root dir " + a + " " + dir); if (dir.getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) { path = dir; break; } } } + if (!path.getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) { + File[] dirsDebug = ApplicationLoader.applicationContext.getExternalFilesDirs(null); + if (dirsDebug != null) { + for (int a = 0; a < dirsDebug.length; a++) { + if (dirsDebug[a] == null) { + continue; + } + FileLog.d("dirsDebug " + a + " " + dirsDebug[a]); + } + } + } } + FileLog.d("external storage = " + path); + File publicMediaDir = null; if (Build.VERSION.SDK_INT >= 30) { File newPath; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index 8528caac4..fa7c83811 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java @@ -305,8 +305,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg private ArrayList loadingOperations = new ArrayList<>(); private boolean attachedToWindow; private boolean videoThumbIsSame; - private boolean allowLoadingOnAttachedOnly; - private boolean shouldLoadOnAttach; + private boolean allowLoadingOnAttachedOnly = false; private boolean skipUpdateFrame; public boolean clip = true; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LinkifyPort.java b/TMessagesProj/src/main/java/org/telegram/messenger/LinkifyPort.java index 1646b7e68..a2e3bf157 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LinkifyPort.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LinkifyPort.java @@ -162,7 +162,7 @@ public class LinkifyPort { + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@"; private static final String PORT_NUMBER = "\\:\\d{1,5}"; private static final String PATH_AND_QUERY = "[/\\?](?:(?:[" + LABEL_CHAR + ";/\\?:@&=#~" + "\\-\\.\\+!\\*'\\(\\),_\\$])|(?:%[a-fA-F0-9]{2}))*"; - private static final String RELAXED_DOMAIN_NAME = "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + "?)+" + "|" + IP_ADDRESS_STRING + ")"; + private static final String RELAXED_DOMAIN_NAME = "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + ")*" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + "?)" + "|" + IP_ADDRESS_STRING + ")"; private static final String WEB_URL_WITHOUT_PROTOCOL = "(" + WORD_BOUNDARY diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java index 061251685..3f17d5e9d 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java @@ -5,9 +5,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.BatteryManager; import android.os.Build; -import android.os.PowerManager; -import android.util.SparseArray; -import android.util.SparseIntArray; import androidx.annotation.RequiresApi; import androidx.core.math.MathUtils; @@ -20,9 +17,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; -import org.telegram.ui.ActionBar.Theme; -import org.telegram.ui.Components.AnimatedEmojiDrawable; - public class LiteMode { public static final int FLAG_ANIMATED_STICKERS_KEYBOARD = 1; @@ -53,8 +47,10 @@ public class LiteMode { public static int PRESET_LOW = ( FLAG_ANIMATED_EMOJI_CHAT_PREMIUM | + FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM | + FLAG_ANIMATED_EMOJI_REACTIONS_PREMIUM | FLAG_AUTOPLAY_GIFS - ); // 2064 + ); // 2076 public static int PRESET_MEDIUM = ( FLAGS_ANIMATED_STICKERS | FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM | @@ -136,6 +132,10 @@ public class LiteMode { } public static boolean isEnabled(int flag) { + if (flag == FLAG_CHAT_FORUM_TWOCOLUMN && AndroidUtilities.isTablet()) { + // always enabled for tablets + return true; + } return (getValue() & preprocessFlag(flag)) > 0; } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 5edcf1216..23a6ae60e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -553,6 +553,23 @@ public class LocaleController { } } + private boolean patching = false; + + public void checkForcePatchLangpack(int currentAccount, Runnable ifDone) { + String lng = LocaleController.getCurrentLanguageName(); + boolean shouldPatch = MessagesController.getInstance(currentAccount).checkResetLangpack > 0 && !MessagesController.getGlobalMainSettings().getBoolean("langpack_patched" + lng, false) && !patching; + if (shouldPatch) { + patching = true; + reloadCurrentRemoteLocale(currentAccount, null, true, () -> AndroidUtilities.runOnUIThread(() -> { + MessagesController.getGlobalMainSettings().edit().putBoolean("langpack_patched" + lng, true).apply(); + if (ifDone != null) { + ifDone.run(); + } + patching = false; + })); + } + } + private String getLocaleString(Locale locale) { if (locale == null) { return "en"; diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java index 3aed83199..1420fd388 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaController.java @@ -556,6 +556,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, private long lastProgress = 0; private MessageObject playingMessageObject; private MessageObject goingToShowMessageObject; + private boolean manualRecording; private Timer progressTimer = null; private final Object progressTimerSync = new Object(); private boolean downloadingCurrentMessage; @@ -1629,7 +1630,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, if (raisedToBack == minCount || accelerometerVertical) { lastAccelerometerDetected = System.currentTimeMillis(); } - if (proximityTouched && (raisedToBack == minCount || accelerometerVertical || System.currentTimeMillis() - lastAccelerometerDetected < 60) && !NotificationsController.audioManager.isWiredHeadsetOn() && !NotificationsController.audioManager.isBluetoothA2dpOn() && !VoIPService.isAnyKindOfCallActive()) { + if (proximityTouched && (raisedToBack == minCount || accelerometerVertical || System.currentTimeMillis() - lastAccelerometerDetected < 60) && !NotificationsController.audioManager.isWiredHeadsetOn() && !NotificationsController.audioManager.isBluetoothA2dpOn() && !VoIPService.isAnyKindOfCallActive() && !manualRecording) { if (SharedConfig.enabledRaiseTo(true) && playingMessageObject == null && recordStartRunnable == null && recordingAudio == null && !PhotoViewer.getInstance().isVisible() && ApplicationLoader.isScreenOn && !inputFieldHasText && allowStartRecord && raiseChat != null && !callInProgress) { if (!raiseToEarRecord) { if (BuildVars.LOGS_ENABLED) { @@ -1639,7 +1640,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, if (!raiseChat.playFirstUnreadVoiceMessage()) { raiseToEarRecord = true; useFrontSpeaker = false; - startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid()); + startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid(), false); } if (useFrontSpeaker) { setUseFrontSpeaker(true); @@ -1668,7 +1669,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, countLess = 0; } else if (proximityTouched && ((accelerometerSensor == null || linearSensor == null) && gravitySensor == null || ignoreAccelerometerGestures()) && !VoIPService.isAnyKindOfCallActive()) { if (playingMessageObject != null && !ApplicationLoader.mainInterfacePaused && (playingMessageObject.isVoice() || playingMessageObject.isRoundVideo()) && SharedConfig.enabledRaiseTo(false)) { - if (!useFrontSpeaker && !NotificationsController.audioManager.isWiredHeadsetOn() && !NotificationsController.audioManager.isBluetoothA2dpOn()) { + if (!useFrontSpeaker && !NotificationsController.audioManager.isWiredHeadsetOn() && !NotificationsController.audioManager.isBluetoothA2dpOn() && !manualRecording) { if (BuildVars.LOGS_ENABLED) { FileLog.d("start listen by proximity only"); } @@ -1680,7 +1681,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, ignoreOnPause = true; } } - } else if (!proximityTouched) { + } else if (!proximityTouched && !manualRecording) { if (raiseToEarRecord) { if (BuildVars.LOGS_ENABLED) { FileLog.d("stop record"); @@ -1728,7 +1729,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return; } raiseToEarRecord = true; - startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid()); + startRecording(raiseChat.getCurrentAccount(), raiseChat.getDialogId(), null, raiseChat.getThreadMessage(), raiseChat.getClassGuid(), false); ignoreOnPause = true; } @@ -2281,20 +2282,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return; } - boolean last = false; - if (SharedConfig.playOrderReversed) { - currentPlaylistNum++; - if (currentPlaylistNum >= currentPlayList.size()) { - currentPlaylistNum = 0; - last = true; - } - } else { - currentPlaylistNum--; - if (currentPlaylistNum < 0) { - currentPlaylistNum = currentPlayList.size() - 1; - last = true; - } - } + boolean last = traversePlaylist(currentPlayList, SharedConfig.playOrderReversed ? +1 : -1); if (last && byStop && SharedConfig.repeatMode == 0 && !forceLoopCurrentPlaylist) { if (audioPlayer != null || videoPlayer != null) { if (audioPlayer != null) { @@ -2351,23 +2339,47 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, return; } - if (SharedConfig.playOrderReversed) { - currentPlaylistNum--; - if (currentPlaylistNum < 0) { - currentPlaylistNum = currentPlayList.size() - 1; - } - } else { - currentPlaylistNum++; - if (currentPlaylistNum >= currentPlayList.size()) { - currentPlaylistNum = 0; - } - } + traversePlaylist(currentPlayList, SharedConfig.playOrderReversed ? -1 : 1); if (currentPlaylistNum >= currentPlayList.size()) { return; } playMusicAgain = true; playMessage(currentPlayList.get(currentPlaylistNum)); } + + private boolean traversePlaylist(ArrayList playlist, int direction) { + boolean last = false; + final int wasCurrentPlaylistNum = currentPlaylistNum; + int connectionState = ConnectionsManager.getInstance(UserConfig.selectedAccount).getConnectionState(); + boolean offline = connectionState == ConnectionsManager.ConnectionStateWaitingForNetwork; + currentPlaylistNum += direction; + if (offline) { + while (currentPlaylistNum < playlist.size() && currentPlaylistNum >= 0) { + MessageObject audio = playlist.get(currentPlaylistNum); + if (audio != null && audio.mediaExists) { + break; + } + currentPlaylistNum += direction; + } + } + if (currentPlaylistNum >= playlist.size() || currentPlaylistNum < 0) { + currentPlaylistNum = currentPlaylistNum >= playlist.size() ? 0 : playlist.size() - 1; + if (offline) { + while (currentPlaylistNum >= 0 && currentPlaylistNum < playlist.size() && (direction > 0 ? currentPlaylistNum <= wasCurrentPlaylistNum : currentPlaylistNum >= wasCurrentPlaylistNum)) { + MessageObject audio = playlist.get(currentPlaylistNum); + if (audio != null && audio.mediaExists) { + break; + } + currentPlaylistNum += direction; + } + if (currentPlaylistNum >= playlist.size() || currentPlaylistNum < 0) { + currentPlaylistNum = currentPlaylistNum >= playlist.size() ? 0 : playlist.size() - 1; + } + } + last = true; + } + return last; + } protected void checkIsNextMediaFileDownloaded() { if (playingMessageObject == null || !playingMessageObject.isMusic()) { @@ -3566,12 +3578,12 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } } - public void startRecording(int currentAccount, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, int guid) { + public void startRecording(int currentAccount, long dialogId, MessageObject replyToMsg, MessageObject replyToTopMsg, int guid, boolean manual) { boolean paused = false; if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) { paused = true; } - + manualRecording = manual; requestAudioFocus(true); try { @@ -3772,6 +3784,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener, } recordingAudio = null; recordingAudioFile = null; + manualRecording = false; } public void stopRecording(final int send, boolean notify, int scheduleDate) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java index 22d4ba4e3..34bc0dfb3 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -53,7 +53,6 @@ import org.telegram.SQLite.SQLiteException; import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.messenger.ringtone.RingtoneDataStore; import org.telegram.messenger.ringtone.RingtoneUploader; -import org.telegram.messenger.support.SparseLongArray; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.RequestDelegate; @@ -4309,6 +4308,7 @@ public class MediaDataController extends BaseController { } } } + boolean recreateShortcuts = Build.VERSION.SDK_INT >= 30; Utilities.globalQueue.postRunnable(() -> { try { if (SharedConfig.directShareHash == null) { @@ -4316,19 +4316,58 @@ public class MediaDataController extends BaseController { ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putString("directShareHash2", SharedConfig.directShareHash).commit(); } - ShortcutManagerCompat.removeAllDynamicShortcuts(ApplicationLoader.applicationContext); + ArrayList shortcutsToUpdate = new ArrayList<>(); + ArrayList newShortcutsIds = new ArrayList<>(); + ArrayList shortcutsToDelete = new ArrayList<>(); + if (recreateShortcuts) { + ShortcutManagerCompat.removeAllDynamicShortcuts(ApplicationLoader.applicationContext); + } else { + List currentShortcuts = ShortcutManagerCompat.getDynamicShortcuts(ApplicationLoader.applicationContext); + if (currentShortcuts != null && !currentShortcuts.isEmpty()) { + newShortcutsIds.add("compose"); + for (int a = 0; a < hintsFinal.size(); a++) { + TLRPC.TL_topPeer hint = hintsFinal.get(a); + newShortcutsIds.add("did3_" + MessageObject.getPeerId(hint.peer)); + } + for (int a = 0; a < currentShortcuts.size(); a++) { + String id = currentShortcuts.get(a).getId(); + if (!newShortcutsIds.remove(id)) { + shortcutsToDelete.add(id); + } + shortcutsToUpdate.add(id); + } + if (newShortcutsIds.isEmpty() && shortcutsToDelete.isEmpty()) { + return; + } + } + + if (!shortcutsToDelete.isEmpty()) { + ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, shortcutsToDelete); + } + } Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class); intent.setAction("new_dialog"); ArrayList arrayList = new ArrayList<>(); - ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, "compose") + ShortcutInfoCompat shortcut = new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, "compose") .setShortLabel(LocaleController.getString("NewConversationShortcut", R.string.NewConversationShortcut)) .setLongLabel(LocaleController.getString("NewConversationShortcut", R.string.NewConversationShortcut)) .setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.shortcut_compose)) .setRank(0) .setIntent(intent) - .build()); + .build(); + if (recreateShortcuts) { + ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, shortcut); + } else { + arrayList.add(shortcut); + if (shortcutsToUpdate.contains("compose")) { + ShortcutManagerCompat.updateShortcuts(ApplicationLoader.applicationContext, arrayList); + } else { + ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList); + } + arrayList.clear(); + } HashSet category = new HashSet<>(1); @@ -4423,7 +4462,18 @@ public class MediaDataController extends BaseController { } else { builder.setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.shortcut_user)); } - ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, builder.build()); + + if (recreateShortcuts) { + ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, builder.build()); + } else { + arrayList.add(builder.build()); + if (shortcutsToUpdate.contains(id)) { + ShortcutManagerCompat.updateShortcuts(ApplicationLoader.applicationContext, arrayList); + } else { + ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList); + } + arrayList.clear(); + } } } catch (Throwable ignore) { @@ -6229,7 +6279,7 @@ public class MediaDataController extends BaseController { return entities; } - private CharSequence parsePattern(CharSequence cs, Pattern pattern, List entities, GenericProvider entityProvider) { + private CharSequence parsePattern(CharSequence cs, Pattern pattern, ArrayList entities, GenericProvider entityProvider) { Matcher m = pattern.matcher(cs); int offset = 0; while (m.find()) { @@ -6249,6 +6299,8 @@ public class MediaDataController extends BaseController { TLRPC.MessageEntity entity = entityProvider.provide(null); entity.offset = m.start() - offset; entity.length = gr.length(); + + removeOffset4After(entity.offset, entity.offset + entity.length, entities); entities.add(entity); } @@ -6257,6 +6309,18 @@ public class MediaDataController extends BaseController { return cs; } + private static void removeOffset4After(int start, int end, ArrayList entities) { + int count = entities.size(); + for (int a = 0; a < count; a++) { + TLRPC.MessageEntity entity = entities.get(a); + if (entity.offset > end) { + entity.offset -= 4; + } else if (entity.offset > start) { + entity.offset -= 2; + } + } + } + //---------------- MESSAGES END ---------------- private LongSparseArray draftsFolderIds = new LongSparseArray<>(); @@ -6950,10 +7014,12 @@ public class MediaDataController extends BaseController { TLRPC.Document document = premiumPreviewStickers.get(i == 2 ? premiumPreviewStickers.size() - 1 : i); if (MessageObject.isPremiumSticker(document)) { ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setAllowLoadingOnAttachedOnly(false); imageReceiver.setImage(ImageLocation.getForDocument(document), null, null, "webp", null, 1); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); imageReceiver = new ImageReceiver(); + imageReceiver.setAllowLoadingOnAttachedOnly(false); imageReceiver.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", null, 1); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java index fd6203d92..f73925f99 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessageObject.java @@ -3333,7 +3333,11 @@ public class MessageObject { int i = messageText.toString().indexOf("un2"); if (i != -1) { SpannableStringBuilder sb = SpannableStringBuilder.valueOf(messageText); - messageText = sb.replace(i, i + 3, BillingController.getInstance().formatCurrency(messageOwner.action.amount, messageOwner.action.currency)); + CharSequence price = BillingController.getInstance().formatCurrency(messageOwner.action.amount, messageOwner.action.currency); + if ((messageOwner.action.flags & 1) != 0) { + price = String.format("%.2f", (messageOwner.action.cryptoAmount * Math.pow(10, -9))) + " " + messageOwner.action.cryptoCurrency + " (~ " + price + ")"; + } + messageText = sb.replace(i, i + 3, price); } } else if (messageOwner.action instanceof TLRPC.TL_messageActionSuggestProfilePhoto) { if (messageOwner.action.photo != null && messageOwner.action.photo.video_sizes != null && !messageOwner.action.photo.video_sizes.isEmpty()) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java index 4bf4b4196..38a352623 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java @@ -295,6 +295,8 @@ public class MessagesController extends BaseController implements NotificationCe private String uploadingWallpaper; private Theme.OverrideWallpaperInfo uploadingWallpaperInfo; + private UserNameResolver userNameResolver; + private boolean loadingAppConfig; private Fetcher appConfigFetcher = new Fetcher() { @Override @@ -750,6 +752,13 @@ public class MessagesController extends BaseController implements NotificationCe return null; } + public UserNameResolver getUserNameResolver() { + if (userNameResolver == null) { + userNameResolver = new UserNameResolver(currentAccount); + } + return userNameResolver; + } + public class SponsoredMessagesInfo { public ArrayList messages; public Integer posts_between; @@ -4137,6 +4146,7 @@ public class MessagesController extends BaseController implements NotificationCe if (user.min) { if (oldUser != null) { if (!fromCache) { + getUserNameResolver().update(oldUser, user); if (user.bot) { if (user.username != null) { oldUser.username = user.username; @@ -4166,6 +4176,7 @@ public class MessagesController extends BaseController implements NotificationCe getUserConfig().setCurrentUser(user); getUserConfig().saveConfig(true); } + getUserNameResolver().update(oldUser, user); if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) { return true; } @@ -4246,6 +4257,7 @@ public class MessagesController extends BaseController implements NotificationCe if (chat.min) { if (oldChat != null) { if (!fromCache) { + getUserNameResolver().update(oldChat, chat); oldChat.title = chat.title; oldChat.photo = chat.photo; oldChat.broadcast = chat.broadcast; @@ -5525,6 +5537,10 @@ public class MessagesController extends BaseController implements NotificationCe } public void unblockPeer(long id) { + unblockPeer(id, null); + } + + public void unblockPeer(long id, Runnable callback) { TLRPC.TL_contacts_unblock req = new TLRPC.TL_contacts_unblock(); TLRPC.User user = null; TLRPC.Chat chat = null; @@ -5547,9 +5563,11 @@ public class MessagesController extends BaseController implements NotificationCe req.id = getInputPeer(chat); } getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad); - getConnectionsManager().sendRequest(req, (response, error) -> { - - }); + getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + if (callback != null) { + callback.run(); + } + })); } public void getBlockedPeers(boolean reset) { @@ -15667,13 +15685,18 @@ public class MessagesController extends BaseController implements NotificationCe } TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE); boolean callStateIsIdle = true; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - //TODO check - if (ActivityCompat.checkSelfPermission(ApplicationLoader.applicationContext, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { + try { + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + //TODO check + if (ActivityCompat.checkSelfPermission(ApplicationLoader.applicationContext, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { + callStateIsIdle = tm.getCallStateForSubscription() == TelephonyManager.CALL_STATE_IDLE; + } + } else { callStateIsIdle = tm.getCallState() == TelephonyManager.CALL_STATE_IDLE; } - } else { - callStateIsIdle = tm.getCallState() == TelephonyManager.CALL_STATE_IDLE; + } catch (Throwable e) { + FileLog.e(e); } if (svc != null || VoIPService.callIShouldHavePutIntoIntent != null || !callStateIsIdle) { if (BuildVars.LOGS_ENABLED) { @@ -17354,10 +17377,8 @@ public class MessagesController extends BaseController implements NotificationCe AlertDialog[] progressDialog = new AlertDialog[] { new AlertDialog(fragment.getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER) }; - - TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername(); - req.username = username; - int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + boolean[] canceled = new boolean[]{false}; + getMessagesController().getUserNameResolver().resolve(username, (peerId) -> { try { if (progress != null) { progress.end(); @@ -17367,15 +17388,14 @@ public class MessagesController extends BaseController implements NotificationCe } catch (Exception ignored) {} progressDialog[0] = null; fragment.setVisibleDialog(null); - if (error == null) { - TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; - putUsers(res.users, false); - putChats(res.chats, false); - getMessagesStorage().putUsersAndChats(res.users, res.chats, false, true); - if (!res.chats.isEmpty()) { - openChatOrProfileWith(null, res.chats.get(0), fragment, 1, false); - } else if (!res.users.isEmpty()) { - openChatOrProfileWith(res.users.get(0), null, fragment, type, false); + if (canceled[0]) { + return; + } + if (peerId != null) { + if (peerId < 0) { + openChatOrProfileWith(null, getChat(-peerId), fragment, 1, false); + } else { + openChatOrProfileWith(getUser(peerId), null, fragment, type, false); } } else { if (fragment.getParentActivity() != null) { @@ -17389,16 +17409,16 @@ public class MessagesController extends BaseController implements NotificationCe } } } - })); + }); if (progress != null) { - progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true)); + progress.onCancel(() -> canceled[0] = true); progress.init(); } else { AndroidUtilities.runOnUIThread(() -> { if (progressDialog[0] == null) { return; } - progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(reqId, true)); + progressDialog[0].setOnCancelListener(dialog -> canceled[0] = true); fragment.showDialog(progressDialog[0]); }, 500); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index fc9238d23..c8e074abc 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -15,7 +15,6 @@ import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; import android.util.SparseIntArray; @@ -88,6 +87,7 @@ public class MessagesStorage extends BaseController { private int archiveUnreadCount; private volatile int pendingMainUnreadCount; private volatile int pendingArchiveUnreadCount; + private boolean databaseCreated; private CountDownLatch openSync = new CountDownLatch(1); @@ -99,7 +99,7 @@ public class MessagesStorage extends BaseController { } } - public final static int LAST_DB_VERSION = 115; + public final static int LAST_DB_VERSION = 116; private boolean databaseMigrationInProgress; public boolean showClearDatabaseAlert; private LongSparseIntArray dialogIsForum = new LongSparseIntArray(); @@ -291,6 +291,7 @@ public class MessagesStorage extends BaseController { boolean createTable = false; + databaseCreated = false; if (!cacheFile.exists()) { createTable = true; } @@ -357,6 +358,7 @@ public class MessagesStorage extends BaseController { } } } + databaseCreated = true; } catch (Exception e) { FileLog.e(e); if (openTries < 3 && e.getMessage() != null && e.getMessage().contains("malformed")) { @@ -367,6 +369,7 @@ public class MessagesStorage extends BaseController { cleanupInternal(false); } openDatabase(openTries == 1 ? 2 : 3); + return; } } @@ -403,6 +406,7 @@ public class MessagesStorage extends BaseController { private boolean recoverDatabase() { database.close(); boolean restored = DatabaseMigrationHelper.recoverDatabase(cacheFile, walCacheFile, shmCacheFile, currentAccount); + FileLog.e("Database restored = " + restored); if (restored) { try { database = new SQLiteDatabase(cacheFile.getPath()); @@ -416,9 +420,14 @@ public class MessagesStorage extends BaseController { } } if (!restored) { + cleanupInternal(true); openDatabase(1); + restored = databaseCreated; + FileLog.e("Try create new database = " + restored); + } + if (restored) { + reset(); } - reset(); return restored; } @@ -505,6 +514,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, send_state, date);").stepThis().dispose(); 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 INDEX IF NOT EXISTS idx_to_reply_scheduled_messages_v2 ON scheduled_messages_v2(reply_to_message_id, mid);").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, group_id INTEGER, 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(); @@ -515,6 +525,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages_v2 ON messages_v2(uid, mention, read_state);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS is_channel_idx_messages_v2 ON messages_v2(mid, is_channel);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_v2 ON messages_v2(mid, reply_to_message_id);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_v2 ON messages_v2(reply_to_message_id, mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_groupid_messages_v2 ON messages_v2(uid, mid, group_id);").stepThis().dispose(); database.executeFast("CREATE TABLE download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, parent TEXT, PRIMARY KEY (uid, type));").stepThis().dispose(); @@ -637,6 +648,7 @@ public class MessagesStorage extends BaseController { database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages_topics ON messages_topics(mid, send_state, date);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS is_channel_idx_messages_topics ON messages_topics(mid, is_channel);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_topics ON messages_topics(mid, reply_to_message_id);").stepThis().dispose(); + database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_topics ON messages_topics(reply_to_message_id, mid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS mid_uid_messages_topics ON messages_topics(mid, uid);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_read_out_idx_messages_topics ON messages_topics(uid, topic_id, mid, read_state, out);").stepThis().dispose(); database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages_topics ON messages_topics(uid, topic_id, mention, read_state);").stepThis().dispose(); @@ -785,6 +797,7 @@ public class MessagesStorage extends BaseController { private void checkSQLException(Throwable e, boolean logToAppCenter) { if (e instanceof SQLiteException && e.getMessage() != null && e.getMessage().contains("is malformed") && !tryRecover) { tryRecover = true; + FileLog.e("disk image malformed detected, try recover"); if (recoverDatabase()) { tryRecover = false; clearLoadingDialogsOffsets(); @@ -1816,6 +1829,18 @@ public class MessagesStorage extends BaseController { }); } + public void removeTopics(long dialogId, ArrayList topicIds) { + storageQueue.postRunnable(() -> { + try { + String topics = TextUtils.join(", ", topicIds); + database.executeFast(String.format(Locale.US, "DELETE FROM topics WHERE did = %d AND topic_id IN (%s)", dialogId, topics)).stepThis().dispose(); + database.executeFast(String.format(Locale.US, "DELETE FROM messages_topics WHERE uid = %d AND topic_id = IN (%s)", dialogId, topics)).stepThis().dispose(); + } catch (SQLiteException e) { + e.printStackTrace(); + } + }); + } + public void updateTopicsWithReadMessages(HashMap topicsReadOutbox) { storageQueue.postRunnable(() -> { for (TopicKey topicKey : topicsReadOutbox.keySet()) { @@ -2815,6 +2840,293 @@ public class MessagesStorage extends BaseController { return array; } +// public void checkLoadedRemoteFilter(TLRPC.DialogFilter newFilter) { +// storageQueue.postRunnable(() -> { +// try { +// SparseArray filtersToDelete = new SparseArray<>(); +// for (int a = 0, N = dialogFilters.size(); a < N; a++) { +// MessagesController.DialogFilter filter = dialogFilters.get(a); +// filtersToDelete.put(filter.id, filter); +// } +// ArrayList filtersOrder = new ArrayList<>(); +// +// ArrayList usersToLoad = new ArrayList<>(); +// HashMap usersToLoadMap = new HashMap<>(); +// ArrayList chatsToLoad = new ArrayList<>(); +// HashMap chatsToLoadMap = new HashMap<>(); +// ArrayList dialogsToLoad = new ArrayList<>(); +// HashMap dialogsToLoadMap = new HashMap<>(); +// +// ArrayList filtersToSave = new ArrayList<>(); +// HashMap> filterDialogRemovals = new HashMap<>(); +// HashSet filtersUnreadCounterReset = new HashSet<>(); +// for (int a = 0, N = vector.objects.size(); a < N; a++) { +// TLRPC.DialogFilter newFilter = (TLRPC.DialogFilter) vector.objects.get(a); +// filtersOrder.add(newFilter.id); +// int newFlags = 0; +// if (newFilter.contacts) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_CONTACTS; +// } +// if (newFilter.non_contacts) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_NON_CONTACTS; +// } +// if (newFilter.groups) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_GROUPS; +// } +// if (newFilter.broadcasts) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_CHANNELS; +// } +// if (newFilter.bots) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_BOTS; +// } +// if (newFilter.exclude_muted) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_MUTED; +// } +// if (newFilter.exclude_read) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ; +// } +// if (newFilter.exclude_archived) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_ARCHIVED; +// } +// if (newFilter instanceof TLRPC.TL_dialogFilterCommunity) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_COMMUNITY; +// if (newFilter.community_can_admin) { +// newFlags |= MessagesController.DIALOG_FILTER_FLAG_COMMUNITY_ADMIN; +// } +// } +// +// MessagesController.DialogFilter filter = dialogFiltersMap.get(newFilter.id); +// if (filter != null) { +// filtersToDelete.remove(newFilter.id); +// boolean changed = false; +// boolean unreadChanged = false; +// if (!TextUtils.equals(filter.name, newFilter.title)) { +// changed = true; +// filter.name = newFilter.title; +// } +// if (filter.flags != newFlags) { +// filter.flags = newFlags; +// changed = true; +// unreadChanged = true; +// } +// +// HashSet existingIds = new HashSet<>(filter.alwaysShow); +// existingIds.addAll(filter.neverShow); +// HashSet existingDialogsIds = new HashSet<>(); +// +// LinkedHashMap secretChatsMap = null; +// if (filter.pinnedDialogs.size() != 0) { +// ArrayList pinArray = new ArrayList<>(); +// boolean hasSecret = false; +// for (int c = 0, N2 = filter.pinnedDialogs.size(); c < N2; c++) { +// long did = filter.pinnedDialogs.keyAt(c); +// if (DialogObject.isEncryptedDialog(did)) { +// hasSecret = true; +// } +// pinArray.add(did); +// } +// if (hasSecret) { +// secretChatsMap = new LinkedHashMap<>(); +// LongSparseIntArray pinnedDialogs = filter.pinnedDialogs; +// Collections.sort(pinArray, (o1, o2) -> { +// int idx1 = pinnedDialogs.get(o1); +// int idx2 = pinnedDialogs.get(o2); +// if (idx1 > idx2) { +// return 1; +// } else if (idx1 < idx2) { +// return -1; +// } +// return 0; +// }); +// for (int c = 0, N2 = pinArray.size(); c < N2; c++) { +// long did = pinArray.get(c); +// if (!DialogObject.isEncryptedDialog(did)) { +// continue; +// } +// secretChatsMap.put(c, did); +// } +// } +// } +// for (int c = 0, N2 = filter.pinnedDialogs.size(); c < N2; c++) { +// long did = filter.pinnedDialogs.keyAt(c); +// if (DialogObject.isEncryptedDialog(did)) { +// continue; +// } +// existingDialogsIds.add(did); +// existingIds.remove(did); +// } +// +// filter.pinnedDialogs.clear(); +// for (int b = 0, N2 = newFilter.pinned_peers.size(); b < N2; b++) { +// TLRPC.InputPeer peer = newFilter.pinned_peers.get(b); +// Long id; +// if (peer.user_id != 0) { +// id = peer.user_id; +// } else { +// id = -(peer.chat_id != 0 ? peer.chat_id : peer.channel_id); +// } +// int index = filter.pinnedDialogs.size(); +// if (secretChatsMap != null) { +// Long did; +// while ((did = secretChatsMap.remove(index)) != null) { +// filter.pinnedDialogs.put(did, index); +// index++; +// } +// } +// filter.pinnedDialogs.put(id, index); +// existingIds.remove(id); +// if (!existingDialogsIds.remove(id)) { +// changed = true; +// if (!dialogsToLoadMap.containsKey(id)) { +// dialogsToLoad.add(id); +// dialogsToLoadMap.put(id, peer); +// } +// } +// } +// if (secretChatsMap != null) { +// for (LinkedHashMap.Entry entry : secretChatsMap.entrySet()) { +// filter.pinnedDialogs.put(entry.getValue(), filter.pinnedDialogs.size()); +// } +// } +// +// for (int c = 0; c < 2; c++) { +// ArrayList fromArray = toPeerIds(c == 0 ? newFilter.include_peers : newFilter.exclude_peers); +// ArrayList toArray = c == 0 ? filter.alwaysShow : filter.neverShow; +// +// if (c == 0) { +// // put pinned_peers into include_peers (alwaysShow) +// ArrayList pinnedArray = toPeerIds(newFilter.pinned_peers); +// for (int i = 0; i < pinnedArray.size(); ++i) { +// fromArray.remove(pinnedArray.get(i)); +// } +// fromArray.addAll(0, pinnedArray); +// } +// +// final int fromArrayCount = fromArray.size(); +// boolean isDifferent = fromArray.size() != toArray.size(); +// if (!isDifferent) { +// for (int i = 0; i < fromArrayCount; ++i) { +// if (!toArray.contains(fromArray.get(i))) { +// isDifferent = true; +// break; +// } +// } +// } +// +// if (isDifferent) { +// unreadChanged = true; +// changed = true; +// if (c == 0) { +// filter.alwaysShow = fromArray; +// } else { +// filter.neverShow = fromArray; +// } +// } +// } +// if (!existingDialogsIds.isEmpty()) { +// filterDialogRemovals.put(filter.id, existingDialogsIds); +// changed = true; +// } +// if (changed) { +// filtersToSave.add(filter); +// } +// if (unreadChanged) { +// filtersUnreadCounterReset.add(filter.id); +// } +// } else { +// filter = new MessagesController.DialogFilter(); +// filter.id = newFilter.id; +// filter.flags = newFlags; +// filter.name = newFilter.title; +// filter.pendingUnreadCount = -1; +// for (int c = 0; c < 2; c++) { +// if (c == 0) { +// for (int b = 0, N2 = newFilter.pinned_peers.size(); b < N2; b++) { +// TLRPC.InputPeer peer = newFilter.pinned_peers.get(b); +// Long id; +// if (peer.user_id != 0) { +// id = peer.user_id; +// } else { +// id = -(peer.chat_id != 0 ? peer.chat_id : peer.channel_id); +// } +// if (!filter.alwaysShow.contains(id)) { +// filter.alwaysShow.add(id); +// } +// filter.pinnedDialogs.put(id, filter.pinnedDialogs.size() + 1); +// if (!dialogsToLoadMap.containsKey(id)) { +// dialogsToLoad.add(id); +// dialogsToLoadMap.put(id, peer); +// } +// } +// } +// ArrayList fromArray = c == 0 ? newFilter.include_peers : newFilter.exclude_peers; +// ArrayList toArray = c == 0 ? filter.alwaysShow : filter.neverShow; +// for (int b = 0, N2 = fromArray.size(); b < N2; b++) { +// TLRPC.InputPeer peer = fromArray.get(b); +// if (peer.user_id != 0) { +// Long uid = peer.user_id; +// if (!toArray.contains(uid)) { +// toArray.add(uid); +// } +// if (!usersToLoadMap.containsKey(uid)) { +// usersToLoad.add(uid); +// usersToLoadMap.put(uid, peer); +// } +// } else { +// Long chatId = peer.chat_id != 0 ? peer.chat_id : peer.channel_id; +// Long dialogId = -chatId; +// if (!toArray.contains(dialogId)) { +// toArray.add(dialogId); +// } +// if (!chatsToLoadMap.containsKey(chatId)) { +// chatsToLoad.add(chatId); +// chatsToLoadMap.put(chatId, peer); +// } +// } +// } +// } +// filtersToSave.add(filter); +// } +// } +// +// TLRPC.messages_Dialogs dialogs; +// if (!dialogsToLoad.isEmpty()) { +// dialogs = loadDialogsByIds(TextUtils.join(",", dialogsToLoad), usersToLoad, chatsToLoad, new ArrayList<>()); +// for (int a = 0, N = dialogs.dialogs.size(); a < N; a++) { +// TLRPC.Dialog dialog = dialogs.dialogs.get(a); +// dialogsToLoadMap.remove(dialog.id); +// } +// } else { +// dialogs = new TLRPC.TL_messages_dialogs(); +// } +// ArrayList users = new ArrayList<>(); +// if (!usersToLoad.isEmpty()) { +// getUsersInternal(TextUtils.join(",", usersToLoad), users); +// for (int a = 0, N = users.size(); a < N; a++) { +// TLRPC.User user = users.get(a); +// usersToLoadMap.remove(user.id); +// } +// } +// ArrayList chats = new ArrayList<>(); +// if (!chatsToLoad.isEmpty()) { +// getChatsInternal(TextUtils.join(",", chatsToLoad), chats); +// for (int a = 0, N = chats.size(); a < N; a++) { +// TLRPC.Chat chat = chats.get(a); +// chatsToLoadMap.remove(chat.id); +// } +// } +// +// if (usersToLoadMap.isEmpty() && chatsToLoadMap.isEmpty() && dialogsToLoadMap.isEmpty()) { +// processLoadedFilterPeersInternal(dialogs, null, users, chats, filtersToSave, filtersToDelete, filtersOrder, filterDialogRemovals, filtersUnreadCounterReset); +// } else { +// getMessagesController().loadFilterPeers(dialogsToLoadMap, usersToLoadMap, chatsToLoadMap, dialogs, new TLRPC.TL_messages_dialogs(), users, chats, filtersToSave, filtersToDelete, filtersOrder, filterDialogRemovals, filtersUnreadCounterReset); +// } +// } catch (Exception e) { +// checkSQLException(e); +// } +// }); +// } + public void checkLoadedRemoteFilters(TLRPC.Vector vector) { storageQueue.postRunnable(() -> { try { @@ -13180,6 +13492,7 @@ public class MessagesStorage extends BaseController { try { 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()) { + cursor.dispose(); return; } readState = cursor.intValue(1); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java index 20fe697f3..9d712401e 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SendMessagesHelper.java @@ -6694,7 +6694,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE); cursor.moveToFirst(); len = cursor.getLong(sizeIndex); - + cursor.close(); } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 86acb8d78..403fe08d4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -10,6 +10,7 @@ package org.telegram.messenger; import android.app.Activity; import android.app.ActivityManager; +import android.app.Dialog; import android.content.Context; import android.content.SharedPreferences; import android.os.Build; @@ -38,7 +39,10 @@ import org.telegram.messenger.partisan.UpdateData; import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.TLRPC; +import org.telegram.ui.ActionBar.AlertDialog; +import org.telegram.ui.ActionBar.BaseFragment; import org.telegram.ui.Components.SwipeGestureSettingsView; +import org.telegram.ui.LaunchActivity; import java.io.File; import java.io.RandomAccessFile; @@ -72,6 +76,40 @@ public class SharedConfig { return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_CHAT); } + public static boolean readOnlyStorageDirAlertShowed; + + public static void checkSdCard(File file) { + if (file == null || SharedConfig.storageCacheDir == null || readOnlyStorageDirAlertShowed) { + return; + } + if (file.getPath().startsWith(SharedConfig.storageCacheDir)) { + AndroidUtilities.runOnUIThread(() -> { + if (readOnlyStorageDirAlertShowed) { + return; + } + BaseFragment fragment = LaunchActivity.getLastFragment(); + if (fragment != null && fragment.getParentActivity() != null) { + SharedConfig.storageCacheDir = null; + SharedConfig.saveConfig(); + ImageLoader.getInstance().checkMediaPaths(() -> { + + }); + + readOnlyStorageDirAlertShowed = true; + AlertDialog.Builder dialog = new AlertDialog.Builder(fragment.getParentActivity()); + dialog.setTitle(LocaleController.getString("SdCardError", R.string.SdCardError)); + dialog.setSubtitle(LocaleController.getString("SdCardErrorDescription", R.string.SdCardErrorDescription)); + dialog.setPositiveButton(LocaleController.getString("DoNotUseSDCard", R.string.DoNotUseSDCard), (dialog1, which) -> { + + }); + Dialog dialogFinal = dialog.create(); + dialogFinal.setCanceledOnTouchOutside(false); + dialogFinal.show(); + } + }); + } + } + @Retention(RetentionPolicy.SOURCE) @IntDef({ PASSCODE_TYPE_PIN, @@ -158,7 +196,7 @@ public class SharedConfig { public static boolean streamMkv = false; public static boolean saveStreamMedia = true; public static boolean pauseMusicOnRecord = false; - public static boolean pauseMusicOnMedia = true; + public static boolean pauseMusicOnMedia = false; public static boolean noiseSupression; public static final boolean noStatusBar = true; public static boolean debugWebView; @@ -684,7 +722,7 @@ public class SharedConfig { streamMedia = preferences.getBoolean("streamMedia", true); saveStreamMedia = preferences.getBoolean("saveStreamMedia", true); pauseMusicOnRecord = preferences.getBoolean("pauseMusicOnRecord", false); - pauseMusicOnMedia = preferences.getBoolean("pauseMusicOnMedia", true); + pauseMusicOnMedia = preferences.getBoolean("pauseMusicOnMedia", false); forceDisableTabletMode = preferences.getBoolean("forceDisableTabletMode", false); streamAllVideo = preferences.getBoolean("streamAllVideo", BuildVars.DEBUG_VERSION); streamMkv = preferences.getBoolean("streamMkv", false); @@ -1422,7 +1460,7 @@ public class SharedConfig { info.ping = data.readInt64(false); info.availableCheckTime = data.readInt64(false); - proxyList.add(info); + proxyList.add(0, info); if (currentProxy == null && !TextUtils.isEmpty(proxyAddress)) { if (proxyAddress.equals(info.address) && proxyPort == info.port && proxyUsername.equals(info.username) && proxyPassword.equals(info.password)) { currentProxy = info; @@ -1440,7 +1478,7 @@ public class SharedConfig { data.readString(false), data.readString(false), data.readString(false)); - proxyList.add(info); + proxyList.add(0, info); if (currentProxy == null && !TextUtils.isEmpty(proxyAddress)) { if (proxyAddress.equals(info.address) && proxyPort == info.port && proxyUsername.equals(info.username) && proxyPassword.equals(info.password)) { currentProxy = info; @@ -1474,7 +1512,7 @@ public class SharedConfig { serializedData.writeByte(PROXY_CURRENT_SCHEMA_VERSION); int count = infoToSerialize.size(); serializedData.writeInt32(count); - for (int a = 0; a < count; a++) { + for (int a = count - 1; a >= 0; a--) { ProxyInfo info = infoToSerialize.get(a); serializedData.writeString(info.address != null ? info.address : ""); serializedData.writeInt32(info.port); diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/StatsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/StatsController.java index 8e33394cb..3ad4a9f33 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/StatsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/StatsController.java @@ -11,6 +11,8 @@ package org.telegram.messenger; import android.content.Context; import android.content.SharedPreferences; +import org.telegram.messenger.utils.ImmutableByteArrayOutputStream; + import java.io.File; import java.io.RandomAccessFile; @@ -78,6 +80,7 @@ public class StatsController extends BaseController { return ((long) bytes[0] & 0xFF) << 56 | ((long) bytes[1] & 0xFF) << 48 | ((long) bytes[2] & 0xFF) << 40 | ((long) bytes[3] & 0xFF) << 32 | ((long) bytes[4] & 0xFF) << 24 | ((long) bytes[5] & 0xFF) << 16 | ((long) bytes[6] & 0xFF) << 8 | ((long) bytes[7] & 0xFF); } + ImmutableByteArrayOutputStream byteArrayOutputStream = new ImmutableByteArrayOutputStream(); private Runnable saveRunnable = new Runnable() { @Override public void run() { @@ -87,25 +90,27 @@ public class StatsController extends BaseController { } lastInternalStatsSaveTime = newTime; try { - statsFile.seek(0); + byteArrayOutputStream.reset(); for (int a = 0; a < 3; a++) { for (int b = 0; b < OLD_TYPES_COUNT; b++) { - statsFile.write(longToBytes(sentBytes[a][b]), 0, 8); - statsFile.write(longToBytes(receivedBytes[a][b]), 0, 8); - statsFile.write(intToBytes(sentItems[a][b]), 0, 4); - statsFile.write(intToBytes(receivedItems[a][b]), 0, 4); + byteArrayOutputStream.write(longToBytes(sentBytes[a][b]), 0, 8); + byteArrayOutputStream.write(longToBytes(receivedBytes[a][b]), 0, 8); + byteArrayOutputStream.write(intToBytes(sentItems[a][b]), 0, 4); + byteArrayOutputStream.write(intToBytes(receivedItems[a][b]), 0, 4); } - statsFile.write(intToBytes(callsTotalTime[a]), 0, 4); - statsFile.write(longToBytes(resetStatsDate[a]), 0, 8); + byteArrayOutputStream.write(intToBytes(callsTotalTime[a]), 0, 4); + byteArrayOutputStream.write(longToBytes(resetStatsDate[a]), 0, 8); } for (int b = OLD_TYPES_COUNT; b < TYPES_COUNT; ++b) { for (int a = 0; a < 3; ++a) { - statsFile.write(longToBytes(sentBytes[a][b]), 0, 8); - statsFile.write(longToBytes(receivedBytes[a][b]), 0, 8); - statsFile.write(intToBytes(sentItems[a][b]), 0, 4); - statsFile.write(intToBytes(receivedItems[a][b]), 0, 4); + byteArrayOutputStream.write(longToBytes(sentBytes[a][b]), 0, 8); + byteArrayOutputStream.write(longToBytes(receivedBytes[a][b]), 0, 8); + byteArrayOutputStream.write(intToBytes(sentItems[a][b]), 0, 4); + byteArrayOutputStream.write(intToBytes(receivedItems[a][b]), 0, 4); } } + statsFile.seek(0); + statsFile.write(byteArrayOutputStream.buf, 0, byteArrayOutputStream.count()); statsFile.getFD().sync(); } catch (Exception ignore) { @@ -280,6 +285,7 @@ public class StatsController extends BaseController { long newTime = System.currentTimeMillis(); if (Math.abs(newTime - lastStatsSaveTime.get()) >= 2000) { lastStatsSaveTime.set(newTime); + statsSaveQueue.cancelRunnable(saveRunnable); statsSaveQueue.postRunnable(saveRunnable); } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java index c766b7421..419bd74e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SvgHelper.java @@ -404,6 +404,26 @@ public class SvgHelper { public void copyCommandFromPosition(int position) { commands.add(commands.get(position)); } + + public SvgDrawable clone() { + SvgDrawable drawable = new SvgDrawable(); + for (int i = 0; i < commands.size(); i++) { + drawable.commands.add(commands.get(i)); + Paint fromPaint = paints.get(commands.get(i)); + if (fromPaint != null) { + Paint toPaint = new Paint(); + toPaint.setColor(fromPaint.getColor()); + toPaint.setStrokeCap(fromPaint.getStrokeCap()); + toPaint.setStrokeJoin(fromPaint.getStrokeJoin()); + toPaint.setStrokeWidth(fromPaint.getStrokeWidth()); + toPaint.setStyle(fromPaint.getStyle()); + drawable.paints.put(commands.get(i), toPaint); + } + } + drawable.width = width; + drawable.height = height; + return drawable; + } } public static Bitmap getBitmap(int res, int width, int height, int color) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java index e77a20330..1ed5fc2a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/TopicsController.java @@ -149,6 +149,7 @@ public class TopicsController extends BaseController { } ArrayList topics = topicsByChatId.get(chatId); ArrayList topicsToReload = null; + ArrayList deletedTopics = null; LongSparseArray topicsMap = topicsMapByChatId.get(chatId); if (topics == null) { @@ -165,6 +166,10 @@ public class TopicsController extends BaseController { for (int i = 0; i < newTopics.size(); i++) { TLRPC.TL_forumTopic newTopic = newTopics.get(i); if (newTopic instanceof TLRPC.TL_forumTopicDeleted) { + if (deletedTopics == null) { + deletedTopics = new ArrayList<>(); + } + deletedTopics.add(newTopic.id); continue; } if (!topicsMap.containsKey(newTopic.id)) { @@ -206,6 +211,17 @@ public class TopicsController extends BaseController { } } + if (deletedTopics != null && loadType == LOAD_TYPE_LOAD_UNKNOWN) { + for (int i = 0; i < deletedTopics.size(); i++) { + for (int j = 0; j < topics.size(); j++) { + if (topics.get(j).id == deletedTopics.get(i)) { + topics.remove(j); + break; + } + } + } + getMessagesStorage().removeTopics(chatId, deletedTopics); + } if (topicsToReload != null && loadType != LOAD_TYPE_LOAD_UNKNOWN) { reloadTopics(chatId, topicsToReload, null); } else if (((loadType == LOAD_TYPE_PRELOAD && !fromCache) || loadType == LOAD_TYPE_LOAD_NEXT) && topics.size() >= totalCount && totalCount >= 0) { diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/UserNameResolver.java b/TMessagesProj/src/main/java/org/telegram/messenger/UserNameResolver.java new file mode 100644 index 000000000..190ca9f76 --- /dev/null +++ b/TMessagesProj/src/main/java/org/telegram/messenger/UserNameResolver.java @@ -0,0 +1,123 @@ +package org.telegram.messenger; + +import android.text.TextUtils; +import android.util.LruCache; + +import com.google.android.exoplayer2.util.Consumer; + +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.Components.BulletinFactory; +import org.telegram.ui.LaunchActivity; + +import java.util.ArrayList; +import java.util.HashMap; + +public class UserNameResolver { + + private final int currentAccount; + private final static long CACHE_TIME = 1000 * 60 * 60; //1 hour + + UserNameResolver(int currentAccount) { + this.currentAccount = currentAccount; + } + + LruCache resolvedCache = new LruCache<>(100); + HashMap>> resolvingConsumers = new HashMap<>(); + + public void resolve(String username, Consumer resolveConsumer) { + CachedPeer cachedPeer = resolvedCache.get(username); + if (cachedPeer != null) { + if (System.currentTimeMillis() - cachedPeer.time < CACHE_TIME) { + resolveConsumer.accept(cachedPeer.peerId); + FileLog.d("resolve username from cache " + username + " " + cachedPeer.peerId); + return; + } else { + resolvedCache.remove(username); + } + } + + ArrayList> consumers = resolvingConsumers.get(username); + if (consumers != null) { + consumers.add(resolveConsumer); + return; + } + consumers = new ArrayList<>(); + consumers.add(resolveConsumer); + resolvingConsumers.put(username, consumers); + + + TLObject req; + if (AndroidUtilities.isNumeric(username)) { + TLRPC.TL_contacts_resolvePhone resolvePhone = new TLRPC.TL_contacts_resolvePhone(); + resolvePhone.phone = username; + req = resolvePhone; + } else { + TLRPC.TL_contacts_resolveUsername resolveUsername = new TLRPC.TL_contacts_resolveUsername(); + resolveUsername.username = username; + req = resolveUsername; + } + ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + ArrayList> finalConsumers = resolvingConsumers.remove(username); + if (finalConsumers == null) { + return; + } + if (error != null) { + for (int i = 0; i < finalConsumers.size(); i++) { + finalConsumers.get(i).accept(null); + } + + if (error != null && error.text != null && error.text.contains("FLOOD_WAIT")) { + BaseFragment fragment = LaunchActivity.getLastFragment(); + if (fragment != null) { + BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("FloodWait", R.string.FloodWait)).show(); + } + } + return; + } + TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; + + MessagesController.getInstance(currentAccount).putUsers(res.users, false); + MessagesController.getInstance(currentAccount).putChats(res.chats, false); + MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, false, true); + + long peerId = MessageObject.getPeerId(res.peer); + resolvedCache.put(username, new CachedPeer(peerId)); + for (int i = 0; i < finalConsumers.size(); i++) { + finalConsumers.get(i).accept(peerId); + } + }, ConnectionsManager.RequestFlagFailOnServerErrors)); + }; + + public void update(TLRPC.User oldUser, TLRPC.User user) { + if (oldUser == null || user == null || oldUser.username == null || TextUtils.equals(oldUser.username, user.username)) { + return; + } + resolvedCache.remove(oldUser.username); + if (user.username != null) { + resolvedCache.put(user.username, new CachedPeer(user.id)); + } + } + + public void update(TLRPC.Chat oldChat, TLRPC.Chat chat) { + if (oldChat == null || chat == null || oldChat.username == null || TextUtils.equals(oldChat.username, chat.username)) { + return; + } + resolvedCache.remove(oldChat.username); + if (chat.username != null) { + resolvedCache.put(chat.username, new CachedPeer(-chat.id)); + } + } + + private class CachedPeer { + final long peerId; + final long time; + + public CachedPeer(long peerId) { + this.peerId = peerId; + time = System.currentTimeMillis(); + } + } +} diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/utils/ImmutableByteArrayOutputStream.java b/TMessagesProj/src/main/java/org/telegram/messenger/utils/ImmutableByteArrayOutputStream.java index 38b6b98a3..6e5bed68c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/utils/ImmutableByteArrayOutputStream.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/utils/ImmutableByteArrayOutputStream.java @@ -90,4 +90,7 @@ public class ImmutableByteArrayOutputStream extends OutputStream { count = 0; } + public int count() { + return count; + } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java index ce3fd3478..21f2ee03f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/video/MediaCodecVideoConvertor.java @@ -83,7 +83,9 @@ public class MediaCodecVideoConvertor { long time = System.currentTimeMillis(); boolean error = false; boolean repeatWithIncreasedTimeout = false; + boolean isAvatar = avatarStartTime >= 0; int videoTrackIndex = -5; + String selectedEncoderName = null; try { MediaCodec.BufferInfo info = new MediaCodec.BufferInfo(); @@ -108,7 +110,7 @@ public class MediaCodecVideoConvertor { boolean decoderDone = false; int framesCount = 0; - if (avatarStartTime >= 0) { + if (isAvatar) { if (durationS <= 2000) { bitrate = 2600000; } else if (durationS <= 5000) { @@ -144,6 +146,10 @@ public class MediaCodecVideoConvertor { outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); encoder = MediaCodec.createEncoderByType(MediaController.VIDEO_MIME_TYPE); + + selectedEncoderName = encoder.getName(); + FileLog.d("selected encoder " + selectedEncoderName); + encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); inputSurface = new InputSurface(encoder.createInputSurface()); inputSurface.makeCurrent(); @@ -345,7 +351,7 @@ public class MediaCodecVideoConvertor { extractor.selectTrack(videoIndex); MediaFormat videoFormat = extractor.getTrackFormat(videoIndex); String encoderName = null; - if (avatarStartTime >= 0) { + if (isAvatar) { if (durationS <= 2000) { bitrate = 2600000; } else if (durationS <= 5000) { @@ -392,21 +398,6 @@ public class MediaCodecVideoConvertor { w = resultWidth; h = resultHeight; } - if (BuildVars.LOGS_ENABLED) { - FileLog.d("create encoder with w = " + w + " h = " + h + " bitrate = " + bitrate); - } - MediaFormat outputFormat = MediaFormat.createVideoFormat(MediaController.VIDEO_MIME_TYPE, w, h); - outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); - outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); - outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate); - outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2); - - if (Build.VERSION.SDK_INT < 23 && Math.min(h, w) <= 480) { - if (bitrate > 921600) { - bitrate = 921600; - } - outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); - } if (encoderName != null) { try { @@ -418,6 +409,30 @@ public class MediaCodecVideoConvertor { if (encoder == null) { encoder = MediaCodec.createEncoderByType(MediaController.VIDEO_MIME_TYPE); } + + if (BuildVars.LOGS_ENABLED) { + FileLog.d("create encoder with w = " + w + " h = " + h + " bitrate = " + bitrate); + } + MediaFormat outputFormat = MediaFormat.createVideoFormat(MediaController.VIDEO_MIME_TYPE, w, h); + outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface); + outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); + if (isAvatar && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // prevent case when result video max 2MB + outputFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR); + } + outputFormat.setInteger( "max-bitrate", bitrate); + outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate); + outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1); + + if (Build.VERSION.SDK_INT < 23 && Math.min(h, w) <= 480 && !isAvatar) { + if (bitrate > 921600) { + bitrate = 921600; + } + outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate); + } + + selectedEncoderName = encoder.getName(); + FileLog.d("selected encoder " + selectedEncoderName); encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE); inputSurface = new InputSurface(encoder.createInputSurface()); inputSurface.makeCurrent(); @@ -825,12 +840,16 @@ public class MediaCodecVideoConvertor { long timeLeft = System.currentTimeMillis() - time; if (BuildVars.LOGS_ENABLED) { - FileLog.d("compression completed time=" + timeLeft + " needCompress=" + needCompress + " w=" + resultWidth + " h=" + resultHeight + " bitrate=" + bitrate + " file size=" + cacheFile.length()); + FileLog.d("compression completed time=" + timeLeft + " needCompress=" + needCompress + " w=" + resultWidth + " h=" + resultHeight + " bitrate=" + bitrate + " file size=" + AndroidUtilities.formatFileSize(cacheFile.length()) + " encoder_name=" + selectedEncoderName); } return error; } + private boolean isMediatekAvcEncoder(MediaCodec encoder) { + return encoder.getName().equals("c2.mtk.avc.encoder"); + } + private long readAndWriteTracks(MediaExtractor extractor, MP4Builder mediaMuxer, MediaCodec.BufferInfo info, long start, long end, long duration, File file, boolean needAudio) throws Exception { int videoTrackIndex = MediaController.findTrack(extractor, false); 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 4a8b4755e..05f18b67e 100755 --- a/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/voip/VoIPService.java @@ -3109,7 +3109,11 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa if (hasAudioFocus) { am.abandonAudioFocus(this); } - Utilities.globalQueue.postRunnable(() -> soundPool.release()); + Utilities.globalQueue.postRunnable(() -> { + if (soundPool != null) { + soundPool.release(); + } + }); } if (USE_CONNECTION_SERVICE) { @@ -3559,6 +3563,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa if (!USE_CONNECTION_SERVICE && btAdapter != null && btAdapter.isEnabled()) { try { MediaRouter mr = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE); + AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); if (Build.VERSION.SDK_INT < 24) { int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET); updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED); @@ -3574,7 +3579,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa l.onAudioSettingsChanged(); } } else { - updateBluetoothHeadsetState(false); + updateBluetoothHeadsetState(am.isBluetoothA2dpOn()); } } } catch (Throwable e) { diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java index 5d8594f0c..81a36b00a 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/ConnectionsManager.java @@ -419,7 +419,11 @@ public class ConnectionsManager extends BaseController { } public void checkConnection() { - native_setIpStrategy(currentAccount, getIpStrategy()); + byte selectedStrategy = getIpStrategy(); + if (BuildVars.LOGS_ENABLED) { + FileLog.d("selected ip strategy " + selectedStrategy); + } + native_setIpStrategy(currentAccount, selectedStrategy); native_setNetworkAvailable(currentAccount, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), ApplicationLoader.isConnectionSlow()); } diff --git a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java index d0ce4099d..9f1d47038 100644 --- a/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java +++ b/TMessagesProj/src/main/java/org/telegram/tgnet/TLRPC.java @@ -70,7 +70,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 = 156; + public static final int LAYER = 157; public static class TL_stats_megagroupStats extends TLObject { public static int constructor = 0xef7ff916; @@ -24362,6 +24362,8 @@ public class TLRPC { public int score; public boolean video; public int months; + public String cryptoCurrency; + public long cryptoAmount; public static MessageAction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) { MessageAction result = null; @@ -24528,7 +24530,7 @@ public class TLRPC { case 0x8f31b327: result = new TL_messageActionPaymentSentMe(); break; - case 0xaba0f5c6: + case 0xc83d6aec: result = new TL_messageActionGiftPremium(); break; case 0xfe77345d: @@ -25504,19 +25506,29 @@ public class TLRPC { } public static class TL_messageActionGiftPremium extends MessageAction { - public static int constructor = 0xaba0f5c6; + public static int constructor = 0xc83d6aec; public void readParams(AbstractSerializedData stream, boolean exception) { + flags = stream.readInt32(exception); currency = stream.readString(exception); amount = stream.readInt64(exception); months = stream.readInt32(exception); + if ((flags & 1) != 0) { + cryptoCurrency = stream.readString(exception); + cryptoAmount = stream.readInt64(exception); + } } public void serializeToStream(AbstractSerializedData stream) { stream.writeInt32(constructor); + stream.writeInt32(flags); stream.writeString(currency); stream.writeInt64(amount); stream.writeInt32(months); + if ((flags & 1) != 0) { + stream.writeString(cryptoCurrency); + stream.writeInt64(cryptoAmount); + } } } 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 f5703551c..0e08316fe 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/AlertDialog.java @@ -213,7 +213,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati super(context); this.resourcesProvider = resourcesProvider; - setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 2)); + setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 2)); setPadding(AndroidUtilities.dp(23), 0, AndroidUtilities.dp(23), 0); imageView = new ImageView(context); 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 b5f3c056d..0024a7740 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java @@ -1540,7 +1540,6 @@ public class BottomSheet extends Dialog { onDismissAnimationStart(); if (!allowCustomAnimation || !onCustomCloseAnimation()) { currentSheetAnimationType = 2; - currentSheetAnimation = new AnimatorSet(); if (navigationBarAnimation != null) { navigationBarAnimation.cancel(); } @@ -1551,11 +1550,14 @@ public class BottomSheet extends Dialog { container.invalidate(); } }); - currentSheetAnimation.playTogether( - containerView == null ? null : ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), - ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0), - navigationBarAnimation - ); + currentSheetAnimation = new AnimatorSet(); + ArrayList animators = new ArrayList<>(); + if (containerView != null) { + animators.add(ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0))); + } + animators.add(ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0)); + animators.add(navigationBarAnimation); + currentSheetAnimation.playTogether(animators); // if (useFastDismiss) { // int height = containerView.getMeasuredHeight(); // duration = Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height)); 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 9707e24d6..fe692f256 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/EmojiThemes.java @@ -368,6 +368,7 @@ public class EmojiThemes { } ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document); ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setAllowLoadingOnAttachedOnly(false); String imageFilter; int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); @@ -428,6 +429,7 @@ public class EmojiThemes { final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 140); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document); ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setAllowLoadingOnAttachedOnly(false); imageReceiver.setImage(imageLocation, "120_140", null, null, null, 1); imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); 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 c69dcaafc..110ad0fb9 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/SimpleTextView.java @@ -913,7 +913,7 @@ public class SimpleTextView extends View implements Drawable.Callback { } if (rightDrawable != null && rightDrawableOutside) { - int x = Math.min(textOffsetX + textWidth + drawablePadding + (scrollingOffset == 0 ? -nextScrollX : (int) -scrollingOffset) + nextScrollX, getMaxTextWidth() - paddingRight + drawablePadding - AndroidUtilities.dp(4)); + int x = Math.min(textOffsetX + textWidth + drawablePadding + (scrollingOffset == 0 ? -nextScrollX : (int) -scrollingOffset) + nextScrollX, getMaxTextWidth() - paddingRight + drawablePadding); int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale); int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale); int y; 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 8530e8f20..caad346af 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/Theme.java @@ -6277,6 +6277,7 @@ public class Theme { 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); } @@ -10878,13 +10879,27 @@ public class Theme { return false; } - public static void turnOffAutoNight(BaseFragment fragment) { - turnOffAutoNight(fragment != null ? fragment.getLayoutContainer() : null, () -> { - INavigationLayout nav = fragment != null ? fragment.getParentLayout() : null; - if (nav != null) { - nav.presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT)); + public static void turnOffAutoNight(@NonNull BaseFragment fragment) { + if (selectedAutoNightType != AUTO_NIGHT_TYPE_NONE) { + if (fragment != null) { + try { + BulletinFactory.of(fragment).createSimpleBulletin( + R.raw.auto_night_off, + selectedAutoNightType == AUTO_NIGHT_TYPE_SYSTEM ? + LocaleController.getString("AutoNightSystemModeOff", R.string.AutoNightSystemModeOff) : + LocaleController.getString("AutoNightModeOff", R.string.AutoNightModeOff), + LocaleController.getString("Settings", R.string.Settings), + Bulletin.DURATION_PROLONG, + () -> fragment.presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT)) + ).show(); + } catch (Exception e) { + FileLog.e(e); + } } - }); + selectedAutoNightType = AUTO_NIGHT_TYPE_NONE; + saveAutoNightThemeConfig(); + cancelAutoNightThemeCallbacks(); + } } public static void turnOffAutoNight(FrameLayout container, Runnable openSettings) { 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 ddc54451a..1255e617e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/DialogsSearchAdapter.java @@ -22,6 +22,8 @@ import androidx.recyclerview.widget.DefaultItemAnimator; 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; @@ -293,6 +295,9 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { if (reqForumId != 0 && reqId != 0) { return; } + if (lastMessagesSearchId != lastSearchId) { + return; + } if (delegate != null && delegate.getSearchForumDialogId() != 0 && !localMessagesSearchEndReached) { searchForumMessagesInternal(lastMessagesSearchString, lastMessagesSearchId); } else { @@ -465,7 +470,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { req.filter = new TLRPC.TL_inputMessagesFilterEmpty(); req.flags |= 1; req.folder_id = folderId; - if (query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty()) { + if (query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty() && lastMessagesSearchId == lastSearchId) { MessageObject lastMessage = searchResultMessages.get(searchResultMessages.size() - 1); req.offset_id = lastMessage.getId(); req.offset_rate = nextSearchRate; @@ -477,7 +482,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { req.offset_peer = new TLRPC.TL_inputPeerEmpty(); } lastMessagesSearchString = query; - final int currentReqId = ++lastReqId; + lastReqId++; + final int currentReqId = lastReqId; reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> { final ArrayList messageObjects = new ArrayList<>(); if (error == null) { @@ -1046,7 +1052,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter { searchResultHashtags.clear(); } - final int searchId = ++lastSearchId; + lastSearchId++; + final int searchId = lastSearchId; waitingResponseCount = 3; globalSearchCollapsed = true; phoneCollapsed = true; diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 7d9fcf3ac..4944a048b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java @@ -20,6 +20,7 @@ import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.RectF; +import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; @@ -44,6 +45,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.core.graphics.ColorUtils; +import androidx.core.math.MathUtils; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -99,6 +101,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.ListView.AdapterWithDiffUtils; import org.telegram.ui.Components.LoadingDrawable; import org.telegram.ui.Components.NestedSizeNotifierLayout; +import org.telegram.ui.Components.RLottieImageView; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SlideChooseView; import org.telegram.ui.Components.StorageDiagramView; @@ -108,6 +111,9 @@ import org.telegram.ui.Components.UndoView; import org.telegram.ui.Storage.CacheModel; import java.io.File; +import java.nio.file.Files; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -823,7 +829,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe return size; } - private void cleanupFolders() { + private void cleanupFolders(Utilities.Callback2 onProgress, Runnable onDone) { if (cacheModel != null) { cacheModel.clearSelection(); } @@ -832,22 +838,125 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe cachedMediaLayout.showActionMode(false); } - progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER); - progressDialog.setCanCancel(false); - progressDialog.showDelayed(500); +// progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER); +// progressDialog.setCanCancel(false); +// progressDialog.showDelayed(500); getFileLoader().cancelLoadAllFiles(); getFileLoader().getFileLoaderQueue().postRunnable(() -> Utilities.globalQueue.postRunnable(() -> { - cleanupFoldersInternal(); + cleanupFoldersInternal(onProgress, onDone); })); setCacheModel(null); loadingDialogs = true; // updateRows(); } - private void cleanupFoldersInternal() { + private static int LISTDIR_DOCTYPE_ALL = 0; + private static int LISTDIR_DOCTYPE_OTHER_THAN_MUSIC = 1; + private static int LISTDIR_DOCTYPE_MUSIC = 2; + + private static int LISTDIR_DOCTYPE2_EMOJI = 3; + private static int LISTDIR_DOCTYPE2_TEMP = 4; + private static int LISTDIR_DOCTYPE2_OTHER = 5; + + public static int countDirJava(String fileName, int docType) { + int count = 0; + File dir = new File(fileName); + if (dir.exists()) { + File[] entries = dir.listFiles(); + for (int i = 0; i < entries.length; ++i) { + File entry = entries[i]; + String name = entry.getName(); + if (".".equals(name)) { + continue; + } + + if (docType > 0 && name.length() >= 4) { + String namelc = name.toLowerCase(); + boolean isMusic = namelc.endsWith(".mp3") || namelc.endsWith(".m4a"); + boolean isEmoji = namelc.endsWith(".tgs") || namelc.endsWith(".webm"); + boolean isTemp = namelc.endsWith(".tmp") || namelc.endsWith(".temp") || namelc.endsWith(".preload"); + + if ( + isMusic && docType == LISTDIR_DOCTYPE_OTHER_THAN_MUSIC || + !isMusic && docType == LISTDIR_DOCTYPE_MUSIC || + isEmoji && docType == LISTDIR_DOCTYPE2_OTHER || + !isEmoji && docType == LISTDIR_DOCTYPE2_EMOJI || + isTemp && docType == LISTDIR_DOCTYPE2_OTHER || + !isTemp && docType == LISTDIR_DOCTYPE2_TEMP + ) { + continue; + } + } + + if (entry.isDirectory()) { + count += countDirJava(fileName + "/" + name, docType); + } else { + count++; + } + } + } + return count; + } + + public static void cleanDirJava(String fileName, int docType, int[] p, Utilities.Callback onProgress) { + int count = countDirJava(fileName, docType); + if (p == null) { + p = new int[] { 0 }; + } + File dir = new File(fileName); + if (dir.exists()) { + File[] entries = dir.listFiles(); + for (int i = 0; i < entries.length; ++i) { + File entry = entries[i]; + String name = entry.getName(); + if (".".equals(name)) { + continue; + } + + if (docType > 0 && name.length() >= 4) { + String namelc = name.toLowerCase(); + boolean isMusic = namelc.endsWith(".mp3") || namelc.endsWith(".m4a"); + boolean isEmoji = namelc.endsWith(".tgs") || namelc.endsWith(".webm"); + boolean isTemp = namelc.endsWith(".tmp") || namelc.endsWith(".temp") || namelc.endsWith(".preload"); + + if ( + isMusic && docType == LISTDIR_DOCTYPE_OTHER_THAN_MUSIC || + !isMusic && docType == LISTDIR_DOCTYPE_MUSIC || + isEmoji && docType == LISTDIR_DOCTYPE2_OTHER || + !isEmoji && docType == LISTDIR_DOCTYPE2_EMOJI || + isTemp && docType == LISTDIR_DOCTYPE2_OTHER || + !isTemp && docType == LISTDIR_DOCTYPE2_TEMP + ) { + continue; + } + } + + if (entry.isDirectory()) { + cleanDirJava(fileName + "/" + name, docType, p, onProgress); + } else { + entry.delete(); + + p[0]++; + onProgress.run(p[0] / (float) count); + } + } + } + } + + private void cleanupFoldersInternal(Utilities.Callback2 onProgress, Runnable onDone) { boolean imagesCleared = false; long clearedSize = 0; boolean allItemsClear = true; + final int[] clearDirI = new int[] { 0 }; + int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0); + long time = System.currentTimeMillis(); + Utilities.Callback updateProgress = t -> { + onProgress.run(clearDirI[0] / (float) clearDirCount + (1f / clearDirCount) * MathUtils.clamp(t, 0, 1), false); + }; + Runnable next = () -> { + final long now = System.currentTimeMillis(); + onProgress.run(clearDirI[0] / (float) clearDirCount, now - time > 250); + }; for (int a = 0; a < 8; a++) { if (!selected[a]) { allItemsClear = false; @@ -894,13 +1003,17 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe file = FileLoader.checkDirectory(type); } if (file != null) { - Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false); + cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress); } + clearDirI[0]++; + next.run(); if (type == 100) { file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE); if (file != null) { - Utilities.clearDir(file.getAbsolutePath(), 3, Long.MAX_VALUE, false); + cleanDirJava(file.getAbsolutePath(), 3, null, updateProgress); } + clearDirI[0]++; + next.run(); } if (type == FileLoader.MEDIA_DIR_IMAGE || type == FileLoader.MEDIA_DIR_VIDEO) { int publicDirectoryType; @@ -912,14 +1025,18 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe file = FileLoader.checkDirectory(publicDirectoryType); if (file != null) { - Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false); + cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress); } + clearDirI[0]++; + next.run(); } 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); + cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress); } + clearDirI[0]++; + next.run(); } if (type == FileLoader.MEDIA_DIR_CACHE) { @@ -1006,6 +1123,10 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe MediaDataController.getInstance(currentAccount).chekAllMedia(true); loadDialogEntities(); + + if (onDone != null) { + onDone.run(); + } }); } @@ -1694,13 +1815,144 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } } + private class ClearingCacheView extends FrameLayout { + + RLottieImageView imageView; + AnimatedTextView percentsTextView; + ProgressView progressView; + TextView title, subtitle; + + public ClearingCacheView(Context context) { + super(context); + + imageView = new RLottieImageView(context); + imageView.setAutoRepeat(true); + imageView.setAnimation(R.raw.utyan_cache, 150, 150); + addView(imageView, LayoutHelper.createFrame(150, 150, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16, 0, 0)); + imageView.playAnimation(); + + percentsTextView = new AnimatedTextView(context, false, true, true); + percentsTextView.setAnimationProperties(.35f, 0, 120, CubicBezierInterpolator.EASE_OUT); + percentsTextView.setGravity(Gravity.CENTER_HORIZONTAL); + percentsTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + percentsTextView.setTextSize(AndroidUtilities.dp(24)); + percentsTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + addView(percentsTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 - 6, 0, 0)); + + progressView = new ProgressView(context); + addView(progressView, LayoutHelper.createFrame(240, 5, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16, 0, 0)); + + title = new TextView(context); + title.setGravity(Gravity.CENTER_HORIZONTAL); + title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + title.setText(LocaleController.getString("ClearingCache", R.string.ClearingCache)); + addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16 + 5 + 30, 0, 0)); + + subtitle = new TextView(context); + subtitle.setGravity(Gravity.CENTER_HORIZONTAL); + subtitle.setTextColor(Theme.getColor(Theme.key_dialogTextBlack)); + subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14); + subtitle.setText(LocaleController.getString("ClearingCacheDescription", R.string.ClearingCacheDescription)); + addView(subtitle, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16 + 5 + 30 + 18 + 10, 0, 0)); + + setProgress(0); + } + + public void setProgress(float t) { + percentsTextView.cancelAnimation(); + percentsTextView.setText(String.format("%d%%", (int) Math.ceil(MathUtils.clamp(t, 0, 1) * 100)), !LocaleController.isRTL); + progressView.setProgress(t); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure( + MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), + MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(350), MeasureSpec.EXACTLY) + ); + } + + class ProgressView extends View { + + Paint in = new Paint(Paint.ANTI_ALIAS_FLAG), out = new Paint(Paint.ANTI_ALIAS_FLAG); + + public ProgressView(Context context) { + super(context); + + in.setColor(Theme.getColor(Theme.key_switchTrackChecked)); + out.setColor(Theme.multAlpha(Theme.getColor(Theme.key_switchTrackChecked), .2f)); + } + + float progress; + AnimatedFloat progressT = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT); + + public void setProgress(float t) { + this.progress = t; + invalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), out); + + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth() * progressT.set(this.progress), getMeasuredHeight()); + canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), in); + } + } + } + private class ClearCacheButtonInternal extends ClearCacheButton { public ClearCacheButtonInternal(Context context) { super(context); ((MarginLayoutParams) button.getLayoutParams()).topMargin = AndroidUtilities.dp(5); button.setOnClickListener(e -> { - cleanupFolders(); + BottomSheet bottomSheet = new BottomSheet(getContext(), false) { + @Override + protected boolean canDismissWithTouchOutside() { + return false; + } + }; + bottomSheet.fixNavigationBar(); + bottomSheet.setCanDismissWithSwipe(false); + bottomSheet.setCancelable(false); + ClearingCacheView cacheView = new ClearingCacheView(getContext()); + bottomSheet.setCustomView(cacheView); + + final boolean[] done = new boolean[] { false }; + final float[] progress = new float[] { 0 }; + final boolean[] nextSection = new boolean[] { false }; + Runnable updateProgress = () -> { + cacheView.setProgress(progress[0]); + if (nextSection[0]) { + updateRows(); + } + }; + + AndroidUtilities.runOnUIThread(() -> { + if (!done[0]) { + showDialog(bottomSheet); + } + }, 150); + + cleanupFolders( + (progressValue, next) -> { + progress[0] = progressValue; + nextSection[0] = next; + AndroidUtilities.cancelRunOnUIThread(updateProgress); + AndroidUtilities.runOnUIThread(updateProgress); + }, + () -> AndroidUtilities.runOnUIThread(() -> { + done[0] = true; + cacheView.setProgress(1F); + bottomSheet.dismiss(); + }) + ); }); } @@ -1778,8 +2030,6 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe } }; button.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 8)); - button.setFocusable(true); - button.setFocusableInTouchMode(true); button.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); if (LocaleController.isRTL) { @@ -1809,6 +2059,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe valueTextView.setTextColor(Theme.adaptHSV(Theme.getColor(Theme.key_featuredStickers_addButton), -.46f, +.08f)); valueTextView.setText(""); + button.setContentDescription(TextUtils.concat(textView.getText(), "\t", valueTextView.getText())); + setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 16, 16, 16, 16)); } 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 d9de94276..81702138a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -82,6 +82,7 @@ import org.telegram.PhoneFormat.PhoneFormat; import org.telegram.messenger.AccountInstance; import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.ApplicationLoader; +import org.telegram.messenger.BuildVars; import org.telegram.messenger.ChatObject; import org.telegram.messenger.ContactsController; import org.telegram.messenger.DialogObject; @@ -182,7 +183,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate public boolean clipToGroupBounds; public boolean drawForBlur; private boolean flipImage; - private boolean visibleOnScreen; + private boolean visibleOnScreen = true; public boolean shouldCheckVisibleOnScreen; float parentBoundsTop; int parentBoundsBottom; @@ -374,6 +375,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (this.visibleOnScreen != visibleOnScreen) { this.visibleOnScreen = visibleOnScreen; checkImageReceiversAttachState(); + if (visibleOnScreen) { + invalidate(); + } } } @@ -3887,9 +3891,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad); cancelShakeAnimation(); - if (animationRunning) { - return; - } if (checkBox != null) { checkBox.onDetachedFromWindow(); } @@ -3946,9 +3947,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded); NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad); -// if (currentMessageObject != null) { -// currentMessageObject.onAttachedWindow(this); -// } if (currentMessageObject != null) { currentMessageObject.animateComments = false; } @@ -4093,26 +4091,30 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate photoImage.onDetachedFromWindow(); blurredPhotoImage.onDetachedFromWindow(); - if (currentMessageObject != null && !currentMessageObject.mediaExists && !currentMessageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(currentMessageObject.messageOwner.id)) { - TLRPC.Document document = currentMessageObject.getDocument(); - boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document); - if (!loadDocumentFromImageReceiver) { - if (document != null) { - FileLoader.getInstance(currentAccount).cancelLoadFile(document); - } else { - TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); - if (photo != null) { - FileLoader.getInstance(currentAccount).cancelLoadFile(photo); - } - } - } - } + cancelLoading(currentMessageObject); AnimatedEmojiSpan.release(this, animatedEmojiDescriptionStack); AnimatedEmojiSpan.release(this, animatedEmojiReplyStack); AnimatedEmojiSpan.release(this, animatedEmojiStack); } } + private void cancelLoading(MessageObject messageObject) { + if (messageObject != null && !messageObject.mediaExists && !messageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(messageObject.messageOwner.id) && !PhotoViewer.getInstance().isVisible()) { + TLRPC.Document document = messageObject.getDocument(); + boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document); + if (!loadDocumentFromImageReceiver) { + if (document != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(document); + } else { + TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize()); + if (photo != null) { + FileLoader.getInstance(currentAccount).cancelLoadFile(photo); + } + } + } + } + } + private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) { if (messageObject.checkLayout() || currentPosition != null && lastHeight != AndroidUtilities.displaySize.y) { currentMessageObject = null; @@ -7595,7 +7597,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate botButtonsByData.put(key, botButton); botButtonsByPosition.put(position, botButton); botButton.x = b * (buttonWidth + AndroidUtilities.dp(5)); - botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(5); + botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(2.5f); botButton.width = buttonWidth; botButton.height = AndroidUtilities.dp(44); CharSequence buttonText; @@ -17663,9 +17665,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate } else { this.willRemoved = false; } - if (getParent() == null && attachedToWindow) { - onDetachedFromWindow(); - } } @Override 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 ebfac4c22..c8934c10a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -515,13 +515,14 @@ public class DialogCell extends BaseCell { for (int i = 0; i < thumbImage.length; ++i) { thumbImage[i] = new ImageReceiver(this); thumbImage[i].setRoundRadius(AndroidUtilities.dp(2)); + thumbImage[i].setAllowLoadingOnAttachedOnly(true); } useForceThreeLines = forceThreeLines; currentAccount = account; - emojiStatus = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(22)); emojiStatus.center = false; + avatarImage.setAllowLoadingOnAttachedOnly(true); } public void setDialog(TLRPC.Dialog dialog, int type, int folder) { @@ -2123,7 +2124,7 @@ public class DialogCell extends BaseCell { } else if (drawScam != 0) { nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth()); } else { - nameMuteLeft = 0; + nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth()); } if (left == 0) { if (widthpx < nameWidth) { @@ -2195,7 +2196,7 @@ public class DialogCell extends BaseCell { nameLeft -= (nameWidth - widthpx); } } - if (dialogMuted || drawUnmute || drawVerified || drawPremium || drawScam != 0) { + if ((dialogMuted || true) || drawUnmute || drawVerified || drawPremium || drawScam != 0) { nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6)); } } @@ -3847,7 +3848,7 @@ public class DialogCell extends BaseCell { float size1; float size2; - if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { + if (!LiteMode.isEnabled(LiteMode.FLAGS_CHAT)) { innerProgress = 0.65f; } if (progressStage == 0) { @@ -3892,7 +3893,7 @@ public class DialogCell extends BaseCell { canvas.restore(); } - if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { + if (LiteMode.isEnabled(LiteMode.FLAGS_CHAT)) { innerProgress += 16f / 400.0f; if (innerProgress >= 1.0f) { innerProgress = 0.0f; 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 dbdc917ff..33defbc85 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ShadowSectionCell.java @@ -22,6 +22,12 @@ public class ShadowSectionCell extends View { private int size; + private int backgroundColor; + private Theme.ResourcesProvider resourcesProvider; + + private boolean top = true; + private boolean bottom = true; + public ShadowSectionCell(Context context) { this(context, 12, null); } @@ -36,8 +42,9 @@ public class ShadowSectionCell extends View { public ShadowSectionCell(Context context, int s, Theme.ResourcesProvider resourcesProvider) { super(context); - setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider))); - size = s; + this.resourcesProvider = resourcesProvider; + this.size = s; + updateBackground(); } public ShadowSectionCell(Context context, int s, int backgroundColor) { @@ -46,12 +53,50 @@ public class ShadowSectionCell extends View { public ShadowSectionCell(Context context, int s, int backgroundColor, Theme.ResourcesProvider resourcesProvider) { super(context); - 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); - setBackgroundDrawable(combinedDrawable); - size = s; + this.resourcesProvider = resourcesProvider; + this.backgroundColor = backgroundColor; + this.size = s; + updateBackground(); + } + + public void setTopBottom(boolean top, boolean bottom) { + if (this.top != top || this.bottom != bottom) { + this.top = top; + this.bottom = bottom; + updateBackground(); + } + } + + private void updateBackground() { + if (backgroundColor == 0) { + if (!top && !bottom) { + setBackground(null); + } else { + setBackground(Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider))); + } + } else { + if (!top && !bottom) { + setBackgroundColor(backgroundColor); + } else { + Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); + Drawable background = new ColorDrawable(backgroundColor); + CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); + combinedDrawable.setFullsize(true); + setBackground(combinedDrawable); + } + } + } + + private int getBackgroundResId() { + if (top && bottom) { + return R.drawable.greydivider; + } else if (top) { + return R.drawable.greydivider_bottom; + } else if (bottom) { + return R.drawable.greydivider_top; + } else { + return R.drawable.transparent; + } } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java index c4fc90163..0aead408a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -300,6 +300,7 @@ import org.telegram.ui.Components.UndoView; import org.telegram.ui.Components.UnreadCounterTextView; import org.telegram.ui.Components.ViewHelper; import org.telegram.ui.Components.spoilers.SpoilerEffect; +import org.telegram.ui.Components.voip.CellFlickerDrawable; import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import org.telegram.ui.DialogBuilder.DialogCheckBox; @@ -388,6 +389,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private GridLayoutManagerFixed chatLayoutManager; private ChatActivityAdapter chatAdapter; private UnreadCounterTextView bottomOverlayChatText; + private TextView bottomOverlayStartButton; private ImageView bottomOverlayImage; private RadialProgressView bottomOverlayProgress; private AnimatorSet bottomOverlayAnimation; @@ -721,6 +723,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not private int loadsCount; private int last_message_id = 0; private long mergeDialogId; + private boolean sentBotStart; private long startMessageAppearTransitionMs; private List messageSkeletons = new ArrayList<>(); @@ -3434,6 +3437,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (themeDelegate.isThemeChangeAvailable()) { headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("ChangeColors", R.string.ChangeColors)); } + boolean addedSettings = false; if (!isTopic) { if (ChatObject.isChannel(currentChat) && !currentChat.creator) { if (!ChatObject.isNotInChat(currentChat)) { @@ -3446,6 +3450,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } else if (!ChatObject.isChannel(currentChat)) { if (currentChat != null) { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit)); + } else if (currentUser != null && currentUser.bot) { + headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); + addedSettings = true; + headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_dialogTextRed), getThemedColor(Theme.key_dialogTextRed)); } else { headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser)); } @@ -3455,7 +3463,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); } if (currentUser != null && currentEncryptedChat == null && currentUser.bot) { - headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); + if (!addedSettings) { + headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings)); + } headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp)); updateBotButtons(); } @@ -5148,26 +5158,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } - @Override - public void onScrolled(int dx, int dy) { - super.onScrolled(dx, dy); - } - - @Override - public void onScrollStateChanged(int state) { - super.onScrollStateChanged(state); - } - - @Override - protected void onScrollChanged(int l, int t, int oldl, int oldt) { - super.onScrollChanged(l, t, oldl, oldt); - } - - @Override - public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { - super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); - } - @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); @@ -5178,7 +5168,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not protected void onDetachedFromWindow() { super.onDetachedFromWindow(); chatListViewAttached = false; - clearMessagesPreloading(); } }; if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { @@ -5534,7 +5523,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not scrollingChatListView = false; checkTextureViewPosition = false; hideFloatingDateView(true); - checkAutoDownloadMessages(scrollUp); if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); } @@ -6821,6 +6809,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not bottomOverlayChat.setClipChildren(false); contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); + bottomOverlayStartButton = new TextView(context) { + CellFlickerDrawable cellFlickerDrawable; + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (cellFlickerDrawable == null) { + cellFlickerDrawable = new CellFlickerDrawable(); + cellFlickerDrawable.drawFrame = false; + cellFlickerDrawable.repeatProgress = 2f; + } + cellFlickerDrawable.setParentWidth(getMeasuredWidth()); + AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); + cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null); + invalidate(); + } + + @Override + public void setVisibility(int visibility) { + super.setVisibility(visibility); + + ViewGroup.LayoutParams params = bottomOverlayChat.getLayoutParams(); + params.height = AndroidUtilities.dp(visibility == VISIBLE ? 51 + 8 * 2 : 51); + } + }; + bottomOverlayStartButton.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 8)); + bottomOverlayStartButton.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText)); + bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStart)); + bottomOverlayStartButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); + bottomOverlayStartButton.setGravity(Gravity.CENTER); + bottomOverlayStartButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM)); + bottomOverlayStartButton.setVisibility(View.GONE); + bottomOverlayStartButton.setOnClickListener(v -> bottomOverlayChatText.callOnClick()); + bottomOverlayChat.addView(bottomOverlayStartButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 8, 8, 8, 8)); + bottomOverlayChatText = new UnreadCounterTextView(context) { @Override protected void updateCounter() { @@ -6875,12 +6898,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (currentUser.bot) { String botUserLast = botUser; botUser = null; - getMessagesController().unblockPeer(currentUser.id); - if (botUserLast != null && botUserLast.length() != 0) { - getMessagesController().sendBotStart(currentUser, botUserLast); - } else { - getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null, false); - } + getMessagesController().unblockPeer(currentUser.id, () -> { + if (botUserLast != null && botUserLast.length() != 0) { + getMessagesController().sendBotStart(currentUser, botUserLast); + } else { + getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null, false); + } + }); } else { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate); builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact)); @@ -10352,127 +10376,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not showDialog(chatAttachAlert); } - ArrayList preloadingMessages = new ArrayList<>(); - ArrayList preloadingMessagesTmp = new ArrayList<>(); - SparseArray attachedMessaesTmp = new SparseArray<>(); - - private void checkAutoDownloadMessages(boolean scrollUp) { - if (chatListView == null || !chatListViewAttached || SharedConfig.deviceIsLow()) { - return; - } - preloadingMessagesTmp.clear(); - preloadingMessagesTmp.addAll(preloadingMessages); - preloadingMessages.clear(); - attachedMessaesTmp.clear(); - int count = chatListView.getChildCount(); - int firstMessagePosition = -1; - int lastMessagePosition = -1; - for (int a = 0; a < count; a++) { - View child = chatListView.getChildAt(a); - if (!(child instanceof ChatMessageCell)) { - continue; - } - RecyclerListView.ViewHolder holder = chatListView.findContainingViewHolder(child); - if (holder != null) { - int p = holder.getAdapterPosition(); - if (firstMessagePosition == -1) { - firstMessagePosition = p; - } - lastMessagePosition = p; - } - ChatMessageCell cell = (ChatMessageCell) child; - MessageObject object = cell.getMessageObject(); - attachedMessaesTmp.put(object.getId(), object); - } - if (firstMessagePosition != -1) { - int lastPosition; - if (scrollUp) { - firstMessagePosition = lastPosition = lastMessagePosition; - firstMessagePosition = Math.min(firstMessagePosition + 10, chatAdapter.messagesEndRow); - for (int a = lastPosition, N = messages.size(); a < firstMessagePosition; a++) { - int n = a - chatAdapter.messagesStartRow; - if (n < 0 || n >= N) { - continue; - } - preloadingMessagesTmp.remove(messages.get(n)); - preloadingMessages.add(messages.get(n)); - checkAutoDownloadMessage(messages.get(n)); - } - } else { - lastPosition = Math.max(firstMessagePosition - 20, chatAdapter.messagesStartRow); - for (int a = firstMessagePosition - 1, N = messages.size(); a >= lastPosition; a--) { - int n = a - chatAdapter.messagesStartRow; - if (n < 0 || n >= N) { - continue; - } - preloadingMessagesTmp.remove(messages.get(n)); - preloadingMessages.add(messages.get(n)); - checkAutoDownloadMessage(messages.get(n)); - } - } - } - for (int i = 0; i < preloadingMessagesTmp.size(); i++) { - MessageObject object = preloadingMessagesTmp.get(i); - if (attachedMessaesTmp.get(object.getId()) != null) { - continue; - } - cancelPreload(object); - } - showNoSoundHint(); - } - - private void cancelPreload(MessageObject object) { - TLRPC.Document document = object.getDocument(); - TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, AndroidUtilities.getPhotoSize()) : null; - if (document == null && photo == null) { - return; - } - if (object.putInDownloadsStore || DownloadController.getInstance(currentAccount).isDownloading(object.messageOwner.id)) { - return; - } - if (document != null) { - getFileLoader().cancelLoadFile(document); - } else { - ImageLocation.getForObject(photo, object.photoThumbsObject); - getFileLoader().cancelLoadFile(ImageLocation.getForObject(photo, object.photoThumbsObject).location, null); - } - } - - private void checkAutoDownloadMessage(MessageObject object) { -// if (object.mediaExists) { -// return; -// } -// TLRPC.Message message = object.messageOwner; -// int canDownload = getDownloadController().canDownloadMedia(message); -// if (canDownload == 0) { -// return; -// } -// TLRPC.Document document = object.getDocument(); -// TLRPC.PhotoSize photo = document == null ? FileLoader.getClosestPhotoSizeWithSize(object.photoThumbs, AndroidUtilities.getPhotoSize()) : null; -// if (document == null && photo == null) { -// return; -// } -// if (canDownload == 2 || canDownload == 1 && object.isVideo()) { -//// if (document != null && currentEncryptedChat == null && !object.shouldEncryptPhotoOrVideo() && object.canStreamVideo()) { -//// getFileLoader().loadFile(document, object, FileLoader.PRIORITY_LOW, 10); -//// } -// } else { -// if (document != null) { -// getFileLoader().loadFile(document, object, FileLoader.PRIORITY_LOW, MessageObject.isVideoDocument(document) && object.shouldEncryptPhotoOrVideo() ? 2 : 0); -// } else { -// getFileLoader().loadFile(ImageLocation.getForObject(photo, object.photoThumbsObject), object, null, FileLoader.PRIORITY_LOW, object.shouldEncryptPhotoOrVideo() ? 2 : 0); -// } -// } - } - - public void clearMessagesPreloading() { - for (int i = 0; i < preloadingMessages.size(); i++) { - MessageObject object = preloadingMessages.get(i); - cancelPreload(object); - } - preloadingMessages.clear(); - } - private void showFloatingDateView(boolean scroll) { if (floatingDateView == null) { return; @@ -11911,7 +11814,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) { if (messageCell != null) { - if (!blurEnabled) { + if (blurEnabled) { messageCell.setVisibleOnScreen(false); } else { messageCell.setVisibleOnScreen(true); @@ -13678,6 +13581,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) { h += keyboardSize; } + if (bottomOverlay != null && bottomOverlay.getVisibility() == View.VISIBLE && bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() != View.GONE) { + h -= AndroidUtilities.dp(16); + } int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), h), View.MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (child == progressView) { @@ -13927,9 +13833,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not invalidateMessagesVisiblePart(); updateTextureViewPosition(false, false); - if (!scrollingChatListView) { - checkAutoDownloadMessages(false); - } notifyHeightChanged(); } @@ -16437,6 +16340,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not getNotificationCenter().runDelayedNotifications(); }); } + + if (did == dialog_id && !messages.isEmpty() && currentUser != null && (bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() == View.VISIBLE)) { + if (!TextUtils.isEmpty(botUser) && !sentBotStart) { + sentBotStart = true; + getMessagesController().sendBotStart(currentUser, botUser); + + bottomOverlayChat.setVisibility(View.GONE); + chatActivityEnterView.setVisibility(View.VISIBLE); + } + } } else if (id == NotificationCenter.invalidateMotionBackground) { if (chatListView != null) { chatListView.invalidateViews(); @@ -16484,9 +16397,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } } else if (id == NotificationCenter.didUpdateConnectionState) { int state = ConnectionsManager.getInstance(account).getConnectionState(); - if (state == ConnectionsManager.ConnectionStateConnected) { - checkAutoDownloadMessages(false); - } } else if (id == NotificationCenter.chatOnlineCountDidLoad) { Long chatId = (Long) args[0]; if (chatInfo == null || currentChat == null || currentChat.id != chatId) { @@ -20815,11 +20725,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not } showBottomOverlayProgress(false, true); } else if (botUser != null && currentUser.bot) { - bottomOverlayChatText.setText(LocaleController.getString("BotStart", R.string.BotStart)); +// bottomOverlayStartButton.setText(LocaleController.getString("BotStart", R.string.BotStart)); + bottomOverlayStartButton.setVisibility(View.VISIBLE); + bottomOverlayChatText.setVisibility(View.GONE); chatActivityEnterView.hidePopup(false); if (getParentActivity() != null) { AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); } + + if (dialog_id == dialog_id && !messages.isEmpty() && currentUser != null) { + if (botUser.length() != 0 && !sentBotStart) { + sentBotStart = true; + } + } } else { bottomOverlayChatText.setText(LocaleController.getString("DeleteThisChat", R.string.DeleteThisChat)); } @@ -20839,6 +20757,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not chatActivityEnterView.setVisibility(View.INVISIBLE); } else if (searchItem != null && searchItemVisible) { createSearchContainer(); + if (searchContainer == null) { + return; + } searchContainer.animate().setListener(null).cancel(); if (searchContainer.getVisibility() != View.VISIBLE) { searchContainer.setVisibility(View.VISIBLE); @@ -20986,6 +20907,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not topViewWasVisible = 0; } } + if (sentBotStart) { + getMessagesController().sendBotStart(currentUser, botUser); + + bottomOverlayChat.setVisibility(View.GONE); + chatActivityEnterView.setVisibility(View.VISIBLE); + } checkRaiseSensors(); } 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 04a9c2be1..570e84cdf 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AlertsCreator.java @@ -1509,7 +1509,19 @@ public class AlertsCreator { lastMessageIsJoined = true; } - if (!second && (secret && !clear || canDeleteInbox) && !UserObject.isDeleted(user) && !lastMessageIsJoined || (deleteChatForAll = checkDeleteForAll && !clear && chat != null && chat.creator)) { + if (user != null && user.bot) { + cell[0] = new CheckBoxCell(context, 1, resourcesProvider); + cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false)); + cell[0].setText(LocaleController.getString(R.string.BlockBot), "", false, false); + cell[0].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0); + cell[0].setChecked(deleteForAll[0] = true, false); + frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0)); + cell[0].setOnClickListener(v -> { + CheckBoxCell cell1 = (CheckBoxCell) v; + deleteForAll[0] = !deleteForAll[0]; + cell1.setChecked(deleteForAll[0], true); + }); + } else 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) { @@ -1603,7 +1615,7 @@ public class AlertsCreator { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureDeleteThisChatSavedMessages", R.string.AreYouSureDeleteThisChatSavedMessages))); } else { if (user.bot && !user.support) { - messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithBot", R.string.AreYouSureDeleteThisChatWithBot, UserObject.getUserName(user, account)))); + messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.AreYouSureDeleteThisChatWithBotWithCheckmark, UserObject.getUserName(user, account)))); } else { messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user, account)))); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java index c91221cbf..49023dfdd 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/AnimatedEmojiDrawable.java @@ -462,6 +462,7 @@ public class AnimatedEmojiDrawable extends Drawable { return super.setImageBitmapByKey(drawable, key, type, memCache, guid); } }; + imageReceiver.setAllowLoadingOnAttachedOnly(true); }; if (cacheType == CACHE_TYPE_RENDERING_VIDEO) { imageReceiver.ignoreNotifications = true; 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 647eaed27..43ab4a0a1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Bulletin.java @@ -93,7 +93,7 @@ public class Bulletin { @SuppressLint("RtlHardcoded") public static Bulletin make(@NonNull BaseFragment fragment, @NonNull Layout contentLayout, int duration) { if (fragment instanceof ChatActivity) { - contentLayout.setWideScreenParams(ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.RIGHT); + contentLayout.setWideScreenParams(ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL); } else if (fragment instanceof DialogsActivity) { contentLayout.setWideScreenParams(ViewGroup.LayoutParams.MATCH_PARENT, Gravity.NO_GRAVITY); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/CanvasButton.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/CanvasButton.java index 344056a31..2cf5bda65 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/CanvasButton.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/CanvasButton.java @@ -29,7 +29,7 @@ public class CanvasButton { ArrayList drawingRects = new ArrayList<>(); int usingRectCount; boolean buttonPressed; - RippleDrawable selectorDrawable; + Drawable selectorDrawable; private final static int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed}; private final View parent; @@ -256,7 +256,9 @@ public class CanvasButton { public void setRoundRadius(int radius) { roundRadius = radius; pathEffect = new CornerPathEffect(radius); - maskPaint.setPathEffect(new CornerPathEffect(radius)); + if (maskPaint != null) { + maskPaint.setPathEffect(new CornerPathEffect(radius)); + } } public void cancelRipple() { 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 b99767e86..4cc272181 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -730,7 +730,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific delegate.needStartRecordAudio(1); startedDraggingX = -1; - MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid); + MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid, true); recordingAudioVideo = true; updateRecordInterface(RECORD_STATE_ENTER); if (recordTimerView != null) { @@ -2022,55 +2022,84 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific sendButtonContainer.setClipToPadding(false); textFieldContainer.addView(sendButtonContainer, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT)); - audioVideoButtonContainer = new FrameLayout(context); - audioVideoButtonContainer.setSoundEffectsEnabled(false); - sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48)); - audioVideoButtonContainer.setFocusable(true); - audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); - audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> { - createRecordCircle(); - if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { - if (recordCircle.isSendButtonVisible()) { - if (!hasRecordVideo || calledRecordRunnable) { - startedDraggingX = -1; - if (hasRecordVideo && isInVideoMode()) { - delegate.needStartRecordVideo(1, true, 0); - } else { - if (recordingAudioVideo && isInScheduleMode()) { - AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); + audioVideoButtonContainer = new FrameLayout(context) { + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return true; + } + + @Override + public boolean onTouchEvent(MotionEvent motionEvent) { + createRecordCircle(); + if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { + if (recordCircle.isSendButtonVisible()) { + if (!hasRecordVideo || calledRecordRunnable) { + startedDraggingX = -1; + if (hasRecordVideo && isInVideoMode()) { + delegate.needStartRecordVideo(1, true, 0); + } else { + if (recordingAudioVideo && isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); + } + MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); + delegate.needStartRecordAudio(0); } - MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); - delegate.needStartRecordAudio(0); + recordingAudioVideo = false; + messageTransitionIsRunning = false; + AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { + moveToSendStateRunnable = null; + updateRecordInterface(RECORD_STATE_SENDING); + }, 200); } - recordingAudioVideo = false; - messageTransitionIsRunning = false; - AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { - moveToSendStateRunnable = null; - updateRecordInterface(RECORD_STATE_SENDING); - }, 200); - } - getParent().requestDisallowInterceptTouchEvent(true); - return true; - } - if (parentFragment != null) { - TLRPC.Chat chat = parentFragment.getCurrentChat(); - TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo(); - if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) { - delegate.needShowMediaBanHint(); + getParent().requestDisallowInterceptTouchEvent(true); return true; } - } - if (hasRecordVideo) { - calledRecordRunnable = false; - recordAudioVideoRunnableStarted = true; - AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150); - } 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) { + if (parentFragment != null) { + TLRPC.Chat chat = parentFragment.getCurrentChat(); + TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo(); + if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) { + delegate.needShowMediaBanHint(); + return true; + } + } + if (hasRecordVideo) { + calledRecordRunnable = false; + recordAudioVideoRunnableStarted = true; + AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150); + } 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) { + if (hasRecordVideo && isInVideoMode()) { + CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); + delegate.needStartRecordVideo(2, true, 0); + } else { + delegate.needStartRecordAudio(0); + MediaController.getInstance().stopRecording(0, false, 0); + } + recordingAudioVideo = false; + updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); + } else { + recordCircle.sendButtonVisible = true; + startLockTransition(); + } + return false; + } + if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) { + if (recordAudioVideoRunnableStarted) { + AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); + } + return false; + } + + float x = motionEvent.getX() + audioVideoButtonContainer.getX(); + float dist = (x - startedDraggingX); + float alpha = 1.0f + dist / distCanMove; + if (alpha < 0.45) { if (hasRecordVideo && isInVideoMode()) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); delegate.needStartRecordVideo(2, true, 0); @@ -2081,119 +2110,264 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific recordingAudioVideo = false; updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); } else { - recordCircle.sendButtonVisible = true; - startLockTransition(); - } - return false; - } - if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) { - if (recordAudioVideoRunnableStarted) { - AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); - } - return false; - } - - float x = motionEvent.getX() + audioVideoButtonContainer.getX(); - float dist = (x - startedDraggingX); - float alpha = 1.0f + dist / distCanMove; - if (alpha < 0.45) { - if (hasRecordVideo && isInVideoMode()) { - CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2, true, 0); - } else { - delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0, false, 0); - } - recordingAudioVideo = false; - updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); - } else { - if (recordAudioVideoRunnableStarted) { - AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); - if (sendVoiceEnabled && sendRoundEnabled) { - delegate.onSwitchRecordMode(!isInVideoMode()); - setRecordVideoButtonVisible(!isInVideoMode(), true); - } else { - delegate.needShowMediaBanHint(); + if (recordAudioVideoRunnableStarted) { + AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); + if (sendVoiceEnabled && sendRoundEnabled) { + delegate.onSwitchRecordMode(!isInVideoMode()); + setRecordVideoButtonVisible(!isInVideoMode(), true); + } else { + delegate.needShowMediaBanHint(); + } + performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); + } else if (!hasRecordVideo || calledRecordRunnable) { + startedDraggingX = -1; + if (hasRecordVideo && isInVideoMode()) { + CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); + delegate.needStartRecordVideo(1, true, 0); + } else if (!sendVoiceEnabled) { + delegate.needShowMediaBanHint(); + } else { + if (recordingAudioVideo && isInScheduleMode()) { + AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); + } + delegate.needStartRecordAudio(0); + MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); + } + recordingAudioVideo = false; + messageTransitionIsRunning = false; + AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { + moveToSendStateRunnable = null; + updateRecordInterface(RECORD_STATE_SENDING); + }, 500); } - performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); - } else if (!hasRecordVideo || calledRecordRunnable) { - startedDraggingX = -1; + } + return true; + } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) { + float x = motionEvent.getX(); + float y = motionEvent.getY(); + if (recordCircle.isSendButtonVisible()) { + return false; + } + if (recordCircle.setLockTranslation(y) == 2) { + startLockTransition(); + return false; + } else { + recordCircle.setMovingCords(x, y); + } + + if (startedDraggingX == -1) { + startedDraggingX = x; + distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35); + if (distCanMove > AndroidUtilities.dp(140)) { + distCanMove = AndroidUtilities.dp(140); + } + } + + x = x + audioVideoButtonContainer.getX(); + float dist = (x - startedDraggingX); + float alpha = 1.0f + dist / distCanMove; + if (startedDraggingX != -1) { + if (alpha > 1) { + alpha = 1; + } else if (alpha < 0) { + alpha = 0; + } + if (slideText != null) { + slideText.setSlideX(alpha); + } + if (recordCircle != null) { + recordCircle.setSlideToCancelProgress(alpha); + } + } + + if (alpha == 0) { if (hasRecordVideo && isInVideoMode()) { CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(1, true, 0); - } else if (!sendVoiceEnabled) { - delegate.needShowMediaBanHint(); + delegate.needStartRecordVideo(2, true, 0); } else { - if (recordingAudioVideo && isInScheduleMode()) { - AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); - } delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); + MediaController.getInstance().stopRecording(0, false, 0); } recordingAudioVideo = false; - messageTransitionIsRunning = false; - AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { - moveToSendStateRunnable = null; - updateRecordInterface(RECORD_STATE_SENDING); - }, 500); + updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); } - } - return true; - } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) { - float x = motionEvent.getX(); - float y = motionEvent.getY(); - if (recordCircle.isSendButtonVisible()) { - return false; - } - if (recordCircle.setLockTranslation(y) == 2) { - startLockTransition(); - return false; - } else { - recordCircle.setMovingCords(x, y); - } - - if (startedDraggingX == -1) { - startedDraggingX = x; - distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35); - if (distCanMove > AndroidUtilities.dp(140)) { - distCanMove = AndroidUtilities.dp(140); - } - } - - x = x + audioVideoButtonContainer.getX(); - float dist = (x - startedDraggingX); - float alpha = 1.0f + dist / distCanMove; - if (startedDraggingX != -1) { - if (alpha > 1) { - alpha = 1; - } else if (alpha < 0) { - alpha = 0; - } - if (slideText != null) { - slideText.setSlideX(alpha); - } - if (recordCircle != null) { - recordCircle.setSlideToCancelProgress(alpha); - } - } - - if (alpha == 0) { - if (hasRecordVideo && isInVideoMode()) { - CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); - delegate.needStartRecordVideo(2, true, 0); - } else { - delegate.needStartRecordAudio(0); - MediaController.getInstance().stopRecording(0, false, 0); - } - recordingAudioVideo = false; - updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); + return true; } return true; } - view.onTouchEvent(motionEvent); - return true; - }); + }; + audioVideoButtonContainer.setSoundEffectsEnabled(false); + sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48)); + audioVideoButtonContainer.setFocusable(true); + audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); +// audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> { +// createRecordCircle(); +// if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { +// if (recordCircle.isSendButtonVisible()) { +// if (!hasRecordVideo || calledRecordRunnable) { +// startedDraggingX = -1; +// if (hasRecordVideo && isInVideoMode()) { +// delegate.needStartRecordVideo(1, true, 0); +// } else { +// if (recordingAudioVideo && isInScheduleMode()) { +// AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); +// } +// MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); +// delegate.needStartRecordAudio(0); +// } +// recordingAudioVideo = false; +// messageTransitionIsRunning = false; +// AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { +// moveToSendStateRunnable = null; +// updateRecordInterface(RECORD_STATE_SENDING); +// }, 200); +// } +// getParent().requestDisallowInterceptTouchEvent(true); +// return true; +// } +// if (parentFragment != null) { +// TLRPC.Chat chat = parentFragment.getCurrentChat(); +// TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo(); +// if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) { +// delegate.needShowMediaBanHint(); +// return true; +// } +// } +// if (hasRecordVideo) { +// calledRecordRunnable = false; +// recordAudioVideoRunnableStarted = true; +// AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150); +// } 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) { +// if (hasRecordVideo && isInVideoMode()) { +// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); +// delegate.needStartRecordVideo(2, true, 0); +// } else { +// delegate.needStartRecordAudio(0); +// MediaController.getInstance().stopRecording(0, false, 0); +// } +// recordingAudioVideo = false; +// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); +// } else { +// recordCircle.sendButtonVisible = true; +// startLockTransition(); +// } +// return false; +// } +// if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) { +// if (recordAudioVideoRunnableStarted) { +// AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); +// } +// return false; +// } +// +// float x = motionEvent.getX() + audioVideoButtonContainer.getX(); +// float dist = (x - startedDraggingX); +// float alpha = 1.0f + dist / distCanMove; +// if (alpha < 0.45) { +// if (hasRecordVideo && isInVideoMode()) { +// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); +// delegate.needStartRecordVideo(2, true, 0); +// } else { +// delegate.needStartRecordAudio(0); +// MediaController.getInstance().stopRecording(0, false, 0); +// } +// recordingAudioVideo = false; +// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); +// } else { +// if (recordAudioVideoRunnableStarted) { +// AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable); +// if (sendVoiceEnabled && sendRoundEnabled) { +// delegate.onSwitchRecordMode(!isInVideoMode()); +// setRecordVideoButtonVisible(!isInVideoMode(), true); +// } else { +// delegate.needShowMediaBanHint(); +// } +// performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP); +// sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); +// } else if (!hasRecordVideo || calledRecordRunnable) { +// startedDraggingX = -1; +// if (hasRecordVideo && isInVideoMode()) { +// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); +// delegate.needStartRecordVideo(1, true, 0); +// } else if (!sendVoiceEnabled) { +// delegate.needShowMediaBanHint(); +// } else { +// if (recordingAudioVideo && isInScheduleMode()) { +// AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider); +// } +// delegate.needStartRecordAudio(0); +// MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0); +// } +// recordingAudioVideo = false; +// messageTransitionIsRunning = false; +// AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> { +// moveToSendStateRunnable = null; +// updateRecordInterface(RECORD_STATE_SENDING); +// }, 500); +// } +// } +// return true; +// } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) { +// float x = motionEvent.getX(); +// float y = motionEvent.getY(); +// if (recordCircle.isSendButtonVisible()) { +// return false; +// } +// if (recordCircle.setLockTranslation(y) == 2) { +// startLockTransition(); +// return false; +// } else { +// recordCircle.setMovingCords(x, y); +// } +// +// if (startedDraggingX == -1) { +// startedDraggingX = x; +// distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35); +// if (distCanMove > AndroidUtilities.dp(140)) { +// distCanMove = AndroidUtilities.dp(140); +// } +// } +// +// x = x + audioVideoButtonContainer.getX(); +// float dist = (x - startedDraggingX); +// float alpha = 1.0f + dist / distCanMove; +// if (startedDraggingX != -1) { +// if (alpha > 1) { +// alpha = 1; +// } else if (alpha < 0) { +// alpha = 0; +// } +// if (slideText != null) { +// slideText.setSlideX(alpha); +// } +// if (recordCircle != null) { +// recordCircle.setSlideToCancelProgress(alpha); +// } +// } +// +// if (alpha == 0) { +// if (hasRecordVideo && isInVideoMode()) { +// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable); +// delegate.needStartRecordVideo(2, true, 0); +// } else { +// delegate.needStartRecordAudio(0); +// MediaController.getInstance().stopRecording(0, false, 0); +// } +// recordingAudioVideo = false; +// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE); +// } +// return true; +// } +// view.onTouchEvent(motionEvent); +// return true; +// }); audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context); audioVideoSendButton.setFocusable(true); @@ -7388,7 +7562,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific return; } if (focus) { - if (searchingType == 0 && !messageEditText.isFocused()) { + if (searchingType == 0 && !messageEditText.isFocused() && (botWebViewMenuContainer == null || botWebViewMenuContainer.getVisibility() == View.GONE)) { AndroidUtilities.runOnUIThread(focusRunnable = () -> { focusRunnable = null; boolean allowFocus; 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 fbfc15056..f2995cbc6 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachAlert.java @@ -37,7 +37,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.text.TextWatcher; import android.text.style.ImageSpan; -import android.util.Log; import android.util.LongSparseArray; import android.util.Property; import android.util.TypedValue; @@ -83,7 +82,6 @@ import org.telegram.messenger.MessagesController; import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.R; import org.telegram.messenger.SendMessagesHelper; -import org.telegram.messenger.SharedConfig; import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserObject; import org.telegram.messenger.fakepasscode.RemoveAfterReadingMessages; @@ -283,7 +281,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N @Override public void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible) { - if (currentAttachLayout != webViewLayout || !webViewLayout.isBotButtonAvailable()) { + if (currentAttachLayout != webViewLayout || !webViewLayout.isBotButtonAvailable() && startCommand == null) { return; } botMainButtonTextView.setClickable(isActive); 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 f3319c7cc..68f658a16 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAvatarContainer.java @@ -1080,7 +1080,6 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent sb.append("\n"); sb.append(subtitleTextView.getText()); info.setContentDescription(sb); - 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/ChatNotificationsPopupWrapper.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java index 68157cad0..b8411b7ec 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatNotificationsPopupWrapper.java @@ -218,6 +218,7 @@ public class ChatNotificationsPopupWrapper { } muteUnmuteButton.setColors(color, color); + muteUnmuteButton.setSelectorColor(Theme.multAlpha(color, .1f)); if (topicExceptions == null || topicExceptions.isEmpty()) { gap.setVisibility(View.GONE); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/FloatingDebug/FloatingDebugView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/FloatingDebug/FloatingDebugView.java index 1bf4067bc..33d8a6cd7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/FloatingDebug/FloatingDebugView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/FloatingDebug/FloatingDebugView.java @@ -57,6 +57,7 @@ import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.SeekBarView; import org.telegram.ui.LaunchActivity; +import org.telegram.ui.ProfileActivity; import java.util.ArrayList; import java.util.List; @@ -520,6 +521,7 @@ public class FloatingDebugView extends FrameLayout implements NotificationCenter NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, finalThemeInfo, true, null, -1); }, 200); })); + items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugSendLogs), () -> ProfileActivity.sendLogs((Activity) getContext(), false))); return items; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumBubbleDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumBubbleDrawable.java index b2ac09801..49adb4254 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumBubbleDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Forum/ForumBubbleDrawable.java @@ -35,6 +35,7 @@ public class ForumBubbleDrawable extends Drawable { private final Paint strokePaint; private final Paint topPaint; + private static SvgHelper.SvgDrawable mainDrawable; private int currentColors[]; @@ -60,7 +61,10 @@ public class ForumBubbleDrawable extends Drawable { public ForumBubbleDrawable(int color) { - svgDrawable = SvgHelper.getDrawable(R.raw.topic_bubble, Color.WHITE); + if (mainDrawable == null) { + mainDrawable = SvgHelper.getDrawable(R.raw.topic_bubble, Color.WHITE); + } + svgDrawable = mainDrawable.clone(); svgDrawable.copyCommandFromPosition(0); topPaint = new Paint(Paint.ANTI_ALIAS_FLAG); strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 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 46a9e4b8e..d1c245a2e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/InstantCameraView.java @@ -51,7 +51,6 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.util.Log; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.MotionEvent; @@ -118,7 +117,6 @@ 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.GL; @TargetApi(18) public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { @@ -1006,8 +1004,14 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter private Size chooseOptimalSize(ArrayList previewSizes) { ArrayList sortedSizes = new ArrayList<>(); + boolean allowBigSizeCamera = allowBigSizeCamera(); + int maxVideoSize = allowBigSizeCamera ? 1440 : 1200; + if (Build.MANUFACTURER.equalsIgnoreCase("Samsung")) { + //1440 lead to gl crashes on samsung s9 + maxVideoSize = 1200; + } for (int i = 0; i < previewSizes.size(); i++) { - if (Math.max(previewSizes.get(i).mHeight, previewSizes.get(i).mWidth) <= 1440 && Math.min(previewSizes.get(i).mHeight, previewSizes.get(i).mWidth) >= 320) { + if (Math.max(previewSizes.get(i).mHeight, previewSizes.get(i).mWidth) <= maxVideoSize && Math.min(previewSizes.get(i).mHeight, previewSizes.get(i).mWidth) >= 320) { sortedSizes.add(previewSizes.get(i)); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineEditText.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineEditText.java index f82238dba..4676050ad 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineEditText.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/OutlineEditText.java @@ -7,6 +7,7 @@ import android.text.InputType; import android.util.TypedValue; import android.view.Gravity; +import org.telegram.messenger.AndroidUtilities; import org.telegram.ui.ActionBar.Theme; public class OutlineEditText extends OutlineTextContainerView { @@ -32,6 +33,9 @@ public class OutlineEditText extends OutlineTextContainerView { editText.setTypeface(Typeface.DEFAULT); editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated)); editText.setCursorWidth(1.5f); + editText.setPadding( + AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), 0 + ); attachEditText(editText); addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java index 1d101ea10..67d907fee 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Premium/PremiumPreviewBottomSheet.java @@ -357,6 +357,9 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i if (isOutboundGift) { titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); + } else if (user != null && user.id == 777000) { + titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); + subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle))); } else { titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null)); subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle))); 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 207a43bed..3ce9b5925 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java @@ -774,6 +774,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio imagesUploadProgress.remove(index); if (index == 0 && !imagesLocations.isEmpty()) { prevImageLocation = imagesLocations.get(0); + prevThumbLocation = null; + prevVectorAvatarThumbDrawable = null; } adapter.notifyDataSetChanged(); return photos.isEmpty(); 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 316ffb6af..37bd5c228 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RLottieDrawable.java @@ -822,6 +822,9 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma } protected void invalidateInternal() { + if (isRecycled) { + return; + } for (int i = 0, N = parentViews.size(); i < N; i++) { parentViews.get(i).invalidate(); } 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 0a134b891..ffea83f71 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java @@ -1847,6 +1847,10 @@ public class RecyclerListView extends RecyclerView { Theme.setSelectorDrawableColor(selectorDrawable, color, true); } + public Integer getSelectorColor(int position) { + return null; + } + public void setOnItemClickListener(OnItemClickListener listener) { onItemClickListener = listener; } @@ -2265,6 +2269,10 @@ public class RecyclerListView extends RecyclerView { selectorDrawable.setVisible(false, false); selectorDrawable.setState(StateSet.NOTHING); } + Integer color = getSelectorColor(position); + if (color != null) { + setListSelectorColor(color); + } selectorDrawable.setBounds(selectorRect); if (positionChanged) { if (getVisibility() == VISIBLE) { 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 183779a52..8235cd5b7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/StickersAlert.java @@ -1662,7 +1662,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not 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))); + pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), Theme.multAlpha(getThemedColor(Theme.key_dialogTextRed), .1f))); pickerBottomFrameLayout.setBackgroundColor(Color.TRANSPARENT); params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0; emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(48); 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 e9a90736e..9c24e29ef 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ThemeSmallPreviewView.java @@ -238,6 +238,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaperDocument.thumbs, PATTERN_BITMAP_MAXWIDTH); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaperDocument); ImageReceiver imageReceiver = new ImageReceiver(); + imageReceiver.setAllowLoadingOnAttachedOnly(false); imageReceiver.setImage(imageLocation, PATTERN_BITMAP_MAXWIDTH + "_" + PATTERN_BITMAP_MAXHEIGHT, null, null, null, 1); imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java index 13974175a..c394ac75a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ContentPreviewViewer.java @@ -490,6 +490,11 @@ public class ContentPreviewViewer { icons.add(R.drawable.msg_send); actions.add(0); } + if (delegate.needSend(currentContentType) && !delegate.isInScheduleMode()) { + items.add(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound)); + icons.add(R.drawable.input_notify_off); + actions.add(4); + } if (delegate.canSchedule()) { items.add(LocaleController.getString("Schedule", R.string.Schedule)); icons.add(R.drawable.msg_autodelete); @@ -528,6 +533,8 @@ public class ContentPreviewViewer { int which = (int) v.getTag(); if (actions.get(which) == 0) { delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, true, 0); + } else if (actions.get(which) == 4) { + delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, false, 0); } else if (actions.get(which) == 1) { MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument); delegate.gifAddedOrDeleted(); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java index 73b9e2800..db55bf118 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DataSettingsActivity.java @@ -22,6 +22,7 @@ import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -45,13 +46,13 @@ import org.telegram.ui.ActionBar.ThemeDescription; import org.telegram.ui.Cells.HeaderCell; import org.telegram.ui.Cells.LanguageCell; import org.telegram.ui.Cells.NotificationsCheckCell; -import org.telegram.ui.Cells.RadioColorCell; import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Components.AlertsCreator; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.voip.VoIPHelper; @@ -73,7 +74,7 @@ public class DataSettingsActivity extends BaseFragment { private int roamingRow; private int wifiRow; private int storageNumRow; - private int resetDownloadRow; + private int resetDownloadRow = -1; private int mediaDownloadSection2Row; private int usageSectionRow; private int storageUsageRow; @@ -117,6 +118,12 @@ public class DataSettingsActivity extends BaseFragment { super.onFragmentCreate(); DownloadController.getInstance(currentAccount).loadAutoDownloadConfig(true); + updateRows(true); + + return true; + } + + private void updateRows(boolean fullNotify) { rowCount = 0; usageSectionRow = rowCount++; @@ -134,7 +141,25 @@ public class DataSettingsActivity extends BaseFragment { mobileRow = rowCount++; wifiRow = rowCount++; roamingRow = rowCount++; - resetDownloadRow = rowCount++; + DownloadController dc = getDownloadController(); + boolean isDefault = !( + !dc.lowPreset.equals(dc.getCurrentRoamingPreset()) || dc.lowPreset.isEnabled() != dc.roamingPreset.enabled || + !dc.mediumPreset.equals(dc.getCurrentMobilePreset()) || dc.mediumPreset.isEnabled() != dc.mobilePreset.enabled || + !dc.highPreset.equals(dc.getCurrentWiFiPreset()) || dc.highPreset.isEnabled() != dc.wifiPreset.enabled + ); + int wasResetDownloadRow = resetDownloadRow; + resetDownloadRow = isDefault ? -1 : rowCount++; + if (listAdapter != null && !fullNotify) { + if (wasResetDownloadRow < 0 && resetDownloadRow >= 0) { + listAdapter.notifyItemChanged(roamingRow); + listAdapter.notifyItemInserted(resetDownloadRow); + } else if (wasResetDownloadRow >= 0 && resetDownloadRow < 0) { + listAdapter.notifyItemChanged(roamingRow); + listAdapter.notifyItemRemoved(wasResetDownloadRow); + } else { + fullNotify = true; + } + } mediaDownloadSection2Row = rowCount++; saveToGallerySectionRow = rowCount++; @@ -169,7 +194,9 @@ public class DataSettingsActivity extends BaseFragment { clearDraftsRow = rowCount++; clearDraftsSectionRow = rowCount++; - return true; + if (listAdapter != null && fullNotify) { + listAdapter.notifyDataSetChanged(); + } } private void loadCacheSize() { @@ -250,7 +277,15 @@ public class DataSettingsActivity extends BaseFragment { fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); FrameLayout frameLayout = (FrameLayout) fragmentView; - listView = new RecyclerListView(context); + listView = new RecyclerListView(context) { + @Override + public Integer getSelectorColor(int position) { + if (position == resetDownloadRow) { + return Theme.multAlpha(getThemedColor(Theme.key_windowBackgroundWhiteRedText2), .1f); + } + return getThemedColor(Theme.key_listSelector); + } + }; listView.setVerticalScrollBarEnabled(false); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT)); @@ -322,9 +357,7 @@ public class DataSettingsActivity extends BaseFragment { } DownloadController.getInstance(currentAccount).checkAutodownloadSettings(); DownloadController.getInstance(currentAccount).savePresetToServer(num); - if (wasEnabled != listAdapter.isRowEnabled(resetDownloadRow)) { - listAdapter.notifyItemChanged(resetDownloadRow); - } + updateRows(false); } else { int type; if (position == mobileRow) { @@ -376,6 +409,7 @@ public class DataSettingsActivity extends BaseFragment { DownloadController.getInstance(currentAccount).savePresetToServer(a); } listAdapter.notifyItemRangeChanged(mobileRow, 4); + updateRows(false); }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); AlertDialog dialog = builder.create(); @@ -465,24 +499,46 @@ public class DataSettingsActivity extends BaseFragment { LanguageCell cell = new LanguageCell(context); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); cell.setTag(a); + String description; + boolean isInternal = storageDir.contains("/storage/emulated/"); + if (fullString && !isInternal) { + description = LocaleController.formatString("StoragePathFreeValueExternal", R.string.StoragePathFreeValueExternal, AndroidUtilities.formatFileSize(file.getFreeSpace()), storageDir); + } else { + if (isInternal) { + description = LocaleController.formatString("StoragePathFreeInternal", R.string.StoragePathFreeInternal, AndroidUtilities.formatFileSize(file.getFreeSpace())); + } else { + description = LocaleController.formatString("StoragePathFreeExternal", R.string.StoragePathFreeExternal, AndroidUtilities.formatFileSize(file.getFreeSpace())); + } + } + cell.setValue( - storageDir.contains("/storage/emulated/") ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard), - fullString ? - LocaleController.formatString("StoragePathFreeValue", R.string.StoragePathFreeValue, AndroidUtilities.formatFileSize(file.getFreeSpace()), storageDir) : - LocaleController.formatString("StoragePathFree", R.string.StoragePathFree, AndroidUtilities.formatFileSize(file.getFreeSpace())) + isInternal ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard), + description ); cell.setLanguageSelected(storageDir.startsWith(dir), false); cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 2)); linearLayout.addView(cell); cell.setOnClickListener(v -> { - SharedConfig.storageCacheDir = storageDir; - SharedConfig.saveConfig(); - builder.getDismissRunnable().run(); - rebind(storageNumRow); - ImageLoader.getInstance().checkMediaPaths(() -> { - CacheControlActivity.resetCalculatedTotalSIze(); - loadCacheSize(); - }); + if (!TextUtils.equals(SharedConfig.storageCacheDir, storageDir)) { + if (!isInternal) { + AlertDialog.Builder confirAlert = new AlertDialog.Builder(getContext()); + confirAlert.setTitle(LocaleController.getString("DecreaseSpeed", R.string.DecreaseSpeed)); + confirAlert.setMessage(LocaleController.getString("SdCardAlert", R.string.SdCardAlert)); + confirAlert.setPositiveButton(LocaleController.getString("Proceed", R.string.Proceed), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + setStorageDirectory(storageDir); + builder.getDismissRunnable().run(); + } + }); + confirAlert.setNegativeButton(LocaleController.getString("Back", R.string.Back), null); + confirAlert.show(); + } else { + setStorageDirectory(storageDir); + builder.getDismissRunnable().run(); + } + + } }); } builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); @@ -534,10 +590,29 @@ public class DataSettingsActivity extends BaseFragment { } } }); + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + listView.setItemAnimator(itemAnimator); return fragmentView; } + private void setStorageDirectory(String storageDir) { + SharedConfig.storageCacheDir = storageDir; + SharedConfig.saveConfig(); + if (storageDir != null) { + SharedConfig.readOnlyStorageDirAlertShowed = false; + } + rebind(storageNumRow); + ImageLoader.getInstance().checkMediaPaths(() -> { + CacheControlActivity.resetCalculatedTotalSIze(); + loadCacheSize(); + }); + } + @Override protected void onDialogDismiss(Dialog dialog) { DownloadController.getInstance(currentAccount).checkAutodownloadSettings(); @@ -548,6 +623,7 @@ public class DataSettingsActivity extends BaseFragment { super.onResume(); loadCacheSize(); rebindAll(); + updateRows(false); } private class ListAdapter extends RecyclerListView.SelectionAdapter { @@ -702,7 +778,7 @@ public class DataSettingsActivity extends BaseFragment { String text; CharSequence description = null; DownloadController.Preset preset = null; - boolean enabled; + boolean enabled, divider = true; if (position == saveToGalleryPeerRow) { text = LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate); description = SaveToGallerySettingsHelper.user.createDescription(currentAccount); @@ -715,6 +791,7 @@ public class DataSettingsActivity extends BaseFragment { text = LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels); description = SaveToGallerySettingsHelper.channels.createDescription(currentAccount); enabled = SaveToGallerySettingsHelper.channels.enabled(); + divider = false; } else if (position == mobileRow) { text = LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData); enabled = DownloadController.getInstance(currentAccount).mobilePreset.enabled; @@ -727,6 +804,7 @@ public class DataSettingsActivity extends BaseFragment { text = LocaleController.getString("WhenRoaming", R.string.WhenRoaming); enabled = DownloadController.getInstance(currentAccount).roamingPreset.enabled; preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset(); + divider = resetDownloadRow >= 0; } boolean checked; if (preset != null) { @@ -776,7 +854,7 @@ public class DataSettingsActivity extends BaseFragment { checked = enabled; } checkCell.setAnimationsEnabled(true); - checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, true); + checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, divider); break; } } @@ -805,15 +883,9 @@ public class DataSettingsActivity extends BaseFragment { } public boolean isRowEnabled(int position) { - if (position == resetDownloadRow) { - DownloadController controller = DownloadController.getInstance(currentAccount); - return !controller.lowPreset.equals(controller.getCurrentRoamingPreset()) || controller.lowPreset.isEnabled() != controller.roamingPreset.enabled || - !controller.mediumPreset.equals(controller.getCurrentMobilePreset()) || controller.mediumPreset.isEnabled() != controller.mobilePreset.enabled || - !controller.highPreset.equals(controller.getCurrentWiFiPreset()) || controller.highPreset.isEnabled() != controller.wifiPreset.enabled; - } 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 == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow; + position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow || position == resetDownloadRow; } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java index a4fa1f39f..9aca8887f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -3280,6 +3280,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. viewPage.listView.setInstantClick(true); viewPage.layoutManager = new LinearLayoutManager(context) { + @Override + protected int firstPosition() { + if (viewPage.dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() && viewPage.archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN) { + return 1; + } + return 0; + } + private boolean fixOffset; @Override @@ -6793,6 +6801,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. chatActivity.setPreloadedSticker(sticker, true); } } + if (AndroidUtilities.isTablet()) { + if (rightSlidingDialogContainer.currentFragment != null) { + rightSlidingDialogContainer.finishPreview(); + } + } presentFragment(chatActivity); } } @@ -7259,6 +7272,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true); deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon)); deleteItem.setTextColor(getThemedColor(Theme.key_dialogTextRed)); + deleteItem.setSelectorColor(Theme.multAlpha(getThemedColor(Theme.key_dialogTextRed), .12f)); deleteItem.setTextAndIcon(LocaleController.getString("Delete", R.string.Delete), R.drawable.msg_delete); deleteItem.setMinimumWidth(160); deleteItem.setOnClickListener(e -> { @@ -8835,7 +8849,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) { updateVisibleRows(0); } else if (id == NotificationCenter.emojiLoaded) { - updateVisibleRows(0); + for (int i = 0; i < viewPages.length; ++i) { + final RecyclerListView listView = viewPages[i].listView; + if (listView != null) { + for (int a = 0; a < listView.getChildCount(); ++a) { + View child = listView.getChildAt(a); + if (child != null) { + child.invalidate(); + } + } + } + } if (filterTabsView != null) { filterTabsView.getTabsContainer().invalidateViews(); } @@ -8961,7 +8985,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. long dialogId = (Long) args[0]; TLRPC.User user = (TLRPC.User) args[1]; TLRPC.Chat chat = (TLRPC.Chat) args[2]; - boolean revoke = (Boolean) args[3]; + boolean revoke; + boolean botBlock; + if (user != null && user.bot) { + revoke = false; + botBlock = (Boolean) args[3]; + } else { + revoke = (Boolean) args[3]; + botBlock = false; + } + Runnable deleteRunnable = () -> { if (chat != null) { if (ChatObject.isNotInChat(chat)) { @@ -8971,7 +9004,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter. } } else { getMessagesController().deleteDialog(dialogId, 0, revoke); - if (user != null && user.bot) { + if (user != null && user.bot && botBlock) { getMessagesController().blockPeer(user.id); } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java b/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java index 79d334f82..e7ac9b0d8 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DownloadProgressIcon.java @@ -161,8 +161,13 @@ public class DownloadProgressIcon extends View implements NotificationCenter.Not } } if (currentListeners.size() == 0 && (getVisibility() != View.VISIBLE || getAlpha() != 1f)) { - progress = 0; - currentProgress = 0; + if (DownloadController.getInstance(currentAccount).hasUnviewedDownloads()) { + progress = 1f; + currentProgress = 1f; + } else { + progress = 0; + currentProgress = 0; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java index f0acd7b7c..b8b0e8f24 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java @@ -51,6 +51,7 @@ import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.CombinedDrawable; +import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; @@ -531,6 +532,12 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe super.dispatchDraw(canvas); } }; + DefaultItemAnimator itemAnimator = new DefaultItemAnimator(); + itemAnimator.setDurations(350); + itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT); + itemAnimator.setDelayAnimations(false); + itemAnimator.setSupportsChangeAnimations(false); + listView.setItemAnimator(itemAnimator); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setVerticalScrollBarEnabled(false); @@ -739,6 +746,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe while (getMessagesController().dialogFiltersById.get(filter.id) != null) { filter.id++; } + filter.order = getMessagesController().dialogFilters.size(); filter.pendingUnreadCount = filter.unreadCount = -1; for (int b = 0; b < 2; b++) { ArrayList fromArray = b == 0 ? suggested.filter.include_peers : suggested.filter.exclude_peers; @@ -781,7 +789,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe filter.flags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_MUTED; } ignoreUpdates = true; - FilterCreateActivity.saveFilterToServer(filter, filter.flags, filter.name, filter.alwaysShow, filter.neverShow, filter.pinnedDialogs, true, true, true, true, false, FiltersSetupActivity.this, () -> { + FilterCreateActivity.saveFilterToServer(filter, filter.flags, filter.name, filter.alwaysShow, filter.neverShow, filter.pinnedDialogs, true, false, true, true, false, FiltersSetupActivity.this, () -> { getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated); ignoreUpdates = false; ArrayList suggestedFilters = getMessagesController().suggestedFilters; @@ -852,9 +860,9 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe } case 3: { if (position == createSectionRow) { - 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)); } else { - holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } break; } @@ -874,7 +882,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe } case 5: { SuggestedFilterCell filterCell = (SuggestedFilterCell) holder.itemView; - filterCell.setFilter(getMessagesController().suggestedFilters.get(position - recommendedStartRow), recommendedStartRow != recommendedEndRow - 1); + filterCell.setFilter(getMessagesController().suggestedFilters.get(position - recommendedStartRow), position < recommendedEndRow - 1); break; } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java index 16fb9dbf0..c4c77dfce 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java @@ -409,21 +409,14 @@ public class LanguageSelectActivity extends BaseFragment implements Notification Collections.sort(unofficialLanguages, comparator); } - private static boolean patching = false; - @Override public void onBecomeFullyVisible() { super.onBecomeFullyVisible(); - boolean shouldPatch = getMessagesController().checkResetLangpack > 0 && !MessagesController.getGlobalMainSettings().getBoolean("langpack_patched", false) && !patching; - if (shouldPatch) { - patching = true; - LocaleController.getInstance().reloadCurrentRemoteLocale(currentAccount, null, true, () -> { - AndroidUtilities.runOnUIThread(() -> { - MessagesController.getGlobalMainSettings().edit().putBoolean("langpack_patched", true).apply(); - updateLanguage(); - }); - }); - } + LocaleController.getInstance().checkForcePatchLangpack(currentAccount, () -> { + if (!isPaused) { + updateLanguage(); + } + }); } @Override diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java index 9a44533f9..ce485b9db 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -3594,27 +3594,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } })); } else if (username != null) { - TLObject req; - if (AndroidUtilities.isNumeric(username)) { - TLRPC.TL_contacts_resolvePhone resolvePhone = new TLRPC.TL_contacts_resolvePhone(); - resolvePhone.phone = username; - req = resolvePhone; - } else { - TLRPC.TL_contacts_resolveUsername resolveUsername = new TLRPC.TL_contacts_resolveUsername(); - resolveUsername.username = username; - req = resolveUsername; - } - requestId[0] = ConnectionsManager.getInstance(intentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> { + MessagesController.getInstance(intentAccount).getUserNameResolver().resolve(username, (peerId) -> { if (!LaunchActivity.this.isFinishing()) { boolean hideProgressDialog = true; - TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response; - if (error == null && actionBarLayout != null && (game == null && voicechat == null || game != null && !res.users.isEmpty() || voicechat != null && !res.chats.isEmpty() || livestream != null && !res.chats.isEmpty())) { - MessagesController.getInstance(intentAccount).putUsers(res.users, false); - MessagesController.getInstance(intentAccount).putChats(res.chats, false); - MessagesStorage.getInstance(intentAccount).putUsersAndChats(res.users, res.chats, false, true); - + if (peerId != null && actionBarLayout != null && (game == null && voicechat == null || game != null && peerId > 0 || voicechat != null && peerId > 0 || livestream != null && peerId < 0)) { if (!TextUtils.isEmpty(botAppMaybe)) { - TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(res.peer.user_id); + TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); if (user != null && user.bot) { TLRPC.TL_messages_getBotApp getBotApp = new TLRPC.TL_messages_getBotApp(); TLRPC.TL_inputBotAppShortName app = new TLRPC.TL_inputBotAppShortName(); @@ -3673,11 +3658,11 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } if (setAsAttachBot != null && attachMenuBotToOpen == null) { - TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(res.peer.user_id); + TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); if (user != null && user.bot) { 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); + getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId); ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> { if (response1 instanceof TLRPC.TL_attachMenuBotsBot) { TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1; @@ -3757,7 +3742,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati .setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BotRequestAttachPermission", R.string.BotRequestAttachPermission, UserObject.getUserName(user, currentAccount)))) .setPositiveButton(LocaleController.getString(R.string.BotAddToMenu), (dialog, which) -> { TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu(); - botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(res.peer.user_id); + botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId); botRequest.enabled = true; botRequest.write_allowed = allowWrite.get(); @@ -3803,8 +3788,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } else { BulletinFactory.of(mainFragmentsStack.get(mainFragmentsStack.size() - 1)).createErrorBulletin(LocaleController.getString(R.string.BotSetAttachLinkNotBot)).show(); } - } else if (messageId != null && (commentId != null || threadId != null) && !res.chats.isEmpty()) { - requestId[0] = runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, res.chats.get(0)); + } else if (messageId != null && (commentId != null || threadId != null) && peerId < 0) { + TLRPC.Chat chat = MessagesController.getInstance(intentAccount).getChat(-peerId); + requestId[0] = runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, chat); if (requestId[0] != 0) { hideProgressDialog = false; } @@ -3816,12 +3802,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati args.putString("selectAlertString", LocaleController.getString("SendGameToText", R.string.SendGameToText)); args.putString("selectAlertStringGroup", LocaleController.getString("SendGameToGroupText", R.string.SendGameToGroupText)); DialogsActivity fragment = new DialogsActivity(args); + TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); fragment.setDelegate((fragment1, dids, message1, param, topicsFragment) -> { long did = dids.get(0).dialogId; TLRPC.TL_inputMediaGame inputMediaGame = new TLRPC.TL_inputMediaGame(); inputMediaGame.id = new TLRPC.TL_inputGameShortName(); inputMediaGame.id.short_name = game; - inputMediaGame.id.bot_id = MessagesController.getInstance(intentAccount).getInputUser(res.users.get(0)); + inputMediaGame.id.bot_id = MessagesController.getInstance(intentAccount).getInputUser(user); SendMessagesHelper.getInstance(intentAccount).sendGame(MessagesController.getInstance(intentAccount).getInputPeer(did), inputMediaGame, 0, 0); Bundle args1 = new Bundle(); @@ -3864,7 +3851,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati drawerLayoutContainer.setAllowOpenDrawer(true, false); } } else if (botChat != null || botChannel != null) { - final TLRPC.User user = !res.users.isEmpty() ? res.users.get(0) : null; + final TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); if (user == null || user.bot && user.bot_nochats) { try { if (!mainFragmentsStack.isEmpty()) { @@ -4016,14 +4003,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati long dialog_id; boolean isBot = false; Bundle args = new Bundle(); - if (!res.chats.isEmpty()) { - args.putLong("chat_id", res.chats.get(0).id); - dialog_id = -res.chats.get(0).id; + TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId); + if (peerId < 0) { + args.putLong("chat_id", -peerId); + dialog_id = peerId; } else { - args.putLong("user_id", res.users.get(0).id); - dialog_id = res.users.get(0).id; + args.putLong("user_id", peerId); + dialog_id = peerId; } - if (botUser != null && res.users.size() > 0 && res.users.get(0).bot) { + if (botUser != null && user != null && user.bot) { args.putString("botUser", botUser); isBot = true; } @@ -4160,17 +4148,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } } else { try { - if (!mainFragmentsStack.isEmpty()) { - BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1); - if (fragment instanceof ChatActivity) { - ((ChatActivity) fragment).shakeContent(); + BaseFragment lastFragment = LaunchActivity.getLastFragment(); + if (lastFragment != null) { + if (lastFragment instanceof ChatActivity) { + ((ChatActivity) lastFragment).shakeContent(); } - 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(); + if (AndroidUtilities.isNumeric(username)) { + BulletinFactory.of(lastFragment).createErrorBulletin(LocaleController.getString("NoPhoneFound", R.string.NoPhoneFound)).show(); } else { - BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound)).show(); + BulletinFactory.of(lastFragment).createErrorBulletin(LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound)).show(); } } } catch (Exception e) { @@ -4186,7 +4172,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati } } } - }, ConnectionsManager.RequestFlagFailOnServerErrors)); + }); } else if (group != null) { if (state == 0) { final TLRPC.TL_messages_checkChatInvite req = new TLRPC.TL_messages_checkChatInvite(); @@ -5065,12 +5051,20 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati visibleDialog.setOnDismissListener(dialog -> { if (visibleDialog != null) { if (visibleDialog == localeDialog) { + BaseFragment fragment = actionBarLayout == null ? null : actionBarLayout.getLastFragment(); try { String shorname = LocaleController.getInstance().getCurrentLocaleInfo().shortName; - BulletinFactory.of(Bulletin.BulletinWindow.make(LaunchActivity.this), null).createSimpleBulletin( - R.raw.msg_translate, - getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater) - ).setDuration(Bulletin.DURATION_PROLONG).show(); + if (fragment != null) { + BulletinFactory.of(fragment).createSimpleBulletin( + R.raw.msg_translate, + getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater) + ).setDuration(Bulletin.DURATION_PROLONG).show(); + } else { + BulletinFactory.of(Bulletin.BulletinWindow.make(LaunchActivity.this), null).createSimpleBulletin( + R.raw.msg_translate, + getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater) + ).setDuration(Bulletin.DURATION_PROLONG).show(); + } } catch (Exception e) { FileLog.e(e); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LiteModeSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LiteModeSettingsActivity.java index c7812f962..0285ce26e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LiteModeSettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LiteModeSettingsActivity.java @@ -78,6 +78,8 @@ public class LiteModeSettingsActivity extends BaseFragment { Bulletin restrictBulletin; + private int FLAGS_CHAT; + @Override public View createView(Context context) { actionBar.setBackButtonImage(R.drawable.ic_ab_back); @@ -142,6 +144,7 @@ public class LiteModeSettingsActivity extends BaseFragment { }); fragmentView = contentView; + FLAGS_CHAT = AndroidUtilities.isTablet() ? (LiteMode.FLAGS_CHAT & ~LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN) : LiteMode.FLAGS_CHAT; updateItems(); @@ -168,7 +171,7 @@ public class LiteModeSettingsActivity extends BaseFragment { return 0; } else if (flags == LiteMode.FLAGS_ANIMATED_EMOJI) { return 1; - } else if (flags == LiteMode.FLAGS_CHAT) { + } else if (flags == FLAGS_CHAT) { return 2; } return -1; @@ -206,10 +209,12 @@ public class LiteModeSettingsActivity extends BaseFragment { items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsAutoplayReactions"), LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS)); items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsAutoplayChat"), LiteMode.FLAG_ANIMATED_EMOJI_CHAT)); } - items.add(Item.asSwitch(R.drawable.msg2_ask_question, LocaleController.getString("LiteOptionsChat"), LiteMode.FLAGS_CHAT)); + items.add(Item.asSwitch(R.drawable.msg2_ask_question, LocaleController.getString("LiteOptionsChat"), FLAGS_CHAT)); if (expanded[2]) { items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsBackground"), LiteMode.FLAG_CHAT_BACKGROUND)); - items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsTopics"), LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN)); + if (!AndroidUtilities.isTablet()) { + items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsTopics"), LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN)); + } items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsSpoiler"), LiteMode.FLAG_CHAT_SPOILER)); if (SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_AVERAGE) { items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsBlur"), LiteMode.FLAG_CHAT_BLUR)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 0c8c498b4..c53b7645a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -3863,6 +3863,8 @@ public class LoginActivity extends BaseFragment { if (currentType == AUTH_TYPE_MESSAGE) { if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) { problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone)); + } else if (nextType == 0) { + problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode)); } else { problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms)); } @@ -4112,9 +4114,11 @@ public class LoginActivity extends BaseFragment { } else if (currentType == AUTH_TYPE_FLASH_CALL) { AndroidUtilities.setWaitingForCall(true); NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReceiveCall); - AndroidUtilities.runOnUIThread(() -> { - CallReceiver.checkLastReceivedCall(); - }); + if (restore) { + AndroidUtilities.runOnUIThread(() -> { + CallReceiver.checkLastReceivedCall(); + }); + } } currentParams = params; @@ -4443,7 +4447,6 @@ public class LoginActivity extends BaseFragment { AndroidUtilities.setWaitingForSms(false); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode); } else if (currentType == AUTH_TYPE_FLASH_CALL) { - AndroidUtilities.setWaitingForCall(false); NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveCall); } waitingForEvent = false; @@ -4674,6 +4677,9 @@ public class LoginActivity extends BaseFragment { } else if (currentType == AUTH_TYPE_FLASH_CALL) { AndroidUtilities.setWaitingForCall(true); NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall); + AndroidUtilities.runOnUIThread(() -> { + CallReceiver.checkLastReceivedCall(); + }); } waitingForEvent = true; if (currentType != AUTH_TYPE_FLASH_CALL) { @@ -4707,6 +4713,7 @@ public class LoginActivity extends BaseFragment { if (ok) { if (currentType == AUTH_TYPE_FLASH_CALL) { AndroidUtilities.endIncomingCall(); + AndroidUtilities.setWaitingForCall(false); } } }), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin); @@ -4718,6 +4725,10 @@ public class LoginActivity extends BaseFragment { } private void animateSuccess(Runnable callback) { + if (currentType == AUTH_TYPE_FLASH_CALL) { + callback.run(); + return; + } for (int i = 0; i < codeFieldContainer.codeField.length; i++) { int finalI = i; codeFieldContainer.postDelayed(()-> codeFieldContainer.codeField[finalI].animateSuccessProgress(1f), i * 75L); @@ -6290,6 +6301,10 @@ public class LoginActivity extends BaseFragment { int minutes = ((timeRemaining % 86400) % 3600) / 60; int seconds = ((timeRemaining % 86400) % 3600) % 60; + if (hours >= 16) { + days++; + } + String time; if (days != 0) { time = LocaleController.formatString(R.string.LoginEmailResetInSinglePattern, LocaleController.formatPluralString("Days", days)); diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java index e7b884003..edb0e7404 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PremiumPreviewFragment.java @@ -664,10 +664,13 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification if (tier == null) { forcePremium = true; - for (TLRPC.TL_premiumSubscriptionOption option : fragment.getAccountInstance().getMediaDataController().getPremiumPromo().period_options) { - if (option.months == 1) { - tier = new SubscriptionTier(option); - break; + TLRPC.TL_help_premiumPromo promo = fragment.getAccountInstance().getMediaDataController().getPremiumPromo(); + if (promo != null) { + for (TLRPC.TL_premiumSubscriptionOption option : promo.period_options) { + if (option.months == 1) { + tier = new SubscriptionTier(option); + break; + } } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 2c37e5b00..68062c6e7 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -1026,21 +1026,18 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio break; case 1: TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; + boolean last = position == getItemCount() - 1; + privacyCell.setBackground(Theme.getThemedDrawable(mContext, last ? R.drawable.greydivider_bottom : R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); if (position == deleteAccountDetailRow) { privacyCell.setText(LocaleController.getString("DeleteAccountHelp", R.string.DeleteAccountHelp)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == groupsDetailRow) { privacyCell.setText(LocaleController.getString("GroupsAndChannelsHelp", R.string.GroupsAndChannelsHelp)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == sessionsDetailRow) { privacyCell.setText(LocaleController.getString("SessionsSettingsInfo", R.string.SessionsSettingsInfo)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == secretDetailRow) { privacyCell.setText(LocaleController.getString("SecretWebPageInfo", R.string.SecretWebPageInfo)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == botsDetailRow) { privacyCell.setText(LocaleController.getString("PrivacyBotsInfo", R.string.PrivacyBotsInfo)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == contactsDetailRow) { /*if (newSync) { privacyCell.setText(LocaleController.getString("SyncContactsInfoOn", R.string.SyncContactsInfoOn)); @@ -1048,10 +1045,8 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio privacyCell.setText(LocaleController.getString("SyncContactsInfoOff", R.string.SyncContactsInfoOff)); }*/ privacyCell.setText(LocaleController.getString("SuggestContactsInfo", R.string.SuggestContactsInfo)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == newChatsSectionRow) { privacyCell.setText(LocaleController.getString("ArchiveAndMuteInfo", R.string.ArchiveAndMuteInfo)); - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } break; case 2: diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java index 6b31c08c1..cfc44d58e 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -1821,10 +1821,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } else { if (!userBlocked) { - getMessagesController().blockPeer(userId); + AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, user, currentEncryptedChat != null, true, true, (param) -> { + if (getParentLayout().getFragmentStack().get(getParentLayout().getFragmentStack().size() - 2) instanceof ChatActivity) { + getParentLayout().removeFragmentFromStack(getParentLayout().getFragmentStack().size() - 2); + } + finishFragment(); + getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialogId, user, currentChat, param); + }, getResourceProvider()); } else { - getMessagesController().unblockPeer(userId); - getSendMessagesHelper().sendMessage("/start", userId, null, null, null, false, null, null, null, true, 0, null, false); + getMessagesController().unblockPeer(userId, ()-> getSendMessagesHelper().sendMessage("/start", userId, null, null, null, false, null, null, null, true, 0, null, false)); finishFragment(); } } @@ -1891,7 +1896,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } finishFragment(); - BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show(); + Context context = getContext(); + if (context != null) { + BulletinFactory.of(Bulletin.BulletinWindow.make(context), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show(); + } dialog.dismiss(); } }); @@ -2208,6 +2216,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. setForegroundImage(true); } if (photo == null || avatarsViewPager.getRealPosition() == 0) { + TLRPC.Photo nextPhoto = avatarsViewPager.getPhoto(1); + if (nextPhoto != null) { + getUserConfig().getCurrentUser().photo =new TLRPC.TL_userProfilePhoto(); + TLRPC.PhotoSize smallSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 90); + TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 1000); + if (smallSize != null && bigSize != null) { + getUserConfig().getCurrentUser().photo.photo_small = smallSize.location; + getUserConfig().getCurrentUser().photo.photo_big = bigSize.location; + } + } else { + getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty(); + } getMessagesController().deleteUserPhoto(null); } else { TLRPC.TL_inputPhoto inputPhoto = new TLRPC.TL_inputPhoto(); @@ -8034,10 +8054,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. if (userBlocked) { otherItem.addSubItem(block_contact, R.drawable.msg_block, LocaleController.getString("Unblock", R.string.Unblock)); } + otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); } else { if (currentEncryptedChat == null) { createAutoDeleteItem(context); } + otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); if (isBot) { otherItem.addSubItem(share, R.drawable.msg_share, LocaleController.getString("BotShare", R.string.BotShare)); } else { @@ -8047,7 +8069,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. otherItem.addSubItem(share_contact, R.drawable.msg_share, LocaleController.getString("ShareContact", R.string.ShareContact)); } if (isBot) { - otherItem.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_retry, !userBlocked ? LocaleController.getString("BotStop", R.string.BotStop) : LocaleController.getString("BotRestart", R.string.BotRestart)); + if (!userBlocked) { + otherItem.addSubItem(block_contact, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_dialogTextRed), getThemedColor(Theme.key_dialogTextRed)); + } else { + otherItem.addSubItem(block_contact, R.drawable.msg_retry, LocaleController.getString("BotRestart", R.string.BotRestart)); + } } else { otherItem.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_block, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock)); } @@ -8070,6 +8096,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } otherItem.addSubItem(start_secret_chat, R.drawable.msg_secret, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat)); } + if (!isBot && getContactsController().contactsDict.get(userId) != null) { + otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + } if (SharedConfig.fakePasscodeActivatedIndex == -1) { if (isBot && SharedConfig.allowRenameChat) { otherItem.addSubItem(edit_chat_name, R.drawable.floating_pencil, LocaleController.getString("EditChatName", R.string.EditChatName)); @@ -8091,7 +8120,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. } } } - otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut)); + } } } else if (chatId != 0) { TLRPC.Chat chat = getMessagesController().getChat(chatId); @@ -8795,6 +8825,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter. try { File dir = AndroidUtilities.getLogsDir(); if (dir == null) { + AndroidUtilities.runOnUIThread(progressDialog::dismiss); return; } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java index ad7fbadad..9ea76815f 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java @@ -899,6 +899,11 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi } break; } + case VIEW_TYPE_SHADOW: { + ShadowSectionCell shadowCell = (ShadowSectionCell) holder.itemView; + shadowCell.setTopBottom(position > 0, position < getItemCount() - 1); + break; + } } } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java index c99ea148f..aeecbbe7c 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -196,7 +196,15 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter emptyView.showProgress(); frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); - listView = new RecyclerListView(context); + listView = new RecyclerListView(context) { + @Override + public Integer getSelectorColor(int position) { + if (position == terminateAllSessionsRow) { + return Theme.multAlpha(getThemedColor(Theme.key_windowBackgroundWhiteRedText2), .1f); + } + return getThemedColor(Theme.key_listSelector); + } + }; listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) { @Override public boolean supportsPredictiveItemAnimations() { @@ -832,7 +840,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter } else { privacyCell.setText(LocaleController.getString("TerminateWebSessionInfo", R.string.TerminateWebSessionInfo)); } - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); + privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } else if (position == passwordSessionsDetailRow) { privacyCell.setText(LocaleController.getString("LoginAttemptsInfo", R.string.LoginAttemptsInfo)); if (otherSessionsTerminateDetail == -1) { @@ -841,7 +849,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); } } else if (position == qrCodeDividerRow || position == ttlDivideRow || position == noOtherSessionsRow) { - privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); + privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); privacyCell.setText(""); privacyCell.setFixedSize(12); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java index e9ba4e267..4ec9a5683 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ThemePreviewActivity.java @@ -1875,11 +1875,13 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro colorPicker.setMinBrightness(0.05f); colorPicker.setMaxBrightness(0.8f); } - int colorsCount = accent.accentColor2 != 0 ? 2 : 1; - colorPicker.setType(1, hasChanges(1), 2, colorsCount, false, 0, false); - colorPicker.setColor(accent.accentColor, 0); - if (accent.accentColor2 != 0) { - colorPicker.setColor(accent.accentColor2, 1); + if (accent != null) { + int colorsCount = accent.accentColor2 != 0 ? 2 : 1; + colorPicker.setType(1, hasChanges(1), 2, colorsCount, false, 0, false); + colorPicker.setColor(accent.accentColor, 0); + if (accent.accentColor2 != 0) { + colorPicker.setColor(accent.accentColor2, 1); + } } } else { patternLayout[a].addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 48)); @@ -2068,10 +2070,12 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro editor.putString("lastDayTheme", applyingTheme.getKey()); editor.commit(); } + BaseFragment lastFragment = getParentLayout().getFragmentStack().get(Math.max(0, getParentLayout().getFragmentStack().size() - 2)); finishFragment(); if (screenType == SCREEN_TYPE_PREVIEW) { NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.didApplyNewTheme, previousTheme, previousAccent, deleteOnCancel); } + Theme.turnOffAutoNight(lastFragment); }); } diff --git a/TMessagesProj/src/main/res/raw/utyan_cache.json b/TMessagesProj/src/main/res/raw/utyan_cache.json new file mode 100644 index 000000000..d05613efc --- /dev/null +++ b/TMessagesProj/src/main/res/raw/utyan_cache.json @@ -0,0 +1 @@ +{"tgs":1,"v":"5.5.2.2","fr":60,"ip":0,"op":180,"w":512,"h":512,"nm":"_043_CLEAN_OUT","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"hand_ bl","parent":2,"sr":1,"ks":{"p":{"a":0,"k":[2.693,-16.281,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":53,"s":[{"i":[[0,0],[-8.532,2.534]],"o":[[14.618,0.702],[0,0]],"v":[[-8.164,6.103],[30.62,-1.089]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":63,"s":[{"i":[[0,0],[-10.305,1.798]],"o":[[5.674,-9.803],[0,0]],"v":[[9.681,6.88],[38.076,-13.532]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":83,"s":[{"i":[[0,0],[-8.532,2.534]],"o":[[14.618,0.702],[0,0]],"v":[[-8.164,6.103],[30.62,-1.089]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":93,"s":[{"i":[[0,0],[-10.305,1.798]],"o":[[5.674,-9.803],[0,0]],"v":[[15.894,3.086],[44.181,-16.778]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":113,"s":[{"i":[[0,0],[-8.532,2.534]],"o":[[14.618,0.702],[0,0]],"v":[[-8.164,6.103],[30.62,-1.089]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":123,"s":[{"i":[[0,0],[-10.305,1.798]],"o":[[5.674,-9.803],[0,0]],"v":[[15.894,3.086],[44.181,-16.778]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":143,"s":[{"i":[[0,0],[-8.532,2.534]],"o":[[14.618,0.702],[0,0]],"v":[[-8.164,6.103],[30.62,-1.089]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[{"i":[[0,0],[-9.549,-4.272]],"o":[[10.185,-4.955],[0,0]],"v":[[-6.783,5.615],[27.776,4.963]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":173,"s":[{"i":[[0,0],[-9.049,6.31]],"o":[[15.247,-0.769],[0,0]],"v":[[-16.678,10.014],[26.813,-5.487]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":183,"s":[{"i":[[0,0],[-9.549,-4.272]],"o":[[10.185,-4.955],[0,0]],"v":[[-6.783,5.615],[27.776,4.963]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":203,"s":[{"i":[[0,0],[-9.049,6.31]],"o":[[15.247,-0.769],[0,0]],"v":[[-16.678,10.014],[26.813,-5.487]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":213,"s":[{"i":[[0,0],[-9.549,-4.272]],"o":[[10.185,-4.955],[0,0]],"v":[[-6.783,5.615],[27.776,4.963]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":233,"s":[{"i":[[0,0],[-8.532,2.534]],"o":[[14.618,0.702],[0,0]],"v":[[-8.164,6.103],[30.62,-1.089]],"c":false}]},{"t":243,"s":[{"i":[[0,0],[-10.305,1.798]],"o":[[5.674,-9.803],[0,0]],"v":[[9.681,6.88],[38.076,-13.532]],"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":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.333],"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.167],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[5]},{"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":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"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.667],"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.333],"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.167],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[100]},{"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":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"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.667],"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":2,"ty":4,"nm":"hand2","parent":13,"sr":1,"ks":{"r":{"a":0,"k":15.439},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":50,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":80,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":150,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":170,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":180,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":200,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":210,"s":[-13.098,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":230,"s":[51.786,139.826,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[-13.098,139.826,0]}]},"a":{"a":0,"k":[-15,32,0]},"s":{"a":0,"k":[100.032,99.928,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":33,"s":[{"i":[[0,0],[-16.252,-16.375],[12.151,-19.676]],"o":[[2.584,-20.092],[11.13,11.213],[0,0]],"v":[[5.16,-4.308],[57.077,-18.917],[16.039,28.035]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":53,"s":[{"i":[[0,0],[-11.573,-8.137],[49.081,-21.581]],"o":[[38.059,2.803],[12.924,9.087],[0,0]],"v":[[-21.197,-20.9],[49.896,-29.908],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":63,"s":[{"i":[[0,0],[-16.252,-16.375],[12.151,-19.676]],"o":[[2.584,-20.092],[11.13,11.213],[0,0]],"v":[[3.478,-16.042],[71.095,-35.769],[16.039,28.035]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":83,"s":[{"i":[[0,0],[-11.573,-8.137],[49.081,-21.581]],"o":[[38.059,2.803],[12.924,9.087],[0,0]],"v":[[-21.197,-20.9],[49.896,-29.908],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":93,"s":[{"i":[[0,0],[-16.252,-16.375],[12.151,-19.676]],"o":[[2.584,-20.092],[11.13,11.213],[0,0]],"v":[[12.034,-20.743],[71.095,-35.769],[16.039,28.035]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":113,"s":[{"i":[[0,0],[-11.573,-8.137],[49.081,-21.581]],"o":[[38.059,2.803],[12.924,9.087],[0,0]],"v":[[-21.197,-20.9],[49.896,-29.908],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":123,"s":[{"i":[[0,0],[-16.252,-16.375],[12.151,-19.676]],"o":[[2.584,-20.092],[11.13,11.213],[0,0]],"v":[[12.034,-20.743],[71.095,-35.769],[16.039,28.035]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":143,"s":[{"i":[[0,0],[-11.573,-8.137],[49.081,-21.581]],"o":[[38.059,2.803],[12.924,9.087],[0,0]],"v":[[-21.197,-20.9],[49.896,-29.908],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[{"i":[[0,0],[-16.252,-16.375],[40.871,-45.265]],"o":[[51.447,-25.296],[11.13,11.213],[0,0]],"v":[[-32.209,-10.068],[55.053,-7.456],[-26.805,51.301]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":173,"s":[{"i":[[0,0],[-16.252,-16.375],[49.081,-21.581]],"o":[[53.513,9.95],[11.13,11.213],[0,0]],"v":[[-44.989,-16.917],[48.432,-35.214],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":183,"s":[{"i":[[0,0],[-16.252,-16.375],[40.871,-45.265]],"o":[[51.447,-25.296],[11.13,11.213],[0,0]],"v":[[-32.209,-10.068],[55.053,-7.456],[-26.805,51.301]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":203,"s":[{"i":[[0,0],[-16.252,-16.375],[49.081,-21.581]],"o":[[53.513,9.95],[11.13,11.213],[0,0]],"v":[[-44.989,-16.917],[48.432,-35.214],[-8.23,47.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":213,"s":[{"i":[[0,0],[-16.252,-16.375],[40.871,-45.265]],"o":[[51.447,-25.296],[11.13,11.213],[0,0]],"v":[[-32.209,-10.068],[55.053,-7.456],[-26.805,51.301]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":233,"s":[{"i":[[0,0],[-11.573,-8.137],[49.081,-21.581]],"o":[[38.059,2.803],[12.924,9.087],[0,0]],"v":[[-21.197,-20.9],[49.896,-29.908],[-8.23,47.203]],"c":false}]},{"t":243,"s":[{"i":[[0,0],[-16.252,-16.375],[12.151,-19.676]],"o":[[2.584,-20.092],[11.13,11.213],[0,0]],"v":[[3.478,-16.042],[71.095,-35.769],[16.039,28.035]],"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":3,"ty":4,"nm":"hand_bl","parent":12,"sr":1,"ks":{"p":{"a":0,"k":[0.298,-6.182,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":53,"s":[{"i":[[0,0],[9.84,-10.211]],"o":[[-6.264,-0.098],[0,0]],"v":[[19.186,5.441],[-14.711,19.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":63,"s":[{"i":[[0,0],[12.011,2.23]],"o":[[-14.143,6.919],[0,0]],"v":[[26.662,4.109],[-20.865,9.586]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":83,"s":[{"i":[[0,0],[10.227,-11.995]],"o":[[-9.926,1.433],[0,0]],"v":[[23.521,-0.81],[-10.955,23.711]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":93,"s":[{"i":[[0,0],[12.011,2.23]],"o":[[-14.143,6.919],[0,0]],"v":[[26.662,4.109],[-20.865,9.586]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":113,"s":[{"i":[[0,0],[10.227,-11.995]],"o":[[-9.926,1.433],[0,0]],"v":[[23.521,-0.81],[-10.955,23.711]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":123,"s":[{"i":[[0,0],[12.011,2.23]],"o":[[-14.143,6.919],[0,0]],"v":[[26.662,4.109],[-20.865,9.586]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":143,"s":[{"i":[[0,0],[10.227,-11.995]],"o":[[-9.926,1.433],[0,0]],"v":[[23.521,-0.81],[-10.955,23.711]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[{"i":[[0,0],[4.58,3.732]],"o":[[-13.967,3.905],[0,0]],"v":[[27.247,23.905],[-7.055,16.788]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":173,"s":[{"i":[[0,0],[9.84,-10.211]],"o":[[-6.264,-0.098],[0,0]],"v":[[19.186,5.441],[-14.711,19.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":183,"s":[{"i":[[0,0],[4.58,3.732]],"o":[[-13.967,3.905],[0,0]],"v":[[27.247,23.905],[-7.055,16.788]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":203,"s":[{"i":[[0,0],[9.84,-10.211]],"o":[[-6.264,-0.098],[0,0]],"v":[[19.186,5.441],[-14.711,19.203]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":213,"s":[{"i":[[0,0],[4.58,3.732]],"o":[[-13.967,3.905],[0,0]],"v":[[27.247,23.905],[-7.055,16.788]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":233,"s":[{"i":[[0,0],[9.84,-10.211]],"o":[[-6.264,-0.098],[0,0]],"v":[[19.186,5.441],[-14.711,19.203]],"c":false}]},{"t":243,"s":[{"i":[[0,0],[12.011,2.23]],"o":[[-14.143,6.919],[0,0]],"v":[[26.662,4.109],[-20.865,9.586]],"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":8.056},"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.333],"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.167],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[5]},{"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":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"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.667],"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.333],"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.167],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[100]},{"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":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"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.667],"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":4,"ty":4,"nm":"Shape Layer 8","sr":1,"ks":{"o":{"a":1,"k":[{"t":3,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":80,"s":[0],"h":1},{"t":116,"s":[100],"h":1},{"t":143,"s":[0],"h":1},{"t":176,"s":[100],"h":1},{"t":203,"s":[0],"h":1},{"t":233,"s":[100],"h":1},{"t":260,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":49,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":61,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":80,"s":[65.461,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":124,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":148,"s":[65.461,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":184,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":210,"s":[65.461,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":241,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":260,"s":[65.461,394.65,0],"h":1}]},"a":{"a":0,"k":[-190.539,209.15,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":51,"s":[10,10,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":62,"s":[100,100,100]},{"t":84,"s":[10,10,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":114,"s":[10,10,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":125,"s":[100,100,100]},{"t":147,"s":[10,10,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":174,"s":[10,10,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":185,"s":[100,100,100]},{"t":207,"s":[10,10,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":231,"s":[10,10,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":242,"s":[100,100,100]},{"t":264,"s":[10,10,100],"h":1}]}},"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":49,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":59,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":84,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":147,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":207,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":239,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":264,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":-30,"op":270,"st":-30,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Shape Layer 7","sr":1,"ks":{"o":{"a":1,"k":[{"t":3,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":80,"s":[0],"h":1},{"t":116,"s":[100],"h":1},{"t":143,"s":[0],"h":1},{"t":176,"s":[100],"h":1},{"t":203,"s":[0],"h":1},{"t":233,"s":[100],"h":1},{"t":260,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[263.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":59,"s":[71.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":88,"s":[72.074,394.897,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":114,"s":[263.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":122,"s":[71.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":142,"s":[72.074,394.897,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[263.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":182,"s":[71.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":205,"s":[72.074,394.897,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":231,"s":[263.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":239,"s":[71.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":268,"s":[72.074,394.897,0],"h":1}]},"a":{"a":0,"k":[-119.176,209.397,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":51,"s":[10,10,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":62,"s":[100,100,100]},{"t":80,"s":[10,10,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":114,"s":[10,10,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":125,"s":[100,100,100]},{"t":143,"s":[10,10,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":174,"s":[10,10,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":185,"s":[100,100,100]},{"t":203,"s":[10,10,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":231,"s":[10,10,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":242,"s":[100,100,100]},{"t":260,"s":[10,10,100],"h":1}]}},"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":49,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":59,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":80,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":143,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":203,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":239,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":260,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":-30,"op":270,"st":-30,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"Shape Layer 6","sr":1,"ks":{"o":{"a":1,"k":[{"t":3,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":80,"s":[0],"h":1},{"t":116,"s":[100],"h":1},{"t":143,"s":[0],"h":1},{"t":176,"s":[100],"h":1},{"t":203,"s":[0],"h":1},{"t":233,"s":[100],"h":1},{"t":260,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":51,"s":[319.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":61,"s":[39.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":82,"s":[40.711,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":114,"s":[319.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":124,"s":[39.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":146,"s":[40.711,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174,"s":[319.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":184,"s":[39.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":200,"s":[40.711,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":231,"s":[319.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":241,"s":[39.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":262,"s":[40.711,394.65,0],"h":1}]},"a":{"a":0,"k":[-190.539,209.15,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":51,"s":[10,10,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":62,"s":[100,100,100]},{"t":80,"s":[10,10,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":114,"s":[10,10,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":125,"s":[100,100,100]},{"t":143,"s":[10,10,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":174,"s":[10,10,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":185,"s":[100,100,100]},{"t":203,"s":[10,10,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":231,"s":[10,10,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":242,"s":[100,100,100]},{"t":260,"s":[10,10,100],"h":1}]}},"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":49,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":59,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":84,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":147,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":207,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":239,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":264,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":-30,"op":270,"st":-30,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"Shape Layer 5","sr":1,"ks":{"o":{"a":1,"k":[{"t":3,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":84,"s":[0],"h":1},{"t":116,"s":[100],"h":1},{"t":147,"s":[0],"h":1},{"t":176,"s":[100],"h":1},{"t":207,"s":[0],"h":1},{"t":233,"s":[100],"h":1},{"t":264,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":49,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":61,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":78,"s":[77.253,400.329,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":124,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":151,"s":[77.253,400.329,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":184,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":211,"s":[77.253,400.329,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":241,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":258,"s":[77.253,400.329,0],"h":1}]},"a":{"a":0,"k":[-178.747,214.829,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":51,"s":[10,10,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":62,"s":[100,100,100]},{"t":86,"s":[10,10,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":114,"s":[10,10,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":125,"s":[100,100,100]},{"t":149,"s":[10,10,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":174,"s":[10,10,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":185,"s":[100,100,100]},{"t":209,"s":[10,10,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":231,"s":[10,10,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":242,"s":[100,100,100]},{"t":266,"s":[10,10,100],"h":1}]}},"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":49,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":59,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":84,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":147,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":207,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":229,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":239,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":264,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":-30,"op":270,"st":-30,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":1,"k":[{"t":33,"s":[0],"h":1},{"t":86,"s":[100],"h":1},{"t":113,"s":[0],"h":1},{"t":146,"s":[100],"h":1},{"t":173,"s":[0],"h":1},{"t":206,"s":[100],"h":1},{"t":233,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":82,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":94,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":114,"s":[65.461,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":154,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":176,"s":[65.461,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[263.711,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":214,"s":[65.461,465.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":233,"s":[65.461,394.65,0],"h":1}]},"a":{"a":0,"k":[-190.539,209.15,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":84,"s":[10,10,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":95,"s":[100,100,100]},{"t":117,"s":[10,10,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":144,"s":[10,10,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":155,"s":[100,100,100]},{"t":177,"s":[10,10,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":204,"s":[10,10,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":215,"s":[100,100,100]},{"t":237,"s":[10,10,100],"h":1}]}},"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":82,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":117,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":177,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[10.281,-5.14],[5.371,-17.659],[-19.285,-3.722],[-3.662,18.569]],"o":[[-5.14,-25.702],[-17.129,-4.659],[-5.785,13.278],[31.838,-0.431]],"v":[[-175.468,202.591],[-206.371,200.659],[-207.215,218.722],[-178.338,222.431]],"c":true}]},{"t":237,"s":[{"i":[[3.598,-1.799],[1.88,-6.181],[-6.75,-1.303],[-1.282,6.499]],"o":[[-1.799,-8.996],[-5.995,-1.631],[-2.025,4.647],[11.143,-0.151]],"v":[[-182.639,206.721],[-193.455,206.045],[-193.75,212.367],[-183.643,213.665]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":1,"k":[{"t":33,"s":[0],"h":1},{"t":86,"s":[100],"h":1},{"t":113,"s":[0],"h":1},{"t":146,"s":[100],"h":1},{"t":173,"s":[0],"h":1},{"t":206,"s":[100],"h":1},{"t":233,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[293.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":92,"s":[101.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":113,"s":[102.074,394.897,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":144,"s":[293.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":152,"s":[101.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":180,"s":[102.074,394.897,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":204,"s":[293.574,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":212,"s":[101.324,475.397,0],"to":[0,0,0],"ti":[0,0,0]},{"t":231,"s":[102.074,394.897,0],"h":1}]},"a":{"a":0,"k":[-119.176,209.397,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":84,"s":[10,10,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":95,"s":[100,100,100]},{"t":113,"s":[10,10,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":144,"s":[10,10,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":155,"s":[100,100,100]},{"t":173,"s":[10,10,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":204,"s":[10,10,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":215,"s":[100,100,100]},{"t":233,"s":[10,10,100],"h":1}]}},"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":82,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":113,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":173,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[15.972,-3.187],[3.626,-11.92],[-23.428,-0.718],[-2.859,5.961]],"o":[[-3.47,-17.349],[-20.485,-1.607],[1.483,10.8],[33.803,0.094]],"v":[[-111.553,203.061],[-134.163,200.008],[-132.233,220.7],[-105.99,223.204]],"c":true}]},{"t":233,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-114.104,206.691],[-122.216,206.015],[-122.438,212.337],[-114.857,213.635]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":1,"k":[{"t":33,"s":[0],"h":1},{"t":86,"s":[100],"h":1},{"t":113,"s":[0],"h":1},{"t":146,"s":[100],"h":1},{"t":173,"s":[0],"h":1},{"t":206,"s":[100],"h":1},{"t":233,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84,"s":[309.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":94,"s":[29.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":121,"s":[30.711,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":144,"s":[309.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":154,"s":[29.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":173,"s":[30.711,394.65,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":204,"s":[309.211,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":214,"s":[29.961,475.15,0],"to":[0,0,0],"ti":[0,0,0]},{"t":238,"s":[30.711,394.65,0],"h":1}]},"a":{"a":0,"k":[-190.539,209.15,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":84,"s":[10,10,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":95,"s":[100,100,100]},{"t":113,"s":[10,10,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":144,"s":[10,10,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":155,"s":[100,100,100]},{"t":173,"s":[10,10,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":204,"s":[10,10,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":215,"s":[100,100,100]},{"t":233,"s":[10,10,100],"h":1}]}},"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":82,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":117,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":177,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[6.939,-3.47],[3.626,-11.92],[-13.017,-2.513],[-2.859,5.961]],"o":[[-3.47,-17.349],[-11.562,-3.145],[-4.185,4.194],[21.49,-0.291]],"v":[[-179.053,204.656],[-204.163,203.602],[-205.233,220.794],[-178.99,223.298]],"c":true}]},{"t":237,"s":[{"i":[[2.699,-1.799],[1.41,-6.181],[-5.062,-1.303],[-0.961,6.499]],"o":[[-1.349,-8.996],[-4.496,-1.631],[-1.519,4.647],[8.357,-0.151]],"v":[[-183.604,206.721],[-191.716,206.045],[-191.938,212.367],[-184.357,213.665]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":1,"k":[{"t":33,"s":[0],"h":1},{"t":86,"s":[100],"h":1},{"t":117,"s":[0],"h":1},{"t":146,"s":[100],"h":1},{"t":177,"s":[0],"h":1},{"t":206,"s":[100],"h":1},{"t":237,"s":[0],"h":1}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":82,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":94,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":116,"s":[77.253,400.329,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":154,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":176,"s":[77.253,400.329,0],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[277.003,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":214,"s":[77.253,470.829,0],"to":[0,0,0],"ti":[0,0,0]},{"t":236,"s":[77.253,400.329,0],"h":1}]},"a":{"a":0,"k":[-178.747,214.829,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":84,"s":[10,10,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":95,"s":[100,100,100]},{"t":119,"s":[10,10,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":144,"s":[10,10,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":155,"s":[100,100,100]},{"t":179,"s":[10,10,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":204,"s":[10,10,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":215,"s":[100,100,100]},{"t":239,"s":[10,10,100],"h":1}]}},"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":82,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":117,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":177,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[10.281,-5.14],[9.852,-24.417],[-19.035,-1.472],[-10.962,-0.56],[9.121,2.485]],"o":[[-5.14,-25.702],[-4.284,-9.424],[16.28,1.259],[35.588,1.819],[-1.285,-11.994]],"v":[[-177.218,214.591],[-212.871,216.159],[-221.215,235.472],[-180.338,236.681],[-161.871,223.515]],"c":true}]},{"t":237,"s":[{"i":[[1.439,-0.719],[1.379,-3.417],[-8.43,-1.972],[0.075,12.529],[5.174,-1.554]],"o":[[-0.719,-3.596],[-0.599,-1.319],[-3.93,7.278],[5.575,0.42],[-0.18,-1.678]],"v":[[-176.731,208.985],[-183.924,209.765],[-184.57,214.472],[-173.575,215.971],[-172.924,209.554]],"c":true}],"h":1}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.780392216701,0.800000059838,0.756862804936,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.781857898189,0.800107230392,0.758165366977,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":"Shape 1","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"hand1","parent":13,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":60,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":80,"s":[33.272]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":90,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":110,"s":[33.272]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":140,"s":[33.272]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":150,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":170,"s":[33.272]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":200,"s":[33.272]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":210,"s":[26.995]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":230,"s":[33.272]},{"t":240,"s":[26.995]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":80,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":110,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":120,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":140,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":150,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":170,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":180,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":200,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":210,"s":[157.289,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":230,"s":[192.821,123.765,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[157.289,123.765,0]}]},"a":{"a":0,"k":[83.716,11.206,0]},"s":{"a":0,"k":[103.539,96.543,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":33,"s":[{"i":[[0,0],[4.511,-10.304],[-56.802,46.311]],"o":[[-25.231,29.469],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-42.946,-6.444],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":53,"s":[{"i":[[0,0],[-3.777,-10.596],[-26.809,-14.182]],"o":[[-42.953,2.447],[3.525,9.89],[0,0]],"v":[[25.587,-12.043],[-30.293,23.676],[61.687,42.773]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":63,"s":[{"i":[[0,0],[4.511,-10.304],[-56.802,46.311]],"o":[[-25.231,29.469],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-42.946,-6.444],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":83,"s":[{"i":[[0,0],[4.511,-10.304],[-54.175,-7.932]],"o":[[-42.953,2.447],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-30.293,23.676],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":93,"s":[{"i":[[0,0],[4.511,-10.304],[-56.802,46.311]],"o":[[-25.231,29.469],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-42.946,-6.444],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":113,"s":[{"i":[[0,0],[4.511,-10.304],[-54.175,-7.932]],"o":[[-42.953,2.447],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-30.293,23.676],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":123,"s":[{"i":[[0,0],[4.511,-10.304],[-56.802,46.311]],"o":[[-25.231,29.469],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-42.946,-6.444],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":143,"s":[{"i":[[0,0],[4.511,-10.304],[-54.175,-7.932]],"o":[[-42.953,2.447],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-30.293,23.676],[83.716,33.465]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":153,"s":[{"i":[[0,0],[4.511,-10.304],[-58.848,31.735]],"o":[[-46.858,11.462],[-8.593,19.63],[0,0]],"v":[[44.578,1.147],[-19.175,-4.319],[70.644,48.162]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":173,"s":[{"i":[[0,0],[-3.777,-10.596],[-26.809,-14.182]],"o":[[-42.953,2.447],[3.525,9.89],[0,0]],"v":[[25.587,-12.043],[-30.293,23.676],[61.687,42.773]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":183,"s":[{"i":[[0,0],[4.511,-10.304],[-58.848,31.735]],"o":[[-46.858,11.462],[-8.593,19.63],[0,0]],"v":[[44.578,1.147],[-19.175,-4.319],[70.644,48.162]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":203,"s":[{"i":[[0,0],[-3.777,-10.596],[-26.809,-14.182]],"o":[[-42.953,2.447],[3.525,9.89],[0,0]],"v":[[25.587,-12.043],[-30.293,23.676],[61.687,42.773]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":213,"s":[{"i":[[0,0],[4.511,-10.304],[-58.848,31.735]],"o":[[-46.858,11.462],[-8.593,19.63],[0,0]],"v":[[44.578,1.147],[-19.175,-4.319],[70.644,48.162]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":233,"s":[{"i":[[0,0],[-3.777,-10.596],[-26.809,-14.182]],"o":[[-42.953,2.447],[3.525,9.89],[0,0]],"v":[[25.587,-12.043],[-30.293,23.676],[61.687,42.773]],"c":false}]},{"t":243,"s":[{"i":[[0,0],[4.511,-10.304],[-56.802,46.311]],"o":[[-25.231,29.469],[-8.593,19.63],[0,0]],"v":[[45.245,-27.116],[-42.946,-6.444],[83.716,33.465]],"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":13,"ty":3,"nm":"NULL CONTROL","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[203.665,234.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":150,"s":[213.665,234.443,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[213.665,234.443,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[203.665,234.443,0]}]},"a":{"a":0,"k":[60,60,0]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"broom","parent":13,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":60,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":80,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":90,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":110,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":120,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":140,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":150,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":170,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":180,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":200,"s":[20]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":210,"s":[60]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.59],"y":[0]},"t":230,"s":[20]},{"t":240,"s":[60]}]},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":60,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":80,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[5.165,0.193,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":90,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":110,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[5.04,-0.057,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":120,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":140,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[4.54,0.318,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":150,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":170,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[5.29,0.068,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":180,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":200,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[6.665,-0.307,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.59,"y":0},"t":210,"s":[60,60,0],"to":[3.335,-14.443,0],"ti":[-2.396,-19.345,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.59,"y":0},"t":230,"s":[80,60,0],"to":[-5.665,0.182,0],"ti":[6.165,0.068,0]},{"t":240,"s":[60,60,0]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[6.287,-0.72],[0,0],[-7.998,-7.94],[0,0]],"o":[[0,0],[-7.941,-7.884],[0,0],[-1.998,7.85]],"v":[[68.069,80.248],[-149.688,-134.151],[-136.315,-147.621],[81.245,66.707]],"c":true}},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.427450984716,0.211764708161,0.019607843831,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.666666686535,0.352941185236,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":15,"ty":4,"nm":"Layer 28","parent":16,"sr":1,"ks":{"p":{"a":0,"k":[307.396,311.699,0]},"a":{"a":0,"k":[307.396,311.699,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":22,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[0,0],[-10.759,-15.839]],"o":[[0,0],[14.953,22.014]],"v":[[8.096,-22.475],[20.08,32.271]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":242,"s":[{"i":[[0,0],[24.873,-24.912]],"o":[[0,0],[-18.803,18.832]],"v":[[0.099,-22.668],[-32.41,43.182]],"c":false}]},{"t":262,"s":[{"i":[[0,0],[-3.267,-22.952]],"o":[[0,0],[3.75,26.346]],"v":[[0.099,-22.668],[-1.775,46.75]],"c":false}]}]},"nm":"Path 1","hd":false},{"ind":1,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":22,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[14.878,26.611],[1.507,28.016]],"o":[[-4.156,-7.433],[0,0]],"v":[[39.217,34.987],[26.917,-15.627]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":242,"s":[{"i":[[-24.478,18.174],[-9.283,33.503]],"o":[[15.705,-11.661],[0,0]],"v":[[-22.566,47.596],[13.148,-22.392]],"c":false}]},{"t":262,"s":[{"i":[[1.157,30.465],[-2.646,35.502]],"o":[[-0.657,-17.292],[0,0]],"v":[[18.134,58.987],[18.919,-15.819]],"c":false}]}]},"nm":"Path 2","hd":false},{"ind":2,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":22,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[0,0],[-7.272,-9.949]],"o":[[-1.93,16.242],[15.027,20.557]],"v":[[-7.273,-18.686],[1.05,28.007]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":242,"s":[{"i":[[0,0],[8.853,-9.838]],"o":[[-5.755,17.938],[-17.033,18.928]],"v":[[-17.974,-10.441],[-42.416,35.898]],"c":false}]},{"t":262,"s":[{"i":[[0,0],[0.331,-10.909]],"o":[[-1.93,16.242],[-0.771,25.452]],"v":[[-17.974,-10.441],[-20.636,35.488]],"c":false}]}]},"nm":"Path 3","hd":false},{"ind":3,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":22,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[23.878,27.851],[5.347,26.082]],"o":[[-8.717,-10.168],[0,0]],"v":[[71.258,38.882],[46.202,-18.638]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":242,"s":[{"i":[[-25.274,26.591],[-5.43,29.461]],"o":[[13.487,-14.19],[0,0]],"v":[[-7.915,51.417],[23.695,-17.415]],"c":false}]},{"t":262,"s":[{"i":[[8.69,35.642],[0.804,34.037]],"o":[[-4.002,-16.414],[0,0]],"v":[[44.593,66.249],[37.964,-8.833]],"c":false}]}]},"nm":"Path 4","hd":false},{"ind":4,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":22,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":27,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":32,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[13.057,30.965],[-0.958,23.715]],"o":[[-7.29,-17.288],[0,0]],"v":[[-16.067,19.93],[-23.319,-42.674]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":242,"s":[{"i":[[-19.739,27.198],[-0.958,23.715]],"o":[[13.916,-19.176],[0,0]],"v":[[-53.655,28.064],[-23.132,-39.783]],"c":false}]},{"t":262,"s":[{"i":[[-1.928,33.55],[-0.958,23.715]],"o":[[1.061,-18.465],[0,0]],"v":[[-34.158,23.496],[-31.317,-42.866]],"c":false}]}]},"nm":"Path 5","hd":false},{"ty":"st","c":{"a":0,"k":[0.749019622803,0.721568644047,0.482352942228,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":[306.046,432.789]},"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":"Layer 27","parent":14,"sr":1,"ks":{"r":{"a":0,"k":-49.27},"p":{"a":0,"k":[67.398,72.639,0]},"a":{"a":0,"k":[307.396,311.699,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":32,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":52,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":57,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":62,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":82,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":87,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":92,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":112,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":117,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":122,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":147,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":152,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":172,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":177,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":182,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":202,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":207,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":212,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":232,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-2.436,-38.309],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-4.094,-41.591],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-45.699,61.189],[62.514,112.114],[47.079,-20.207]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":237,"s":[{"i":[[15.679,7.33],[9.521,-25.774],[-15.864,-21.822],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-11.552,31.272],[13.112,15.425],[-29.069,-28.363],[-6.041,-43.501]],"v":[[3.085,-76.044],[-35.172,-61.266],[-27.984,60.794],[93.152,80.082],[47.079,-20.207]],"c":true}]},{"t":242,"s":[{"i":[[15.679,7.33],[2.724,-8.945],[29.234,-24.482],[-24.681,11.569],[3.3,23.762]],"o":[[-14.861,-6.948],[-9.712,31.891],[13.112,15.425],[36.667,-31.413],[-6.041,-43.501]],"v":[[3.085,-76.044],[-22.269,-51.34],[-65.202,64.285],[2.214,91.838],[36.392,-20.368]],"c":true}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.749019622803,0.721568644047,0.482352942228,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0.972549021244,0.631372570992,1]},"o":{"a":0,"k":100},"r":1,"bm":0,"nm":"Fill 1","hd":false},{"ty":"tr","p":{"a":0,"k":[307.396,387.743]},"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":17,"ty":4,"nm":"eye 2","parent":21,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":130,"s":[-14.275]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":150,"s":[-18.825]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":220,"s":[-18.825]},{"t":240,"s":[-14.275]}]},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[73.221,-37.839,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":150,"s":[42.544,-36.499,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[42.544,-36.499,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[73.221,-37.839,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":130,"s":[100,100,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":150,"s":[70,100,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":220,"s":[70,100,100]},{"t":240,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[10.105,-12.856],[-1.443,24.985]],"o":[[-14.223,18.095],[1.403,-24.284]],"v":[[22.43,16.471],[-25.239,0.304]],"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":12},"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":18,"ty":4,"nm":"eye","parent":21,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":130,"s":[0]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":150,"s":[0]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":220,"s":[0]},{"t":240,"s":[0]}]},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[-74.182,-41.257,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":150,"s":[-80.128,-37.35,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[-80.128,-37.35,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[-74.182,-41.257,0]}]},"s":{"a":1,"k":[{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":130,"s":[100,100,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":150,"s":[100,100,100]},{"i":{"x":[0.4,0.4,0.4],"y":[1,1,1]},"o":{"x":[0.6,0.6,0.6],"y":[0,0,0]},"t":220,"s":[100,100,100]},{"t":240,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[8.193,-14.152],[3.791,17.21]],"o":[[-14.566,25.159],[-5.232,-23.756]],"v":[[26.002,7.53],[-25.189,4.249]],"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":12},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 1","bm":0,"hd":false},{"ty":"gr","it":[{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0},"nm":"Transform"}],"nm":"Group 2","bm":0,"hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"mouth","parent":21,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":60,"s":[-5.3,14.686,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":72,"s":[7.991,13.664,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":90,"s":[7.991,13.664,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":102,"s":[-5.3,14.686,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":132,"s":[-5.3,14.686,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":144,"s":[7.991,13.664,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":180,"s":[7.991,13.664,0],"to":[0,0,0],"ti":[0,0,0]},{"t":192,"s":[-5.3,14.686,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":68.182,"s":[140,140,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":76.363,"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":84.545,"s":[140,140,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":92.727,"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":100.908,"s":[140,140,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":109.092,"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":117.273,"s":[140,140,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":125.455,"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":133.637,"s":[140,140,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":141.818,"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":150,"s":[140,140,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":158.182,"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":166.363,"s":[140,140,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":174.545,"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":182.727,"s":[140,140,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":190.908,"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":199.092,"s":[140,140,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":207.273,"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":215.455,"s":[140,140,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":223.637,"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":231.818,"s":[140,140,100]},{"t":240,"s":[100,100,100]}]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[-0.592,-2.673],[3.638,-0.805],[0.592,2.673],[-3.638,0.805]],"o":[[0.592,2.673],[-3.638,0.805],[-0.592,-2.673],[3.638,-0.805]],"v":[[6.587,-1.458],[1.072,4.841],[-6.587,1.458],[-1.072,-4.841]],"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":8},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","hd":false},{"ty":"fl","c":{"a":0,"k":[0.490196079016,0.035294119269,0.035294119269,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":20,"ty":4,"nm":"beak_bl","parent":21,"sr":1,"ks":{"p":{"a":0,"k":[-8.202,-11.28,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":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68.201,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76.4,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84.6,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92.799,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":101,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109.201,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":117.4,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":125.6,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":133.799,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":142,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":150,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":158,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":166.223,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":174.445,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":182.666,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":190.889,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":199.111,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":207.334,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":215.555,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":223.777,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-10.849,13.904],[1.757,-10.439]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":232,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-8.519,15.824],[4.086,-8.518]],"c":false}]},{"t":240,"s":[{"i":[[-9.069,5.866],[0.172,8.401]],"o":[[9.069,-5.866],[-0.172,-8.401]],"v":[[-7.047,12.289],[7.043,-12.289]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[1,0.686274528503,0.482352942228,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.333],"y":[0]},"t":106,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":118,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":154,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":178,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":190,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":202,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":214,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":226,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":238,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":250,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":262,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":274,"s":[5]},{"t":286,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":118,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":154,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":178,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":190,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":202,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":214,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":226,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":238,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":250,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":262,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":274,"s":[100]},{"t":286,"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":21,"ty":4,"nm":"beak","parent":24,"sr":1,"ks":{"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":54,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":69,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":84,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":99,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":114,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":129,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":144,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":159,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":174,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":189,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":204,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":219,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":234,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":249,"s":[-10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":264,"s":[10]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":279,"s":[10]},{"t":294,"s":[-10]}]},"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[25.534,63.017,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":150,"s":[94.543,53.944,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[94.543,53.944,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[25.534,63.017,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":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":68.182,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-1.387,-37.531],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":76.363,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":84.545,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-1.387,-37.531],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":92.727,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":100.908,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-1.387,-37.531],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":109.092,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":117.273,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-1.387,-37.531],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":125.455,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":133.637,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-1.387,-37.531],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":142,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":150,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":158.182,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":166,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":174.545,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":182.727,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":190.908,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":199.092,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":207.273,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":215.455,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":223.637,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-8.809,-36.352],[-25.717,-3],[-2.689,34.365]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":231.818,"s":[{"i":[[27.697,16.739],[13.536,-1.651],[15.526,-13.647],[-35.005,-0.37]],"o":[[-17.059,-10.31],[-12.819,1.564],[-21.253,18.68],[25.828,0.273]],"v":[[18.826,-6.032],[-8.628,-36.255],[-22.316,-3.677],[-0.244,40.458]],"c":true}]},{"t":240,"s":[{"i":[[8.26,10.634],[13.536,-1.651],[15.354,-13.84],[-25.948,1.81]],"o":[[-12.227,-15.741],[-12.819,1.564],[-11.83,10.664],[20.482,-1.429]],"v":[[16.289,-3.677],[-1.387,-37.531],[-25.717,-3],[-2.689,34.365]],"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":8},"lc":1,"lj":1,"ml":10,"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_bl2","parent":24,"sr":1,"ks":{"p":{"a":0,"k":[110.767,-12.191,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,-32.545]],"o":[[25.697,23.283],[0,26.097]],"v":[[-20.895,-44.053],[20.895,44.053]],"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.333],"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.167],"y":[0]},"t":84,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[5]},{"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":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[0]},{"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.667],"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.333],"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.167],"y":[0]},"t":84,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":96,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":108,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":120,"s":[100]},{"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":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":180,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":192,"s":[95]},{"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.667],"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_bl1","parent":24,"sr":1,"ks":{"p":{"a":0,"k":[-71.747,-52.879,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[-66.529,16.966]],"o":[[0.491,-1.153],[0,0]],"v":[[-44.782,38.184],[44.782,-38.184]],"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":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.333],"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.333],"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":24,"ty":4,"nm":"head","parent":27,"sr":1,"ks":{"p":{"a":0,"k":[14.771,-30.59,0]},"a":{"a":0,"k":[0,119.642,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":0,"k":{"i":[[0,0],[0,35.832],[85.15,0],[0,-76.12],[-26.176,-21.683]],"o":[[26.507,-21.855],[0,-76.12],[-85.149,0],[0,35.929],[0,0]],"v":[[112.275,119.642],[154.176,31.41],[0,-119.642],[-154.176,31.41],[-112.529,119.431]],"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":25,"ty":3,"nm":"NULL CONTROL","sr":1,"ks":{"o":{"a":0,"k":0},"p":{"a":0,"k":[287.497,390.228,0]},"a":{"a":0,"k":[60,60,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":[102,98,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":75,"s":[98,102,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":90,"s":[102,98,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":105,"s":[98,102,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":[102,98,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":135,"s":[98,102,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":150,"s":[102,98,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":165,"s":[98,102,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":[102,98,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":195,"s":[98,102,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":210,"s":[102,98,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":225,"s":[98,102,100]},{"t":240,"s":[102,98,100]}]}},"ao":0,"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":"head_bl3","parent":27,"sr":1,"ks":{"p":{"a":0,"k":[-86.442,3.614,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.14,"y":1},"o":{"x":0.86,"y":0},"t":130,"s":[{"i":[[18.994,8.348],[0.775,3.247]],"o":[[-15.978,-7.022],[-1.857,-7.779]],"v":[[-15.224,69.036],[-38.349,46.522]],"c":false}]},{"i":{"x":0.14,"y":1},"o":{"x":0.86,"y":0},"t":150,"s":[{"i":[[18.994,8.348],[0.775,3.247]],"o":[[-15.978,-7.022],[-1.857,-7.779]],"v":[[-15.224,69.036],[-38.349,46.522]],"c":false}]},{"i":{"x":0.14,"y":1},"o":{"x":0.86,"y":0},"t":220,"s":[{"i":[[18.994,8.348],[0.775,3.247]],"o":[[-15.978,-7.022],[-1.857,-7.779]],"v":[[-15.224,69.036],[-38.349,46.522]],"c":false}]},{"t":240,"s":[{"i":[[18.994,8.348],[0.775,3.247]],"o":[[-15.978,-7.022],[-1.857,-7.779]],"v":[[-15.224,69.036],[-38.349,46.522]],"c":false}]}]},"nm":"Path 1","hd":false},{"ty":"st","c":{"a":0,"k":[0.988235353956,0.933333393172,0.129411764706,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.333],"y":[0]},"t":106,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":118,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":154,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":178,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":190,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":202,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":214,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":226,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":238,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":250,"s":[5]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":262,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":274,"s":[5]},{"t":286,"s":[5]}]},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":106,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":118,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":130,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":142,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":154,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":166,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":178,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":190,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":202,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":214,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":226,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":238,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":250,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":262,"s":[95]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":274,"s":[100]},{"t":286,"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":27,"ty":4,"nm":"body","parent":25,"sr":1,"ks":{"p":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[60,60,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":0.4},"o":{"x":0.6,"y":0.6},"t":150,"s":[-40,60,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[-40,60,0],"to":[0,0,0],"ti":[0,0,0]},{"t":240,"s":[60,60,0]}]},"a":{"a":0,"k":[0,102.595,0]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":130,"s":[{"i":[[62.122,0],[-6.87,62.153],[-14.913,32.929],[-70.318,0],[-16.073,-54.605],[1.199,-16.579]],"o":[[-53.421,0],[1.145,-10.363],[28.624,-63.204],[61.046,0],[4.134,14.046],[-4.256,58.848]],"v":[[-6.239,104.556],[-142.51,26.493],[-127.984,-26.672],[10.638,-102.595],[140.488,-14.198],[161.969,32.829]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":150,"s":[{"i":[[62.122,0],[-10.354,65.601],[-14.913,32.929],[-70.318,0],[-16.889,-53.203],[1.267,-17.522]],"o":[[-53.421,0],[1.626,-10.299],[28.624,-63.204],[60.152,0],[4.659,14.678],[-4.256,58.848]],"v":[[-14.912,102.595],[-144.658,21.101],[-117.887,-26.672],[10.638,-102.595],[139.759,-16.581],[145.132,31.849]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":220,"s":[{"i":[[62.122,0],[-10.354,65.601],[-14.913,32.929],[-70.318,0],[-16.889,-53.203],[1.267,-17.522]],"o":[[-53.421,0],[1.626,-10.299],[28.624,-63.204],[60.152,0],[4.659,14.678],[-4.256,58.848]],"v":[[-14.912,102.595],[-144.658,21.101],[-117.887,-26.672],[10.638,-102.595],[139.759,-16.581],[145.132,31.849]],"c":true}]},{"t":240,"s":[{"i":[[62.122,0],[-6.87,62.153],[-14.913,32.929],[-70.318,0],[-16.073,-54.605],[1.199,-16.579]],"o":[[-53.421,0],[1.145,-10.363],[28.624,-63.204],[61.046,0],[4.134,14.046],[-4.256,58.848]],"v":[[-6.239,104.556],[-142.51,26.493],[-127.984,-26.672],[10.638,-102.595],[140.488,-14.198],[161.969,32.829]],"c":true}]}]},"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}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"_043_CLEAN","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":133,"op":313,"st":73,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"_043_CLEAN","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":-47,"op":133,"st":-107,"bm":0}]} \ No newline at end of file diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index c48efd098..cda848eb8 100644 --- a/TMessagesProj/src/main/res/values/strings.xml +++ b/TMessagesProj/src/main/res/values/strings.xml @@ -2445,6 +2445,8 @@ Clear Cache Clear Selected Free up disk space on your device; your media will stay in the cloud. + Clearing cache… + Please keep this window open while Telegram is clearing your cache. Change Phone Number Move your account, chats and media to a new number. Your phone number has been successfully changed to %1$s. @@ -5838,6 +5840,7 @@ Emoji status is a premium feature. Other features included in **Telegram Premium**: This is %1$s\'s current status. **%1$s** has gifted you a %2$s subscription for Telegram Premium. + Someone has gifted you a %1$s subscription for Telegram Premium. You now have access to additional features. You gifted **%1$s** a %2$s subscription for Telegram Premium. **%1$s** now have access to additional features. @@ -6352,8 +6355,9 @@ You can\'t create a link This user can\'t be invited This users can\'t be invited - %1$s free - %1$s free, %2$s + %1$s free, high speed + %1$s free, slow speed\ + %1$s free, slow speed %2$s enabled when below %s%% %s%% Rate up @@ -6370,7 +6374,15 @@ Telegram Premium Required Due to the high cost of SMS in your country, you need a **Telegram Premium** account to immediately reset this email via an SMS code.\n\nYou can ask a friend to gift a Premium subscription for your account **%1$s** Resetting email, please wait... - + Delete and Block + Block bot + Are you sure you want to delete the chat with **%1$s**? + Decrease speed + Storing on SD card will make Telegram slow. Proceed anyway? + Proceed + SD Card Error + Telegram is unable to save data on your SD card. + Do not use SD card Fake Passcode Change Fake Passcode diff --git a/TMessagesProj_AppHockeyApp/build.gradle b/TMessagesProj_AppHockeyApp/build.gradle index 9c3c8aa73..dd7981fb2 100644 --- a/TMessagesProj_AppHockeyApp/build.gradle +++ b/TMessagesProj_AppHockeyApp/build.gradle @@ -67,8 +67,8 @@ android { buildTypes { HA_private { - debuggable false - jniDebuggable false + debuggable true + jniDebuggable true signingConfig signingConfigs.debug applicationIdSuffix ".beta" minifyEnabled true diff --git a/gradle.properties b/gradle.properties index 1116ac4ba..54a3dcbaf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,8 +13,8 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sat Mar 12 05:53:50 MSK 2016 -APP_VERSION_CODE=3227 -APP_VERSION_NAME=9.5.4 +APP_VERSION_CODE=3249 +APP_VERSION_NAME=9.5.7 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=UCKJJtMyqB!9uGrAw6xu RELEASE_KEY_ALIAS=key0