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/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 d512cb78d..ae50f3b18 100644 --- a/TMessagesProj/jni/tgnet/ConnectionsManager.cpp +++ b/TMessagesProj/jni/tgnet/ConnectionsManager.cpp @@ -1825,14 +1825,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; } @@ -3029,12 +3032,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; @@ -3057,7 +3062,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 { @@ -3607,6 +3612,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 4ddf0283b..d92a1cea5 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.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(); @@ -4782,6 +4797,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..b8f5f58e9 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/AutoDeleteMediaTask.java @@ -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/BuildVars.java b/TMessagesProj/src/main/java/org/telegram/messenger/BuildVars.java index 3008e0bdf..8ad58eacd 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 = 3236; + public static String BUILD_VERSION_STRING = "9.5.5"; public static int APP_ID = 4; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; 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..86a67a9b8 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.remove(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..426e9e035 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoaderPriorityQueue.java @@ -3,14 +3,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 +26,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 +48,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 +65,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 { @@ -87,4 +92,11 @@ public class FileLoaderPriorityQueue { 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/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..e5b55df05 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/ImageLoader.java @@ -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); } } } diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java b/TMessagesProj/src/main/java/org/telegram/messenger/ImageReceiver.java index fea0f1ca2..6bce07a09 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/LiteMode.java b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java index 061251685..43290e42c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LiteMode.java @@ -53,8 +53,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 | diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java index 5e115fd32..6d2b4348f 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/LocaleController.java @@ -552,6 +552,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 9fd030974..eef27a325 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MediaDataController.java @@ -34,7 +34,6 @@ import android.text.TextUtils; import android.text.style.CharacterStyle; import android.text.style.URLSpan; import android.text.util.Linkify; -import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -53,7 +52,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; @@ -6934,10 +6932,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/MessagesStorage.java b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java index d961c5809..167e3f80c 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/MessagesStorage.java @@ -13137,6 +13137,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/SharedConfig.java b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java index 5ac470400..bfe8a891b 100644 --- a/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java +++ b/TMessagesProj/src/main/java/org/telegram/messenger/SharedConfig.java @@ -10,7 +10,9 @@ package org.telegram.messenger; import android.app.Activity; import android.app.ActivityManager; +import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.os.Build; @@ -27,7 +29,11 @@ import org.json.JSONObject; 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.CacheControlActivity; import org.telegram.ui.Components.SwipeGestureSettingsView; +import org.telegram.ui.LaunchActivity; import java.io.File; import java.io.RandomAccessFile; @@ -57,6 +63,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, 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/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/CacheControlActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CacheControlActivity.java index 5d25cdf6b..2f1835676 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; @@ -96,6 +98,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; @@ -105,6 +108,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; @@ -817,7 +823,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(); } @@ -826,22 +832,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; @@ -888,13 +997,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; @@ -906,14 +1019,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) { @@ -1000,6 +1117,10 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe MediaDataController.getInstance(currentAccount).chekAllMedia(true); loadDialogEntities(); + + if (onDone != null) { + onDone.run(); + } }); } @@ -1688,13 +1809,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(); + }) + ); }); } @@ -1772,8 +2024,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) { @@ -1803,6 +2053,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 e9190c525..106bb7417 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java @@ -181,7 +181,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; @@ -373,6 +373,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate if (this.visibleOnScreen != visibleOnScreen) { this.visibleOnScreen = visibleOnScreen; checkImageReceiversAttachState(); + if (visibleOnScreen) { + invalidate(); + } } } @@ -4092,26 +4095,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)) { + 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; @@ -7586,7 +7593,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; @@ -17646,9 +17653,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 b206cd138..2a569fff5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java @@ -511,13 +511,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) { @@ -2118,7 +2119,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) { @@ -2190,7 +2191,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)); } } @@ -3830,7 +3831,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) { @@ -3875,7 +3876,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 49a108eda..3cb2eece1 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java @@ -295,6 +295,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; @@ -378,6 +379,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; @@ -5001,26 +5003,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(); @@ -5031,7 +5013,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) { @@ -5387,7 +5368,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); } @@ -6674,6 +6654,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.BotStartButton)); + 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() { @@ -10189,127 +10204,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; @@ -11748,7 +11642,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); @@ -13763,9 +13657,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not invalidateMessagesVisiblePart(); updateTextureViewPosition(false, false); - if (!scrollingChatListView) { - checkAutoDownloadMessages(false); - } notifyHeightChanged(); } @@ -15337,6 +15228,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not int loaded_max_id = (Integer) args[12]; int loaded_mentions_count = chatWasReset ? 0 : (Integer) args[13]; + if (did == dialog_id && count > 0 && currentUser != null && (bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() == View.VISIBLE)) { + if (!TextUtils.isEmpty(botUser)) { + getMessagesController().sendBotStart(currentUser, botUser); + + bottomOverlayChat.setVisibility(View.GONE); + chatActivityEnterView.setVisibility(View.VISIBLE); + } + } + if (loaded_mentions_count < 0) { loaded_mentions_count *= -1; hasAllMentionsLocal = false; @@ -16317,9 +16217,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) { @@ -20624,7 +20521,9 @@ 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()); @@ -20648,6 +20547,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); 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 c8a422842..b60a9792b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java @@ -727,7 +727,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) { @@ -7350,7 +7350,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 6195a6952..7e0dae548 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.tgnet.ConnectionsManager; @@ -282,7 +280,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/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/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/ProfileGalleryView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ProfileGalleryView.java index badfd965c..439208441 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 5b8575c9b..4fd9a7182 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java @@ -3244,6 +3244,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 @@ -7123,6 +7131,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 -> { @@ -8669,7 +8678,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(); } diff --git a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java index 1e28cf548..e8169f834 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/FiltersSetupActivity.java @@ -49,6 +49,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; @@ -527,6 +528,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); @@ -735,6 +742,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; @@ -777,7 +785,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; @@ -848,9 +856,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; } @@ -870,7 +878,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 1d67b36ba..e9f8df0f5 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java @@ -4981,12 +4981,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/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java index 36e107c52..09b8176e4 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java @@ -6085,6 +6085,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/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java index 5e74d92db..0937f003a 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java @@ -1021,21 +1021,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)); @@ -1043,10 +1040,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 51271bc4d..618765557 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java @@ -1876,7 +1876,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(); } }); @@ -2193,6 +2196,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(); 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 4178a369c..52378092b 100644 --- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java +++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java @@ -192,7 +192,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() { @@ -799,7 +807,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) { @@ -808,7 +816,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..a36a46b81 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)); diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml index 7fe1968b4..b0300e866 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. @@ -3490,6 +3492,7 @@ has no access to messages What can this bot do? START + Start bot RESTART Stop bot Restart bot @@ -6353,8 +6356,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 @@ -6371,4 +6375,10 @@ 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... + 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 diff --git a/TMessagesProj_AppHockeyApp/build.gradle b/TMessagesProj_AppHockeyApp/build.gradle index d055126a9..ef33612c7 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 2b238f9fd..7072f5543 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=3236 +APP_VERSION_NAME=9.5.5 APP_PACKAGE=org.telegram.messenger RELEASE_KEY_PASSWORD=android RELEASE_KEY_ALIAS=androidkey