update to 9.5.5

This commit is contained in:
xaxtix 2023-03-24 15:38:14 +04:00
parent c06f56dcad
commit 5e5b7659cb
76 changed files with 1180 additions and 482 deletions

View file

@ -5,6 +5,7 @@
#include "tgnet/ConnectionsManager.h" #include "tgnet/ConnectionsManager.h"
#include "tgnet/MTProtoScheme.h" #include "tgnet/MTProtoScheme.h"
#include "tgnet/ConnectionSocket.h" #include "tgnet/ConnectionSocket.h"
#include "tgnet/FileLog.h"
JavaVM *java; JavaVM *java;
jclass jclass_RequestDelegateInternal; 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(); TL_api_request *request = new TL_api_request();
request->request = (NativeByteBuffer *) (intptr_t) object; request->request = (NativeByteBuffer *) (intptr_t) object;
if (onComplete != nullptr) { if (onComplete != nullptr) {
DEBUG_REF("sendRequest onComplete");
onComplete = env->NewGlobalRef(onComplete); onComplete = env->NewGlobalRef(onComplete);
} }
if (onQuickAck != nullptr) { if (onQuickAck != nullptr) {
DEBUG_REF("sendRequest onQuickAck");
onQuickAck = env->NewGlobalRef(onQuickAck); onQuickAck = env->NewGlobalRef(onQuickAck);
} }
if (onWriteToSocket != nullptr) { if (onWriteToSocket != nullptr) {
DEBUG_REF("sendRequest onWriteToSocket");
onWriteToSocket = env->NewGlobalRef(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) { 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); const char *secretStr = env->GetStringUTFChars(secret, 0);
if (requestTimeFunc != nullptr) { if (requestTimeFunc != nullptr) {
DEBUG_REF("sendRequest requestTimeFunc");
requestTimeFunc = env->NewGlobalRef(requestTimeFunc); requestTimeFunc = env->NewGlobalRef(requestTimeFunc);
} }
@ -484,6 +489,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("RequestDelegateInternal class");
jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal")); jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal"));
if (jclass_RequestDelegateInternal == 0) { if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE; return JNI_FALSE;
@ -493,6 +499,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("RequestTimeDelegate class");
jclass_RequestTimeDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestTimeDelegate")); jclass_RequestTimeDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestTimeDelegate"));
if (jclass_RequestTimeDelegate == 0) { if (jclass_RequestTimeDelegate == 0) {
return JNI_FALSE; return JNI_FALSE;
@ -502,6 +509,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("QuickAckDelegate class");
jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate")); jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate"));
if (jclass_RequestDelegateInternal == 0) { if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE; return JNI_FALSE;
@ -511,6 +519,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("WriteToSocketDelegate class");
jclass_WriteToSocketDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/WriteToSocketDelegate")); jclass_WriteToSocketDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/WriteToSocketDelegate"));
if (jclass_WriteToSocketDelegate == 0) { if (jclass_WriteToSocketDelegate == 0) {
return JNI_FALSE; return JNI_FALSE;
@ -519,6 +528,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
if (jclass_WriteToSocketDelegate_run == 0) { if (jclass_WriteToSocketDelegate_run == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("ConnectionsManager class");
jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager")); jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager"));
if (jclass_ConnectionsManager == 0) { if (jclass_ConnectionsManager == 0) {
return JNI_FALSE; return JNI_FALSE;

View file

@ -121,6 +121,7 @@ typedef struct VideoInfo {
} else { } else {
attached = false; attached = false;
} }
DEBUG_DELREF("gifvideocpp stream");
jniEnv->DeleteGlobalRef(stream); jniEnv->DeleteGlobalRef(stream);
if (attached) { if (attached) {
javaVm->DetachCurrentThread(); javaVm->DetachCurrentThread();
@ -955,6 +956,7 @@ extern "C" JNIEXPORT jlong JNICALL Java_org_telegram_ui_Components_AnimatedFileD
int ret; int ret;
if (streamFileSize != 0) { if (streamFileSize != 0) {
info->file_size = streamFileSize; info->file_size = streamFileSize;
DEBUG_REF("gifvideo.cpp new stream");
info->stream = env->NewGlobalRef(stream); info->stream = env->NewGlobalRef(stream);
info->account = account; info->account = account;
info->fd = open(info->src, O_RDONLY, S_IRUSR); 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) { extern "C" jint videoOnJNILoad(JavaVM *vm, JNIEnv *env) {
//av_log_set_callback(custom_log); //av_log_set_callback(custom_log);
DEBUG_REF("gifvideo.cpp AnimatedFileDrawableStream ref");
jclass_AnimatedFileDrawableStream = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/AnimatedFileDrawableStream")); jclass_AnimatedFileDrawableStream = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/AnimatedFileDrawableStream"));
if (jclass_AnimatedFileDrawableStream == 0) { if (jclass_AnimatedFileDrawableStream == 0) {
return JNI_FALSE; return JNI_FALSE;

View file

@ -27,14 +27,17 @@ jfieldID jclass_Options_outHeight;
jfieldID jclass_Options_outWidth; jfieldID jclass_Options_outWidth;
jint imageOnJNILoad(JavaVM *vm, JNIEnv *env) { jint imageOnJNILoad(JavaVM *vm, JNIEnv *env) {
DEBUG_REF("image.cpp nullpointerexception class");
jclass_NullPointerException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/NullPointerException")); jclass_NullPointerException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/NullPointerException"));
if (jclass_NullPointerException == 0) { if (jclass_NullPointerException == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("image.cpp runtimeexception class");
jclass_RuntimeException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/RuntimeException")); jclass_RuntimeException = (jclass) env->NewGlobalRef(env->FindClass("java/lang/RuntimeException"));
if (jclass_RuntimeException == 0) { if (jclass_RuntimeException == 0) {
return JNI_FALSE; return JNI_FALSE;
} }
DEBUG_REF("image.cpp bitmapfactoryoptions class");
jclass_Options = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/BitmapFactory$Options")); jclass_Options = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/BitmapFactory$Options"));
if (jclass_Options == 0) { if (jclass_Options == 0) {
return JNI_FALSE; return JNI_FALSE;

View file

@ -274,7 +274,7 @@ JNIEXPORT jlong Java_org_telegram_messenger_Utilities_getLastUsageFileTime(JNIEn
struct stat attrib; struct stat attrib;
stat(fileName, &attrib); stat(fileName, &attrib);
jlong value; jlong value;
if (attrib.st_atim.tv_sec != 0) { if (attrib.st_atim.tv_sec > 316000000) {
value = attrib.st_atim.tv_sec; value = attrib.st_atim.tv_sec;
} else { } else {
value = attrib.st_mtim.tv_sec; value = attrib.st_mtim.tv_sec;

View file

@ -56,6 +56,7 @@ void TL_dcOption::readParams(NativeByteBuffer *stream, int32_t instanceNum, bool
cdn = (flags & 8) != 0; cdn = (flags & 8) != 0;
isStatic = (flags & 16) != 0; isStatic = (flags & 16) != 0;
thisPortOnly = (flags & 32) != 0; thisPortOnly = (flags & 32) != 0;
force_try_ipv6 = (flags & 16384) != 0;
id = stream->readInt32(&error); id = stream->readInt32(&error);
ip_address = stream->readString(&error); ip_address = stream->readString(&error);
port = stream->readInt32(&error); port = stream->readInt32(&error);
@ -72,6 +73,7 @@ void TL_dcOption::serializeToStream(NativeByteBuffer *stream) {
flags = cdn ? (flags | 8) : (flags &~ 8); flags = cdn ? (flags | 8) : (flags &~ 8);
flags = isStatic ? (flags | 16) : (flags &~ 16); flags = isStatic ? (flags | 16) : (flags &~ 16);
flags = thisPortOnly ? (flags | 32) : (flags &~ 32); flags = thisPortOnly ? (flags | 32) : (flags &~ 32);
flags = force_try_ipv6 ? (flags | 16384) : (flags &~ 16384);
stream->writeInt32(flags); stream->writeInt32(flags);
stream->writeInt32(id); stream->writeInt32(id);
stream->writeString(ip_address); stream->writeString(ip_address);

View file

@ -50,6 +50,7 @@ public:
bool cdn; bool cdn;
bool isStatic; bool isStatic;
bool thisPortOnly; bool thisPortOnly;
bool force_try_ipv6;
int32_t id; int32_t id;
std::string ip_address; std::string ip_address;
int32_t port; int32_t port;

View file

@ -1825,14 +1825,17 @@ void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete
exit(1); exit(1);
} }
if (ptr1 != nullptr) { if (ptr1 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr1");
env->DeleteGlobalRef(ptr1); env->DeleteGlobalRef(ptr1);
ptr1 = nullptr; ptr1 = nullptr;
} }
if (ptr2 != nullptr) { if (ptr2 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr2");
env->DeleteGlobalRef(ptr2); env->DeleteGlobalRef(ptr2);
ptr2 = nullptr; ptr2 = nullptr;
} }
if (ptr3 != nullptr) { if (ptr3 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr3");
env->DeleteGlobalRef(ptr3); env->DeleteGlobalRef(ptr3);
ptr3 = nullptr; ptr3 = nullptr;
} }
@ -3029,12 +3032,14 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
std::vector<TcpAddress> addressesIpv4Download; std::vector<TcpAddress> addressesIpv4Download;
std::vector<TcpAddress> addressesIpv6Download; std::vector<TcpAddress> addressesIpv6Download;
bool isCdn = false; bool isCdn = false;
bool forceTryIpV6;
void addAddressAndPort(TL_dcOption *dcOption) { void addAddressAndPort(TL_dcOption *dcOption) {
std::vector<TcpAddress> *addresses; std::vector<TcpAddress> *addresses;
if (!isCdn) { if (!isCdn) {
isCdn = dcOption->cdn; isCdn = dcOption->cdn;
} }
forceTryIpV6 = dcOption->force_try_ipv6;
if (dcOption->media_only) { if (dcOption->media_only) {
if (dcOption->ipv6) { if (dcOption->ipv6) {
addresses = &addressesIpv6Download; addresses = &addressesIpv6Download;
@ -3057,7 +3062,7 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
if (dcOption->secret != nullptr) { if (dcOption->secret != nullptr) {
secret = std::string((const char *) dcOption->secret->bytes, dcOption->secret->length); 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) { if (dcOption->thisPortOnly) {
addresses->insert(addresses->begin(), TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret)); addresses->insert(addresses->begin(), TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret));
} else { } else {
@ -3607,6 +3612,7 @@ void ConnectionsManager::useJavaVM(JavaVM *vm, bool useJavaByteBuffers) {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv"); if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1); exit(1);
} }
DEBUG_REF("connectionsmanager byte buffer");
jclass_ByteBuffer = (jclass) env->NewGlobalRef(env->FindClass("java/nio/ByteBuffer")); jclass_ByteBuffer = (jclass) env->NewGlobalRef(env->FindClass("java/nio/ByteBuffer"));
if (jclass_ByteBuffer == nullptr) { if (jclass_ByteBuffer == nullptr) {
if (LOGS_ENABLED) DEBUG_E("can't find java ByteBuffer class"); if (LOGS_ENABLED) DEBUG_E("can't find java ByteBuffer class");

View file

@ -22,6 +22,8 @@ bool LOGS_ENABLED = true;
bool LOGS_ENABLED = false; bool LOGS_ENABLED = false;
#endif #endif
bool REF_LOGS_ENABLED = false;
FileLog &FileLog::getInstance() { FileLog &FileLog::getInstance() {
static FileLog instance; static FileLog instance;
return instance; return instance;
@ -166,3 +168,43 @@ void FileLog::d(const char *message, ...) {
va_end(argptr); 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);
}

View file

@ -19,6 +19,8 @@ public:
static void e(const char *message, ...) __attribute__((format (printf, 1, 2))); static void e(const char *message, ...) __attribute__((format (printf, 1, 2)));
static void w(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 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(); static FileLog &getInstance();
@ -34,4 +36,7 @@ extern bool LOGS_ENABLED;
#define DEBUG_W FileLog::getInstance().w #define DEBUG_W FileLog::getInstance().w
#define DEBUG_D FileLog::getInstance().d #define DEBUG_D FileLog::getInstance().d
#define DEBUG_REF FileLog::getInstance().ref
#define DEBUG_DELREF FileLog::getInstance().delref
#endif #endif

View file

@ -14,6 +14,8 @@
#include "ConnectionsManager.h" #include "ConnectionsManager.h"
#include "BuffersStorage.h" #include "BuffersStorage.h"
static int buffersCount = 0;
NativeByteBuffer::NativeByteBuffer(uint32_t size) { NativeByteBuffer::NativeByteBuffer(uint32_t size) {
#ifdef ANDROID #ifdef ANDROID
if (jclass_ByteBuffer != nullptr) { if (jclass_ByteBuffer != nullptr) {
@ -27,6 +29,7 @@ NativeByteBuffer::NativeByteBuffer(uint32_t size) {
if (LOGS_ENABLED) DEBUG_E("can't create javaByteBuffer"); if (LOGS_ENABLED) DEBUG_E("can't create javaByteBuffer");
exit(1); exit(1);
} }
DEBUG_REF("nativebytebuffer");
jobject globalRef = env->NewGlobalRef(javaByteBuffer); jobject globalRef = env->NewGlobalRef(javaByteBuffer);
env->DeleteLocalRef(javaByteBuffer); env->DeleteLocalRef(javaByteBuffer);
javaByteBuffer = globalRef; javaByteBuffer = globalRef;
@ -43,6 +46,7 @@ NativeByteBuffer::NativeByteBuffer(uint32_t size) {
if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer"); if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer");
exit(1); exit(1);
} }
_limit = _capacity = size; _limit = _capacity = size;
} }
@ -64,6 +68,7 @@ NativeByteBuffer::~NativeByteBuffer() {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv"); if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1); exit(1);
} }
DEBUG_DELREF("nativebytebuffer");
env->DeleteGlobalRef(javaByteBuffer); env->DeleteGlobalRef(javaByteBuffer);
javaByteBuffer = nullptr; javaByteBuffer = nullptr;
} }
@ -694,6 +699,7 @@ jobject NativeByteBuffer::getJavaByteBuffer() {
if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer"); if (LOGS_ENABLED) DEBUG_E("can't allocate NativeByteBuffer buffer");
exit(1); exit(1);
} }
DEBUG_REF("nativebytebuffer");
jobject globalRef = env->NewGlobalRef(javaByteBuffer); jobject globalRef = env->NewGlobalRef(javaByteBuffer);
env->DeleteLocalRef(javaByteBuffer); env->DeleteLocalRef(javaByteBuffer);
javaByteBuffer = globalRef; javaByteBuffer = globalRef;

View file

@ -8,10 +8,12 @@
#include "ProxyCheckInfo.h" #include "ProxyCheckInfo.h"
#include "ConnectionsManager.h" #include "ConnectionsManager.h"
#include "FileLog.h"
ProxyCheckInfo::~ProxyCheckInfo() { ProxyCheckInfo::~ProxyCheckInfo() {
#ifdef ANDROID #ifdef ANDROID
if (ptr1 != nullptr) { if (ptr1 != nullptr) {
DEBUG_DELREF("tgnet (2) request ptr1");
jniEnv[instanceNum]->DeleteGlobalRef(ptr1); jniEnv[instanceNum]->DeleteGlobalRef(ptr1);
ptr1 = nullptr; ptr1 = nullptr;
} }

View file

@ -13,6 +13,7 @@
#include "ConnectionsManager.h" #include "ConnectionsManager.h"
#include "Datacenter.h" #include "Datacenter.h"
#include "Connection.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) { Request::Request(int32_t instance, int32_t token, ConnectionType type, uint32_t flags, uint32_t datacenter, onCompleteFunc completeFunc, onQuickAckFunc quickAckFunc, onWriteToSocketFunc writeToSocketFunc) {
requestToken = token; requestToken = token;
@ -29,14 +30,17 @@ Request::Request(int32_t instance, int32_t token, ConnectionType type, uint32_t
Request::~Request() { Request::~Request() {
#ifdef ANDROID #ifdef ANDROID
if (ptr1 != nullptr) { if (ptr1 != nullptr) {
DEBUG_DELREF("tgnet request ptr1");
jniEnv[instanceNum]->DeleteGlobalRef(ptr1); jniEnv[instanceNum]->DeleteGlobalRef(ptr1);
ptr1 = nullptr; ptr1 = nullptr;
} }
if (ptr2 != nullptr) { if (ptr2 != nullptr) {
DEBUG_DELREF("tgnet request ptr2");
jniEnv[instanceNum]->DeleteGlobalRef(ptr2); jniEnv[instanceNum]->DeleteGlobalRef(ptr2);
ptr2 = nullptr; ptr2 = nullptr;
} }
if (ptr3 != nullptr) { if (ptr3 != nullptr) {
DEBUG_DELREF("tgnet request ptr3");
jniEnv[instanceNum]->DeleteGlobalRef(ptr3); jniEnv[instanceNum]->DeleteGlobalRef(ptr3);
ptr3 = nullptr; ptr3 = nullptr;
} }

View file

@ -8,6 +8,7 @@
#include <stdio.h> #include <stdio.h>
#include "../../logging.h" #include "../../logging.h"
#include "JNIUtilities.h" #include "JNIUtilities.h"
#include "tgnet/FileLog.h"
extern JavaVM* sharedJVM; extern JavaVM* sharedJVM;
@ -25,6 +26,7 @@ AudioInputAndroid::AudioInputAndroid(){
jni::DoWithJNI([this](JNIEnv* env){ jni::DoWithJNI([this](JNIEnv* env){
jmethodID ctor=env->GetMethodID(jniClass, "<init>", "(J)V"); jmethodID ctor=env->GetMethodID(jniClass, "<init>", "(J)V");
jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this); jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this);
DEBUG_REF("AudioInputAndroid");
javaObject=env->NewGlobalRef(obj); javaObject=env->NewGlobalRef(obj);
env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2); env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2);
@ -38,6 +40,7 @@ AudioInputAndroid::~AudioInputAndroid(){
MutexGuard guard(mutex); MutexGuard guard(mutex);
jni::DoWithJNI([this](JNIEnv* env){ jni::DoWithJNI([this](JNIEnv* env){
env->CallVoidMethod(javaObject, releaseMethod); env->CallVoidMethod(javaObject, releaseMethod);
DEBUG_DELREF("AudioInputAndroid");
env->DeleteGlobalRef(javaObject); env->DeleteGlobalRef(javaObject);
javaObject=NULL; javaObject=NULL;
}); });

View file

@ -7,6 +7,7 @@
#include "AudioOutputAndroid.h" #include "AudioOutputAndroid.h"
#include <stdio.h> #include <stdio.h>
#include "../../logging.h" #include "../../logging.h"
#include "tgnet/FileLog.h"
extern JavaVM* sharedJVM; extern JavaVM* sharedJVM;
@ -30,6 +31,7 @@ AudioOutputAndroid::AudioOutputAndroid(){
jmethodID ctor=env->GetMethodID(jniClass, "<init>", "(J)V"); jmethodID ctor=env->GetMethodID(jniClass, "<init>", "(J)V");
jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this); jobject obj=env->NewObject(jniClass, ctor, (jlong)(intptr_t)this);
DEBUG_REF("AudioOutputAndroid");
javaObject=env->NewGlobalRef(obj); javaObject=env->NewGlobalRef(obj);
env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2); env->CallVoidMethod(javaObject, initMethod, 48000, 16, 1, 960*2);
@ -50,6 +52,7 @@ AudioOutputAndroid::~AudioOutputAndroid(){
} }
env->CallVoidMethod(javaObject, releaseMethod); env->CallVoidMethod(javaObject, releaseMethod);
DEBUG_DELREF("AudioOutputAndroid");
env->DeleteGlobalRef(javaObject); env->DeleteGlobalRef(javaObject);
javaObject=NULL; javaObject=NULL;

View file

@ -6,6 +6,7 @@
#include "JNIUtilities.h" #include "JNIUtilities.h"
#include "../../logging.h" #include "../../logging.h"
#include "../../PrivateDefines.h" #include "../../PrivateDefines.h"
#include "tgnet/FileLog.h"
using namespace tgvoip; using namespace tgvoip;
using namespace tgvoip::video; using namespace tgvoip::video;
@ -27,6 +28,7 @@ VideoSourceAndroid::VideoSourceAndroid(jobject jobj) : javaObject(jobj){
VideoSourceAndroid::~VideoSourceAndroid(){ VideoSourceAndroid::~VideoSourceAndroid(){
jni::DoWithJNI([this](JNIEnv* env){ jni::DoWithJNI([this](JNIEnv* env){
DEBUG_DELREF("VideoSourceAndroid");
env->DeleteGlobalRef(javaObject); env->DeleteGlobalRef(javaObject);
}); });
} }

View file

@ -381,9 +381,13 @@ void initWebRTC(JNIEnv *env) {
rtc::InitializeSSL(); rtc::InitializeSSL();
webrtcLoaded = true; webrtcLoaded = true;
DEBUG_REF("NativeInstanceClass");
NativeInstanceClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/NativeInstance"))); NativeInstanceClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/NativeInstance")));
DEBUG_REF("TrafficStatsClass");
TrafficStatsClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$TrafficStats"))); TrafficStatsClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$TrafficStats")));
DEBUG_REF("FingerprintClass");
FingerprintClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$Fingerprint"))); FingerprintClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$Fingerprint")));
DEBUG_REF("FinalStateClass");
FinalStateClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$FinalState"))); FinalStateClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$FinalState")));
FinalStateInitMethod = env->GetMethodID(FinalStateClass, "<init>", "([BLjava/lang/String;Lorg/telegram/messenger/voip/Instance$TrafficStats;Z)V"); FinalStateInitMethod = env->GetMethodID(FinalStateClass, "<init>", "([BLjava/lang/String;Lorg/telegram/messenger/voip/Instance$TrafficStats;Z)V");
} }

View file

@ -20,6 +20,7 @@
#include "libtgvoip/PrivateDefines.h" #include "libtgvoip/PrivateDefines.h"
#include "libtgvoip/logging.h" #include "libtgvoip/logging.h"
#include "../c_utils.h" #include "../c_utils.h"
#include "tgnet/FileLog.h"
#ifdef TGVOIP_HAS_CONFIG #ifdef TGVOIP_HAS_CONFIG
#include <tgvoip_config.h> #include <tgvoip_config.h>
@ -63,6 +64,7 @@ namespace tgvoip {
jlong VoIPController_nativeInit(JNIEnv *env, jobject thiz, jstring persistentStateFile) { jlong VoIPController_nativeInit(JNIEnv *env, jobject thiz, jstring persistentStateFile) {
ImplDataAndroid *impl = new ImplDataAndroid(); ImplDataAndroid *impl = new ImplDataAndroid();
DEBUG_REF("VoIPController_nativeInit");
impl->javaObject = env->NewGlobalRef(thiz); impl->javaObject = env->NewGlobalRef(thiz);
if (persistentStateFile) { if (persistentStateFile) {
impl->persistentStateFile = jni::JavaStringToStdString(env, persistentStateFile); impl->persistentStateFile = jni::JavaStringToStdString(env, persistentStateFile);
@ -123,6 +125,7 @@ namespace tgvoip {
ctlr->Stop(); ctlr->Stop();
std::vector<uint8_t> state = ctlr->GetPersistentState(); std::vector<uint8_t> state = ctlr->GetPersistentState();
delete ctlr; delete ctlr;
DEBUG_DELREF("VoIPController_nativeRelease");
env->DeleteGlobalRef(impl->javaObject); env->DeleteGlobalRef(impl->javaObject);
if (!impl->persistentStateFile.empty()) { if (!impl->persistentStateFile.empty()) {
FILE *f = fopen(impl->persistentStateFile.c_str(), "w"); FILE *f = fopen(impl->persistentStateFile.c_str(), "w");
@ -294,6 +297,7 @@ int tgvoipOnJNILoad(JavaVM *vm, JNIEnv *env) {
env->GetJavaVM(&sharedJVM); env->GetJavaVM(&sharedJVM);
if (!AudioInputAndroid::jniClass) { if (!AudioInputAndroid::jniClass) {
jclass cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioRecordJNI"); jclass cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioRecordJNI");
DEBUG_REF("AudioRecordJNI");
AudioInputAndroid::jniClass = (jclass) env->NewGlobalRef(cls); AudioInputAndroid::jniClass = (jclass) env->NewGlobalRef(cls);
AudioInputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V"); AudioInputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V");
AudioInputAndroid::releaseMethod = env->GetMethodID(cls, "release", "()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"); AudioInputAndroid::getEnabledEffectsMaskMethod = env->GetMethodID(cls, "getEnabledEffectsMask", "()I");
cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioTrackJNI"); cls = env->FindClass(TGVOIP_PACKAGE_PATH "/AudioTrackJNI");
DEBUG_REF("AudioTrackJNI");
AudioOutputAndroid::jniClass = (jclass) env->NewGlobalRef(cls); AudioOutputAndroid::jniClass = (jclass) env->NewGlobalRef(cls);
AudioOutputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V"); AudioOutputAndroid::initMethod = env->GetMethodID(cls, "init", "(IIII)V");
AudioOutputAndroid::releaseMethod = env->GetMethodID(cls, "release", "()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"); setSignalBarsMethod = env->GetMethodID(controller, "handleSignalBarsChange", "(I)V");
if (!jniUtilitiesClass) { if (!jniUtilitiesClass) {
DEBUG_REF("JNIUtilities");
jniUtilitiesClass = (jclass) env->NewGlobalRef(env->FindClass(TGVOIP_PACKAGE_PATH "/JNIUtilities")); jniUtilitiesClass = (jclass) env->NewGlobalRef(env->FindClass(TGVOIP_PACKAGE_PATH "/JNIUtilities"));
} }

View file

@ -6,9 +6,12 @@
namespace tgcalls { namespace tgcalls {
AndroidContext::AndroidContext(JNIEnv *env, jobject instance, bool screencast) { AndroidContext::AndroidContext(JNIEnv *env, jobject instance, bool screencast) {
DEBUG_REF("VideoCapturerDevice");
VideoCapturerDeviceClass = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/VideoCapturerDevice")); VideoCapturerDeviceClass = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/VideoCapturerDevice"));
jmethodID initMethodId = env->GetMethodID(VideoCapturerDeviceClass, "<init>", "(Z)V"); jmethodID initMethodId = env->GetMethodID(VideoCapturerDeviceClass, "<init>", "(Z)V");
DEBUG_REF("VideoCapturerDevice javaCapturer");
javaCapturer = env->NewGlobalRef(env->NewObject(VideoCapturerDeviceClass, initMethodId, screencast)); javaCapturer = env->NewGlobalRef(env->NewObject(VideoCapturerDeviceClass, initMethodId, screencast));
DEBUG_REF("VideoCapturerDevice javaInstance");
javaInstance = env->NewGlobalRef(instance); javaInstance = env->NewGlobalRef(instance);
} }
@ -17,17 +20,21 @@ AndroidContext::~AndroidContext() {
jmethodID onDestroyMethodId = env->GetMethodID(VideoCapturerDeviceClass, "onDestroy", "()V"); jmethodID onDestroyMethodId = env->GetMethodID(VideoCapturerDeviceClass, "onDestroy", "()V");
env->CallVoidMethod(javaCapturer, onDestroyMethodId); env->CallVoidMethod(javaCapturer, onDestroyMethodId);
DEBUG_DELREF("javaCapturer");
env->DeleteGlobalRef(javaCapturer); env->DeleteGlobalRef(javaCapturer);
javaCapturer = nullptr; javaCapturer = nullptr;
DEBUG_DELREF("VideoCapturerDeviceClass");
env->DeleteGlobalRef(VideoCapturerDeviceClass); env->DeleteGlobalRef(VideoCapturerDeviceClass);
if (javaInstance) { if (javaInstance) {
DEBUG_DELREF("javaInstance");
env->DeleteGlobalRef(javaInstance); env->DeleteGlobalRef(javaInstance);
} }
} }
void AndroidContext::setJavaInstance(JNIEnv *env, jobject instance) { void AndroidContext::setJavaInstance(JNIEnv *env, jobject instance) {
DEBUG_REF("setJavaInstance");
javaInstance = env->NewGlobalRef(instance); javaInstance = env->NewGlobalRef(instance);
} }

View file

@ -7,6 +7,8 @@
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/logging.h" #include "base/logging.h"
#include <tgnet/FileLog.h>
namespace base { namespace base {
namespace android { namespace android {
namespace { namespace {
@ -60,10 +62,14 @@ void JavaRef<jobject>::SetNewGlobalRef(JNIEnv* env, jobject obj) {
} else { } else {
DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread. DCHECK_EQ(env, AttachCurrentThread()); // Is |env| on correct thread.
} }
if (obj) if (obj) {
DEBUG_REF("scoped_java_ref.cc");
obj = env->NewGlobalRef(obj); obj = env->NewGlobalRef(obj);
if (obj_) }
if (obj_) {
DEBUG_DELREF("scoped_java_ref.cc");
env->DeleteGlobalRef(obj_); env->DeleteGlobalRef(obj_);
}
obj_ = obj; obj_ = obj;
} }
@ -77,6 +83,7 @@ void JavaRef<jobject>::ResetLocalRef(JNIEnv* env) {
void JavaRef<jobject>::ResetGlobalRef() { void JavaRef<jobject>::ResetGlobalRef() {
if (obj_) { if (obj_) {
DEBUG_DELREF("webrtc ResetGlobalRef");
AttachCurrentThread()->DeleteGlobalRef(obj_); AttachCurrentThread()->DeleteGlobalRef(obj_);
obj_ = nullptr; obj_ = nullptr;
} }

View file

@ -17,6 +17,7 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/platform_thread.h" #include "rtc_base/platform_thread.h"
#include "tgnet/FileLog.h"
#define TAG "HelpersAndroid" #define TAG "HelpersAndroid"
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #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) { jobject NewGlobalRef(JNIEnv* jni, jobject o) {
DEBUG_REF("webrtc new global ref");
jobject ret = jni->NewGlobalRef(o); jobject ret = jni->NewGlobalRef(o);
CHECK_EXCEPTION(jni) << "Error during NewGlobalRef"; CHECK_EXCEPTION(jni) << "Error during NewGlobalRef";
RTC_CHECK(ret); RTC_CHECK(ret);
@ -83,6 +85,7 @@ jobject NewGlobalRef(JNIEnv* jni, jobject o) {
} }
void DeleteGlobalRef(JNIEnv* jni, jobject o) { void DeleteGlobalRef(JNIEnv* jni, jobject o) {
DEBUG_DELREF("webrtc remove global ref");
jni->DeleteGlobalRef(o); jni->DeleteGlobalRef(o);
CHECK_EXCEPTION(jni) << "Error during DeleteGlobalRef"; CHECK_EXCEPTION(jni) << "Error during DeleteGlobalRef";
} }

View file

@ -17,6 +17,7 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
#include "rtc_base/platform_thread.h" #include "rtc_base/platform_thread.h"
#include "tgnet/FileLog.h"
namespace webrtc { namespace webrtc {
@ -44,6 +45,7 @@ void LoadClasses(JNIEnv* jni) {
RTC_LOG(LS_INFO) << "name: " << c.name; RTC_LOG(LS_INFO) << "name: " << c.name;
CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name; CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name;
RTC_CHECK(localRef) << c.name; RTC_CHECK(localRef) << c.name;
DEBUG_REF("webrtc 4 globalref");
jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef)); jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name; CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name;
RTC_CHECK(globalRef) << c.name; RTC_CHECK(globalRef) << c.name;
@ -53,6 +55,7 @@ void LoadClasses(JNIEnv* jni) {
void FreeClassReferences(JNIEnv* jni) { void FreeClassReferences(JNIEnv* jni) {
for (auto& c : loaded_classes) { for (auto& c : loaded_classes) {
DEBUG_DELREF("FreeClassReferences");
jni->DeleteGlobalRef(c.clazz); jni->DeleteGlobalRef(c.clazz);
c.clazz = nullptr; c.clazz = nullptr;
} }
@ -94,11 +97,13 @@ JvmThreadConnector::~JvmThreadConnector() {
// GlobalRef implementation. // GlobalRef implementation.
GlobalRef::GlobalRef(JNIEnv* jni, jobject object) GlobalRef::GlobalRef(JNIEnv* jni, jobject object)
: jni_(jni), j_object_(NewGlobalRef(jni, object)) { : jni_(jni), j_object_(NewGlobalRef(jni, object)) {
DEBUG_REF("webrtc jvm globalref");
RTC_LOG(LS_INFO) << "GlobalRef::ctor"; RTC_LOG(LS_INFO) << "GlobalRef::ctor";
} }
GlobalRef::~GlobalRef() { GlobalRef::~GlobalRef() {
RTC_LOG(LS_INFO) << "GlobalRef::dtor"; RTC_LOG(LS_INFO) << "GlobalRef::dtor";
DEBUG_DELREF("webrtc jvm globalref");
DeleteGlobalRef(jni_, j_object_); DeleteGlobalRef(jni_, j_object_);
} }

View file

@ -33,6 +33,7 @@ class ClassLoader {
public: public:
explicit ClassLoader(JNIEnv* env) explicit ClassLoader(JNIEnv* env)
: class_loader_(jni::Java_WebRtcClassLoader_getClassLoader(env)) { : class_loader_(jni::Java_WebRtcClassLoader_getClassLoader(env)) {
DEBUG_REF("webrtc class_loader");
class_loader_class_ = reinterpret_cast<jclass>( class_loader_class_ = reinterpret_cast<jclass>(
env->NewGlobalRef(env->FindClass("java/lang/ClassLoader"))); env->NewGlobalRef(env->FindClass("java/lang/ClassLoader")));
CHECK_EXCEPTION(env); CHECK_EXCEPTION(env);

View file

@ -19,6 +19,7 @@
#include <utility> #include <utility>
#include "sdk/android/native_api/jni/jvm.h" #include "sdk/android/native_api/jni/jvm.h"
#include "tgnet/FileLog.h"
namespace webrtc { namespace webrtc {
@ -182,9 +183,11 @@ class ScopedJavaGlobalRef : public JavaRef<T> {
: JavaRef<T>(other.Release()) {} : JavaRef<T>(other.Release()) {}
~ScopedJavaGlobalRef() { ~ScopedJavaGlobalRef() {
if (obj_ != nullptr) if (obj_ != nullptr) {
DEBUG_DELREF("ScopedJavaGlobalRef");
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_); AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
} }
}
ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete; ScopedJavaGlobalRef(const ScopedJavaGlobalRef&) = delete;
ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef&) = delete; ScopedJavaGlobalRef& operator=(const ScopedJavaGlobalRef&) = delete;
@ -192,13 +195,20 @@ class ScopedJavaGlobalRef : public JavaRef<T> {
void operator=(const JavaRef<T>& other) { void operator=(const JavaRef<T>& other) {
JNIEnv* env = AttachCurrentThreadIfNeeded(); JNIEnv* env = AttachCurrentThreadIfNeeded();
if (obj_ != nullptr) { if (obj_ != nullptr) {
DEBUG_DELREF("webrtc 3 delete global ref");
env->DeleteGlobalRef(obj_); 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) { void operator=(std::nullptr_t) {
if (obj_ != nullptr) { if (obj_ != nullptr) {
DEBUG_DELREF("webrtc 3 delete global ref");
AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_); AttachCurrentThreadIfNeeded()->DeleteGlobalRef(obj_);
} }
obj_ = nullptr; obj_ = nullptr;

View file

@ -12,6 +12,7 @@
#include <vector> #include <vector>
#include "sdk/android/native_api/jni/java_types.h" #include "sdk/android/native_api/jni/java_types.h"
#include "tgnet/FileLog.h"
namespace webrtc { namespace webrtc {
namespace jni { namespace jni {
@ -26,6 +27,7 @@ ScopedJavaLocalRef<jobject> NewDirectByteBuffer(JNIEnv* env,
} }
jobject NewGlobalRef(JNIEnv* jni, jobject o) { jobject NewGlobalRef(JNIEnv* jni, jobject o) {
DEBUG_REF("webrtc 2 new global ref");
jobject ret = jni->NewGlobalRef(o); jobject ret = jni->NewGlobalRef(o);
CHECK_EXCEPTION(jni) << "error during NewGlobalRef"; CHECK_EXCEPTION(jni) << "error during NewGlobalRef";
RTC_CHECK(ret); RTC_CHECK(ret);
@ -33,6 +35,7 @@ jobject NewGlobalRef(JNIEnv* jni, jobject o) {
} }
void DeleteGlobalRef(JNIEnv* jni, jobject o) { void DeleteGlobalRef(JNIEnv* jni, jobject o) {
DEBUG_DELREF("webrtc 2 delete global ref");
jni->DeleteGlobalRef(o); jni->DeleteGlobalRef(o);
CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef"; CHECK_EXCEPTION(jni) << "error during DeleteGlobalRef";
} }

View file

@ -802,6 +802,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager implements
mLayoutState.mScrapList = null; mLayoutState.mScrapList = null;
} }
protected int firstPosition() {
return 0;
}
private void updateAnchorInfoForLayout(RecyclerView.Recycler recycler, RecyclerView.State state, private void updateAnchorInfoForLayout(RecyclerView.Recycler recycler, RecyclerView.State state,
AnchorInfo anchorInfo) { AnchorInfo anchorInfo) {
if (updateAnchorFromPendingData(state, 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"); Log.d(TAG, "deciding anchor info for fresh state");
} }
anchorInfo.assignCoordinateFromPadding(); anchorInfo.assignCoordinateFromPadding();
anchorInfo.mPosition = mStackFromEnd ? state.getItemCount() - 1 : 0; anchorInfo.mPosition = mStackFromEnd ? state.getItemCount() - 1 : firstPosition();
} }
/** /**

View file

@ -493,6 +493,16 @@ public class AndroidUtilities {
} }
public static void recycleBitmaps(List<Bitmap> bitmapToRecycle) { public static void recycleBitmaps(List<Bitmap> 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()) { if (bitmapToRecycle != null && !bitmapToRecycle.isEmpty()) {
AndroidUtilities.runOnUIThread(() -> Utilities.globalQueue.postRunnable(() -> { AndroidUtilities.runOnUIThread(() -> Utilities.globalQueue.postRunnable(() -> {
for (int i = 0; i < bitmapToRecycle.size(); i++) { 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) { if (TextUtils.indexOf(s, '─') >= 0) {
s = new SpannableStringBuilder(s.toString().replace('─', ' ')); 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); Matcher m = pattern.matcher(s);
while (m.find()) { while (m.find()) {
int start = m.start(); 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) { public static CharSequence replaceCharSequence(String what, CharSequence from, CharSequence obj) {
SpannableStringBuilder spannableStringBuilder; SpannableStringBuilder spannableStringBuilder;
if (from instanceof SpannableStringBuilder) { if (from instanceof SpannableStringBuilder) {

View file

@ -103,13 +103,16 @@ public class AutoDeleteMediaTask {
} }
long lastUsageTime = Utilities.getLastUsageFileTime(file.file.getAbsolutePath()); long lastUsageTime = Utilities.getLastUsageFileTime(file.file.getAbsolutePath());
long timeLocal = time - seconds; 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) { if (needDelete) {
try { try {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
autoDeletedFiles++; autoDeletedFiles++;
autoDeletedFilesSize += file.file.length(); 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(); file.file.delete();
} catch (Exception exception) { } catch (Exception exception) {
FileLog.e(exception); FileLog.e(exception);

View file

@ -24,8 +24,8 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true; public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true; public static boolean CHECK_UPDATES = true;
public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29; public static boolean NO_SCOPED_STORAGE = Build.VERSION.SDK_INT <= 29;
public static int BUILD_VERSION = 3227; public static int BUILD_VERSION = 3236;
public static String BUILD_VERSION_STRING = "9.5.4"; public static String BUILD_VERSION_STRING = "9.5.5";
public static int APP_ID = 4; public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -33,6 +33,7 @@ public class FileLoadOperation {
private final static int FINISH_CODE_DEFAULT = 0; private final static int FINISH_CODE_DEFAULT = 0;
private final static int FINISH_CODE_FILE_ALREADY_EXIST = 1; private final static int FINISH_CODE_FILE_ALREADY_EXIST = 1;
public boolean preFinished;
FileLoadOperationStream stream; FileLoadOperationStream stream;
boolean streamPriority; boolean streamPriority;
@ -41,6 +42,7 @@ public class FileLoadOperation {
public static volatile DispatchQueue filesQueue = new DispatchQueue("writeFileQueue"); public static volatile DispatchQueue filesQueue = new DispatchQueue("writeFileQueue");
public static ImmutableByteArrayOutputStream filesQueueByteBuffer; public static ImmutableByteArrayOutputStream filesQueueByteBuffer;
private boolean forceSmallChunk; private boolean forceSmallChunk;
private Runnable fileWriteRunnable;
public void setStream(FileLoadOperationStream stream, boolean streamPriority, long streamOffset) { public void setStream(FileLoadOperationStream stream, boolean streamPriority, long streamOffset) {
this.stream = stream; this.stream = stream;
@ -48,6 +50,10 @@ public class FileLoadOperation {
this.streamPriority = streamPriority; this.streamPriority = streamPriority;
} }
public int getPositionInQueue() {
return getQueue().getPosition(this);
}
protected static class RequestInfo { protected static class RequestInfo {
public long requestStartTime; public long requestStartTime;
private int requestToken; private int requestToken;
@ -205,6 +211,7 @@ public class FileLoadOperation {
private FileLoaderPriorityQueue priorityQueue; private FileLoaderPriorityQueue priorityQueue;
public interface FileLoadOperationDelegate { public interface FileLoadOperationDelegate {
void didPreFinishLoading(FileLoadOperation operation, File finalFile);
void didFinishLoadingFile(FileLoadOperation operation, File finalFile); void didFinishLoadingFile(FileLoadOperation operation, File finalFile);
void didFailedLoadingFile(FileLoadOperation operation, int state); void didFailedLoadingFile(FileLoadOperation operation, int state);
void didChangedLoadProgress(FileLoadOperation operation, long uploadedSize, long totalSize); void didChangedLoadProgress(FileLoadOperation operation, long uploadedSize, long totalSize);
@ -521,7 +528,10 @@ public class FileLoadOperation {
if (save) { if (save) {
if (modified) { if (modified) {
ArrayList<FileLoadOperation.Range> rangesFinal = new ArrayList<>(ranges); ArrayList<FileLoadOperation.Range> rangesFinal = new ArrayList<>(ranges);
filesQueue.postRunnable(() -> { if (fileWriteRunnable != null) {
filesQueue.cancelRunnable(fileWriteRunnable);
}
filesQueue.postRunnable(fileWriteRunnable = () -> {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
try { try {
if (filePartsStream == null) { if (filePartsStream == null) {
@ -551,6 +561,8 @@ public class FileLoadOperation {
FileLog.e(e, false); FileLog.e(e, false);
if (AndroidUtilities.isENOSPC(e)) { if (AndroidUtilities.isENOSPC(e)) {
LaunchActivity.checkFreeDiscSpaceStatic(1); LaunchActivity.checkFreeDiscSpaceStatic(1);
} else if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
} }
} }
totalTime += System.currentTimeMillis() - time; totalTime += System.currentTimeMillis() - time;
@ -715,7 +727,7 @@ public class FileLoadOperation {
requestedBytesCount -= currentDownloadChunkSize; requestedBytesCount -= currentDownloadChunkSize;
removePart(notRequestedBytesRanges, priorityRequestInfo.offset, priorityRequestInfo.offset + currentDownloadChunkSize); removePart(notRequestedBytesRanges, priorityRequestInfo.offset, priorityRequestInfo.offset + currentDownloadChunkSize);
if (priorityRequestInfo.requestToken != 0) { if (priorityRequestInfo.requestToken != 0) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(priorityRequestInfo.requestToken, true); ConnectionsManager.getInstance(currentAccount).cancelRequest(priorityRequestInfo.requestToken, false);
requestsCount--; requestsCount--;
} }
if (BuildVars.DEBUG_VERSION) { if (BuildVars.DEBUG_VERSION) {
@ -884,6 +896,9 @@ public class FileLoadOperation {
if (AndroidUtilities.isENOSPC(e)) { if (AndroidUtilities.isENOSPC(e)) {
LaunchActivity.checkFreeDiscSpaceStatic(1); LaunchActivity.checkFreeDiscSpaceStatic(1);
FileLog.e(e, false); FileLog.e(e, false);
} else if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
FileLog.e(e, false);
} else { } else {
FileLog.e(e); FileLog.e(e);
} }
@ -1048,6 +1063,9 @@ public class FileLoadOperation {
if (AndroidUtilities.isENOSPC(e)) { if (AndroidUtilities.isENOSPC(e)) {
LaunchActivity.checkFreeDiscSpaceStatic(1); LaunchActivity.checkFreeDiscSpaceStatic(1);
FileLog.e(e, false); FileLog.e(e, false);
} else if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
FileLog.e(e, false);
} else { } else {
FileLog.e(e); FileLog.e(e);
} }
@ -1068,6 +1086,11 @@ public class FileLoadOperation {
LaunchActivity.checkFreeDiscSpaceStatic(1); LaunchActivity.checkFreeDiscSpaceStatic(1);
onFail(true, -1); onFail(true, -1);
return false; return false;
} else if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
FileLog.e(e, false);
onFail(true, -1);
return false;
} }
} }
if (fileOutputStream == null) { if (fileOutputStream == null) {
@ -1091,13 +1114,17 @@ public class FileLoadOperation {
try { try {
onFinishLoadingFile(false, FINISH_CODE_FILE_ALREADY_EXIST); onFinishLoadingFile(false, FINISH_CODE_FILE_ALREADY_EXIST);
if (pathSaveData != null) { if (pathSaveData != null) {
delegate.saveFilePath(pathSaveData, null); delegate.saveFilePath(pathSaveData, cacheFileFinal);
} }
} catch (Exception e) { } catch (Exception e) {
FileLog.e(e, false); FileLog.e(e, false);
if (AndroidUtilities.isENOSPC(e)) { if (AndroidUtilities.isENOSPC(e)) {
LaunchActivity.checkFreeDiscSpaceStatic(1); LaunchActivity.checkFreeDiscSpaceStatic(1);
onFail(true, -1); onFail(true, -1);
} if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
onFail(true, -1);
return false;
} else { } else {
onFail(true, 0); onFail(true, 0);
} }
@ -1153,7 +1180,7 @@ public class FileLoadOperation {
cancel(false); cancel(false);
} }
public void cancel(boolean deleteFiles) { private void cancel(boolean deleteFiles) {
Utilities.stageQueue.postRunnable(() -> { Utilities.stageQueue.postRunnable(() -> {
if (state != stateFinished && state != stateFailed) { if (state != stateFinished && state != stateFailed) {
cancelRequests(); cancelRequests();
@ -1214,7 +1241,7 @@ public class FileLoadOperation {
for (int a = 0; a < requestInfos.size(); a++) { for (int a = 0; a < requestInfos.size(); a++) {
RequestInfo requestInfo = requestInfos.get(a); RequestInfo requestInfo = requestInfos.get(a);
if (requestInfo.requestToken != 0) { 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 cacheFilePartsFinal = cacheFileParts;
final File cacheFilePreloadFinal = cacheFilePreload; final File cacheFilePreloadFinal = cacheFilePreload;
final File cacheFileTempFinal = cacheFileTemp; final File cacheFileTempFinal = cacheFileTemp;
Utilities.globalQueue.postRunnable(() -> { filesQueue.postRunnable(() -> {
if (cacheIvTempFinal != null) { if (cacheIvTempFinal != null) {
cacheIvTempFinal.delete(); cacheIvTempFinal.delete();
} }
@ -1449,6 +1476,7 @@ public class FileLoadOperation {
cacheIvTemp = null; cacheIvTemp = null;
cacheFileParts = null; cacheFileParts = null;
cacheFilePreload = null; cacheFilePreload = null;
delegate.didPreFinishLoading(FileLoadOperation.this, cacheFileFinal);
} }
} }
@ -1782,6 +1810,9 @@ public class FileLoadOperation {
FileLog.e(e, !AndroidUtilities.isFilNotFoundException(e) && !AndroidUtilities.isENOSPC(e)); FileLog.e(e, !AndroidUtilities.isFilNotFoundException(e) && !AndroidUtilities.isENOSPC(e));
if (AndroidUtilities.isENOSPC(e)) { if (AndroidUtilities.isENOSPC(e)) {
onFail(false, -1); onFail(false, -1);
} else if (AndroidUtilities.isEROFS(e)) {
SharedConfig.checkSdCard(cacheFileFinal);
onFail(true, -1);
} else { } else {
onFail(false, 0); onFail(false, 0);
} }
@ -1844,7 +1875,11 @@ public class FileLoadOperation {
if (delegate != null) { if (delegate != null) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
long time = startTime == 0 ? 0 : (System.currentTimeMillis() - startTime); 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) { if (thread) {
Utilities.stageQueue.postRunnable(() -> delegate.didFailedLoadingFile(FileLoadOperation.this, reason)); Utilities.stageQueue.postRunnable(() -> delegate.didFailedLoadingFile(FileLoadOperation.this, reason));
@ -1868,7 +1903,7 @@ public class FileLoadOperation {
continue; continue;
} }
if (info.requestToken != 0) { if (info.requestToken != 0) {
ConnectionsManager.getInstance(currentAccount).cancelRequest(info.requestToken, true); ConnectionsManager.getInstance(currentAccount).cancelRequest(info.requestToken, false);
} }
} }
requestInfos.clear(); requestInfos.clear();
@ -1904,7 +1939,7 @@ public class FileLoadOperation {
if (requestingReference) { if (requestingReference) {
return; return;
} }
clearOperaion(requestInfo, false); clearOperaion(null, false);
requestingReference = true; requestingReference = true;
if (parentObject instanceof MessageObject) { if (parentObject instanceof MessageObject) {
MessageObject messageObject = (MessageObject) parentObject; MessageObject messageObject = (MessageObject) parentObject;
@ -1912,12 +1947,19 @@ public class FileLoadOperation {
parentObject = messageObject.messageOwner.media.webpage; 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); FileRefController.getInstance(currentAccount).requestReference(parentObject, location, this, requestInfo);
} }
protected void startDownloadRequest() { protected void startDownloadRequest() {
if (paused || reuploadingCdn || if (BuildVars.DEBUG_PRIVATE_VERSION) {
state != stateDownloading || 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 && ( streamPriorityStartOffset == 0 && (
!nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) || !nextPartWasPreloaded && (requestInfos.size() + delayedRequestInfos.size() >= currentMaxDownloadRequests) ||
isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0))) { isPreloadVideoOperation && (requestedBytesCount > preloadMaxBytes || moovFound != 0 && requestInfos.size() > 0))) {
@ -2085,7 +2127,7 @@ public class FileLoadOperation {
return; return;
} }
if (BuildVars.LOGS_ENABLED) { 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 (requestInfo == priorityRequestInfo) {
if (BuildVars.DEBUG_VERSION) { if (BuildVars.DEBUG_VERSION) {
@ -2197,6 +2239,9 @@ public class FileLoadOperation {
processRequestResult(requestInfo, error); processRequestResult(requestInfo, error);
} }
}, null, null, flags, datacenterId, connectionType, isLast); }, null, null, flags, datacenterId, connectionType, isLast);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("debug_loading: " + cacheFileFinal.getName() + " send reqId " + requestInfo.requestToken);
}
requestsCount++; requestsCount++;
} }
} }

View file

@ -204,7 +204,7 @@ public class FileLoader extends BaseController {
filePathDatabase = new FilePathDatabase(instance); filePathDatabase = new FilePathDatabase(instance);
for (int i = 0; i < smallFilesQueue.length; i++) { for (int i = 0; i < smallFilesQueue.length; i++) {
smallFilesQueue[i] = new FileLoaderPriorityQueue("smallFilesQueue dc" + (i + 1), 5); 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(); dumpFilesQueue();
} }
@ -667,11 +667,9 @@ public class FileLoader extends BaseController {
getDownloadController().startDownloadFile(document, (MessageObject) parentObject); 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); priority = getPriorityValue(priority);
if (operation != null) { if (operation != null) {
@ -684,6 +682,7 @@ public class FileLoader extends BaseController {
operation.getQueue().add(operation); operation.getQueue().add(operation);
operation.updateProgress(); operation.updateProgress();
operation.getQueue().checkLoadingOperations(); operation.getQueue().checkLoadingOperations();
FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount);
return operation; return operation;
} }
@ -734,18 +733,11 @@ public class FileLoader extends BaseController {
} }
FileLoaderPriorityQueue loaderQueue; FileLoaderPriorityQueue loaderQueue;
int index = Utilities.clamp(operation.getDatacenterId() - 1, 4, 0); 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]; loaderQueue = largeFilesQueue[index];
} else { } else {
loaderQueue = smallFilesQueue[index]; 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; String storeFileName = fileName;
@ -804,6 +796,20 @@ public class FileLoader extends BaseController {
final int finalType = type; final int finalType = type;
FileLoadOperation.FileLoadOperationDelegate fileLoadOperationDelegate = new FileLoadOperation.FileLoadOperationDelegate() { 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 @Override
public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) { public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) {
if (!operation.isPreloadVideoOperation() && operation.isPreloadFinished()) { if (!operation.isPreloadVideoOperation() && operation.isPreloadFinished()) {
@ -864,16 +870,16 @@ public class FileLoader extends BaseController {
}; };
operation.setDelegate(fileLoadOperationDelegate); operation.setDelegate(fileLoadOperationDelegate);
loadOperationPaths.put(fileName, operation); loadOperationPaths.put(finalFileName, operation);
operation.setPriority(priority); operation.setPriority(priority);
operation.setStream(stream, streamPriority, streamOffset); operation.setStream(stream, streamPriority, streamOffset);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document));
}
loaderQueue.add(operation); loaderQueue.add(operation);
loaderQueue.checkLoadingOperations(); 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; return operation;
} }
@ -1681,8 +1687,8 @@ public class FileLoader extends BaseController {
Runnable dumpFilesQueueRunnable = () -> { Runnable dumpFilesQueueRunnable = () -> {
for (int i = 0; i < smallFilesQueue.length; i++) { for (int i = 0; i < smallFilesQueue.length; i++) {
if (smallFilesQueue[i].allOperations.size() > 0 || largeFilesQueue[i].allOperations.size() > 0) { if (smallFilesQueue[i].getCount() > 0 || largeFilesQueue[i].getCount() > 0) {
FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].allOperations.size() + " large_operations=" + largeFilesQueue[i].allOperations.size()); FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].getCount() + " large_operations=" + largeFilesQueue[i].getCount());
} }
} }
dumpFilesQueue(); dumpFilesQueue();

View file

@ -3,14 +3,13 @@ package org.telegram.messenger;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects;
public class FileLoaderPriorityQueue { public class FileLoaderPriorityQueue {
private final int maxActiveOperationsCount; private final int maxActiveOperationsCount;
String name; String name;
ArrayList<FileLoadOperation> allOperations = new ArrayList<>(); private ArrayList<FileLoadOperation> allOperations = new ArrayList<>();
private int PRIORITY_VALUE_MAX = (1 << 20); private int PRIORITY_VALUE_MAX = (1 << 20);
private int PRIORITY_VALUE_NORMAL = (1 << 16); private int PRIORITY_VALUE_NORMAL = (1 << 16);
@ -27,7 +26,7 @@ public class FileLoaderPriorityQueue {
} }
int index = -1; int index = -1;
for (int i = 0; i < allOperations.size(); i++) { 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); allOperations.remove(i);
i--; i--;
} }
@ -49,14 +48,16 @@ public class FileLoaderPriorityQueue {
if (operation == null) { if (operation == null) {
return; return;
} }
allOperations.remove(operation); if (allOperations.remove(operation)) {
operation.cancel(); operation.cancel();
} }
}
public void checkLoadingOperations() { public void checkLoadingOperations() {
int activeCount = 0; int activeCount = 0;
int lastPriority = 0; int lastPriority = 0;
boolean pauseAllNextOperations = false; boolean pauseAllNextOperations = false;
int max = maxActiveOperationsCount;
for (int i = 0; i < allOperations.size(); i++) { for (int i = 0; i < allOperations.size(); i++) {
FileLoadOperation operation = allOperations.get(i); FileLoadOperation operation = allOperations.get(i);
if (i > 0 && !pauseAllNextOperations) { if (i > 0 && !pauseAllNextOperations) {
@ -64,7 +65,11 @@ public class FileLoaderPriorityQueue {
pauseAllNextOperations = true; pauseAllNextOperations = true;
} }
} }
if (!pauseAllNextOperations && i < maxActiveOperationsCount) { if (operation.preFinished) {
//operation will not use connections
//just skip
max++;
} else if (!pauseAllNextOperations && i < max) {
operation.start(); operation.start();
activeCount++; activeCount++;
} else { } else {
@ -87,4 +92,11 @@ public class FileLoaderPriorityQueue {
allOperations.remove(operation); allOperations.remove(operation);
} }
public int getCount() {
return allOperations.size();
}
public int getPosition(FileLoadOperation fileLoadOperation) {
return allOperations.indexOf(fileLoadOperation);
}
} }

View file

@ -170,7 +170,7 @@ public class FilePathDatabase {
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]); FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]);
} }
} }
} catch (SQLiteException e) { } catch (Throwable e) {
FileLog.e(e); FileLog.e(e);
} finally { } finally {
if (cursor != null) { if (cursor != null) {
@ -287,10 +287,11 @@ public class FilePathDatabase {
MessageObject messageObject = arrayListFinal.get(i); MessageObject messageObject = arrayListFinal.get(i);
messageObject.checkMediaExistance(false); messageObject.checkMediaExistance(false);
} }
} catch (Exception e) { } catch (Throwable e) {
e.printStackTrace(); FileLog.e(e);
} } finally {
syncLatch.countDown(); syncLatch.countDown();
}
}); });
try { try {
@ -332,8 +333,9 @@ public class FilePathDatabase {
} }
} catch (Exception e) { } catch (Exception e) {
FileLog.e(e); FileLog.e(e);
} } finally {
syncLatch.countDown(); syncLatch.countDown();
}
}); });
try { try {
@ -417,7 +419,7 @@ public class FilePathDatabase {
for (int i = 0; i < filesToRemove.size(); i++) { 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(); 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); FileLog.e(e);
} finally { } finally {
database.commitTransaction(); database.commitTransaction();
@ -443,10 +445,11 @@ public class FilePathDatabase {
list.add(keepMediaFiles.get(i)); list.add(keepMediaFiles.get(i));
} }
} }
} catch (Exception e) { } catch (Throwable e) {
FileLog.e(e); FileLog.e(e);
} } finally {
syncLatch.countDown(); syncLatch.countDown();
}
}); });
try { try {
syncLatch.await(); syncLatch.await();

View file

@ -22,7 +22,6 @@ public class FileRefController extends BaseController {
private static class CachedResult { private static class CachedResult {
private TLObject response; private TLObject response;
private long lastQueryTime;
private long firstQueryTime; private long firstQueryTime;
} }
@ -124,7 +123,7 @@ public class FileRefController extends BaseController {
String locationKey; String locationKey;
TLRPC.InputFileLocation location; TLRPC.InputFileLocation location;
if (BuildVars.LOGS_ENABLED) { 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) { if (args[0] instanceof TLRPC.TL_inputSingleMedia) {
TLRPC.TL_inputSingleMedia req = (TLRPC.TL_inputSingleMedia) args[0]; TLRPC.TL_inputSingleMedia req = (TLRPC.TL_inputSingleMedia) args[0];
@ -291,7 +290,7 @@ public class FileRefController extends BaseController {
cleanupCache(); cleanupCache();
CachedResult cachedResult = getCachedResponse(cacheKey); CachedResult cachedResult = getCachedResponse(cacheKey);
if (cachedResult != null) { if (cachedResult != null) {
if (!onRequestComplete(locationKey, parentKey, cachedResult.response, false, true)) { if (!onRequestComplete(locationKey, parentKey, cachedResult.response, null,false, true)) {
responseCache.remove(locationKey); responseCache.remove(locationKey);
} else { } else {
return; return;
@ -299,21 +298,34 @@ public class FileRefController extends BaseController {
} else { } else {
cachedResult = getCachedResponse(parentKey); cachedResult = getCachedResponse(parentKey);
if (cachedResult != null) { if (cachedResult != null) {
if (!onRequestComplete(locationKey, parentKey, cachedResult.response, false, true)) { if (!onRequestComplete(locationKey, parentKey, cachedResult.response, null, false, true)) {
responseCache.remove(parentKey); responseCache.remove(parentKey);
} else { } else {
return; return;
} }
} }
} }
requestReferenceFromServer(parentObject, locationKey, parentKey, args); requestReferenceFromServer(parentObject, locationKey, parentKey, args);
} }
private void broadcastWaitersData(ArrayList<Waiter> 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<Waiter> waiters, TLObject response, TLRPC.TL_error error) {
for (int a = 0, N = waiters.size(); a < N; a++) { for (int a = 0, N = waiters.size(); a < N; a++) {
Waiter waiter = waiters.get(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(); waiters.clear();
} }
@ -328,22 +340,22 @@ public class FileRefController extends BaseController {
getMediaDataController().processLoadedPremiumPromo(r, date, false); 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) { } else if (parentObject instanceof TLRPC.TL_availableReaction) {
TLRPC.TL_messages_getAvailableReactions req = new TLRPC.TL_messages_getAvailableReactions(); TLRPC.TL_messages_getAvailableReactions req = new TLRPC.TL_messages_getAvailableReactions();
req.hash = 0; 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) { } else if (parentObject instanceof TLRPC.BotInfo) {
TLRPC.BotInfo botInfo = (TLRPC.BotInfo) parentObject; TLRPC.BotInfo botInfo = (TLRPC.BotInfo) parentObject;
TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser(); TLRPC.TL_users_getFullUser req = new TLRPC.TL_users_getFullUser();
req.id = getMessagesController().getInputUser(botInfo.user_id); 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) { } else if (parentObject instanceof TLRPC.TL_attachMenuBot) {
TLRPC.TL_attachMenuBot bot = (TLRPC.TL_attachMenuBot) parentObject; TLRPC.TL_attachMenuBot bot = (TLRPC.TL_attachMenuBot) parentObject;
TLRPC.TL_messages_getAttachMenuBot req = new TLRPC.TL_messages_getAttachMenuBot(); TLRPC.TL_messages_getAttachMenuBot req = new TLRPC.TL_messages_getAttachMenuBot();
req.bot = getMessagesController().getInputUser(bot.bot_id); 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) { } else if (parentObject instanceof MessageObject) {
MessageObject messageObject = (MessageObject) parentObject; MessageObject messageObject = (MessageObject) parentObject;
long channelId = messageObject.getChannelId(); long channelId = messageObject.getChannelId();
@ -351,16 +363,16 @@ public class FileRefController extends BaseController {
TLRPC.TL_messages_getScheduledMessages req = new TLRPC.TL_messages_getScheduledMessages(); TLRPC.TL_messages_getScheduledMessages req = new TLRPC.TL_messages_getScheduledMessages();
req.peer = getMessagesController().getInputPeer(messageObject.getDialogId()); req.peer = getMessagesController().getInputPeer(messageObject.getDialogId());
req.id.add(messageObject.getRealId()); 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) { } else if (channelId != 0) {
TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages();
req.channel = getMessagesController().getInputChannel(channelId); req.channel = getMessagesController().getInputChannel(channelId);
req.id.add(messageObject.getRealId()); 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 { } else {
TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages();
req.id.add(messageObject.getRealId()); 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) { } else if (parentObject instanceof TLRPC.TL_wallPaper) {
TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) parentObject; TLRPC.TL_wallPaper wallPaper = (TLRPC.TL_wallPaper) parentObject;
@ -369,7 +381,7 @@ public class FileRefController extends BaseController {
inputWallPaper.id = wallPaper.id; inputWallPaper.id = wallPaper.id;
inputWallPaper.access_hash = wallPaper.access_hash; inputWallPaper.access_hash = wallPaper.access_hash;
req.wallpaper = inputWallPaper; 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) { } else if (parentObject instanceof TLRPC.TL_theme) {
TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject; TLRPC.TL_theme theme = (TLRPC.TL_theme) parentObject;
TLRPC.TL_account_getTheme req = new TLRPC.TL_account_getTheme(); 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; inputTheme.access_hash = theme.access_hash;
req.theme = inputTheme; req.theme = inputTheme;
req.format = "android"; 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) { } else if (parentObject instanceof TLRPC.WebPage) {
TLRPC.WebPage webPage = (TLRPC.WebPage) parentObject; TLRPC.WebPage webPage = (TLRPC.WebPage) parentObject;
TLRPC.TL_messages_getWebPage req = new TLRPC.TL_messages_getWebPage(); TLRPC.TL_messages_getWebPage req = new TLRPC.TL_messages_getWebPage();
req.url = webPage.url; req.url = webPage.url;
req.hash = 0; 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) { } else if (parentObject instanceof TLRPC.User) {
TLRPC.User user = (TLRPC.User) parentObject; TLRPC.User user = (TLRPC.User) parentObject;
TLRPC.TL_users_getUsers req = new TLRPC.TL_users_getUsers(); TLRPC.TL_users_getUsers req = new TLRPC.TL_users_getUsers();
req.id.add(getMessagesController().getInputUser(user)); 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) { } else if (parentObject instanceof TLRPC.Chat) {
TLRPC.Chat chat = (TLRPC.Chat) parentObject; TLRPC.Chat chat = (TLRPC.Chat) parentObject;
if (chat instanceof TLRPC.TL_chat) { if (chat instanceof TLRPC.TL_chat) {
TLRPC.TL_messages_getChats req = new TLRPC.TL_messages_getChats(); TLRPC.TL_messages_getChats req = new TLRPC.TL_messages_getChats();
req.id.add(chat.id); 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) { } else if (chat instanceof TLRPC.TL_channel) {
TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels(); TLRPC.TL_channels_getChannels req = new TLRPC.TL_channels_getChannels();
req.id.add(MessagesController.getInputChannel(chat)); 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) { } else if (parentObject instanceof String) {
String string = (String) parentObject; String string = (String) parentObject;
if ("wallpaper".equals(string)) { if ("wallpaper".equals(string)) {
if (wallpaperWaiters.isEmpty()) { if (wallpaperWaiters.isEmpty()) {
TLRPC.TL_account_getWallPapers req = new TLRPC.TL_account_getWallPapers(); 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)); wallpaperWaiters.add(new Waiter(locationKey, parentKey));
} else if (string.startsWith("gif")) { } else if (string.startsWith("gif")) {
if (savedGifsWaiters.isEmpty()) { if (savedGifsWaiters.isEmpty()) {
TLRPC.TL_messages_getSavedGifs req = new TLRPC.TL_messages_getSavedGifs(); 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)); savedGifsWaiters.add(new Waiter(locationKey, parentKey));
} else if ("recent".equals(string)) { } else if ("recent".equals(string)) {
if (recentStickersWaiter.isEmpty()) { if (recentStickersWaiter.isEmpty()) {
TLRPC.TL_messages_getRecentStickers req = new TLRPC.TL_messages_getRecentStickers(); 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)); recentStickersWaiter.add(new Waiter(locationKey, parentKey));
} else if ("fav".equals(string)) { } else if ("fav".equals(string)) {
if (favStickersWaiter.isEmpty()) { if (favStickersWaiter.isEmpty()) {
TLRPC.TL_messages_getFavedStickers req = new TLRPC.TL_messages_getFavedStickers(); 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)); favStickersWaiter.add(new Waiter(locationKey, parentKey));
} else if ("update".equals(string)) { } else if ("update".equals(string)) {
@ -437,7 +449,7 @@ public class FileRefController extends BaseController {
if (req.source == null) { if (req.source == null) {
req.source = ""; 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_")) { } else if (string.startsWith("avatar_")) {
long id = Utilities.parseLong(string); long id = Utilities.parseLong(string);
if (id > 0) { if (id > 0) {
@ -446,7 +458,7 @@ public class FileRefController extends BaseController {
req.offset = 0; req.offset = 0;
req.max_id = 0; req.max_id = 0;
req.user_id = getMessagesController().getInputUser(id); 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 { } else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search(); TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.filter = new TLRPC.TL_inputMessagesFilterChatPhotos(); req.filter = new TLRPC.TL_inputMessagesFilterChatPhotos();
@ -454,7 +466,7 @@ public class FileRefController extends BaseController {
req.offset_id = 0; req.offset_id = 0;
req.q = ""; req.q = "";
req.peer = getMessagesController().getInputPeer(id); 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_")) { } else if (string.startsWith("sent_")) {
String[] params = string.split("_"); String[] params = string.split("_");
@ -464,11 +476,11 @@ public class FileRefController extends BaseController {
TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages(); TLRPC.TL_channels_getMessages req = new TLRPC.TL_channels_getMessages();
req.channel = getMessagesController().getInputChannel(channelId); req.channel = getMessagesController().getInputChannel(channelId);
req.id.add(Utilities.parseInt(params[2])); 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 { } else {
TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages(); TLRPC.TL_messages_getMessages req = new TLRPC.TL_messages_getMessages();
req.id.add(Utilities.parseInt(params[2])); 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 { } else {
sendErrorToObject(args, 0); sendErrorToObject(args, 0);
@ -482,18 +494,18 @@ public class FileRefController extends BaseController {
req.stickerset = new TLRPC.TL_inputStickerSetID(); req.stickerset = new TLRPC.TL_inputStickerSetID();
req.stickerset.id = stickerSet.set.id; req.stickerset.id = stickerSet.set.id;
req.stickerset.access_hash = stickerSet.set.access_hash; 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) { } else if (parentObject instanceof TLRPC.StickerSetCovered) {
TLRPC.StickerSetCovered stickerSet = (TLRPC.StickerSetCovered) parentObject; TLRPC.StickerSetCovered stickerSet = (TLRPC.StickerSetCovered) parentObject;
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = new TLRPC.TL_inputStickerSetID(); req.stickerset = new TLRPC.TL_inputStickerSetID();
req.stickerset.id = stickerSet.set.id; req.stickerset.id = stickerSet.set.id;
req.stickerset.access_hash = stickerSet.set.access_hash; 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) { } else if (parentObject instanceof TLRPC.InputStickerSet) {
TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet(); TLRPC.TL_messages_getStickerSet req = new TLRPC.TL_messages_getStickerSet();
req.stickerset = (TLRPC.InputStickerSet) parentObject; 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 { } else {
sendErrorToObject(args, 0); sendErrorToObject(args, 0);
} }
@ -624,18 +636,35 @@ public class FileRefController extends BaseController {
getConnectionsManager().sendRequest(req, (RequestDelegate) requester.args[1]); getConnectionsManager().sendRequest(req, (RequestDelegate) requester.args[1]);
} else if (requester.args[1] instanceof FileLoadOperation) { } else if (requester.args[1] instanceof FileLoadOperation) {
FileLoadOperation fileLoadOperation = (FileLoadOperation) requester.args[1]; FileLoadOperation fileLoadOperation = (FileLoadOperation) requester.args[1];
String oldRef = null;
String newRef = null;
if (locationReplacement != null) { if (locationReplacement != null) {
if (fromCache && isSameReference(fileLoadOperation.location.file_reference, locationReplacement.file_reference)) { if (fromCache && isSameReference(fileLoadOperation.location.file_reference, locationReplacement.file_reference)) {
return false; return false;
} }
if (BuildVars.LOGS_ENABLED) {
oldRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference);
}
fileLoadOperation.location = locationReplacement; fileLoadOperation.location = locationReplacement;
if (BuildVars.LOGS_ENABLED) {
newRef = Utilities.bytesToHex(fileLoadOperation.location.file_reference);
}
} else { } else {
if (fromCache && isSameReference(requester.location.file_reference, file_reference)) { if (fromCache && isSameReference(requester.location.file_reference, file_reference)) {
return false; 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; fileLoadOperation.requestingReference = false;
if (BuildVars.LOGS_ENABLED) {
FileLog.d("debug_loading: " + fileLoadOperation.getCacheFileFinal().getName() + " " + oldRef + " " + newRef + " reference updated resume download");
}
fileLoadOperation.startDownloadRequest(); fileLoadOperation.startDownloadRequest();
} }
return true; return true;
@ -665,26 +694,16 @@ public class FileRefController extends BaseController {
TLRPC.TL_messages_getAttachedStickers req = (TLRPC.TL_messages_getAttachedStickers) args[0]; TLRPC.TL_messages_getAttachedStickers req = (TLRPC.TL_messages_getAttachedStickers) args[0];
getConnectionsManager().sendRequest(req, (RequestDelegate) args[1]); getConnectionsManager().sendRequest(req, (RequestDelegate) args[1]);
} else { } 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) { if (args[1] instanceof FileLoadOperation) {
FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1]; FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1];
fileLoadOperation.requestingReference = false; fileLoadOperation.requestingReference = false;
FileLog.e("debug_loading: " + fileLoadOperation.getCacheFileFinal().getName() + "reference can't update: fail operation ");
fileLoadOperation.onFail(false, 0); 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; boolean found = false;
String cacheKey = parentKey; String cacheKey = parentKey;
if (response instanceof TLRPC.TL_help_premiumPromo) { if (response instanceof TLRPC.TL_help_premiumPromo) {
@ -706,7 +725,7 @@ public class FileRefController extends BaseController {
if (requester.completed) { if (requester.completed) {
continue; continue;
} }
if (onRequestComplete(requester.locationKey, null, response, cache && !found, fromCache)) { if (onRequestComplete(requester.locationKey, null, response, error, cache && !found, fromCache)) {
found = true; found = true;
} }
} }
@ -729,6 +748,13 @@ public class FileRefController extends BaseController {
if (requester.completed) { if (requester.completed) {
continue; 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) { if (requester.location instanceof TLRPC.TL_inputFileLocation || requester.location instanceof TLRPC.TL_inputPeerPhotoFileLocation) {
locationReplacement = new TLRPC.InputFileLocation[1]; locationReplacement = new TLRPC.InputFileLocation[1];
needReplacement = new boolean[1]; needReplacement = new boolean[1];
@ -768,6 +794,10 @@ public class FileRefController extends BaseController {
FileLog.d("file ref not found in messages, replacing message"); 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) { } else if (response instanceof TLRPC.TL_help_premiumPromo) {
TLRPC.TL_help_premiumPromo premiumPromo = (TLRPC.TL_help_premiumPromo) response; TLRPC.TL_help_premiumPromo premiumPromo = (TLRPC.TL_help_premiumPromo) response;
@ -1007,7 +1037,7 @@ public class FileRefController extends BaseController {
ArrayList<String> keysToDelete = null; ArrayList<String> keysToDelete = null;
for (HashMap.Entry<String, CachedResult> entry : responseCache.entrySet()) { for (HashMap.Entry<String, CachedResult> entry : responseCache.entrySet()) {
CachedResult cachedResult = entry.getValue(); 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) { if (keysToDelete == null) {
keysToDelete = new ArrayList<>(); keysToDelete = new ArrayList<>();
} }
@ -1023,7 +1053,7 @@ public class FileRefController extends BaseController {
private CachedResult getCachedResponse(String key) { private CachedResult getCachedResponse(String key) {
CachedResult cachedResult = responseCache.get(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); responseCache.remove(key);
cachedResult = null; cachedResult = null;
} }
@ -1035,10 +1065,9 @@ public class FileRefController extends BaseController {
if (cachedResult == null) { if (cachedResult == null) {
cachedResult = new CachedResult(); cachedResult = new CachedResult();
cachedResult.response = response; cachedResult.response = response;
cachedResult.firstQueryTime = SystemClock.uptimeMillis(); cachedResult.firstQueryTime = System.currentTimeMillis();
responseCache.put(key, cachedResult); responseCache.put(key, cachedResult);
} }
cachedResult.lastQueryTime = SystemClock.uptimeMillis();
} }
private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) { private byte[] getFileReference(TLRPC.Document document, TLRPC.InputFileLocation location, boolean[] needReplacement, TLRPC.InputFileLocation[] replacement) {

View file

@ -1433,52 +1433,8 @@ public class ImageLoader {
Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable); Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable);
file.close(); file.close();
} else { } 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) { if (image == null) {
FileInputStream is; FileInputStream is;
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " try get image from stream ");
}
if (secureDocumentKey != null) { if (secureDocumentKey != null) {
is = new EncryptedFileInputStream(cacheFileFinal, secureDocumentKey); is = new EncryptedFileInputStream(cacheFileFinal, secureDocumentKey);
} else if (inEncryptedFile) { } else if (inEncryptedFile) {
@ -1517,9 +1473,38 @@ public class ImageLoader {
} }
image = BitmapFactory.decodeStream(is, null, opts); image = BitmapFactory.decodeStream(is, null, opts);
is.close(); is.close();
}
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) { if (image == null) {
FileLog.d(DEBUG_TAG + " image2 " + image); 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);
} }
} }
} }

View file

@ -305,8 +305,7 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
private ArrayList<Runnable> loadingOperations = new ArrayList<>(); private ArrayList<Runnable> loadingOperations = new ArrayList<>();
private boolean attachedToWindow; private boolean attachedToWindow;
private boolean videoThumbIsSame; private boolean videoThumbIsSame;
private boolean allowLoadingOnAttachedOnly; private boolean allowLoadingOnAttachedOnly = false;
private boolean shouldLoadOnAttach;
private boolean skipUpdateFrame; private boolean skipUpdateFrame;
public boolean clip = true; public boolean clip = true;

View file

@ -53,8 +53,10 @@ public class LiteMode {
public static int PRESET_LOW = ( public static int PRESET_LOW = (
FLAG_ANIMATED_EMOJI_CHAT_PREMIUM | FLAG_ANIMATED_EMOJI_CHAT_PREMIUM |
FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM |
FLAG_ANIMATED_EMOJI_REACTIONS_PREMIUM |
FLAG_AUTOPLAY_GIFS FLAG_AUTOPLAY_GIFS
); // 2064 ); // 2076
public static int PRESET_MEDIUM = ( public static int PRESET_MEDIUM = (
FLAGS_ANIMATED_STICKERS | FLAGS_ANIMATED_STICKERS |
FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM | FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM |

View file

@ -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) { private String getLocaleString(Locale locale) {
if (locale == null) { if (locale == null) {
return "en"; return "en";

View file

@ -556,6 +556,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
private long lastProgress = 0; private long lastProgress = 0;
private MessageObject playingMessageObject; private MessageObject playingMessageObject;
private MessageObject goingToShowMessageObject; private MessageObject goingToShowMessageObject;
private boolean manualRecording;
private Timer progressTimer = null; private Timer progressTimer = null;
private final Object progressTimerSync = new Object(); private final Object progressTimerSync = new Object();
private boolean downloadingCurrentMessage; private boolean downloadingCurrentMessage;
@ -1629,7 +1630,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (raisedToBack == minCount || accelerometerVertical) { if (raisedToBack == minCount || accelerometerVertical) {
lastAccelerometerDetected = System.currentTimeMillis(); 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 (SharedConfig.enabledRaiseTo(true) && playingMessageObject == null && recordStartRunnable == null && recordingAudio == null && !PhotoViewer.getInstance().isVisible() && ApplicationLoader.isScreenOn && !inputFieldHasText && allowStartRecord && raiseChat != null && !callInProgress) {
if (!raiseToEarRecord) { if (!raiseToEarRecord) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
@ -1639,7 +1640,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
if (!raiseChat.playFirstUnreadVoiceMessage()) { if (!raiseChat.playFirstUnreadVoiceMessage()) {
raiseToEarRecord = true; raiseToEarRecord = true;
useFrontSpeaker = false; 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) { if (useFrontSpeaker) {
setUseFrontSpeaker(true); setUseFrontSpeaker(true);
@ -1668,7 +1669,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
countLess = 0; countLess = 0;
} else if (proximityTouched && ((accelerometerSensor == null || linearSensor == null) && gravitySensor == null || ignoreAccelerometerGestures()) && !VoIPService.isAnyKindOfCallActive()) { } 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 (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) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("start listen by proximity only"); FileLog.d("start listen by proximity only");
} }
@ -1680,7 +1681,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
ignoreOnPause = true; ignoreOnPause = true;
} }
} }
} else if (!proximityTouched) { } else if (!proximityTouched && !manualRecording) {
if (raiseToEarRecord) { if (raiseToEarRecord) {
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("stop record"); FileLog.d("stop record");
@ -1728,7 +1729,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return; return;
} }
raiseToEarRecord = true; 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; ignoreOnPause = true;
} }
@ -2281,20 +2282,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return; return;
} }
boolean last = false; boolean last = traversePlaylist(currentPlayList, SharedConfig.playOrderReversed ? +1 : -1);
if (SharedConfig.playOrderReversed) {
currentPlaylistNum++;
if (currentPlaylistNum >= currentPlayList.size()) {
currentPlaylistNum = 0;
last = true;
}
} else {
currentPlaylistNum--;
if (currentPlaylistNum < 0) {
currentPlaylistNum = currentPlayList.size() - 1;
last = true;
}
}
if (last && byStop && SharedConfig.repeatMode == 0 && !forceLoopCurrentPlaylist) { if (last && byStop && SharedConfig.repeatMode == 0 && !forceLoopCurrentPlaylist) {
if (audioPlayer != null || videoPlayer != null) { if (audioPlayer != null || videoPlayer != null) {
if (audioPlayer != null) { if (audioPlayer != null) {
@ -2351,17 +2339,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return; return;
} }
if (SharedConfig.playOrderReversed) { traversePlaylist(currentPlayList, SharedConfig.playOrderReversed ? -1 : 1);
currentPlaylistNum--;
if (currentPlaylistNum < 0) {
currentPlaylistNum = currentPlayList.size() - 1;
}
} else {
currentPlaylistNum++;
if (currentPlaylistNum >= currentPlayList.size()) {
currentPlaylistNum = 0;
}
}
if (currentPlaylistNum >= currentPlayList.size()) { if (currentPlaylistNum >= currentPlayList.size()) {
return; return;
} }
@ -2369,6 +2347,40 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
playMessage(currentPlayList.get(currentPlaylistNum)); playMessage(currentPlayList.get(currentPlaylistNum));
} }
private boolean traversePlaylist(ArrayList<MessageObject> 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() { protected void checkIsNextMediaFileDownloaded() {
if (playingMessageObject == null || !playingMessageObject.isMusic()) { if (playingMessageObject == null || !playingMessageObject.isMusic()) {
return; return;
@ -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; boolean paused = false;
if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) { if (playingMessageObject != null && isPlayingMessage(playingMessageObject) && !isMessagePaused()) {
paused = true; paused = true;
} }
manualRecording = manual;
requestAudioFocus(true); requestAudioFocus(true);
try { try {
@ -3772,6 +3784,7 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
} }
recordingAudio = null; recordingAudio = null;
recordingAudioFile = null; recordingAudioFile = null;
manualRecording = false;
} }
public void stopRecording(final int send, boolean notify, int scheduleDate) { public void stopRecording(final int send, boolean notify, int scheduleDate) {

View file

@ -34,7 +34,6 @@ import android.text.TextUtils;
import android.text.style.CharacterStyle; import android.text.style.CharacterStyle;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.text.util.Linkify; import android.text.util.Linkify;
import android.util.Log;
import android.util.Pair; import android.util.Pair;
import android.util.SparseArray; import android.util.SparseArray;
@ -53,7 +52,6 @@ import org.telegram.SQLite.SQLiteException;
import org.telegram.SQLite.SQLitePreparedStatement; import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.messenger.ringtone.RingtoneDataStore; import org.telegram.messenger.ringtone.RingtoneDataStore;
import org.telegram.messenger.ringtone.RingtoneUploader; import org.telegram.messenger.ringtone.RingtoneUploader;
import org.telegram.messenger.support.SparseLongArray;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer; import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.RequestDelegate; 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); TLRPC.Document document = premiumPreviewStickers.get(i == 2 ? premiumPreviewStickers.size() - 1 : i);
if (MessageObject.isPremiumSticker(document)) { if (MessageObject.isPremiumSticker(document)) {
ImageReceiver imageReceiver = new ImageReceiver(); ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(ImageLocation.getForDocument(document), null, null, "webp", null, 1); imageReceiver.setImage(ImageLocation.getForDocument(document), null, null, "webp", null, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
imageReceiver = new ImageReceiver(); imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", null, 1); imageReceiver.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", null, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver); ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
} }

View file

@ -13137,6 +13137,7 @@ public class MessagesStorage extends BaseController {
try { 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))); 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()) { if (!cursor.next()) {
cursor.dispose();
return; return;
} }
readState = cursor.intValue(1); readState = cursor.intValue(1);

View file

@ -10,7 +10,9 @@ package org.telegram.messenger;
import android.app.Activity; import android.app.Activity;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.os.Build; import android.os.Build;
@ -27,7 +29,11 @@ import org.json.JSONObject;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData; import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC; 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.Components.SwipeGestureSettingsView;
import org.telegram.ui.LaunchActivity;
import java.io.File; import java.io.File;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
@ -57,6 +63,40 @@ public class SharedConfig {
return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_CHAT); 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) @Retention(RetentionPolicy.SOURCE)
@IntDef({ @IntDef({
PASSCODE_TYPE_PIN, PASSCODE_TYPE_PIN,

View file

@ -419,7 +419,11 @@ public class ConnectionsManager extends BaseController {
} }
public void checkConnection() { 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()); native_setNetworkAvailable(currentAccount, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), ApplicationLoader.isConnectionSlow());
} }

View file

@ -213,7 +213,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
super(context); super(context);
this.resourcesProvider = resourcesProvider; 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); setPadding(AndroidUtilities.dp(23), 0, AndroidUtilities.dp(23), 0);
imageView = new ImageView(context); imageView = new ImageView(context);

View file

@ -1540,7 +1540,6 @@ public class BottomSheet extends Dialog {
onDismissAnimationStart(); onDismissAnimationStart();
if (!allowCustomAnimation || !onCustomCloseAnimation()) { if (!allowCustomAnimation || !onCustomCloseAnimation()) {
currentSheetAnimationType = 2; currentSheetAnimationType = 2;
currentSheetAnimation = new AnimatorSet();
if (navigationBarAnimation != null) { if (navigationBarAnimation != null) {
navigationBarAnimation.cancel(); navigationBarAnimation.cancel();
} }
@ -1551,11 +1550,14 @@ public class BottomSheet extends Dialog {
container.invalidate(); container.invalidate();
} }
}); });
currentSheetAnimation.playTogether( currentSheetAnimation = new AnimatorSet();
containerView == null ? null : ObjectAnimator.ofFloat(containerView, View.TRANSLATION_Y, getContainerViewHeight() + container.keyboardHeight + AndroidUtilities.dp(10) + (scrollNavBar ? getBottomInset() : 0)), ArrayList<Animator> animators = new ArrayList<>();
ObjectAnimator.ofInt(backDrawable, AnimationProperties.COLOR_DRAWABLE_ALPHA, 0), if (containerView != null) {
navigationBarAnimation 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) { // if (useFastDismiss) {
// int height = containerView.getMeasuredHeight(); // int height = containerView.getMeasuredHeight();
// duration = Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height)); // duration = Math.max(60, (int) (250 * (height - containerView.getTranslationY()) / (float) height));

View file

@ -368,6 +368,7 @@ public class EmojiThemes {
} }
ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document); ImageLocation imageLocation = ImageLocation.getForDocument(wallPaper.document);
ImageReceiver imageReceiver = new ImageReceiver(); ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
String imageFilter; String imageFilter;
int w = Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y); 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); final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaper.document.thumbs, 140);
ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaper.document);
ImageReceiver imageReceiver = new ImageReceiver(); ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(imageLocation, "120_140", null, null, null, 1); imageReceiver.setImage(imageLocation, "120_140", null, null, null, 1);
imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { imageReceiver.setDelegate((receiver, set, thumb, memCache) -> {
ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe();

View file

@ -913,7 +913,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
} }
if (rightDrawable != null && rightDrawableOutside) { 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 dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale); int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale);
int y; int y;

View file

@ -20,6 +20,7 @@ import android.graphics.Path;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -44,6 +45,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;
import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; 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.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.LoadingDrawable; import org.telegram.ui.Components.LoadingDrawable;
import org.telegram.ui.Components.NestedSizeNotifierLayout; import org.telegram.ui.Components.NestedSizeNotifierLayout;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SlideChooseView; import org.telegram.ui.Components.SlideChooseView;
import org.telegram.ui.Components.StorageDiagramView; import org.telegram.ui.Components.StorageDiagramView;
@ -105,6 +108,9 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Storage.CacheModel; import org.telegram.ui.Storage.CacheModel;
import java.io.File; 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@ -817,7 +823,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
return size; return size;
} }
private void cleanupFolders() { private void cleanupFolders(Utilities.Callback2<Float, Boolean> onProgress, Runnable onDone) {
if (cacheModel != null) { if (cacheModel != null) {
cacheModel.clearSelection(); cacheModel.clearSelection();
} }
@ -826,22 +832,125 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
cachedMediaLayout.showActionMode(false); cachedMediaLayout.showActionMode(false);
} }
progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER); // progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER);
progressDialog.setCanCancel(false); // progressDialog.setCanCancel(false);
progressDialog.showDelayed(500); // progressDialog.showDelayed(500);
getFileLoader().cancelLoadAllFiles(); getFileLoader().cancelLoadAllFiles();
getFileLoader().getFileLoaderQueue().postRunnable(() -> Utilities.globalQueue.postRunnable(() -> { getFileLoader().getFileLoaderQueue().postRunnable(() -> Utilities.globalQueue.postRunnable(() -> {
cleanupFoldersInternal(); cleanupFoldersInternal(onProgress, onDone);
})); }));
setCacheModel(null); setCacheModel(null);
loadingDialogs = true; loadingDialogs = true;
// updateRows(); // 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<Float> 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<Float, Boolean> onProgress, Runnable onDone) {
boolean imagesCleared = false; boolean imagesCleared = false;
long clearedSize = 0; long clearedSize = 0;
boolean allItemsClear = true; 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<Float> 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++) { for (int a = 0; a < 8; a++) {
if (!selected[a]) { if (!selected[a]) {
allItemsClear = false; allItemsClear = false;
@ -888,13 +997,17 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
file = FileLoader.checkDirectory(type); file = FileLoader.checkDirectory(type);
} }
if (file != null) { 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) { if (type == 100) {
file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE); file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE);
if (file != null) { 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) { if (type == FileLoader.MEDIA_DIR_IMAGE || type == FileLoader.MEDIA_DIR_VIDEO) {
int publicDirectoryType; int publicDirectoryType;
@ -906,14 +1019,18 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
file = FileLoader.checkDirectory(publicDirectoryType); file = FileLoader.checkDirectory(publicDirectoryType);
if (file != null) { 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) { if (type == FileLoader.MEDIA_DIR_DOCUMENT) {
file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES); file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES);
if (file != null) { 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) { if (type == FileLoader.MEDIA_DIR_CACHE) {
@ -1000,6 +1117,10 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
MediaDataController.getInstance(currentAccount).chekAllMedia(true); MediaDataController.getInstance(currentAccount).chekAllMedia(true);
loadDialogEntities(); 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 { private class ClearCacheButtonInternal extends ClearCacheButton {
public ClearCacheButtonInternal(Context context) { public ClearCacheButtonInternal(Context context) {
super(context); super(context);
((MarginLayoutParams) button.getLayoutParams()).topMargin = AndroidUtilities.dp(5); ((MarginLayoutParams) button.getLayoutParams()).topMargin = AndroidUtilities.dp(5);
button.setOnClickListener(e -> { 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.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 8));
button.setFocusable(true);
button.setFocusableInTouchMode(true);
button.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); button.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
if (LocaleController.isRTL) { 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.setTextColor(Theme.adaptHSV(Theme.getColor(Theme.key_featuredStickers_addButton), -.46f, +.08f));
valueTextView.setText(""); valueTextView.setText("");
button.setContentDescription(TextUtils.concat(textView.getText(), "\t", valueTextView.getText()));
setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 16, 16, 16, 16)); addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 16, 16, 16, 16));
} }

View file

@ -181,7 +181,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public boolean clipToGroupBounds; public boolean clipToGroupBounds;
public boolean drawForBlur; public boolean drawForBlur;
private boolean flipImage; private boolean flipImage;
private boolean visibleOnScreen; private boolean visibleOnScreen = true;
public boolean shouldCheckVisibleOnScreen; public boolean shouldCheckVisibleOnScreen;
float parentBoundsTop; float parentBoundsTop;
int parentBoundsBottom; int parentBoundsBottom;
@ -373,6 +373,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (this.visibleOnScreen != visibleOnScreen) { if (this.visibleOnScreen != visibleOnScreen) {
this.visibleOnScreen = visibleOnScreen; this.visibleOnScreen = visibleOnScreen;
checkImageReceiversAttachState(); checkImageReceiversAttachState();
if (visibleOnScreen) {
invalidate();
}
} }
} }
@ -4092,24 +4095,28 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
photoImage.onDetachedFromWindow(); photoImage.onDetachedFromWindow();
blurredPhotoImage.onDetachedFromWindow(); blurredPhotoImage.onDetachedFromWindow();
if (currentMessageObject != null && !currentMessageObject.mediaExists && !currentMessageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(currentMessageObject.messageOwner.id)) { cancelLoading(currentMessageObject);
TLRPC.Document document = currentMessageObject.getDocument(); 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); boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document);
if (!loadDocumentFromImageReceiver) { if (!loadDocumentFromImageReceiver) {
if (document != null) { if (document != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(document); FileLoader.getInstance(currentAccount).cancelLoadFile(document);
} else { } else {
TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.getPhotoSize()); TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
if (photo != null) { if (photo != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(photo); FileLoader.getInstance(currentAccount).cancelLoadFile(photo);
} }
} }
} }
} }
AnimatedEmojiSpan.release(this, animatedEmojiDescriptionStack);
AnimatedEmojiSpan.release(this, animatedEmojiReplyStack);
AnimatedEmojiSpan.release(this, animatedEmojiStack);
}
} }
private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) { private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) {
@ -7586,7 +7593,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
botButtonsByData.put(key, botButton); botButtonsByData.put(key, botButton);
botButtonsByPosition.put(position, botButton); botButtonsByPosition.put(position, botButton);
botButton.x = b * (buttonWidth + AndroidUtilities.dp(5)); 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.width = buttonWidth;
botButton.height = AndroidUtilities.dp(44); botButton.height = AndroidUtilities.dp(44);
CharSequence buttonText; CharSequence buttonText;
@ -17646,9 +17653,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else { } else {
this.willRemoved = false; this.willRemoved = false;
} }
if (getParent() == null && attachedToWindow) {
onDetachedFromWindow();
}
} }
@Override @Override

View file

@ -511,13 +511,14 @@ public class DialogCell extends BaseCell {
for (int i = 0; i < thumbImage.length; ++i) { for (int i = 0; i < thumbImage.length; ++i) {
thumbImage[i] = new ImageReceiver(this); thumbImage[i] = new ImageReceiver(this);
thumbImage[i].setRoundRadius(AndroidUtilities.dp(2)); thumbImage[i].setRoundRadius(AndroidUtilities.dp(2));
thumbImage[i].setAllowLoadingOnAttachedOnly(true);
} }
useForceThreeLines = forceThreeLines; useForceThreeLines = forceThreeLines;
currentAccount = account; currentAccount = account;
emojiStatus = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(22)); emojiStatus = new AnimatedEmojiDrawable.SwapAnimatedEmojiDrawable(this, AndroidUtilities.dp(22));
emojiStatus.center = false; emojiStatus.center = false;
avatarImage.setAllowLoadingOnAttachedOnly(true);
} }
public void setDialog(TLRPC.Dialog dialog, int type, int folder) { public void setDialog(TLRPC.Dialog dialog, int type, int folder) {
@ -2118,7 +2119,7 @@ public class DialogCell extends BaseCell {
} else if (drawScam != 0) { } else if (drawScam != 0) {
nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth()); nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - (drawScam == 1 ? Theme.dialogs_scamDrawable : Theme.dialogs_fakeDrawable).getIntrinsicWidth());
} else { } else {
nameMuteLeft = 0; nameMuteLeft = (int) (nameLeft + (nameWidth - widthpx) - AndroidUtilities.dp(6) - Theme.dialogs_muteDrawable.getIntrinsicWidth());
} }
if (left == 0) { if (left == 0) {
if (widthpx < nameWidth) { if (widthpx < nameWidth) {
@ -2190,7 +2191,7 @@ public class DialogCell extends BaseCell {
nameLeft -= (nameWidth - widthpx); 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)); nameMuteLeft = (int) (nameLeft + left + AndroidUtilities.dp(6));
} }
} }
@ -3830,7 +3831,7 @@ public class DialogCell extends BaseCell {
float size1; float size1;
float size2; float size2;
if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { if (!LiteMode.isEnabled(LiteMode.FLAGS_CHAT)) {
innerProgress = 0.65f; innerProgress = 0.65f;
} }
if (progressStage == 0) { if (progressStage == 0) {
@ -3875,7 +3876,7 @@ public class DialogCell extends BaseCell {
canvas.restore(); canvas.restore();
} }
if (!LiteMode.isEnabled(LiteMode.FLAG_CHAT_BACKGROUND)) { if (LiteMode.isEnabled(LiteMode.FLAGS_CHAT)) {
innerProgress += 16f / 400.0f; innerProgress += 16f / 400.0f;
if (innerProgress >= 1.0f) { if (innerProgress >= 1.0f) {
innerProgress = 0.0f; innerProgress = 0.0f;

View file

@ -22,6 +22,12 @@ public class ShadowSectionCell extends View {
private int size; private int size;
private int backgroundColor;
private Theme.ResourcesProvider resourcesProvider;
private boolean top = true;
private boolean bottom = true;
public ShadowSectionCell(Context context) { public ShadowSectionCell(Context context) {
this(context, 12, null); this(context, 12, null);
} }
@ -36,8 +42,9 @@ public class ShadowSectionCell extends View {
public ShadowSectionCell(Context context, int s, Theme.ResourcesProvider resourcesProvider) { public ShadowSectionCell(Context context, int s, Theme.ResourcesProvider resourcesProvider) {
super(context); super(context);
setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider))); this.resourcesProvider = resourcesProvider;
size = s; this.size = s;
updateBackground();
} }
public ShadowSectionCell(Context context, int s, int backgroundColor) { 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) { public ShadowSectionCell(Context context, int s, int backgroundColor, Theme.ResourcesProvider resourcesProvider) {
super(context); super(context);
Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)); 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); Drawable background = new ColorDrawable(backgroundColor);
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0); CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true); combinedDrawable.setFullsize(true);
setBackgroundDrawable(combinedDrawable); setBackground(combinedDrawable);
size = s; }
}
}
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 @Override

View file

@ -295,6 +295,7 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Components.UnreadCounterTextView; import org.telegram.ui.Components.UnreadCounterTextView;
import org.telegram.ui.Components.ViewHelper; import org.telegram.ui.Components.ViewHelper;
import org.telegram.ui.Components.spoilers.SpoilerEffect; 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.Components.voip.VoIPHelper;
import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate; import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate;
@ -378,6 +379,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private GridLayoutManagerFixed chatLayoutManager; private GridLayoutManagerFixed chatLayoutManager;
private ChatActivityAdapter chatAdapter; private ChatActivityAdapter chatAdapter;
private UnreadCounterTextView bottomOverlayChatText; private UnreadCounterTextView bottomOverlayChatText;
private TextView bottomOverlayStartButton;
private ImageView bottomOverlayImage; private ImageView bottomOverlayImage;
private RadialProgressView bottomOverlayProgress; private RadialProgressView bottomOverlayProgress;
private AnimatorSet bottomOverlayAnimation; 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 @Override
protected void onAttachedToWindow() { protected void onAttachedToWindow() {
super.onAttachedToWindow(); super.onAttachedToWindow();
@ -5031,7 +5013,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
protected void onDetachedFromWindow() { protected void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
chatListViewAttached = false; chatListViewAttached = false;
clearMessagesPreloading();
} }
}; };
if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) { if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) {
@ -5387,7 +5368,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
scrollingChatListView = false; scrollingChatListView = false;
checkTextureViewPosition = false; checkTextureViewPosition = false;
hideFloatingDateView(true); hideFloatingDateView(true);
checkAutoDownloadMessages(scrollUp);
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) { if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512); NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512);
} }
@ -6674,6 +6654,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
bottomOverlayChat.setClipChildren(false); bottomOverlayChat.setClipChildren(false);
contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM)); 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) { bottomOverlayChatText = new UnreadCounterTextView(context) {
@Override @Override
protected void updateCounter() { protected void updateCounter() {
@ -10189,127 +10204,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showDialog(chatAttachAlert); showDialog(chatAttachAlert);
} }
ArrayList<MessageObject> preloadingMessages = new ArrayList<>();
ArrayList<MessageObject> preloadingMessagesTmp = new ArrayList<>();
SparseArray<MessageObject> 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) { private void showFloatingDateView(boolean scroll) {
if (floatingDateView == null) { if (floatingDateView == null) {
return; return;
@ -11748,7 +11642,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) { if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) {
if (messageCell != null) { if (messageCell != null) {
if (!blurEnabled) { if (blurEnabled) {
messageCell.setVisibleOnScreen(false); messageCell.setVisibleOnScreen(false);
} else { } else {
messageCell.setVisibleOnScreen(true); messageCell.setVisibleOnScreen(true);
@ -13763,9 +13657,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
invalidateMessagesVisiblePart(); invalidateMessagesVisiblePart();
updateTextureViewPosition(false, false); updateTextureViewPosition(false, false);
if (!scrollingChatListView) {
checkAutoDownloadMessages(false);
}
notifyHeightChanged(); notifyHeightChanged();
} }
@ -15337,6 +15228,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int loaded_max_id = (Integer) args[12]; int loaded_max_id = (Integer) args[12];
int loaded_mentions_count = chatWasReset ? 0 : (Integer) args[13]; 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) { if (loaded_mentions_count < 0) {
loaded_mentions_count *= -1; loaded_mentions_count *= -1;
hasAllMentionsLocal = false; hasAllMentionsLocal = false;
@ -16317,9 +16217,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} }
} else if (id == NotificationCenter.didUpdateConnectionState) { } else if (id == NotificationCenter.didUpdateConnectionState) {
int state = ConnectionsManager.getInstance(account).getConnectionState(); int state = ConnectionsManager.getInstance(account).getConnectionState();
if (state == ConnectionsManager.ConnectionStateConnected) {
checkAutoDownloadMessages(false);
}
} else if (id == NotificationCenter.chatOnlineCountDidLoad) { } else if (id == NotificationCenter.chatOnlineCountDidLoad) {
Long chatId = (Long) args[0]; Long chatId = (Long) args[0];
if (chatInfo == null || currentChat == null || currentChat.id != chatId) { if (chatInfo == null || currentChat == null || currentChat.id != chatId) {
@ -20624,7 +20521,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} }
showBottomOverlayProgress(false, true); showBottomOverlayProgress(false, true);
} else if (botUser != null && currentUser.bot) { } 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); chatActivityEnterView.hidePopup(false);
if (getParentActivity() != null) { if (getParentActivity() != null) {
AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus()); AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus());
@ -20648,6 +20547,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatActivityEnterView.setVisibility(View.INVISIBLE); chatActivityEnterView.setVisibility(View.INVISIBLE);
} else if (searchItem != null && searchItemVisible) { } else if (searchItem != null && searchItemVisible) {
createSearchContainer(); createSearchContainer();
if (searchContainer == null) {
return;
}
searchContainer.animate().setListener(null).cancel(); searchContainer.animate().setListener(null).cancel();
if (searchContainer.getVisibility() != View.VISIBLE) { if (searchContainer.getVisibility() != View.VISIBLE) {
searchContainer.setVisibility(View.VISIBLE); searchContainer.setVisibility(View.VISIBLE);

View file

@ -727,7 +727,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
delegate.needStartRecordAudio(1); delegate.needStartRecordAudio(1);
startedDraggingX = -1; startedDraggingX = -1;
MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid); MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid, true);
recordingAudioVideo = true; recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER); updateRecordInterface(RECORD_STATE_ENTER);
if (recordTimerView != null) { if (recordTimerView != null) {
@ -7350,7 +7350,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
return; return;
} }
if (focus) { if (focus) {
if (searchingType == 0 && !messageEditText.isFocused()) { if (searchingType == 0 && !messageEditText.isFocused() && (botWebViewMenuContainer == null || botWebViewMenuContainer.getVisibility() == View.GONE)) {
AndroidUtilities.runOnUIThread(focusRunnable = () -> { AndroidUtilities.runOnUIThread(focusRunnable = () -> {
focusRunnable = null; focusRunnable = null;
boolean allowFocus; boolean allowFocus;

View file

@ -37,7 +37,6 @@ import android.text.TextPaint;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.TextWatcher; import android.text.TextWatcher;
import android.text.style.ImageSpan; import android.text.style.ImageSpan;
import android.util.Log;
import android.util.LongSparseArray; import android.util.LongSparseArray;
import android.util.Property; import android.util.Property;
import android.util.TypedValue; import android.util.TypedValue;
@ -83,7 +82,6 @@ import org.telegram.messenger.MessagesController;
import org.telegram.messenger.NotificationCenter; import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.SendMessagesHelper; import org.telegram.messenger.SendMessagesHelper;
import org.telegram.messenger.SharedConfig;
import org.telegram.messenger.UserConfig; import org.telegram.messenger.UserConfig;
import org.telegram.messenger.UserObject; import org.telegram.messenger.UserObject;
import org.telegram.tgnet.ConnectionsManager; import org.telegram.tgnet.ConnectionsManager;
@ -282,7 +280,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override @Override
public void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible) { 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; return;
} }
botMainButtonTextView.setClickable(isActive); botMainButtonTextView.setClickable(isActive);

View file

@ -218,6 +218,7 @@ public class ChatNotificationsPopupWrapper {
} }
muteUnmuteButton.setColors(color, color); muteUnmuteButton.setColors(color, color);
muteUnmuteButton.setSelectorColor(Theme.multAlpha(color, .1f));
if (topicExceptions == null || topicExceptions.isEmpty()) { if (topicExceptions == null || topicExceptions.isEmpty()) {
gap.setVisibility(View.GONE); gap.setVisibility(View.GONE);

View file

@ -51,7 +51,6 @@ import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.MotionEvent; 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.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay; import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface; import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL;
@TargetApi(18) @TargetApi(18)
public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate { public class InstantCameraView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
@ -1006,8 +1004,14 @@ public class InstantCameraView extends FrameLayout implements NotificationCenter
private Size chooseOptimalSize(ArrayList<Size> previewSizes) { private Size chooseOptimalSize(ArrayList<Size> previewSizes) {
ArrayList<Size> sortedSizes = new ArrayList<>(); ArrayList<Size> 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++) { 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)); sortedSizes.add(previewSizes.get(i));
} }
} }

View file

@ -7,6 +7,7 @@ import android.text.InputType;
import android.util.TypedValue; import android.util.TypedValue;
import android.view.Gravity; import android.view.Gravity;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.ui.ActionBar.Theme; import org.telegram.ui.ActionBar.Theme;
public class OutlineEditText extends OutlineTextContainerView { public class OutlineEditText extends OutlineTextContainerView {
@ -32,6 +33,9 @@ public class OutlineEditText extends OutlineTextContainerView {
editText.setTypeface(Typeface.DEFAULT); editText.setTypeface(Typeface.DEFAULT);
editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated)); editText.setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated));
editText.setCursorWidth(1.5f); editText.setCursorWidth(1.5f);
editText.setPadding(
AndroidUtilities.dp(15), 0, AndroidUtilities.dp(15), 0
);
attachEditText(editText); attachEditText(editText);
addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL)); addView(editText, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL));

View file

@ -774,6 +774,8 @@ public class ProfileGalleryView extends CircularViewPager implements Notificatio
imagesUploadProgress.remove(index); imagesUploadProgress.remove(index);
if (index == 0 && !imagesLocations.isEmpty()) { if (index == 0 && !imagesLocations.isEmpty()) {
prevImageLocation = imagesLocations.get(0); prevImageLocation = imagesLocations.get(0);
prevThumbLocation = null;
prevVectorAvatarThumbDrawable = null;
} }
adapter.notifyDataSetChanged(); adapter.notifyDataSetChanged();
return photos.isEmpty(); return photos.isEmpty();

View file

@ -822,6 +822,9 @@ public class RLottieDrawable extends BitmapDrawable implements Animatable, Bitma
} }
protected void invalidateInternal() { protected void invalidateInternal() {
if (isRecycled) {
return;
}
for (int i = 0, N = parentViews.size(); i < N; i++) { for (int i = 0, N = parentViews.size(); i < N; i++) {
parentViews.get(i).invalidate(); parentViews.get(i).invalidate();
} }

View file

@ -1847,6 +1847,10 @@ public class RecyclerListView extends RecyclerView {
Theme.setSelectorDrawableColor(selectorDrawable, color, true); Theme.setSelectorDrawableColor(selectorDrawable, color, true);
} }
public Integer getSelectorColor(int position) {
return null;
}
public void setOnItemClickListener(OnItemClickListener listener) { public void setOnItemClickListener(OnItemClickListener listener) {
onItemClickListener = listener; onItemClickListener = listener;
} }
@ -2265,6 +2269,10 @@ public class RecyclerListView extends RecyclerView {
selectorDrawable.setVisible(false, false); selectorDrawable.setVisible(false, false);
selectorDrawable.setState(StateSet.NOTHING); selectorDrawable.setState(StateSet.NOTHING);
} }
Integer color = getSelectorColor(position);
if (color != null) {
setListSelectorColor(color);
}
selectorDrawable.setBounds(selectorRect); selectorDrawable.setBounds(selectorRect);
if (positionChanged) { if (positionChanged) {
if (getVisibility() == VISIBLE) { if (getVisibility() == VISIBLE) {

View file

@ -1662,7 +1662,7 @@ public class StickersAlert extends BottomSheet implements NotificationCenter.Not
params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = AndroidUtilities.dp(8); params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = AndroidUtilities.dp(8);
emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(64); emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(64);
} else { } 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); pickerBottomFrameLayout.setBackgroundColor(Color.TRANSPARENT);
params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0; params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0;
emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(48); emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(48);

View file

@ -238,6 +238,7 @@ public class ThemeSmallPreviewView extends FrameLayout implements NotificationCe
final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaperDocument.thumbs, PATTERN_BITMAP_MAXWIDTH); final TLRPC.PhotoSize thumbSize = FileLoader.getClosestPhotoSizeWithSize(wallpaperDocument.thumbs, PATTERN_BITMAP_MAXWIDTH);
ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaperDocument); ImageLocation imageLocation = ImageLocation.getForDocument(thumbSize, wallpaperDocument);
ImageReceiver imageReceiver = new ImageReceiver(); ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(imageLocation, PATTERN_BITMAP_MAXWIDTH + "_" + PATTERN_BITMAP_MAXHEIGHT, null, null, null, 1); imageReceiver.setImage(imageLocation, PATTERN_BITMAP_MAXWIDTH + "_" + PATTERN_BITMAP_MAXHEIGHT, null, null, null, 1);
imageReceiver.setDelegate((receiver, set, thumb, memCache) -> { imageReceiver.setDelegate((receiver, set, thumb, memCache) -> {
ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe(); ImageReceiver.BitmapHolder holder = receiver.getBitmapSafe();

View file

@ -490,6 +490,11 @@ public class ContentPreviewViewer {
icons.add(R.drawable.msg_send); icons.add(R.drawable.msg_send);
actions.add(0); 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()) { if (delegate.canSchedule()) {
items.add(LocaleController.getString("Schedule", R.string.Schedule)); items.add(LocaleController.getString("Schedule", R.string.Schedule));
icons.add(R.drawable.msg_autodelete); icons.add(R.drawable.msg_autodelete);
@ -528,6 +533,8 @@ public class ContentPreviewViewer {
int which = (int) v.getTag(); int which = (int) v.getTag();
if (actions.get(which) == 0) { if (actions.get(which) == 0) {
delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, true, 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) { } else if (actions.get(which) == 1) {
MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument); MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument);
delegate.gifAddedOrDeleted(); delegate.gifAddedOrDeleted();

View file

@ -22,6 +22,7 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; 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.HeaderCell;
import org.telegram.ui.Cells.LanguageCell; import org.telegram.ui.Cells.LanguageCell;
import org.telegram.ui.Cells.NotificationsCheckCell; import org.telegram.ui.Cells.NotificationsCheckCell;
import org.telegram.ui.Cells.RadioColorCell;
import org.telegram.ui.Cells.ShadowSectionCell; import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextCell; import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextCheckCell; import org.telegram.ui.Cells.TextCheckCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell; import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.TextSettingsCell; import org.telegram.ui.Cells.TextSettingsCell;
import org.telegram.ui.Components.AlertsCreator; import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView; import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.voip.VoIPHelper; import org.telegram.ui.Components.voip.VoIPHelper;
@ -73,7 +74,7 @@ public class DataSettingsActivity extends BaseFragment {
private int roamingRow; private int roamingRow;
private int wifiRow; private int wifiRow;
private int storageNumRow; private int storageNumRow;
private int resetDownloadRow; private int resetDownloadRow = -1;
private int mediaDownloadSection2Row; private int mediaDownloadSection2Row;
private int usageSectionRow; private int usageSectionRow;
private int storageUsageRow; private int storageUsageRow;
@ -117,6 +118,12 @@ public class DataSettingsActivity extends BaseFragment {
super.onFragmentCreate(); super.onFragmentCreate();
DownloadController.getInstance(currentAccount).loadAutoDownloadConfig(true); DownloadController.getInstance(currentAccount).loadAutoDownloadConfig(true);
updateRows(true);
return true;
}
private void updateRows(boolean fullNotify) {
rowCount = 0; rowCount = 0;
usageSectionRow = rowCount++; usageSectionRow = rowCount++;
@ -134,7 +141,25 @@ public class DataSettingsActivity extends BaseFragment {
mobileRow = rowCount++; mobileRow = rowCount++;
wifiRow = rowCount++; wifiRow = rowCount++;
roamingRow = 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++; mediaDownloadSection2Row = rowCount++;
saveToGallerySectionRow = rowCount++; saveToGallerySectionRow = rowCount++;
@ -169,7 +194,9 @@ public class DataSettingsActivity extends BaseFragment {
clearDraftsRow = rowCount++; clearDraftsRow = rowCount++;
clearDraftsSectionRow = rowCount++; clearDraftsSectionRow = rowCount++;
return true; if (listAdapter != null && fullNotify) {
listAdapter.notifyDataSetChanged();
}
} }
private void loadCacheSize() { private void loadCacheSize() {
@ -250,7 +277,15 @@ public class DataSettingsActivity extends BaseFragment {
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray)); fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
FrameLayout frameLayout = (FrameLayout) fragmentView; 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.setVerticalScrollBarEnabled(false);
listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, 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)); 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).checkAutodownloadSettings();
DownloadController.getInstance(currentAccount).savePresetToServer(num); DownloadController.getInstance(currentAccount).savePresetToServer(num);
if (wasEnabled != listAdapter.isRowEnabled(resetDownloadRow)) { updateRows(false);
listAdapter.notifyItemChanged(resetDownloadRow);
}
} else { } else {
int type; int type;
if (position == mobileRow) { if (position == mobileRow) {
@ -376,6 +409,7 @@ public class DataSettingsActivity extends BaseFragment {
DownloadController.getInstance(currentAccount).savePresetToServer(a); DownloadController.getInstance(currentAccount).savePresetToServer(a);
} }
listAdapter.notifyItemRangeChanged(mobileRow, 4); listAdapter.notifyItemRangeChanged(mobileRow, 4);
updateRows(false);
}); });
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
AlertDialog dialog = builder.create(); AlertDialog dialog = builder.create();
@ -465,24 +499,46 @@ public class DataSettingsActivity extends BaseFragment {
LanguageCell cell = new LanguageCell(context); LanguageCell cell = new LanguageCell(context);
cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0); cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
cell.setTag(a); 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( cell.setValue(
storageDir.contains("/storage/emulated/") ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard), isInternal ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard),
fullString ? description
LocaleController.formatString("StoragePathFreeValue", R.string.StoragePathFreeValue, AndroidUtilities.formatFileSize(file.getFreeSpace()), storageDir) :
LocaleController.formatString("StoragePathFree", R.string.StoragePathFree, AndroidUtilities.formatFileSize(file.getFreeSpace()))
); );
cell.setLanguageSelected(storageDir.startsWith(dir), false); cell.setLanguageSelected(storageDir.startsWith(dir), false);
cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 2)); cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 2));
linearLayout.addView(cell); linearLayout.addView(cell);
cell.setOnClickListener(v -> { cell.setOnClickListener(v -> {
SharedConfig.storageCacheDir = storageDir; if (!TextUtils.equals(SharedConfig.storageCacheDir, storageDir)) {
SharedConfig.saveConfig(); 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(); builder.getDismissRunnable().run();
rebind(storageNumRow); }
ImageLoader.getInstance().checkMediaPaths(() -> {
CacheControlActivity.resetCalculatedTotalSIze();
loadCacheSize();
}); });
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); 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; 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 @Override
protected void onDialogDismiss(Dialog dialog) { protected void onDialogDismiss(Dialog dialog) {
DownloadController.getInstance(currentAccount).checkAutodownloadSettings(); DownloadController.getInstance(currentAccount).checkAutodownloadSettings();
@ -548,6 +623,7 @@ public class DataSettingsActivity extends BaseFragment {
super.onResume(); super.onResume();
loadCacheSize(); loadCacheSize();
rebindAll(); rebindAll();
updateRows(false);
} }
private class ListAdapter extends RecyclerListView.SelectionAdapter { private class ListAdapter extends RecyclerListView.SelectionAdapter {
@ -702,7 +778,7 @@ public class DataSettingsActivity extends BaseFragment {
String text; String text;
CharSequence description = null; CharSequence description = null;
DownloadController.Preset preset = null; DownloadController.Preset preset = null;
boolean enabled; boolean enabled, divider = true;
if (position == saveToGalleryPeerRow) { if (position == saveToGalleryPeerRow) {
text = LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate); text = LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate);
description = SaveToGallerySettingsHelper.user.createDescription(currentAccount); description = SaveToGallerySettingsHelper.user.createDescription(currentAccount);
@ -715,6 +791,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels); text = LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels);
description = SaveToGallerySettingsHelper.channels.createDescription(currentAccount); description = SaveToGallerySettingsHelper.channels.createDescription(currentAccount);
enabled = SaveToGallerySettingsHelper.channels.enabled(); enabled = SaveToGallerySettingsHelper.channels.enabled();
divider = false;
} else if (position == mobileRow) { } else if (position == mobileRow) {
text = LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData); text = LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData);
enabled = DownloadController.getInstance(currentAccount).mobilePreset.enabled; enabled = DownloadController.getInstance(currentAccount).mobilePreset.enabled;
@ -727,6 +804,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("WhenRoaming", R.string.WhenRoaming); text = LocaleController.getString("WhenRoaming", R.string.WhenRoaming);
enabled = DownloadController.getInstance(currentAccount).roamingPreset.enabled; enabled = DownloadController.getInstance(currentAccount).roamingPreset.enabled;
preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset(); preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset();
divider = resetDownloadRow >= 0;
} }
boolean checked; boolean checked;
if (preset != null) { if (preset != null) {
@ -776,7 +854,7 @@ public class DataSettingsActivity extends BaseFragment {
checked = enabled; checked = enabled;
} }
checkCell.setAnimationsEnabled(true); checkCell.setAnimationsEnabled(true);
checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, true); checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, divider);
break; break;
} }
} }
@ -805,15 +883,9 @@ public class DataSettingsActivity extends BaseFragment {
} }
public boolean isRowEnabled(int position) { 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 || 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 == 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 @Override

View file

@ -3244,6 +3244,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
viewPage.listView.setInstantClick(true); viewPage.listView.setInstantClick(true);
viewPage.layoutManager = new LinearLayoutManager(context) { 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; private boolean fixOffset;
@Override @Override
@ -7123,6 +7131,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true); ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true);
deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon)); deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon));
deleteItem.setTextColor(getThemedColor(Theme.key_dialogTextRed)); 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.setTextAndIcon(LocaleController.getString("Delete", R.string.Delete), R.drawable.msg_delete);
deleteItem.setMinimumWidth(160); deleteItem.setMinimumWidth(160);
deleteItem.setOnClickListener(e -> { deleteItem.setOnClickListener(e -> {
@ -8669,7 +8678,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) { } else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
updateVisibleRows(0); updateVisibleRows(0);
} else if (id == NotificationCenter.emojiLoaded) { } 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) { if (filterTabsView != null) {
filterTabsView.getTabsContainer().invalidateViews(); filterTabsView.getTabsContainer().invalidateViews();
} }

View file

@ -49,6 +49,7 @@ import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Components.Bulletin; import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory; import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.CombinedDrawable; import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet; import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet; import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
@ -527,6 +528,12 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
super.dispatchDraw(canvas); 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); ((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false);
listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)); listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
listView.setVerticalScrollBarEnabled(false); listView.setVerticalScrollBarEnabled(false);
@ -735,6 +742,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
while (getMessagesController().dialogFiltersById.get(filter.id) != null) { while (getMessagesController().dialogFiltersById.get(filter.id) != null) {
filter.id++; filter.id++;
} }
filter.order = getMessagesController().dialogFilters.size();
filter.pendingUnreadCount = filter.unreadCount = -1; filter.pendingUnreadCount = filter.unreadCount = -1;
for (int b = 0; b < 2; b++) { for (int b = 0; b < 2; b++) {
ArrayList<TLRPC.InputPeer> fromArray = b == 0 ? suggested.filter.include_peers : suggested.filter.exclude_peers; ArrayList<TLRPC.InputPeer> 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; filter.flags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_MUTED;
} }
ignoreUpdates = true; 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); getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated);
ignoreUpdates = false; ignoreUpdates = false;
ArrayList<TLRPC.TL_dialogFilterSuggested> suggestedFilters = getMessagesController().suggestedFilters; ArrayList<TLRPC.TL_dialogFilterSuggested> suggestedFilters = getMessagesController().suggestedFilters;
@ -848,9 +856,9 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
} }
case 3: { case 3: {
if (position == createSectionRow) { 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 { } 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; break;
} }
@ -870,7 +878,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
} }
case 5: { case 5: {
SuggestedFilterCell filterCell = (SuggestedFilterCell) holder.itemView; 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; break;
} }
} }

View file

@ -409,21 +409,14 @@ public class LanguageSelectActivity extends BaseFragment implements Notification
Collections.sort(unofficialLanguages, comparator); Collections.sort(unofficialLanguages, comparator);
} }
private static boolean patching = false;
@Override @Override
public void onBecomeFullyVisible() { public void onBecomeFullyVisible() {
super.onBecomeFullyVisible(); super.onBecomeFullyVisible();
boolean shouldPatch = getMessagesController().checkResetLangpack > 0 && !MessagesController.getGlobalMainSettings().getBoolean("langpack_patched", false) && !patching; LocaleController.getInstance().checkForcePatchLangpack(currentAccount, () -> {
if (shouldPatch) { if (!isPaused) {
patching = true;
LocaleController.getInstance().reloadCurrentRemoteLocale(currentAccount, null, true, () -> {
AndroidUtilities.runOnUIThread(() -> {
MessagesController.getGlobalMainSettings().edit().putBoolean("langpack_patched", true).apply();
updateLanguage(); updateLanguage();
});
});
} }
});
} }
@Override @Override

View file

@ -4981,12 +4981,20 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
visibleDialog.setOnDismissListener(dialog -> { visibleDialog.setOnDismissListener(dialog -> {
if (visibleDialog != null) { if (visibleDialog != null) {
if (visibleDialog == localeDialog) { if (visibleDialog == localeDialog) {
BaseFragment fragment = actionBarLayout == null ? null : actionBarLayout.getLastFragment();
try { try {
String shorname = LocaleController.getInstance().getCurrentLocaleInfo().shortName; String shorname = LocaleController.getInstance().getCurrentLocaleInfo().shortName;
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( BulletinFactory.of(Bulletin.BulletinWindow.make(LaunchActivity.this), null).createSimpleBulletin(
R.raw.msg_translate, R.raw.msg_translate,
getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater) getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater)
).setDuration(Bulletin.DURATION_PROLONG).show(); ).setDuration(Bulletin.DURATION_PROLONG).show();
}
} catch (Exception e) { } catch (Exception e) {
FileLog.e(e); FileLog.e(e);
} }

View file

@ -6085,6 +6085,10 @@ public class LoginActivity extends BaseFragment {
int minutes = ((timeRemaining % 86400) % 3600) / 60; int minutes = ((timeRemaining % 86400) % 3600) / 60;
int seconds = ((timeRemaining % 86400) % 3600) % 60; int seconds = ((timeRemaining % 86400) % 3600) % 60;
if (hours >= 16) {
days++;
}
String time; String time;
if (days != 0) { if (days != 0) {
time = LocaleController.formatString(R.string.LoginEmailResetInSinglePattern, LocaleController.formatPluralString("Days", days)); time = LocaleController.formatString(R.string.LoginEmailResetInSinglePattern, LocaleController.formatPluralString("Days", days));

View file

@ -1021,21 +1021,18 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
break; break;
case 1: case 1:
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView; 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) { if (position == deleteAccountDetailRow) {
privacyCell.setText(LocaleController.getString("DeleteAccountHelp", R.string.DeleteAccountHelp)); privacyCell.setText(LocaleController.getString("DeleteAccountHelp", R.string.DeleteAccountHelp));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == groupsDetailRow) { } else if (position == groupsDetailRow) {
privacyCell.setText(LocaleController.getString("GroupsAndChannelsHelp", R.string.GroupsAndChannelsHelp)); privacyCell.setText(LocaleController.getString("GroupsAndChannelsHelp", R.string.GroupsAndChannelsHelp));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == sessionsDetailRow) { } else if (position == sessionsDetailRow) {
privacyCell.setText(LocaleController.getString("SessionsSettingsInfo", R.string.SessionsSettingsInfo)); privacyCell.setText(LocaleController.getString("SessionsSettingsInfo", R.string.SessionsSettingsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == secretDetailRow) { } else if (position == secretDetailRow) {
privacyCell.setText(LocaleController.getString("SecretWebPageInfo", R.string.SecretWebPageInfo)); privacyCell.setText(LocaleController.getString("SecretWebPageInfo", R.string.SecretWebPageInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == botsDetailRow) { } else if (position == botsDetailRow) {
privacyCell.setText(LocaleController.getString("PrivacyBotsInfo", R.string.PrivacyBotsInfo)); privacyCell.setText(LocaleController.getString("PrivacyBotsInfo", R.string.PrivacyBotsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == contactsDetailRow) { } else if (position == contactsDetailRow) {
/*if (newSync) { /*if (newSync) {
privacyCell.setText(LocaleController.getString("SyncContactsInfoOn", R.string.SyncContactsInfoOn)); 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("SyncContactsInfoOff", R.string.SyncContactsInfoOff));
}*/ }*/
privacyCell.setText(LocaleController.getString("SuggestContactsInfo", R.string.SuggestContactsInfo)); privacyCell.setText(LocaleController.getString("SuggestContactsInfo", R.string.SuggestContactsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == newChatsSectionRow) { } else if (position == newChatsSectionRow) {
privacyCell.setText(LocaleController.getString("ArchiveAndMuteInfo", R.string.ArchiveAndMuteInfo)); privacyCell.setText(LocaleController.getString("ArchiveAndMuteInfo", R.string.ArchiveAndMuteInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} }
break; break;
case 2: case 2:

View file

@ -1876,7 +1876,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
} }
finishFragment(); 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(); dialog.dismiss();
} }
}); });
@ -2193,6 +2196,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
setForegroundImage(true); setForegroundImage(true);
} }
if (photo == null || avatarsViewPager.getRealPosition() == 0) { 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); getMessagesController().deleteUserPhoto(null);
} else { } else {
TLRPC.TL_inputPhoto inputPhoto = new TLRPC.TL_inputPhoto(); TLRPC.TL_inputPhoto inputPhoto = new TLRPC.TL_inputPhoto();

View file

@ -899,6 +899,11 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
} }
break; break;
} }
case VIEW_TYPE_SHADOW: {
ShadowSectionCell shadowCell = (ShadowSectionCell) holder.itemView;
shadowCell.setTopBottom(position > 0, position < getItemCount() - 1);
break;
}
} }
} }

View file

@ -192,7 +192,15 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
emptyView.showProgress(); emptyView.showProgress();
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER)); 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) { listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
@Override @Override
public boolean supportsPredictiveItemAnimations() { public boolean supportsPredictiveItemAnimations() {
@ -799,7 +807,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
} else { } else {
privacyCell.setText(LocaleController.getString("TerminateWebSessionInfo", R.string.TerminateWebSessionInfo)); 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) { } else if (position == passwordSessionsDetailRow) {
privacyCell.setText(LocaleController.getString("LoginAttemptsInfo", R.string.LoginAttemptsInfo)); privacyCell.setText(LocaleController.getString("LoginAttemptsInfo", R.string.LoginAttemptsInfo));
if (otherSessionsTerminateDetail == -1) { 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)); privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} }
} else if (position == qrCodeDividerRow || position == ttlDivideRow || position == noOtherSessionsRow) { } 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.setText("");
privacyCell.setFixedSize(12); privacyCell.setFixedSize(12);
} }

View file

@ -1875,12 +1875,14 @@ public class ThemePreviewActivity extends BaseFragment implements DownloadContro
colorPicker.setMinBrightness(0.05f); colorPicker.setMinBrightness(0.05f);
colorPicker.setMaxBrightness(0.8f); colorPicker.setMaxBrightness(0.8f);
} }
if (accent != null) {
int colorsCount = accent.accentColor2 != 0 ? 2 : 1; int colorsCount = accent.accentColor2 != 0 ? 2 : 1;
colorPicker.setType(1, hasChanges(1), 2, colorsCount, false, 0, false); colorPicker.setType(1, hasChanges(1), 2, colorsCount, false, 0, false);
colorPicker.setColor(accent.accentColor, 0); colorPicker.setColor(accent.accentColor, 0);
if (accent.accentColor2 != 0) { if (accent.accentColor2 != 0) {
colorPicker.setColor(accent.accentColor2, 1); colorPicker.setColor(accent.accentColor2, 1);
} }
}
} else { } else {
patternLayout[a].addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 48)); patternLayout[a].addView(colorPicker, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER_HORIZONTAL, 0, 0, 0, 48));
} }

View file

@ -2445,6 +2445,8 @@
<string name="ClearCache">Clear Cache</string> <string name="ClearCache">Clear Cache</string>
<string name="ClearSelectedCache">Clear Selected</string> <string name="ClearSelectedCache">Clear Selected</string>
<string name="ClearCacheInfo">Free up disk space on your device; your media will stay in the cloud.</string> <string name="ClearCacheInfo">Free up disk space on your device; your media will stay in the cloud.</string>
<string name="ClearingCache">Clearing cache…</string>
<string name="ClearingCacheDescription">Please keep this window open while Telegram is clearing your cache.</string>
<string name="ChangePhoneNumber">Change Phone Number</string> <string name="ChangePhoneNumber">Change Phone Number</string>
<string name="ChangePhoneNumberInfo">Move your account, chats and media to a new number.</string> <string name="ChangePhoneNumberInfo">Move your account, chats and media to a new number.</string>
<string name="ChangePhoneNumberSuccessWithPhone">Your phone number has been successfully changed to %1$s.</string> <string name="ChangePhoneNumberSuccessWithPhone">Your phone number has been successfully changed to %1$s.</string>
@ -3490,6 +3492,7 @@
<string name="BotStatusCantRead">has no access to messages</string> <string name="BotStatusCantRead">has no access to messages</string>
<string name="BotInfoTitle">What can this bot do?</string> <string name="BotInfoTitle">What can this bot do?</string>
<string name="BotStart">START</string> <string name="BotStart">START</string>
<string name="BotStartButton">Start bot</string>
<string name="BotUnblock">RESTART</string> <string name="BotUnblock">RESTART</string>
<string name="BotStop">Stop bot</string> <string name="BotStop">Stop bot</string>
<string name="BotRestart">Restart bot</string> <string name="BotRestart">Restart bot</string>
@ -6353,8 +6356,9 @@
<string name="ChannelInviteViaLinkRestricted">You can\'t create a link</string> <string name="ChannelInviteViaLinkRestricted">You can\'t create a link</string>
<string name="ChannelInviteViaLinkRestricted2">This user can\'t be invited</string> <string name="ChannelInviteViaLinkRestricted2">This user can\'t be invited</string>
<string name="ChannelInviteViaLinkRestricted3">This users can\'t be invited</string> <string name="ChannelInviteViaLinkRestricted3">This users can\'t be invited</string>
<string name="StoragePathFree">%1$s free</string> <string name="StoragePathFreeInternal">%1$s free, high speed</string>
<string name="StoragePathFreeValue">%1$s free, %2$s</string> <string name="StoragePathFreeExternal">%1$s free, slow speed</string>\
<string name="StoragePathFreeValueExternal">%1$s free, slow speed %2$s</string>
<string name="AccDescrLiteBatteryWhenBelow">enabled when below %s%%</string> <string name="AccDescrLiteBatteryWhenBelow">enabled when below %s%%</string>
<string name="AccDescrLiteBatteryLevelAnnounce">%s%%</string> <string name="AccDescrLiteBatteryLevelAnnounce">%s%%</string>
<string name="AccDescrRateTranscriptionUp">Rate up</string> <string name="AccDescrRateTranscriptionUp">Rate up</string>
@ -6371,4 +6375,10 @@
<string name="LoginEmailResetPremiumRequiredTitle">Telegram Premium Required</string> <string name="LoginEmailResetPremiumRequiredTitle">Telegram Premium Required</string>
<string name="LoginEmailResetPremiumRequiredMessage">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**</string> <string name="LoginEmailResetPremiumRequiredMessage">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**</string>
<string name="LoginEmailResetPleaseWait">Resetting email, please wait...</string> <string name="LoginEmailResetPleaseWait">Resetting email, please wait...</string>
<string name="DecreaseSpeed">Decrease speed</string>
<string name="SdCardAlert">Storing on SD card will make Telegram slow. Proceed anyway?</string>
<string name="Proceed">Proceed</string>
<string name="SdCardError">SD Card Error</string>
<string name="SdCardErrorDescription">Telegram is unable to save data on your SD card.</string>
<string name="DoNotUseSDCard">Do not use SD card</string>
</resources> </resources>

View file

@ -67,8 +67,8 @@ android {
buildTypes { buildTypes {
HA_private { HA_private {
debuggable false debuggable true
jniDebuggable false jniDebuggable true
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
applicationIdSuffix ".beta" applicationIdSuffix ".beta"
minifyEnabled true minifyEnabled true

View file

@ -13,8 +13,8 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true # org.gradle.parallel=true
#Sat Mar 12 05:53:50 MSK 2016 #Sat Mar 12 05:53:50 MSK 2016
APP_VERSION_CODE=3227 APP_VERSION_CODE=3236
APP_VERSION_NAME=9.5.4 APP_VERSION_NAME=9.5.5
APP_PACKAGE=org.telegram.messenger APP_PACKAGE=org.telegram.messenger
RELEASE_KEY_PASSWORD=android RELEASE_KEY_PASSWORD=android
RELEASE_KEY_ALIAS=androidkey RELEASE_KEY_ALIAS=androidkey