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/MTProtoScheme.h"
#include "tgnet/ConnectionSocket.h"
#include "tgnet/FileLog.h"
JavaVM *java;
jclass jclass_RequestDelegateInternal;
@ -96,12 +97,15 @@ void sendRequest(JNIEnv *env, jclass c, jint instanceNum, jlong object, jobject
TL_api_request *request = new TL_api_request();
request->request = (NativeByteBuffer *) (intptr_t) object;
if (onComplete != nullptr) {
DEBUG_REF("sendRequest onComplete");
onComplete = env->NewGlobalRef(onComplete);
}
if (onQuickAck != nullptr) {
DEBUG_REF("sendRequest onQuickAck");
onQuickAck = env->NewGlobalRef(onQuickAck);
}
if (onWriteToSocket != nullptr) {
DEBUG_REF("sendRequest onWriteToSocket");
onWriteToSocket = env->NewGlobalRef(onWriteToSocket);
}
ConnectionsManager::getInstance(instanceNum).sendRequest(request, ([onComplete, instanceNum](TLObject *response, TL_error *error, int32_t networkType, int64_t responseTime, int64_t msgId) {
@ -238,6 +242,7 @@ jlong checkProxy(JNIEnv *env, jclass c, jint instanceNum, jstring address, jint
const char *secretStr = env->GetStringUTFChars(secret, 0);
if (requestTimeFunc != nullptr) {
DEBUG_REF("sendRequest requestTimeFunc");
requestTimeFunc = env->NewGlobalRef(requestTimeFunc);
}
@ -484,6 +489,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("RequestDelegateInternal class");
jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
@ -493,6 +499,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("RequestTimeDelegate class");
jclass_RequestTimeDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestTimeDelegate"));
if (jclass_RequestTimeDelegate == 0) {
return JNI_FALSE;
@ -502,6 +509,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("QuickAckDelegate class");
jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
@ -511,6 +519,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("WriteToSocketDelegate class");
jclass_WriteToSocketDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/WriteToSocketDelegate"));
if (jclass_WriteToSocketDelegate == 0) {
return JNI_FALSE;
@ -519,6 +528,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
if (jclass_WriteToSocketDelegate_run == 0) {
return JNI_FALSE;
}
DEBUG_REF("ConnectionsManager class");
jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager"));
if (jclass_ConnectionsManager == 0) {
return JNI_FALSE;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -22,6 +22,8 @@ bool LOGS_ENABLED = true;
bool LOGS_ENABLED = false;
#endif
bool REF_LOGS_ENABLED = false;
FileLog &FileLog::getInstance() {
static FileLog instance;
return instance;
@ -166,3 +168,43 @@ void FileLog::d(const char *message, ...) {
va_end(argptr);
}
static int refsCount = 0;
void FileLog::ref(const char *message, ...) {
if (!REF_LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
time_t t = time(0);
struct tm *now = localtime(&t);
refsCount++;
#ifdef ANDROID
std::ostringstream s;
s << refsCount << " refs (+ref): " << message;
__android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr);
va_end(argptr);
va_start(argptr, message);
#endif
va_end(argptr);
}
void FileLog::delref(const char *message, ...) {
if (!REF_LOGS_ENABLED) {
return;
}
va_list argptr;
va_start(argptr, message);
time_t t = time(0);
struct tm *now = localtime(&t);
refsCount--;
#ifdef ANDROID
std::ostringstream s;
s << refsCount << " refs (-ref): " << message;
__android_log_vprint(ANDROID_LOG_VERBOSE, "tgnetREF", s.str().c_str(), argptr);
va_end(argptr);
va_start(argptr, message);
#endif
va_end(argptr);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -493,6 +493,16 @@ public class AndroidUtilities {
}
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()) {
AndroidUtilities.runOnUIThread(() -> Utilities.globalQueue.postRunnable(() -> {
for (int i = 0; i < bitmapToRecycle.size(); i++) {
@ -505,7 +515,7 @@ public class AndroidUtilities {
}
}
}
}), Build.VERSION.SDK_INT <= 23 ? 100 : 36);
}), 36);
}
}
@ -628,6 +638,11 @@ public class AndroidUtilities {
if (TextUtils.indexOf(s, '─') >= 0) {
s = new SpannableStringBuilder(s.toString().replace('─', ' '));
}
if (TextUtils.lastIndexOf(s, '_') == s.length() - 1) {
//fix infinity loop regex
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(s.toString());
s = spannableStringBuilder.replace(s.length() - 1, s.length(), "a");
}
Matcher m = pattern.matcher(s);
while (m.find()) {
int start = m.start();
@ -4782,6 +4797,13 @@ public class AndroidUtilities {
);
}
public static boolean isEROFS(Exception e) {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && e instanceof IOException &&
(e.getCause() instanceof ErrnoException && ((ErrnoException) e.getCause()).errno == OsConstants.EROFS) ||
(e.getMessage() != null && e.getMessage().toLowerCase().contains("read-only file system"))
);
}
public static CharSequence replaceCharSequence(String what, CharSequence from, CharSequence obj) {
SpannableStringBuilder spannableStringBuilder;
if (from instanceof SpannableStringBuilder) {

View file

@ -103,13 +103,16 @@ public class AutoDeleteMediaTask {
}
long lastUsageTime = Utilities.getLastUsageFileTime(file.file.getAbsolutePath());
long timeLocal = time - seconds;
boolean needDelete = lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath());
boolean needDelete = lastUsageTime > 316000000 && lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath());
if (needDelete) {
try {
if (BuildVars.LOGS_ENABLED) {
autoDeletedFiles++;
autoDeletedFilesSize += file.file.length();
}
if (BuildVars.DEBUG_PRIVATE_VERSION) {
FileLog.d("delete file " + file.file.getPath() + " last_usage_time=" + lastUsageTime + " time_local=" + timeLocal);
}
file.file.delete();
} catch (Exception exception) {
FileLog.e(exception);

View file

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

View file

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

View file

@ -204,7 +204,7 @@ public class FileLoader extends BaseController {
filePathDatabase = new FilePathDatabase(instance);
for (int i = 0; i < smallFilesQueue.length; i++) {
smallFilesQueue[i] = new FileLoaderPriorityQueue("smallFilesQueue dc" + (i + 1), 5);
largeFilesQueue[i] = new FileLoaderPriorityQueue("largeFilesQueue dc" + (i + 1), 2);
largeFilesQueue[i] = new FileLoaderPriorityQueue("largeFilesQueue dc" + (i + 1), 1);
}
dumpFilesQueue();
}
@ -667,11 +667,9 @@ public class FileLoader extends BaseController {
getDownloadController().startDownloadFile(document, (MessageObject) parentObject);
}
FileLoadOperation operation = loadOperationPaths.get(fileName);
final String finalFileName = fileName;
FileLoadOperation operation = loadOperationPaths.get(finalFileName);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("checkFile operation fileName=" + fileName + " documentName=" + getDocumentFileName(document) + " operation=" + operation + " priority=" + priority + " account=" + currentAccount);
}
priority = getPriorityValue(priority);
if (operation != null) {
@ -684,6 +682,7 @@ public class FileLoader extends BaseController {
operation.getQueue().add(operation);
operation.updateProgress();
operation.getQueue().checkLoadingOperations();
FileLog.d("load operation update position fileName=" + finalFileName + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount);
return operation;
}
@ -734,18 +733,11 @@ public class FileLoader extends BaseController {
}
FileLoaderPriorityQueue loaderQueue;
int index = Utilities.clamp(operation.getDatacenterId() - 1, 4, 0);
if (operation.totalBytesCount > 20 * 1024 * 1024) {
if (operation.totalBytesCount > 20 * 1024 * 1024) {//20mb
loaderQueue = largeFilesQueue[index];
} else {
loaderQueue = smallFilesQueue[index];
}
// if (type == MEDIA_DIR_AUDIO) {
// loaderQueue = audioQueue;
// } else if (secureDocument != null || location != null && (imageLocation == null || imageLocation.imageType != IMAGE_TYPE_ANIMATION) || MessageObject.isImageWebDocument(webDocument) || MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isVideoStickerDocument(document)) {
// loaderQueue = imagesQueue;
// } else {
// }
String storeFileName = fileName;
@ -804,6 +796,20 @@ public class FileLoader extends BaseController {
final int finalType = type;
FileLoadOperation.FileLoadOperationDelegate fileLoadOperationDelegate = new FileLoadOperation.FileLoadOperationDelegate() {
@Override
public void didPreFinishLoading(FileLoadOperation operation, File finalFile) {
FileLoaderPriorityQueue queue = operation.getQueue();
fileLoaderQueue.postRunnable(() -> {
FileLoadOperation currentOperation = loadOperationPaths.remove(fileName);
if (currentOperation != null) {
currentOperation.preFinished = true;
queue.checkLoadingOperations();
}
});
checkDownloadQueue(operation.getQueue(), fileName);
}
@Override
public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) {
if (!operation.isPreloadVideoOperation() && operation.isPreloadFinished()) {
@ -864,16 +870,16 @@ public class FileLoader extends BaseController {
};
operation.setDelegate(fileLoadOperationDelegate);
loadOperationPaths.put(fileName, operation);
loadOperationPaths.put(finalFileName, operation);
operation.setPriority(priority);
operation.setStream(stream, streamPriority, streamOffset);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document));
}
loaderQueue.add(operation);
loaderQueue.checkLoadingOperations();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount);
}
return operation;
}
@ -1681,8 +1687,8 @@ public class FileLoader extends BaseController {
Runnable dumpFilesQueueRunnable = () -> {
for (int i = 0; i < smallFilesQueue.length; i++) {
if (smallFilesQueue[i].allOperations.size() > 0 || largeFilesQueue[i].allOperations.size() > 0) {
FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].allOperations.size() + " large_operations=" + largeFilesQueue[i].allOperations.size());
if (smallFilesQueue[i].getCount() > 0 || largeFilesQueue[i].getCount() > 0) {
FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].getCount() + " large_operations=" + largeFilesQueue[i].getCount());
}
}
dumpFilesQueue();

View file

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

View file

@ -170,7 +170,7 @@ public class FilePathDatabase {
FileLog.d("get file path id=" + documentId + " dc=" + dc + " type=" + type + " path=" + res[0]);
}
}
} catch (SQLiteException e) {
} catch (Throwable e) {
FileLog.e(e);
} finally {
if (cursor != null) {
@ -287,10 +287,11 @@ public class FilePathDatabase {
MessageObject messageObject = arrayListFinal.get(i);
messageObject.checkMediaExistance(false);
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Throwable e) {
FileLog.e(e);
} finally {
syncLatch.countDown();
}
});
try {
@ -332,8 +333,9 @@ public class FilePathDatabase {
}
} catch (Exception e) {
FileLog.e(e);
}
} finally {
syncLatch.countDown();
}
});
try {
@ -344,7 +346,7 @@ public class FilePathDatabase {
return res[0];
}
public void saveFileDialogId(File file,FileMeta fileMeta) {
public void saveFileDialogId(File file, FileMeta fileMeta) {
if (file == null || fileMeta == null) {
return;
}
@ -417,7 +419,7 @@ public class FilePathDatabase {
for (int i = 0; i < filesToRemove.size(); i++) {
database.executeFast("DELETE FROM paths_by_dialog_id WHERE path = '" + shield(filesToRemove.get(i).file.getPath()) + "'").stepThis().dispose();
}
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
} finally {
database.commitTransaction();
@ -443,10 +445,11 @@ public class FilePathDatabase {
list.add(keepMediaFiles.get(i));
}
}
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
}
} finally {
syncLatch.countDown();
}
});
try {
syncLatch.await();

View file

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

View file

@ -1433,52 +1433,8 @@ public class ImageLoader {
Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable);
file.close();
} else {
String DEBUG_TAG = "secured_document_image";
try {
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d( DEBUG_TAG + " try get image from secured document " + secureDocumentKey + " encryption path " + cacheImage.encryptionKeyPath);
}
RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r");
int len = (int) f.length();
int offset = 0;
byte[] bytes = bytesLocal.get();
byte[] data = bytes != null && bytes.length >= len ? bytes : null;
if (data == null) {
bytes = data = new byte[len];
bytesLocal.set(bytes);
}
f.readFully(data, 0, len);
f.close();
boolean error = false;
if (secureDocumentKey != null) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey);
byte[] hash = Utilities.computeSHA256(data, 0, len);
if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) {
error = true;
}
offset = (data[0] & 0xff);
len -= offset;
} else if (inEncryptedFile) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath);
}
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " check error " + error);
}
if (!error) {
image = BitmapFactory.decodeByteArray(data, offset, len, opts);
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d( DEBUG_TAG + " image " + image);
}
}
} catch (Throwable e) {
FileLog.e(e);
}
if (image == null) {
FileInputStream is;
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " try get image from stream ");
}
if (secureDocumentKey != null) {
is = new EncryptedFileInputStream(cacheFileFinal, secureDocumentKey);
} else if (inEncryptedFile) {
@ -1517,9 +1473,38 @@ public class ImageLoader {
}
image = BitmapFactory.decodeStream(is, null, opts);
is.close();
}
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " image2 " + image);
if (image == null) {
try {
RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r");
int len = (int) f.length();
int offset = 0;
byte[] bytes = bytesLocal.get();
byte[] data = bytes != null && bytes.length >= len ? bytes : null;
if (data == null) {
bytes = data = new byte[len];
bytesLocal.set(bytes);
}
f.readFully(data, 0, len);
f.close();
boolean error = false;
if (secureDocumentKey != null) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey);
byte[] hash = Utilities.computeSHA256(data, 0, len);
if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) {
error = true;
}
offset = (data[0] & 0xff);
len -= offset;
} else if (inEncryptedFile) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath);
}
if (!error) {
image = BitmapFactory.decodeByteArray(data, offset, len, opts);
}
} catch (Throwable e) {
FileLog.e(e);
}
}
}

View file

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

View file

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

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) {
if (locale == null) {
return "en";

View file

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

View file

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

View file

@ -13137,6 +13137,7 @@ public class MessagesStorage extends BaseController {
try {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state, custom_params FROM messages_v2 WHERE mid = %d AND uid = %d LIMIT 1", message.id, MessageObject.getDialogId(message)));
if (!cursor.next()) {
cursor.dispose();
return;
}
readState = cursor.intValue(1);

View file

@ -10,7 +10,9 @@ package org.telegram.messenger;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.os.Build;
@ -27,7 +29,11 @@ import org.json.JSONObject;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.CacheControlActivity;
import org.telegram.ui.Components.SwipeGestureSettingsView;
import org.telegram.ui.LaunchActivity;
import java.io.File;
import java.io.RandomAccessFile;
@ -57,6 +63,40 @@ public class SharedConfig {
return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_CHAT);
}
public static boolean readOnlyStorageDirAlertShowed;
public static void checkSdCard(File file) {
if (file == null || SharedConfig.storageCacheDir == null || readOnlyStorageDirAlertShowed) {
return;
}
if (file.getPath().startsWith(SharedConfig.storageCacheDir)) {
AndroidUtilities.runOnUIThread(() -> {
if (readOnlyStorageDirAlertShowed) {
return;
}
BaseFragment fragment = LaunchActivity.getLastFragment();
if (fragment != null && fragment.getParentActivity() != null) {
SharedConfig.storageCacheDir = null;
SharedConfig.saveConfig();
ImageLoader.getInstance().checkMediaPaths(() -> {
});
readOnlyStorageDirAlertShowed = true;
AlertDialog.Builder dialog = new AlertDialog.Builder(fragment.getParentActivity());
dialog.setTitle(LocaleController.getString("SdCardError", R.string.SdCardError));
dialog.setSubtitle(LocaleController.getString("SdCardErrorDescription", R.string.SdCardErrorDescription));
dialog.setPositiveButton(LocaleController.getString("DoNotUseSDCard", R.string.DoNotUseSDCard), (dialog1, which) -> {
});
Dialog dialogFinal = dialog.create();
dialogFinal.setCanceledOnTouchOutside(false);
dialogFinal.show();
}
});
}
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PASSCODE_TYPE_PIN,

View file

@ -419,7 +419,11 @@ public class ConnectionsManager extends BaseController {
}
public void checkConnection() {
native_setIpStrategy(currentAccount, getIpStrategy());
byte selectedStrategy = getIpStrategy();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("selected ip strategy " + selectedStrategy);
}
native_setIpStrategy(currentAccount, selectedStrategy);
native_setNetworkAvailable(currentAccount, ApplicationLoader.isNetworkOnline(), ApplicationLoader.getCurrentNetworkType(), ApplicationLoader.isConnectionSlow());
}

View file

@ -213,7 +213,7 @@ public class AlertDialog extends Dialog implements Drawable.Callback, Notificati
super(context);
this.resourcesProvider = resourcesProvider;
setBackgroundDrawable(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 2));
setBackground(Theme.createSelectorDrawable(getThemedColor(Theme.key_dialogButtonSelector), 2));
setPadding(AndroidUtilities.dp(23), 0, AndroidUtilities.dp(23), 0);
imageView = new ImageView(context);

View file

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

View file

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

View file

@ -913,7 +913,7 @@ public class SimpleTextView extends View implements Drawable.Callback {
}
if (rightDrawable != null && rightDrawableOutside) {
int x = Math.min(textOffsetX + textWidth + drawablePadding + (scrollingOffset == 0 ? -nextScrollX : (int) -scrollingOffset) + nextScrollX, getMaxTextWidth() - paddingRight + drawablePadding - AndroidUtilities.dp(4));
int x = Math.min(textOffsetX + textWidth + drawablePadding + (scrollingOffset == 0 ? -nextScrollX : (int) -scrollingOffset) + nextScrollX, getMaxTextWidth() - paddingRight + drawablePadding);
int dw = (int) (rightDrawable.getIntrinsicWidth() * rightDrawableScale);
int dh = (int) (rightDrawable.getIntrinsicHeight() * rightDrawableScale);
int y;

View file

@ -20,6 +20,7 @@ import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
@ -44,6 +45,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.graphics.ColorUtils;
import androidx.core.math.MathUtils;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -96,6 +98,7 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.ListView.AdapterWithDiffUtils;
import org.telegram.ui.Components.LoadingDrawable;
import org.telegram.ui.Components.NestedSizeNotifierLayout;
import org.telegram.ui.Components.RLottieImageView;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SlideChooseView;
import org.telegram.ui.Components.StorageDiagramView;
@ -105,6 +108,9 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Storage.CacheModel;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -817,7 +823,7 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
return size;
}
private void cleanupFolders() {
private void cleanupFolders(Utilities.Callback2<Float, Boolean> onProgress, Runnable onDone) {
if (cacheModel != null) {
cacheModel.clearSelection();
}
@ -826,22 +832,125 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
cachedMediaLayout.showActionMode(false);
}
progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER);
progressDialog.setCanCancel(false);
progressDialog.showDelayed(500);
// progressDialog = new AlertDialog(getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER);
// progressDialog.setCanCancel(false);
// progressDialog.showDelayed(500);
getFileLoader().cancelLoadAllFiles();
getFileLoader().getFileLoaderQueue().postRunnable(() -> Utilities.globalQueue.postRunnable(() -> {
cleanupFoldersInternal();
cleanupFoldersInternal(onProgress, onDone);
}));
setCacheModel(null);
loadingDialogs = true;
// updateRows();
}
private void cleanupFoldersInternal() {
private static int LISTDIR_DOCTYPE_ALL = 0;
private static int LISTDIR_DOCTYPE_OTHER_THAN_MUSIC = 1;
private static int LISTDIR_DOCTYPE_MUSIC = 2;
private static int LISTDIR_DOCTYPE2_EMOJI = 3;
private static int LISTDIR_DOCTYPE2_TEMP = 4;
private static int LISTDIR_DOCTYPE2_OTHER = 5;
public static int countDirJava(String fileName, int docType) {
int count = 0;
File dir = new File(fileName);
if (dir.exists()) {
File[] entries = dir.listFiles();
for (int i = 0; i < entries.length; ++i) {
File entry = entries[i];
String name = entry.getName();
if (".".equals(name)) {
continue;
}
if (docType > 0 && name.length() >= 4) {
String namelc = name.toLowerCase();
boolean isMusic = namelc.endsWith(".mp3") || namelc.endsWith(".m4a");
boolean isEmoji = namelc.endsWith(".tgs") || namelc.endsWith(".webm");
boolean isTemp = namelc.endsWith(".tmp") || namelc.endsWith(".temp") || namelc.endsWith(".preload");
if (
isMusic && docType == LISTDIR_DOCTYPE_OTHER_THAN_MUSIC ||
!isMusic && docType == LISTDIR_DOCTYPE_MUSIC ||
isEmoji && docType == LISTDIR_DOCTYPE2_OTHER ||
!isEmoji && docType == LISTDIR_DOCTYPE2_EMOJI ||
isTemp && docType == LISTDIR_DOCTYPE2_OTHER ||
!isTemp && docType == LISTDIR_DOCTYPE2_TEMP
) {
continue;
}
}
if (entry.isDirectory()) {
count += countDirJava(fileName + "/" + name, docType);
} else {
count++;
}
}
}
return count;
}
public static void cleanDirJava(String fileName, int docType, int[] p, Utilities.Callback<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;
long clearedSize = 0;
boolean allItemsClear = true;
final int[] clearDirI = new int[] { 0 };
int clearDirCount = (selected[0] ? 2 : 0) + (selected[1] ? 2 : 0) + (selected[2] ? 2 : 0) + (selected[3] ? 2 : 0) + (selected[4] ? 1 : 0) + (selected[5] ? 2 : 0) + (selected[6] ? 1 : 0) + (selected[7] ? 1 : 0);
long time = System.currentTimeMillis();
Utilities.Callback<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++) {
if (!selected[a]) {
allItemsClear = false;
@ -888,13 +997,17 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
file = FileLoader.checkDirectory(type);
}
if (file != null) {
Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false);
cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress);
}
clearDirI[0]++;
next.run();
if (type == 100) {
file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_CACHE);
if (file != null) {
Utilities.clearDir(file.getAbsolutePath(), 3, Long.MAX_VALUE, false);
cleanDirJava(file.getAbsolutePath(), 3, null, updateProgress);
}
clearDirI[0]++;
next.run();
}
if (type == FileLoader.MEDIA_DIR_IMAGE || type == FileLoader.MEDIA_DIR_VIDEO) {
int publicDirectoryType;
@ -906,14 +1019,18 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
file = FileLoader.checkDirectory(publicDirectoryType);
if (file != null) {
Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false);
cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress);
}
clearDirI[0]++;
next.run();
}
if (type == FileLoader.MEDIA_DIR_DOCUMENT) {
file = FileLoader.checkDirectory(FileLoader.MEDIA_DIR_FILES);
if (file != null) {
Utilities.clearDir(file.getAbsolutePath(), documentsMusicType, Long.MAX_VALUE, false);
cleanDirJava(file.getAbsolutePath(), documentsMusicType, null, updateProgress);
}
clearDirI[0]++;
next.run();
}
if (type == FileLoader.MEDIA_DIR_CACHE) {
@ -1000,6 +1117,10 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
MediaDataController.getInstance(currentAccount).chekAllMedia(true);
loadDialogEntities();
if (onDone != null) {
onDone.run();
}
});
}
@ -1688,13 +1809,144 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
}
}
private class ClearingCacheView extends FrameLayout {
RLottieImageView imageView;
AnimatedTextView percentsTextView;
ProgressView progressView;
TextView title, subtitle;
public ClearingCacheView(Context context) {
super(context);
imageView = new RLottieImageView(context);
imageView.setAutoRepeat(true);
imageView.setAnimation(R.raw.utyan_cache, 150, 150);
addView(imageView, LayoutHelper.createFrame(150, 150, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16, 0, 0));
imageView.playAnimation();
percentsTextView = new AnimatedTextView(context, false, true, true);
percentsTextView.setAnimationProperties(.35f, 0, 120, CubicBezierInterpolator.EASE_OUT);
percentsTextView.setGravity(Gravity.CENTER_HORIZONTAL);
percentsTextView.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
percentsTextView.setTextSize(AndroidUtilities.dp(24));
percentsTextView.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
addView(percentsTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 32, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 - 6, 0, 0));
progressView = new ProgressView(context);
addView(progressView, LayoutHelper.createFrame(240, 5, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16, 0, 0));
title = new TextView(context);
title.setGravity(Gravity.CENTER_HORIZONTAL);
title.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
title.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
title.setText(LocaleController.getString("ClearingCache", R.string.ClearingCache));
addView(title, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16 + 5 + 30, 0, 0));
subtitle = new TextView(context);
subtitle.setGravity(Gravity.CENTER_HORIZONTAL);
subtitle.setTextColor(Theme.getColor(Theme.key_dialogTextBlack));
subtitle.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
subtitle.setText(LocaleController.getString("ClearingCacheDescription", R.string.ClearingCacheDescription));
addView(subtitle, LayoutHelper.createFrame(240, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP, 0, 16 + 150 + 16 + 28 + 16 + 5 + 30 + 18 + 10, 0, 0));
setProgress(0);
}
public void setProgress(float t) {
percentsTextView.cancelAnimation();
percentsTextView.setText(String.format("%d%%", (int) Math.ceil(MathUtils.clamp(t, 0, 1) * 100)), !LocaleController.isRTL);
progressView.setProgress(t);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(
MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(350), MeasureSpec.EXACTLY)
);
}
class ProgressView extends View {
Paint in = new Paint(Paint.ANTI_ALIAS_FLAG), out = new Paint(Paint.ANTI_ALIAS_FLAG);
public ProgressView(Context context) {
super(context);
in.setColor(Theme.getColor(Theme.key_switchTrackChecked));
out.setColor(Theme.multAlpha(Theme.getColor(Theme.key_switchTrackChecked), .2f));
}
float progress;
AnimatedFloat progressT = new AnimatedFloat(this, 350, CubicBezierInterpolator.EASE_OUT);
public void setProgress(float t) {
this.progress = t;
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), out);
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth() * progressT.set(this.progress), getMeasuredHeight());
canvas.drawRoundRect(AndroidUtilities.rectTmp, AndroidUtilities.dp(3), AndroidUtilities.dp(3), in);
}
}
}
private class ClearCacheButtonInternal extends ClearCacheButton {
public ClearCacheButtonInternal(Context context) {
super(context);
((MarginLayoutParams) button.getLayoutParams()).topMargin = AndroidUtilities.dp(5);
button.setOnClickListener(e -> {
cleanupFolders();
BottomSheet bottomSheet = new BottomSheet(getContext(), false) {
@Override
protected boolean canDismissWithTouchOutside() {
return false;
}
};
bottomSheet.fixNavigationBar();
bottomSheet.setCanDismissWithSwipe(false);
bottomSheet.setCancelable(false);
ClearingCacheView cacheView = new ClearingCacheView(getContext());
bottomSheet.setCustomView(cacheView);
final boolean[] done = new boolean[] { false };
final float[] progress = new float[] { 0 };
final boolean[] nextSection = new boolean[] { false };
Runnable updateProgress = () -> {
cacheView.setProgress(progress[0]);
if (nextSection[0]) {
updateRows();
}
};
AndroidUtilities.runOnUIThread(() -> {
if (!done[0]) {
showDialog(bottomSheet);
}
}, 150);
cleanupFolders(
(progressValue, next) -> {
progress[0] = progressValue;
nextSection[0] = next;
AndroidUtilities.cancelRunOnUIThread(updateProgress);
AndroidUtilities.runOnUIThread(updateProgress);
},
() -> AndroidUtilities.runOnUIThread(() -> {
done[0] = true;
cacheView.setProgress(1F);
bottomSheet.dismiss();
})
);
});
}
@ -1772,8 +2024,6 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
}
};
button.setBackground(Theme.AdaptiveRipple.filledRect(Theme.key_featuredStickers_addButton, 8));
button.setFocusable(true);
button.setFocusableInTouchMode(true);
button.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
if (LocaleController.isRTL) {
@ -1803,6 +2053,8 @@ public class CacheControlActivity extends BaseFragment implements NotificationCe
valueTextView.setTextColor(Theme.adaptHSV(Theme.getColor(Theme.key_featuredStickers_addButton), -.46f, +.08f));
valueTextView.setText("");
button.setContentDescription(TextUtils.concat(textView.getText(), "\t", valueTextView.getText()));
setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite));
addView(button, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.FILL, 16, 16, 16, 16));
}

View file

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

View file

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

View file

@ -22,6 +22,12 @@ public class ShadowSectionCell extends View {
private int size;
private int backgroundColor;
private Theme.ResourcesProvider resourcesProvider;
private boolean top = true;
private boolean bottom = true;
public ShadowSectionCell(Context context) {
this(context, 12, null);
}
@ -36,8 +42,9 @@ public class ShadowSectionCell extends View {
public ShadowSectionCell(Context context, int s, Theme.ResourcesProvider resourcesProvider) {
super(context);
setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)));
size = s;
this.resourcesProvider = resourcesProvider;
this.size = s;
updateBackground();
}
public ShadowSectionCell(Context context, int s, int backgroundColor) {
@ -46,12 +53,50 @@ public class ShadowSectionCell extends View {
public ShadowSectionCell(Context context, int s, int backgroundColor, Theme.ResourcesProvider resourcesProvider) {
super(context);
Drawable shadowDrawable = Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider));
this.resourcesProvider = resourcesProvider;
this.backgroundColor = backgroundColor;
this.size = s;
updateBackground();
}
public void setTopBottom(boolean top, boolean bottom) {
if (this.top != top || this.bottom != bottom) {
this.top = top;
this.bottom = bottom;
updateBackground();
}
}
private void updateBackground() {
if (backgroundColor == 0) {
if (!top && !bottom) {
setBackground(null);
} else {
setBackground(Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)));
}
} else {
if (!top && !bottom) {
setBackgroundColor(backgroundColor);
} else {
Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider));
Drawable background = new ColorDrawable(backgroundColor);
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
setBackgroundDrawable(combinedDrawable);
size = s;
setBackground(combinedDrawable);
}
}
}
private int getBackgroundResId() {
if (top && bottom) {
return R.drawable.greydivider;
} else if (top) {
return R.drawable.greydivider_bottom;
} else if (bottom) {
return R.drawable.greydivider_top;
} else {
return R.drawable.transparent;
}
}
@Override

View file

@ -295,6 +295,7 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Components.UnreadCounterTextView;
import org.telegram.ui.Components.ViewHelper;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import org.telegram.ui.Components.voip.VoIPHelper;
import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate;
@ -378,6 +379,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private GridLayoutManagerFixed chatLayoutManager;
private ChatActivityAdapter chatAdapter;
private UnreadCounterTextView bottomOverlayChatText;
private TextView bottomOverlayStartButton;
private ImageView bottomOverlayImage;
private RadialProgressView bottomOverlayProgress;
private AnimatorSet bottomOverlayAnimation;
@ -5001,26 +5003,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public void onScrolled(int dx, int dy) {
super.onScrolled(dx, dy);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@ -5031,7 +5013,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
chatListViewAttached = false;
clearMessagesPreloading();
}
};
if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) {
@ -5387,7 +5368,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
scrollingChatListView = false;
checkTextureViewPosition = false;
hideFloatingDateView(true);
checkAutoDownloadMessages(scrollUp);
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512);
}
@ -6674,6 +6654,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
bottomOverlayChat.setClipChildren(false);
contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM));
bottomOverlayStartButton = new TextView(context) {
CellFlickerDrawable cellFlickerDrawable;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cellFlickerDrawable == null) {
cellFlickerDrawable = new CellFlickerDrawable();
cellFlickerDrawable.drawFrame = false;
cellFlickerDrawable.repeatProgress = 2f;
}
cellFlickerDrawable.setParentWidth(getMeasuredWidth());
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null);
invalidate();
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
ViewGroup.LayoutParams params = bottomOverlayChat.getLayoutParams();
params.height = AndroidUtilities.dp(visibility == VISIBLE ? 51 + 8 * 2 : 51);
}
};
bottomOverlayStartButton.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 8));
bottomOverlayStartButton.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText));
bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStartButton));
bottomOverlayStartButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
bottomOverlayStartButton.setGravity(Gravity.CENTER);
bottomOverlayStartButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
bottomOverlayStartButton.setVisibility(View.GONE);
bottomOverlayStartButton.setOnClickListener(v -> bottomOverlayChatText.callOnClick());
bottomOverlayChat.addView(bottomOverlayStartButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 8, 8, 8, 8));
bottomOverlayChatText = new UnreadCounterTextView(context) {
@Override
protected void updateCounter() {
@ -10189,127 +10204,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showDialog(chatAttachAlert);
}
ArrayList<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) {
if (floatingDateView == null) {
return;
@ -11748,7 +11642,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) {
if (messageCell != null) {
if (!blurEnabled) {
if (blurEnabled) {
messageCell.setVisibleOnScreen(false);
} else {
messageCell.setVisibleOnScreen(true);
@ -13763,9 +13657,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
invalidateMessagesVisiblePart();
updateTextureViewPosition(false, false);
if (!scrollingChatListView) {
checkAutoDownloadMessages(false);
}
notifyHeightChanged();
}
@ -15337,6 +15228,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int loaded_max_id = (Integer) args[12];
int loaded_mentions_count = chatWasReset ? 0 : (Integer) args[13];
if (did == dialog_id && count > 0 && currentUser != null && (bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() == View.VISIBLE)) {
if (!TextUtils.isEmpty(botUser)) {
getMessagesController().sendBotStart(currentUser, botUser);
bottomOverlayChat.setVisibility(View.GONE);
chatActivityEnterView.setVisibility(View.VISIBLE);
}
}
if (loaded_mentions_count < 0) {
loaded_mentions_count *= -1;
hasAllMentionsLocal = false;
@ -16317,9 +16217,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else if (id == NotificationCenter.didUpdateConnectionState) {
int state = ConnectionsManager.getInstance(account).getConnectionState();
if (state == ConnectionsManager.ConnectionStateConnected) {
checkAutoDownloadMessages(false);
}
} else if (id == NotificationCenter.chatOnlineCountDidLoad) {
Long chatId = (Long) args[0];
if (chatInfo == null || currentChat == null || currentChat.id != chatId) {
@ -20624,7 +20521,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
showBottomOverlayProgress(false, true);
} else if (botUser != null && currentUser.bot) {
bottomOverlayChatText.setText(LocaleController.getString("BotStart", R.string.BotStart));
// bottomOverlayStartButton.setText(LocaleController.getString("BotStart", R.string.BotStart));
bottomOverlayStartButton.setVisibility(View.VISIBLE);
bottomOverlayChatText.setVisibility(View.GONE);
chatActivityEnterView.hidePopup(false);
if (getParentActivity() != null) {
AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus());
@ -20648,6 +20547,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatActivityEnterView.setVisibility(View.INVISIBLE);
} else if (searchItem != null && searchItemVisible) {
createSearchContainer();
if (searchContainer == null) {
return;
}
searchContainer.animate().setListener(null).cancel();
if (searchContainer.getVisibility() != View.VISIBLE) {
searchContainer.setVisibility(View.VISIBLE);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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);
emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(64);
} else {
pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), getThemedColor(Theme.key_listSelector)));
pickerBottomLayout.setBackground(Theme.createSelectorWithBackgroundDrawable(getThemedColor(Theme.key_dialogBackground), Theme.multAlpha(getThemedColor(Theme.key_dialogTextRed), .1f)));
pickerBottomFrameLayout.setBackgroundColor(Color.TRANSPARENT);
params.leftMargin = params.topMargin = params.rightMargin = params.bottomMargin = 0;
emptyParams.bottomMargin = gridParams.bottomMargin = shadowParams.bottomMargin = AndroidUtilities.dp(48);

View file

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

View file

@ -490,6 +490,11 @@ public class ContentPreviewViewer {
icons.add(R.drawable.msg_send);
actions.add(0);
}
if (delegate.needSend(currentContentType) && !delegate.isInScheduleMode()) {
items.add(LocaleController.getString("SendWithoutSound", R.string.SendWithoutSound));
icons.add(R.drawable.input_notify_off);
actions.add(4);
}
if (delegate.canSchedule()) {
items.add(LocaleController.getString("Schedule", R.string.Schedule));
icons.add(R.drawable.msg_autodelete);
@ -528,6 +533,8 @@ public class ContentPreviewViewer {
int which = (int) v.getTag();
if (actions.get(which) == 0) {
delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, true, 0);
} else if (actions.get(which) == 4) {
delegate.sendGif(currentDocument != null ? currentDocument : inlineResult, parentObject, false, 0);
} else if (actions.get(which) == 1) {
MediaDataController.getInstance(currentAccount).removeRecentGif(currentDocument);
delegate.gifAddedOrDeleted();

View file

@ -22,6 +22,7 @@ import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@ -45,13 +46,13 @@ import org.telegram.ui.ActionBar.ThemeDescription;
import org.telegram.ui.Cells.HeaderCell;
import org.telegram.ui.Cells.LanguageCell;
import org.telegram.ui.Cells.NotificationsCheckCell;
import org.telegram.ui.Cells.RadioColorCell;
import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Cells.TextCell;
import org.telegram.ui.Cells.TextCheckCell;
import org.telegram.ui.Cells.TextInfoPrivacyCell;
import org.telegram.ui.Cells.TextSettingsCell;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.voip.VoIPHelper;
@ -73,7 +74,7 @@ public class DataSettingsActivity extends BaseFragment {
private int roamingRow;
private int wifiRow;
private int storageNumRow;
private int resetDownloadRow;
private int resetDownloadRow = -1;
private int mediaDownloadSection2Row;
private int usageSectionRow;
private int storageUsageRow;
@ -117,6 +118,12 @@ public class DataSettingsActivity extends BaseFragment {
super.onFragmentCreate();
DownloadController.getInstance(currentAccount).loadAutoDownloadConfig(true);
updateRows(true);
return true;
}
private void updateRows(boolean fullNotify) {
rowCount = 0;
usageSectionRow = rowCount++;
@ -134,7 +141,25 @@ public class DataSettingsActivity extends BaseFragment {
mobileRow = rowCount++;
wifiRow = rowCount++;
roamingRow = rowCount++;
resetDownloadRow = rowCount++;
DownloadController dc = getDownloadController();
boolean isDefault = !(
!dc.lowPreset.equals(dc.getCurrentRoamingPreset()) || dc.lowPreset.isEnabled() != dc.roamingPreset.enabled ||
!dc.mediumPreset.equals(dc.getCurrentMobilePreset()) || dc.mediumPreset.isEnabled() != dc.mobilePreset.enabled ||
!dc.highPreset.equals(dc.getCurrentWiFiPreset()) || dc.highPreset.isEnabled() != dc.wifiPreset.enabled
);
int wasResetDownloadRow = resetDownloadRow;
resetDownloadRow = isDefault ? -1 : rowCount++;
if (listAdapter != null && !fullNotify) {
if (wasResetDownloadRow < 0 && resetDownloadRow >= 0) {
listAdapter.notifyItemChanged(roamingRow);
listAdapter.notifyItemInserted(resetDownloadRow);
} else if (wasResetDownloadRow >= 0 && resetDownloadRow < 0) {
listAdapter.notifyItemChanged(roamingRow);
listAdapter.notifyItemRemoved(wasResetDownloadRow);
} else {
fullNotify = true;
}
}
mediaDownloadSection2Row = rowCount++;
saveToGallerySectionRow = rowCount++;
@ -169,7 +194,9 @@ public class DataSettingsActivity extends BaseFragment {
clearDraftsRow = rowCount++;
clearDraftsSectionRow = rowCount++;
return true;
if (listAdapter != null && fullNotify) {
listAdapter.notifyDataSetChanged();
}
}
private void loadCacheSize() {
@ -250,7 +277,15 @@ public class DataSettingsActivity extends BaseFragment {
fragmentView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundGray));
FrameLayout frameLayout = (FrameLayout) fragmentView;
listView = new RecyclerListView(context);
listView = new RecyclerListView(context) {
@Override
public Integer getSelectorColor(int position) {
if (position == resetDownloadRow) {
return Theme.multAlpha(getThemedColor(Theme.key_windowBackgroundWhiteRedText2), .1f);
}
return getThemedColor(Theme.key_listSelector);
}
};
listView.setVerticalScrollBarEnabled(false);
listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
@ -322,9 +357,7 @@ public class DataSettingsActivity extends BaseFragment {
}
DownloadController.getInstance(currentAccount).checkAutodownloadSettings();
DownloadController.getInstance(currentAccount).savePresetToServer(num);
if (wasEnabled != listAdapter.isRowEnabled(resetDownloadRow)) {
listAdapter.notifyItemChanged(resetDownloadRow);
}
updateRows(false);
} else {
int type;
if (position == mobileRow) {
@ -376,6 +409,7 @@ public class DataSettingsActivity extends BaseFragment {
DownloadController.getInstance(currentAccount).savePresetToServer(a);
}
listAdapter.notifyItemRangeChanged(mobileRow, 4);
updateRows(false);
});
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
AlertDialog dialog = builder.create();
@ -465,24 +499,46 @@ public class DataSettingsActivity extends BaseFragment {
LanguageCell cell = new LanguageCell(context);
cell.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
cell.setTag(a);
String description;
boolean isInternal = storageDir.contains("/storage/emulated/");
if (fullString && !isInternal) {
description = LocaleController.formatString("StoragePathFreeValueExternal", R.string.StoragePathFreeValueExternal, AndroidUtilities.formatFileSize(file.getFreeSpace()), storageDir);
} else {
if (isInternal) {
description = LocaleController.formatString("StoragePathFreeInternal", R.string.StoragePathFreeInternal, AndroidUtilities.formatFileSize(file.getFreeSpace()));
} else {
description = LocaleController.formatString("StoragePathFreeExternal", R.string.StoragePathFreeExternal, AndroidUtilities.formatFileSize(file.getFreeSpace()));
}
}
cell.setValue(
storageDir.contains("/storage/emulated/") ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard),
fullString ?
LocaleController.formatString("StoragePathFreeValue", R.string.StoragePathFreeValue, AndroidUtilities.formatFileSize(file.getFreeSpace()), storageDir) :
LocaleController.formatString("StoragePathFree", R.string.StoragePathFree, AndroidUtilities.formatFileSize(file.getFreeSpace()))
isInternal ? LocaleController.getString("InternalStorage", R.string.InternalStorage) : LocaleController.getString("SdCard", R.string.SdCard),
description
);
cell.setLanguageSelected(storageDir.startsWith(dir), false);
cell.setBackground(Theme.createSelectorDrawable(Theme.getColor(Theme.key_dialogButtonSelector), 2));
linearLayout.addView(cell);
cell.setOnClickListener(v -> {
SharedConfig.storageCacheDir = storageDir;
SharedConfig.saveConfig();
if (!TextUtils.equals(SharedConfig.storageCacheDir, storageDir)) {
if (!isInternal) {
AlertDialog.Builder confirAlert = new AlertDialog.Builder(getContext());
confirAlert.setTitle(LocaleController.getString("DecreaseSpeed", R.string.DecreaseSpeed));
confirAlert.setMessage(LocaleController.getString("SdCardAlert", R.string.SdCardAlert));
confirAlert.setPositiveButton(LocaleController.getString("Proceed", R.string.Proceed), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setStorageDirectory(storageDir);
builder.getDismissRunnable().run();
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);
@ -534,10 +590,29 @@ public class DataSettingsActivity extends BaseFragment {
}
}
});
DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setDurations(350);
itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
itemAnimator.setDelayAnimations(false);
itemAnimator.setSupportsChangeAnimations(false);
listView.setItemAnimator(itemAnimator);
return fragmentView;
}
private void setStorageDirectory(String storageDir) {
SharedConfig.storageCacheDir = storageDir;
SharedConfig.saveConfig();
if (storageDir != null) {
SharedConfig.readOnlyStorageDirAlertShowed = false;
}
rebind(storageNumRow);
ImageLoader.getInstance().checkMediaPaths(() -> {
CacheControlActivity.resetCalculatedTotalSIze();
loadCacheSize();
});
}
@Override
protected void onDialogDismiss(Dialog dialog) {
DownloadController.getInstance(currentAccount).checkAutodownloadSettings();
@ -548,6 +623,7 @@ public class DataSettingsActivity extends BaseFragment {
super.onResume();
loadCacheSize();
rebindAll();
updateRows(false);
}
private class ListAdapter extends RecyclerListView.SelectionAdapter {
@ -702,7 +778,7 @@ public class DataSettingsActivity extends BaseFragment {
String text;
CharSequence description = null;
DownloadController.Preset preset = null;
boolean enabled;
boolean enabled, divider = true;
if (position == saveToGalleryPeerRow) {
text = LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate);
description = SaveToGallerySettingsHelper.user.createDescription(currentAccount);
@ -715,6 +791,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels);
description = SaveToGallerySettingsHelper.channels.createDescription(currentAccount);
enabled = SaveToGallerySettingsHelper.channels.enabled();
divider = false;
} else if (position == mobileRow) {
text = LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData);
enabled = DownloadController.getInstance(currentAccount).mobilePreset.enabled;
@ -727,6 +804,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("WhenRoaming", R.string.WhenRoaming);
enabled = DownloadController.getInstance(currentAccount).roamingPreset.enabled;
preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset();
divider = resetDownloadRow >= 0;
}
boolean checked;
if (preset != null) {
@ -776,7 +854,7 @@ public class DataSettingsActivity extends BaseFragment {
checked = enabled;
}
checkCell.setAnimationsEnabled(true);
checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, true);
checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, divider);
break;
}
}
@ -805,15 +883,9 @@ public class DataSettingsActivity extends BaseFragment {
}
public boolean isRowEnabled(int position) {
if (position == resetDownloadRow) {
DownloadController controller = DownloadController.getInstance(currentAccount);
return !controller.lowPreset.equals(controller.getCurrentRoamingPreset()) || controller.lowPreset.isEnabled() != controller.roamingPreset.enabled ||
!controller.mediumPreset.equals(controller.getCurrentMobilePreset()) || controller.mediumPreset.isEnabled() != controller.mobilePreset.enabled ||
!controller.highPreset.equals(controller.getCurrentWiFiPreset()) || controller.highPreset.isEnabled() != controller.wifiPreset.enabled;
}
return position == mobileRow || position == roamingRow || position == wifiRow || position == storageUsageRow || position == useLessDataForCallsRow || position == dataUsageRow || position == proxyRow || position == clearDraftsRow ||
position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == quickRepliesRow || position == autoplayVideoRow || position == autoplayGifsRow ||
position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow;
position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow || position == resetDownloadRow;
}
@Override

View file

@ -3244,6 +3244,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
viewPage.listView.setInstantClick(true);
viewPage.layoutManager = new LinearLayoutManager(context) {
@Override
protected int firstPosition() {
if (viewPage.dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() && viewPage.archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN) {
return 1;
}
return 0;
}
private boolean fixOffset;
@Override
@ -7123,6 +7131,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true);
deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon));
deleteItem.setTextColor(getThemedColor(Theme.key_dialogTextRed));
deleteItem.setSelectorColor(Theme.multAlpha(getThemedColor(Theme.key_dialogTextRed), .12f));
deleteItem.setTextAndIcon(LocaleController.getString("Delete", R.string.Delete), R.drawable.msg_delete);
deleteItem.setMinimumWidth(160);
deleteItem.setOnClickListener(e -> {
@ -8669,7 +8678,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
updateVisibleRows(0);
} else if (id == NotificationCenter.emojiLoaded) {
updateVisibleRows(0);
for (int i = 0; i < viewPages.length; ++i) {
final RecyclerListView listView = viewPages[i].listView;
if (listView != null) {
for (int a = 0; a < listView.getChildCount(); ++a) {
View child = listView.getChildAt(a);
if (child != null) {
child.invalidate();
}
}
}
}
if (filterTabsView != null) {
filterTabsView.getTabsContainer().invalidateViews();
}

View file

@ -49,6 +49,7 @@ import org.telegram.ui.Cells.ShadowSectionCell;
import org.telegram.ui.Components.Bulletin;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.Components.CombinedDrawable;
import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.Premium.LimitReachedBottomSheet;
import org.telegram.ui.Components.Premium.PremiumFeatureBottomSheet;
@ -527,6 +528,12 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
super.dispatchDraw(canvas);
}
};
DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setDurations(350);
itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
itemAnimator.setDelayAnimations(false);
itemAnimator.setSupportsChangeAnimations(false);
listView.setItemAnimator(itemAnimator);
((DefaultItemAnimator) listView.getItemAnimator()).setDelayAnimations(false);
listView.setLayoutManager(layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false));
listView.setVerticalScrollBarEnabled(false);
@ -735,6 +742,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
while (getMessagesController().dialogFiltersById.get(filter.id) != null) {
filter.id++;
}
filter.order = getMessagesController().dialogFilters.size();
filter.pendingUnreadCount = filter.unreadCount = -1;
for (int b = 0; b < 2; b++) {
ArrayList<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;
}
ignoreUpdates = true;
FilterCreateActivity.saveFilterToServer(filter, filter.flags, filter.name, filter.alwaysShow, filter.neverShow, filter.pinnedDialogs, true, true, true, true, false, FiltersSetupActivity.this, () -> {
FilterCreateActivity.saveFilterToServer(filter, filter.flags, filter.name, filter.alwaysShow, filter.neverShow, filter.pinnedDialogs, true, false, true, true, false, FiltersSetupActivity.this, () -> {
getNotificationCenter().postNotificationName(NotificationCenter.dialogFiltersUpdated);
ignoreUpdates = false;
ArrayList<TLRPC.TL_dialogFilterSuggested> suggestedFilters = getMessagesController().suggestedFilters;
@ -848,9 +856,9 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
}
case 3: {
if (position == createSectionRow) {
holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
} else {
holder.itemView.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
holder.itemView.setBackground(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
}
break;
}
@ -870,7 +878,7 @@ public class FiltersSetupActivity extends BaseFragment implements NotificationCe
}
case 5: {
SuggestedFilterCell filterCell = (SuggestedFilterCell) holder.itemView;
filterCell.setFilter(getMessagesController().suggestedFilters.get(position - recommendedStartRow), recommendedStartRow != recommendedEndRow - 1);
filterCell.setFilter(getMessagesController().suggestedFilters.get(position - recommendedStartRow), position < recommendedEndRow - 1);
break;
}
}

View file

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

View file

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

View file

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

View file

@ -1021,21 +1021,18 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
break;
case 1:
TextInfoPrivacyCell privacyCell = (TextInfoPrivacyCell) holder.itemView;
boolean last = position == getItemCount() - 1;
privacyCell.setBackground(Theme.getThemedDrawable(mContext, last ? R.drawable.greydivider_bottom : R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
if (position == deleteAccountDetailRow) {
privacyCell.setText(LocaleController.getString("DeleteAccountHelp", R.string.DeleteAccountHelp));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == groupsDetailRow) {
privacyCell.setText(LocaleController.getString("GroupsAndChannelsHelp", R.string.GroupsAndChannelsHelp));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == sessionsDetailRow) {
privacyCell.setText(LocaleController.getString("SessionsSettingsInfo", R.string.SessionsSettingsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == secretDetailRow) {
privacyCell.setText(LocaleController.getString("SecretWebPageInfo", R.string.SecretWebPageInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == botsDetailRow) {
privacyCell.setText(LocaleController.getString("PrivacyBotsInfo", R.string.PrivacyBotsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == contactsDetailRow) {
/*if (newSync) {
privacyCell.setText(LocaleController.getString("SyncContactsInfoOn", R.string.SyncContactsInfoOn));
@ -1043,10 +1040,8 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
privacyCell.setText(LocaleController.getString("SyncContactsInfoOff", R.string.SyncContactsInfoOff));
}*/
privacyCell.setText(LocaleController.getString("SuggestContactsInfo", R.string.SuggestContactsInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == newChatsSectionRow) {
privacyCell.setText(LocaleController.getString("ArchiveAndMuteInfo", R.string.ArchiveAndMuteInfo));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
}
break;
case 2:

View file

@ -1876,7 +1876,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
finishFragment();
BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show();
Context context = getContext();
if (context != null) {
BulletinFactory.of(Bulletin.BulletinWindow.make(context), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show();
}
dialog.dismiss();
}
});
@ -2193,6 +2196,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
setForegroundImage(true);
}
if (photo == null || avatarsViewPager.getRealPosition() == 0) {
TLRPC.Photo nextPhoto = avatarsViewPager.getPhoto(1);
if (nextPhoto != null) {
getUserConfig().getCurrentUser().photo =new TLRPC.TL_userProfilePhoto();
TLRPC.PhotoSize smallSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 90);
TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 1000);
if (smallSize != null && bigSize != null) {
getUserConfig().getCurrentUser().photo.photo_small = smallSize.location;
getUserConfig().getCurrentUser().photo.photo_big = bigSize.location;
}
} else {
getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty();
}
getMessagesController().deleteUserPhoto(null);
} else {
TLRPC.TL_inputPhoto inputPhoto = new TLRPC.TL_inputPhoto();

View file

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

View file

@ -192,7 +192,15 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
emptyView.showProgress();
frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER));
listView = new RecyclerListView(context);
listView = new RecyclerListView(context) {
@Override
public Integer getSelectorColor(int position) {
if (position == terminateAllSessionsRow) {
return Theme.multAlpha(getThemedColor(Theme.key_windowBackgroundWhiteRedText2), .1f);
}
return getThemedColor(Theme.key_listSelector);
}
};
listView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) {
@Override
public boolean supportsPredictiveItemAnimations() {
@ -799,7 +807,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
} else {
privacyCell.setText(LocaleController.getString("TerminateWebSessionInfo", R.string.TerminateWebSessionInfo));
}
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
} else if (position == passwordSessionsDetailRow) {
privacyCell.setText(LocaleController.getString("LoginAttemptsInfo", R.string.LoginAttemptsInfo));
if (otherSessionsTerminateDetail == -1) {
@ -808,7 +816,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
}
} else if (position == qrCodeDividerRow || position == ttlDivideRow || position == noOtherSessionsRow) {
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow));
privacyCell.setBackgroundDrawable(Theme.getThemedDrawable(mContext, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow));
privacyCell.setText("");
privacyCell.setFixedSize(12);
}

View file

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

View file

@ -2445,6 +2445,8 @@
<string name="ClearCache">Clear Cache</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="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="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>
@ -3490,6 +3492,7 @@
<string name="BotStatusCantRead">has no access to messages</string>
<string name="BotInfoTitle">What can this bot do?</string>
<string name="BotStart">START</string>
<string name="BotStartButton">Start bot</string>
<string name="BotUnblock">RESTART</string>
<string name="BotStop">Stop bot</string>
<string name="BotRestart">Restart bot</string>
@ -6353,8 +6356,9 @@
<string name="ChannelInviteViaLinkRestricted">You can\'t create a link</string>
<string name="ChannelInviteViaLinkRestricted2">This user can\'t be invited</string>
<string name="ChannelInviteViaLinkRestricted3">This users can\'t be invited</string>
<string name="StoragePathFree">%1$s free</string>
<string name="StoragePathFreeValue">%1$s free, %2$s</string>
<string name="StoragePathFreeInternal">%1$s free, high speed</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="AccDescrLiteBatteryLevelAnnounce">%s%%</string>
<string name="AccDescrRateTranscriptionUp">Rate up</string>
@ -6371,4 +6375,10 @@
<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="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>

View file

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

View file

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