merge original 9.5.7

This commit is contained in:
wrwrabbit 2023-04-02 11:59:37 +03:00
commit 4c191ba88f
107 changed files with 2589 additions and 930 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);
}
@ -483,7 +488,8 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
if (!registerNativeMethods(env, ConnectionsManagerClassPathName, ConnectionsManagerMethods, sizeof(ConnectionsManagerMethods) / sizeof(ConnectionsManagerMethods[0]))) {
return JNI_FALSE;
}
DEBUG_REF("RequestDelegateInternal class");
jclass_RequestDelegateInternal = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestDelegateInternal"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
@ -493,6 +499,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("RequestTimeDelegate class");
jclass_RequestTimeDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/RequestTimeDelegate"));
if (jclass_RequestTimeDelegate == 0) {
return JNI_FALSE;
@ -502,6 +509,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("QuickAckDelegate class");
jclass_QuickAckDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/QuickAckDelegate"));
if (jclass_RequestDelegateInternal == 0) {
return JNI_FALSE;
@ -511,6 +519,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
return JNI_FALSE;
}
DEBUG_REF("WriteToSocketDelegate class");
jclass_WriteToSocketDelegate = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/WriteToSocketDelegate"));
if (jclass_WriteToSocketDelegate == 0) {
return JNI_FALSE;
@ -519,6 +528,7 @@ extern "C" int registerNativeTgNetFunctions(JavaVM *vm, JNIEnv *env) {
if (jclass_WriteToSocketDelegate_run == 0) {
return JNI_FALSE;
}
DEBUG_REF("ConnectionsManager class");
jclass_ConnectionsManager = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/tgnet/ConnectionsManager"));
if (jclass_ConnectionsManager == 0) {
return JNI_FALSE;

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

@ -98,9 +98,9 @@ public:
inline void getColorReplacement(std::map<int32_t, int32_t> *colorMap, const LottieColor &c, float &r, float &g, float &b) {
if (colorMap != nullptr && !colorMap->empty()) {
int32_t rr = (int32_t) (c.r * 255);
int32_t gg = (int32_t) (c.g * 255);
int32_t bb = (int32_t) (c.b * 255);
int32_t rr = (int32_t) round(c.r * 255);
int32_t gg = (int32_t) round(c.g * 255);
int32_t bb = (int32_t) round(c.b * 255);
int32_t cc = (int32_t) (((bb & 0xff) << 16) | ((gg & 0xff) << 8) | (rr & 0xff));
std::map<int32_t, int32_t>::iterator iter = colorMap->find(cc);
if (iter != colorMap->end()) {

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

@ -1899,14 +1899,17 @@ void ConnectionsManager::sendRequest(TLObject *object, onCompleteFunc onComplete
exit(1);
}
if (ptr1 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr1");
env->DeleteGlobalRef(ptr1);
ptr1 = nullptr;
}
if (ptr2 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr2");
env->DeleteGlobalRef(ptr2);
ptr2 = nullptr;
}
if (ptr3 != nullptr) {
DEBUG_DELREF("connectionsmanager ptr3");
env->DeleteGlobalRef(ptr3);
ptr3 = nullptr;
}
@ -3103,12 +3106,14 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
std::vector<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;
@ -3131,7 +3136,7 @@ void ConnectionsManager::updateDcSettings(uint32_t dcNum, bool workaround) {
if (dcOption->secret != nullptr) {
secret = std::string((const char *) dcOption->secret->bytes, dcOption->secret->length);
}
if (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has_secret = %d[%d], try_this_port_only = %d", dcOption->ip_address.c_str(), dcOption->port, dcOption->id, dcOption->flags, dcOption->secret != nullptr ? 1 : 0, dcOption->secret != nullptr ? dcOption->secret->length : 0, dcOption->thisPortOnly ? 1 : 0);
if (LOGS_ENABLED) DEBUG_D("getConfig add %s:%d to dc%d, flags %d, has_secret = %d[%d], try_this_port_only = %d, force_try_ipv6 = %d", dcOption->ip_address.c_str(), dcOption->port, dcOption->id, dcOption->flags, dcOption->secret != nullptr ? 1 : 0, dcOption->secret != nullptr ? dcOption->secret->length : 0, dcOption->thisPortOnly ? 1 : 0, dcOption->force_try_ipv6 ? 1 : 0);
if (dcOption->thisPortOnly) {
addresses->insert(addresses->begin(), TcpAddress(dcOption->ip_address, dcOption->port, dcOption->flags, secret));
} else {
@ -3681,6 +3686,7 @@ void ConnectionsManager::useJavaVM(JavaVM *vm, bool useJavaByteBuffers) {
if (LOGS_ENABLED) DEBUG_E("can't get jnienv");
exit(1);
}
DEBUG_REF("connectionsmanager byte buffer");
jclass_ByteBuffer = (jclass) env->NewGlobalRef(env->FindClass("java/nio/ByteBuffer"));
if (jclass_ByteBuffer == nullptr) {
if (LOGS_ENABLED) DEBUG_E("can't find java ByteBuffer class");

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,8 +183,10 @@ 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;
@ -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.isEmpty(s) && TextUtils.lastIndexOf(s, '_') == s.length() - 1) {
//fix infinity loop regex
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(s.toString());
s = spannableStringBuilder.replace(s.length() - 1, s.length(), "a");
}
Matcher m = pattern.matcher(s);
while (m.find()) {
int start = m.start();
@ -1934,20 +1949,18 @@ public class AndroidUtilities {
FileLog.d("external dir mounted");
try {
File file;
if (Build.VERSION.SDK_INT >= 19) {
File[] dirs = ApplicationLoader.applicationContext.getExternalCacheDirs();
file = dirs[0];
if (!TextUtils.isEmpty(SharedConfig.storageCacheDir)) {
for (int a = 0; a < dirs.length; a++) {
if (dirs[a] != null && dirs[a].getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) {
file = dirs[a];
break;
}
File[] dirs = ApplicationLoader.applicationContext.getExternalCacheDirs();
file = dirs[0];
if (!TextUtils.isEmpty(SharedConfig.storageCacheDir)) {
for (int a = 0; a < dirs.length; a++) {
if (dirs[a] != null && dirs[a].getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) {
file = dirs[a];
break;
}
}
} else {
file = ApplicationLoader.applicationContext.getExternalCacheDir();
}
FileLog.d("check dir " + (file == null ? null : file.getPath()) + " ");
if (file != null && (file.exists() || file.mkdirs()) && file.canWrite()) {
// boolean canWrite = true;
@ -4782,6 +4795,13 @@ public class AndroidUtilities {
);
}
public static boolean isEROFS(Exception e) {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && e instanceof IOException &&
(e.getCause() instanceof ErrnoException && ((ErrnoException) e.getCause()).errno == OsConstants.EROFS) ||
(e.getMessage() != null && e.getMessage().toLowerCase().contains("read-only file system"))
);
}
public static CharSequence replaceCharSequence(String what, CharSequence from, CharSequence obj) {
SpannableStringBuilder spannableStringBuilder;
if (from instanceof SpannableStringBuilder) {

View file

@ -14,7 +14,7 @@ public class AutoDeleteMediaTask {
public static void run() {
int time = (int) (System.currentTimeMillis() / 1000);
if (!BuildVars.DEBUG_PRIVATE_VERSION && Math.abs(time - SharedConfig.lastKeepMediaCheckTime) < 24 * 60 * 60) {
if (Math.abs(time - SharedConfig.lastKeepMediaCheckTime) < 24 * 60 * 60) {
return;
}
SharedConfig.lastKeepMediaCheckTime = time;
@ -103,13 +103,16 @@ public class AutoDeleteMediaTask {
}
long lastUsageTime = Utilities.getLastUsageFileTime(file.file.getAbsolutePath());
long timeLocal = time - seconds;
boolean needDelete = lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath());
boolean needDelete = lastUsageTime > 316000000 && lastUsageTime < timeLocal && !usingFilePaths.contains(file.file.getPath());
if (needDelete) {
try {
if (BuildVars.LOGS_ENABLED) {
autoDeletedFiles++;
autoDeletedFilesSize += file.file.length();
}
if (BuildVars.DEBUG_PRIVATE_VERSION) {
FileLog.d("delete file " + file.file.getPath() + " last_usage_time=" + lastUsageTime + " time_local=" + timeLocal);
}
file.file.delete();
} catch (Exception exception) {
FileLog.e(exception);

View file

@ -315,6 +315,7 @@ public class BillingController implements PurchasesUpdatedListener, BillingClien
@Override
public void onBillingSetupFinished(@NonNull BillingResult setupBillingResult) {
FileLog.d("Billing setup finished with result " + setupBillingResult);
if (setupBillingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
queryProductDetails(Collections.singletonList(PREMIUM_PRODUCT), (billingResult, list) -> {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {

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 = 3249;
public static String BUILD_VERSION_STRING = "9.5.7";
public static int APP_ID = 12652123; // set you own APP_ID
public static String APP_HASH = "bb81fa5b3c3f80706ac142c9b72ce9ef"; // set you own APP_HASH

View file

@ -23,13 +23,13 @@ import android.net.Uri;
import android.os.Build;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import androidx.collection.LongSparseArray;
import com.google.android.exoplayer2.util.Log;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.fakepasscode.FakePasscode;
import org.telegram.messenger.fakepasscode.FakePasscodeUtils;
@ -641,6 +641,7 @@ public class ContactsController extends BaseController {
ArrayList<String> idsArr = new ArrayList<>();
pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
long time = System.currentTimeMillis();
int lastContactId = 1;
if (pCur != null) {
int count = pCur.getCount();
@ -809,68 +810,96 @@ public class ContactsController extends BaseController {
}
pCur = null;
}
FileLog.d("loading contacts 1 query time = " + (System.currentTimeMillis() - time) + " contactsSize = " + (contactsMap == null ? 0 : contactsMap.size()));
time = System.currentTimeMillis();
HashMap<String, PhoneBookContact> phoneBookContactHashMap = new HashMap<>();
ArrayList<String> phonebookContactsId = new ArrayList<>();
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, new String[]{
ContactsContract.Contacts._ID,
ContactsContract.Contacts.LOOKUP_KEY,
ContactsContract.Contacts.DISPLAY_NAME
}, ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?", new String[]{"0"}, null);
Cursor cur = cr.query(ContactsContract.Contacts.CONTENT_URI, null,ContactsContract.Contacts.HAS_PHONE_NUMBER + " = ?", new String[]{"0"}, null);
if (cur != null) {
String[] metadata = new String[5];
Pattern phonePattern = Pattern.compile(".*(\\+[0-9 \\-]+).*");
while (cur.moveToNext()) {
String id = cur.getString(cur.getColumnIndex(ContactsContract.Contacts._ID));
String lookup_key = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
String name = cur.getString(cur.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
String phone = null;
if ((contactsMap != null && contactsMap.get(lookup_key) != null) || TextUtils.isEmpty(name)) {
PhoneBookContact phoneBookContact = new PhoneBookContact();
phoneBookContact.id = cur.getString(0);
phoneBookContact.lookup_key = cur.getString(1);
phoneBookContact.name = cur.getString(2);
if ((contactsMap != null && contactsMap.get(phoneBookContact.lookup_key) != null) || TextUtils.isEmpty(phoneBookContact.name)) {
continue;
}
pCur = cr.query(
ContactsContract.Data.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?",
new String[]{id}, null);
loop : while (pCur.moveToNext()) {
metadata[0] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA1));
metadata[1] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA2));
metadata[2] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA3));
metadata[3] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA4));
metadata[4] = pCur.getString(pCur.getColumnIndex(ContactsContract.Data.DATA5));
for (int i = 0; i < metadata.length; i++) {
if (metadata[i] == null) {
continue;
}
Matcher matcher = phonePattern.matcher(metadata[i]);
if (matcher.matches()) {
phone = matcher.group(1).replace(" ", "").replace("-", "");
break loop;
}
}
}
pCur.close();
if (phone != null) {
String shortNumber = phone;
if (phone.startsWith("+")) {
shortNumber = phone.substring(1);
}
Contact contact = new Contact();
contact.first_name = name;
contact.last_name = "";
contact.contact_id = lastContactId++;
contact.key = lookup_key;
contact.phones.add(phone);
contact.shortPhones.add(shortNumber);
contact.phoneDeleted.add(0);
contact.phoneTypes.add(LocaleController.getString("PhoneOther", R.string.PhoneOther));
// contact.provider = accountType;
// contact.isGoodProvider = isGoodAccountType;
contactsMap.put(lookup_key, contact);
}
phoneBookContactHashMap.put(phoneBookContact.id, phoneBookContact);
phonebookContactsId.add(phoneBookContact.id);
}
cur.close();
}
FileLog.d("loading contacts 2 query time = " + (System.currentTimeMillis() - time) + " phoneBookConacts size = " + phonebookContactsId.size());
time = System.currentTimeMillis();
if (!phonebookContactsId.isEmpty()) {
String[] metadata = new String[4];
Pattern phonePattern = Pattern.compile(".*(\\+[0-9 \\-]+).*");
pCur = cr.query(
ContactsContract.Data.CONTENT_URI,
new String[]{
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.Data.DATA1,
ContactsContract.Data.DATA2,
ContactsContract.Data.DATA3,
ContactsContract.Data.DATA4,
},
ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " IN (" + TextUtils.join(", ", phonebookContactsId) + ")",
null, null);
if (pCur != null) {
while (pCur.moveToNext()) {
String id = pCur.getString(0);
PhoneBookContact phoneBookContact = phoneBookContactHashMap.get(id);
if (phoneBookContact != null) {
metadata[0] = pCur.getString(1);
metadata[1] = pCur.getString(2);
metadata[2] = pCur.getString(3);
metadata[3] = pCur.getString(4);
for (int i = 0; i < metadata.length; i++) {
if (metadata[i] == null) {
continue;
}
Matcher matcher = phonePattern.matcher(metadata[i]);
if (matcher.matches()) {
phoneBookContact.phone = matcher.group(1).replace(" ", "").replace("-", "");
}
if (phoneBookContact.phone != null) {
String shortNumber = phoneBookContact.phone;
if (phoneBookContact.phone.startsWith("+")) {
shortNumber = phoneBookContact.phone.substring(1);
}
Contact contact = new Contact();
contact.first_name = phoneBookContact.name;
contact.last_name = "";
contact.contact_id = lastContactId++;
contact.key = phoneBookContact.lookup_key;
contact.phones.add(phoneBookContact.phone);
contact.shortPhones.add(shortNumber);
contact.phoneDeleted.add(0);
contact.phoneTypes.add(LocaleController.getString("PhoneOther", R.string.PhoneOther));
if (contactsMap == null) {
contactsMap = new HashMap<>();
}
contactsMap.put(phoneBookContact.lookup_key, contact);
break;
}
}
}
}
pCur.close();
}
}
FileLog.d("loading contacts 3 query time = " + (System.currentTimeMillis() - time));
} catch (Throwable e) {
FileLog.e(e);
@ -1955,6 +1984,7 @@ public class ContactsController extends BaseController {
private void performWriteContactsToPhoneBookInternal(ArrayList<TLRPC.TL_contact> contactsArray) {
Cursor cursor = null;
long time = System.currentTimeMillis();
try {
Account account = systemAccount;
if (!hasContactsPermission() || account == null) {
@ -1966,7 +1996,7 @@ public class ContactsController extends BaseController {
settings.edit().putBoolean("contacts_updated_v7", true).commit();
}
final ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type).build();
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI;
cursor = contentResolver.query(rawContactUri, new String[]{BaseColumns._ID, ContactsContract.RawContacts.SYNC2}, null, null, null);
LongSparseArray<Long> bookContacts = new LongSparseArray<>();
if (cursor != null) {
@ -1976,12 +2006,26 @@ public class ContactsController extends BaseController {
cursor.close();
cursor = null;
FileLog.d("performWriteContactsToPhoneBookInternal contacts array " + contactsArray.size() + " " + forceUpdate + " bookContactsSize=" + bookContacts.size() + " currentAccount=" + currentAccount);
ArrayList<ContentProviderOperation> query = null;
for (int a = 0; a < contactsArray.size(); a++) {
TLRPC.TL_contact u = contactsArray.get(a);
if (forceUpdate || bookContacts.indexOfKey(u.user_id) < 0) {
addContactToPhoneBook(getMessagesController().getUser(u.user_id), forceUpdate);
if (query == null) {
query = new ArrayList<>();
}
applyContactToPhoneBook(query, getMessagesController().getUser(u.user_id));
if (query.size() > 450) {
contentResolver.applyBatch(ContactsContract.AUTHORITY, query);
query.clear();
}
}
}
if (query != null && !query.isEmpty()) {
contentResolver.applyBatch(ContactsContract.AUTHORITY, query);
query.clear();
}
}
} catch (Exception e) {
FileLog.e(e);
@ -1990,6 +2034,8 @@ public class ContactsController extends BaseController {
cursor.close();
}
}
FileLog.d("performWriteContactsToPhoneBookInternal " + (System.currentTimeMillis() - time)) ;
}
private void performWriteContactsToPhoneBook() {
@ -2180,56 +2226,7 @@ public class ContactsController extends BaseController {
}
ArrayList<ContentProviderOperation> query = new ArrayList<>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type);
builder.withValue(ContactsContract.RawContacts.SYNC1, TextUtils.isEmpty(user.phone) ? "" : user.phone);
builder.withValue(ContactsContract.RawContacts.SYNC2, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name);
query.add(builder.build());
// builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
// builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
// builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
// builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+" + user.phone);
// builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
// query.add(builder.build());
final String phoneOrName = TextUtils.isEmpty(user.phone) ? ContactsController.formatName(user.first_name, user.last_name) : "+" + user.phone;
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutMessage", R.string.ContactShortcutMessage, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Voice Call");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVoiceCall", R.string.ContactShortcutVoiceCall, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Video Call");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVideoCall", R.string.ContactShortcutVideoCall, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
applyContactToPhoneBook(query, user);
try {
ContentProviderResult[] result = contentResolver.applyBatch(ContactsContract.AUTHORITY, query);
@ -2245,6 +2242,55 @@ public class ContactsController extends BaseController {
return res;
}
private void applyContactToPhoneBook(ArrayList<ContentProviderOperation> query, TLRPC.User user) {
if (user == null) {
return;
}
int rawContactId = query.size();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type);
builder.withValue(ContactsContract.RawContacts.SYNC1, TextUtils.isEmpty(user.phone) ? "" : user.phone);
builder.withValue(ContactsContract.RawContacts.SYNC2, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name);
query.add(builder.build());
final String phoneOrName = TextUtils.isEmpty(user.phone) ? ContactsController.formatName(user.first_name, user.last_name) : "+" + user.phone;
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutMessage", R.string.ContactShortcutMessage, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Voice Call");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVoiceCall", R.string.ContactShortcutVoiceCall, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, rawContactId);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video");
builder.withValue(ContactsContract.Data.DATA1, user.id);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Video Call");
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVideoCall", R.string.ContactShortcutVideoCall, phoneOrName));
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
}
private void deleteContactFromPhoneBook(long uid) {
if (!hasContactsPermission()) {
return;
@ -2854,4 +2900,11 @@ public class ContactsController extends BaseController {
}
return result.toString();
}
private class PhoneBookContact {
String id;
String lookup_key;
String name;
String phone;
}
}

View file

@ -1247,6 +1247,13 @@ public class DatabaseMigrationHelper {
database.executeFast("PRAGMA user_version = 115").stepThis().dispose();
version = 115;
}
if (version == 115) {
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_v2 ON messages_v2(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_scheduled_messages_v2 ON scheduled_messages_v2(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_topics ON messages_topics(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("PRAGMA user_version = 116").stepThis().dispose();
version = 116;
}
return version;
}

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.get(fileName);
if (currentOperation != null) {
currentOperation.preFinished = true;
queue.checkLoadingOperations();
}
});
checkDownloadQueue(operation.getQueue(), fileName);
}
@Override
public void didFinishLoadingFile(FileLoadOperation operation, File finalFile) {
if (!operation.isPreloadVideoOperation() && operation.isPreloadFinished()) {
@ -864,16 +870,16 @@ public class FileLoader extends BaseController {
};
operation.setDelegate(fileLoadOperationDelegate);
loadOperationPaths.put(fileName, operation);
loadOperationPaths.put(finalFileName, operation);
operation.setPriority(priority);
operation.setStream(stream, streamPriority, streamOffset);
if (BuildVars.LOGS_ENABLED) {
FileLog.d("loadFileInternal fileName=" + fileName + " documentName=" + getDocumentFileName(document));
}
loaderQueue.add(operation);
loaderQueue.checkLoadingOperations();
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create load operation fileName=" + finalFileName + " documentName=" + getDocumentFileName(document) + "size=" + AndroidUtilities.formatFileSize(operation.totalBytesCount) + " position in queue " + operation.getPositionInQueue() + " account=" + currentAccount);
}
return operation;
}
@ -1681,8 +1687,8 @@ public class FileLoader extends BaseController {
Runnable dumpFilesQueueRunnable = () -> {
for (int i = 0; i < smallFilesQueue.length; i++) {
if (smallFilesQueue[i].allOperations.size() > 0 || largeFilesQueue[i].allOperations.size() > 0) {
FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].allOperations.size() + " large_operations=" + largeFilesQueue[i].allOperations.size());
if (smallFilesQueue[i].getCount() > 0 || largeFilesQueue[i].getCount() > 0) {
FileLog.d("download queue: dc" + (i + 1) + " account=" + currentAccount + " small_operations=" + smallFilesQueue[i].getCount() + " large_operations=" + largeFilesQueue[i].getCount());
}
}
dumpFilesQueue();

View file

@ -1,16 +1,13 @@
package org.telegram.messenger;
import org.telegram.tgnet.ConnectionsManager;
import java.util.ArrayList;
import java.util.Objects;
public class FileLoaderPriorityQueue {
private final int maxActiveOperationsCount;
String name;
ArrayList<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 +24,7 @@ public class FileLoaderPriorityQueue {
}
int index = -1;
for (int i = 0; i < allOperations.size(); i++) {
if (allOperations.get(i) == operation || Objects.equals(allOperations.get(i).getFileName(), (operation.getFileName()))) {
if (allOperations.get(i) == operation) {
allOperations.remove(i);
i--;
}
@ -49,14 +46,16 @@ public class FileLoaderPriorityQueue {
if (operation == null) {
return;
}
allOperations.remove(operation);
operation.cancel();
if (allOperations.remove(operation)) {
operation.cancel();
}
}
public void checkLoadingOperations() {
int activeCount = 0;
int lastPriority = 0;
boolean pauseAllNextOperations = false;
int max = maxActiveOperationsCount;
for (int i = 0; i < allOperations.size(); i++) {
FileLoadOperation operation = allOperations.get(i);
if (i > 0 && !pauseAllNextOperations) {
@ -64,7 +63,11 @@ public class FileLoaderPriorityQueue {
pauseAllNextOperations = true;
}
}
if (!pauseAllNextOperations && i < maxActiveOperationsCount) {
if (operation.preFinished) {
//operation will not use connections
//just skip
max++;
} else if (!pauseAllNextOperations && i < max) {
operation.start();
activeCount++;
} else {
@ -80,11 +83,14 @@ public class FileLoaderPriorityQueue {
if (operation == null) {
return;
}
ConnectionsManager connectionsManager = ConnectionsManager.getInstance(operation.currentAccount);
if (connectionsManager != null && connectionsManager.getConnectionState() == ConnectionsManager.ConnectionStateWaitingForNetwork) {
operation.cancel();
}
allOperations.remove(operation);
}
public int getCount() {
return allOperations.size();
}
public int getPosition(FileLoadOperation fileLoadOperation) {
return allOperations.indexOf(fileLoadOperation);
}
}

View file

@ -8,6 +8,8 @@
package org.telegram.messenger;
import android.content.Context;
import android.content.res.ColorStateList;
import android.util.Log;
import com.google.gson.ExclusionStrategy;
@ -116,7 +118,7 @@ public class FileLog {
}
public static void dumpUnparsedMessage(TLObject message, long messageId) {
if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null) {
if (!BuildVars.DEBUG_PRIVATE_VERSION || !BuildVars.LOGS_ENABLED || message == null || SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) {
return;
}
try {
@ -160,6 +162,7 @@ public class FileLog {
privateFields.add("networkType");
privateFields.add("disableFree");
privateFields.add("mContext");
//exclude file loading
excludeRequests = new HashSet<>();
@ -178,6 +181,9 @@ public class FileLog {
@Override
public boolean shouldSkipClass(Class<?> clazz) {
if (clazz.isInstance(ColorStateList.class) || clazz.isInstance(Context.class)) {
return true;
}
return false;
}
}).create();

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();
}
syncLatch.countDown();
});
try {
@ -332,8 +333,9 @@ public class FilePathDatabase {
}
} catch (Exception e) {
FileLog.e(e);
} finally {
syncLatch.countDown();
}
syncLatch.countDown();
});
try {
@ -344,7 +346,7 @@ public class FilePathDatabase {
return res[0];
}
public void saveFileDialogId(File file,FileMeta fileMeta) {
public void saveFileDialogId(File file, FileMeta fileMeta) {
if (file == null || fileMeta == null) {
return;
}
@ -417,7 +419,7 @@ public class FilePathDatabase {
for (int i = 0; i < filesToRemove.size(); i++) {
database.executeFast("DELETE FROM paths_by_dialog_id WHERE path = '" + shield(filesToRemove.get(i).file.getPath()) + "'").stepThis().dispose();
}
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
} finally {
database.commitTransaction();
@ -443,10 +445,11 @@ public class FilePathDatabase {
list.add(keepMediaFiles.get(i));
}
}
} catch (Exception e) {
} catch (Throwable e) {
FileLog.e(e);
} finally {
syncLatch.countDown();
}
syncLatch.countDown();
});
try {
syncLatch.await();

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;
fileLoadOperation.onFail(false, 0);
}
if (args[1] instanceof FileLoadOperation) {
FileLoadOperation fileLoadOperation = (FileLoadOperation) args[1];
fileLoadOperation.requestingReference = false;
FileLog.e("debug_loading: " + fileLoadOperation.getCacheFileFinal().getName() + "reference can't update: fail operation ");
fileLoadOperation.onFail(false, 0);
}
}
}
private boolean onRequestComplete(String locationKey, String parentKey, TLObject response, boolean cache, boolean fromCache) {
private boolean onRequestComplete(String locationKey, String parentKey, TLObject response, TLRPC.TL_error error, boolean cache, boolean fromCache) {
boolean found = false;
String cacheKey = parentKey;
if (response instanceof TLRPC.TL_help_premiumPromo) {
@ -706,7 +725,7 @@ public class FileRefController extends BaseController {
if (requester.completed) {
continue;
}
if (onRequestComplete(requester.locationKey, null, response, cache && !found, fromCache)) {
if (onRequestComplete(requester.locationKey, null, response, error, cache && !found, fromCache)) {
found = true;
}
}
@ -729,6 +748,13 @@ public class FileRefController extends BaseController {
if (requester.completed) {
continue;
}
if (error != null && BuildVars.LOGS_ENABLED) {
if (requester.args[1] instanceof FileLoadOperation) {
FileLoadOperation operation = (FileLoadOperation) requester.args[1];
FileLog.e("debug_loading: " + operation.getCacheFileFinal().getName() + " can't update file reference: " + error.code + " " + error.text);
}
}
if (requester.location instanceof TLRPC.TL_inputFileLocation || requester.location instanceof TLRPC.TL_inputPeerPhotoFileLocation) {
locationReplacement = new TLRPC.InputFileLocation[1];
needReplacement = new boolean[1];
@ -768,6 +794,10 @@ public class FileRefController extends BaseController {
FileLog.d("file ref not found in messages, replacing message");
}
}
} else {
if (BuildVars.DEBUG_VERSION) {
FileLog.d("empty messages, file ref not found");
}
}
} else if (response instanceof TLRPC.TL_help_premiumPromo) {
TLRPC.TL_help_premiumPromo premiumPromo = (TLRPC.TL_help_premiumPromo) response;
@ -1007,7 +1037,7 @@ public class FileRefController extends BaseController {
ArrayList<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

@ -582,7 +582,7 @@ public class ImageLoader {
}
}
} catch (Exception e) {
FileLog.e(e);
FileLog.e(e, false);
}
if (imageSize == 0 && httpConnection != null) {
try {
@ -1433,52 +1433,8 @@ public class ImageLoader {
Utilities.loadWebpImage(image, buffer, buffer.limit(), null, !opts.inPurgeable);
file.close();
} else {
String DEBUG_TAG = "secured_document_image";
try {
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d( DEBUG_TAG + " try get image from secured document " + secureDocumentKey + " encryption path " + cacheImage.encryptionKeyPath);
}
RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r");
int len = (int) f.length();
int offset = 0;
byte[] bytes = bytesLocal.get();
byte[] data = bytes != null && bytes.length >= len ? bytes : null;
if (data == null) {
bytes = data = new byte[len];
bytesLocal.set(bytes);
}
f.readFully(data, 0, len);
f.close();
boolean error = false;
if (secureDocumentKey != null) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey);
byte[] hash = Utilities.computeSHA256(data, 0, len);
if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) {
error = true;
}
offset = (data[0] & 0xff);
len -= offset;
} else if (inEncryptedFile) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath);
}
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " check error " + error);
}
if (!error) {
image = BitmapFactory.decodeByteArray(data, offset, len, opts);
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d( DEBUG_TAG + " image " + image);
}
}
} catch (Throwable e) {
FileLog.e(e);
}
if (image == null) {
FileInputStream is;
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " try get image from stream ");
}
if (secureDocumentKey != null) {
is = new EncryptedFileInputStream(cacheFileFinal, secureDocumentKey);
} else if (inEncryptedFile) {
@ -1517,9 +1473,38 @@ public class ImageLoader {
}
image = BitmapFactory.decodeStream(is, null, opts);
is.close();
}
if (secureDocumentKey != null || cacheImage.encryptionKeyPath != null) {
FileLog.d(DEBUG_TAG + " image2 " + image);
if (image == null) {
try {
RandomAccessFile f = new RandomAccessFile(cacheFileFinal, "r");
int len = (int) f.length();
int offset = 0;
byte[] bytes = bytesLocal.get();
byte[] data = bytes != null && bytes.length >= len ? bytes : null;
if (data == null) {
bytes = data = new byte[len];
bytesLocal.set(bytes);
}
f.readFully(data, 0, len);
f.close();
boolean error = false;
if (secureDocumentKey != null) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, secureDocumentKey);
byte[] hash = Utilities.computeSHA256(data, 0, len);
if (secureDocumentHash == null || !Arrays.equals(hash, secureDocumentHash)) {
error = true;
}
offset = (data[0] & 0xff);
len -= offset;
} else if (inEncryptedFile) {
EncryptedFileInputStream.decryptBytesWithKeyFile(data, 0, len, cacheImage.encryptionKeyPath);
}
if (!error) {
image = BitmapFactory.decodeByteArray(data, offset, len, opts);
}
} catch (Throwable e) {
FileLog.e(e);
}
}
}
@ -2245,6 +2230,8 @@ public class ImageLoader {
FileLog.d("cache path = " + cachePath);
}
FileLog.d("selected SD card = " + SharedConfig.storageCacheDir);
try {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File path = Environment.getExternalStorageDirectory();
@ -2253,14 +2240,28 @@ public class ImageLoader {
if (dirs != null) {
for (int a = 0, N = dirs.size(); a < N; a++) {
File dir = dirs.get(a);
FileLog.d("root dir " + a + " " + dir);
if (dir.getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) {
path = dir;
break;
}
}
}
if (!path.getAbsolutePath().startsWith(SharedConfig.storageCacheDir)) {
File[] dirsDebug = ApplicationLoader.applicationContext.getExternalFilesDirs(null);
if (dirsDebug != null) {
for (int a = 0; a < dirsDebug.length; a++) {
if (dirsDebug[a] == null) {
continue;
}
FileLog.d("dirsDebug " + a + " " + dirsDebug[a]);
}
}
}
}
FileLog.d("external storage = " + path);
File publicMediaDir = null;
if (Build.VERSION.SDK_INT >= 30) {
File newPath;

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

@ -162,7 +162,7 @@ public class LinkifyPort {
+ "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@";
private static final String PORT_NUMBER = "\\:\\d{1,5}";
private static final String PATH_AND_QUERY = "[/\\?](?:(?:[" + LABEL_CHAR + ";/\\?:@&=#~" + "\\-\\.\\+!\\*'\\(\\),_\\$])|(?:%[a-fA-F0-9]{2}))*";
private static final String RELAXED_DOMAIN_NAME = "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + "?)+" + "|" + IP_ADDRESS_STRING + ")";
private static final String RELAXED_DOMAIN_NAME = "(?:" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + ")*" + "(?:" + IRI_LABEL + "(?:\\.(?=\\S))" + "?)" + "|" + IP_ADDRESS_STRING + ")";
private static final String WEB_URL_WITHOUT_PROTOCOL = "("
+ WORD_BOUNDARY

View file

@ -5,9 +5,6 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.BatteryManager;
import android.os.Build;
import android.os.PowerManager;
import android.util.SparseArray;
import android.util.SparseIntArray;
import androidx.annotation.RequiresApi;
import androidx.core.math.MathUtils;
@ -20,9 +17,6 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Components.AnimatedEmojiDrawable;
public class LiteMode {
public static final int FLAG_ANIMATED_STICKERS_KEYBOARD = 1;
@ -53,8 +47,10 @@ public class LiteMode {
public static int PRESET_LOW = (
FLAG_ANIMATED_EMOJI_CHAT_PREMIUM |
FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM |
FLAG_ANIMATED_EMOJI_REACTIONS_PREMIUM |
FLAG_AUTOPLAY_GIFS
); // 2064
); // 2076
public static int PRESET_MEDIUM = (
FLAGS_ANIMATED_STICKERS |
FLAG_ANIMATED_EMOJI_KEYBOARD_PREMIUM |
@ -136,6 +132,10 @@ public class LiteMode {
}
public static boolean isEnabled(int flag) {
if (flag == FLAG_CHAT_FORUM_TWOCOLUMN && AndroidUtilities.isTablet()) {
// always enabled for tablets
return true;
}
return (getValue() & preprocessFlag(flag)) > 0;
}

View file

@ -553,6 +553,23 @@ public class LocaleController {
}
}
private boolean patching = false;
public void checkForcePatchLangpack(int currentAccount, Runnable ifDone) {
String lng = LocaleController.getCurrentLanguageName();
boolean shouldPatch = MessagesController.getInstance(currentAccount).checkResetLangpack > 0 && !MessagesController.getGlobalMainSettings().getBoolean("langpack_patched" + lng, false) && !patching;
if (shouldPatch) {
patching = true;
reloadCurrentRemoteLocale(currentAccount, null, true, () -> AndroidUtilities.runOnUIThread(() -> {
MessagesController.getGlobalMainSettings().edit().putBoolean("langpack_patched" + lng, true).apply();
if (ifDone != null) {
ifDone.run();
}
patching = false;
}));
}
}
private String getLocaleString(Locale locale) {
if (locale == null) {
return "en";

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,23 +2339,47 @@ public class MediaController implements AudioManager.OnAudioFocusChangeListener,
return;
}
if (SharedConfig.playOrderReversed) {
currentPlaylistNum--;
if (currentPlaylistNum < 0) {
currentPlaylistNum = currentPlayList.size() - 1;
}
} else {
currentPlaylistNum++;
if (currentPlaylistNum >= currentPlayList.size()) {
currentPlaylistNum = 0;
}
}
traversePlaylist(currentPlayList, SharedConfig.playOrderReversed ? -1 : 1);
if (currentPlaylistNum >= currentPlayList.size()) {
return;
}
playMusicAgain = true;
playMessage(currentPlayList.get(currentPlaylistNum));
}
private boolean traversePlaylist(ArrayList<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()) {
@ -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

@ -53,7 +53,6 @@ import org.telegram.SQLite.SQLiteException;
import org.telegram.SQLite.SQLitePreparedStatement;
import org.telegram.messenger.ringtone.RingtoneDataStore;
import org.telegram.messenger.ringtone.RingtoneUploader;
import org.telegram.messenger.support.SparseLongArray;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.NativeByteBuffer;
import org.telegram.tgnet.RequestDelegate;
@ -4309,6 +4308,7 @@ public class MediaDataController extends BaseController {
}
}
}
boolean recreateShortcuts = Build.VERSION.SDK_INT >= 30;
Utilities.globalQueue.postRunnable(() -> {
try {
if (SharedConfig.directShareHash == null) {
@ -4316,19 +4316,58 @@ public class MediaDataController extends BaseController {
ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit().putString("directShareHash2", SharedConfig.directShareHash).commit();
}
ShortcutManagerCompat.removeAllDynamicShortcuts(ApplicationLoader.applicationContext);
ArrayList<String> shortcutsToUpdate = new ArrayList<>();
ArrayList<String> newShortcutsIds = new ArrayList<>();
ArrayList<String> shortcutsToDelete = new ArrayList<>();
if (recreateShortcuts) {
ShortcutManagerCompat.removeAllDynamicShortcuts(ApplicationLoader.applicationContext);
} else {
List<ShortcutInfoCompat> currentShortcuts = ShortcutManagerCompat.getDynamicShortcuts(ApplicationLoader.applicationContext);
if (currentShortcuts != null && !currentShortcuts.isEmpty()) {
newShortcutsIds.add("compose");
for (int a = 0; a < hintsFinal.size(); a++) {
TLRPC.TL_topPeer hint = hintsFinal.get(a);
newShortcutsIds.add("did3_" + MessageObject.getPeerId(hint.peer));
}
for (int a = 0; a < currentShortcuts.size(); a++) {
String id = currentShortcuts.get(a).getId();
if (!newShortcutsIds.remove(id)) {
shortcutsToDelete.add(id);
}
shortcutsToUpdate.add(id);
}
if (newShortcutsIds.isEmpty() && shortcutsToDelete.isEmpty()) {
return;
}
}
if (!shortcutsToDelete.isEmpty()) {
ShortcutManagerCompat.removeDynamicShortcuts(ApplicationLoader.applicationContext, shortcutsToDelete);
}
}
Intent intent = new Intent(ApplicationLoader.applicationContext, LaunchActivity.class);
intent.setAction("new_dialog");
ArrayList<ShortcutInfoCompat> arrayList = new ArrayList<>();
ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, "compose")
ShortcutInfoCompat shortcut = new ShortcutInfoCompat.Builder(ApplicationLoader.applicationContext, "compose")
.setShortLabel(LocaleController.getString("NewConversationShortcut", R.string.NewConversationShortcut))
.setLongLabel(LocaleController.getString("NewConversationShortcut", R.string.NewConversationShortcut))
.setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.shortcut_compose))
.setRank(0)
.setIntent(intent)
.build());
.build();
if (recreateShortcuts) {
ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, shortcut);
} else {
arrayList.add(shortcut);
if (shortcutsToUpdate.contains("compose")) {
ShortcutManagerCompat.updateShortcuts(ApplicationLoader.applicationContext, arrayList);
} else {
ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList);
}
arrayList.clear();
}
HashSet<String> category = new HashSet<>(1);
@ -4423,7 +4462,18 @@ public class MediaDataController extends BaseController {
} else {
builder.setIcon(IconCompat.createWithResource(ApplicationLoader.applicationContext, R.drawable.shortcut_user));
}
ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, builder.build());
if (recreateShortcuts) {
ShortcutManagerCompat.pushDynamicShortcut(ApplicationLoader.applicationContext, builder.build());
} else {
arrayList.add(builder.build());
if (shortcutsToUpdate.contains(id)) {
ShortcutManagerCompat.updateShortcuts(ApplicationLoader.applicationContext, arrayList);
} else {
ShortcutManagerCompat.addDynamicShortcuts(ApplicationLoader.applicationContext, arrayList);
}
arrayList.clear();
}
}
} catch (Throwable ignore) {
@ -6229,7 +6279,7 @@ public class MediaDataController extends BaseController {
return entities;
}
private CharSequence parsePattern(CharSequence cs, Pattern pattern, List<TLRPC.MessageEntity> entities, GenericProvider<Void, TLRPC.MessageEntity> entityProvider) {
private CharSequence parsePattern(CharSequence cs, Pattern pattern, ArrayList<TLRPC.MessageEntity> entities, GenericProvider<Void, TLRPC.MessageEntity> entityProvider) {
Matcher m = pattern.matcher(cs);
int offset = 0;
while (m.find()) {
@ -6249,6 +6299,8 @@ public class MediaDataController extends BaseController {
TLRPC.MessageEntity entity = entityProvider.provide(null);
entity.offset = m.start() - offset;
entity.length = gr.length();
removeOffset4After(entity.offset, entity.offset + entity.length, entities);
entities.add(entity);
}
@ -6257,6 +6309,18 @@ public class MediaDataController extends BaseController {
return cs;
}
private static void removeOffset4After(int start, int end, ArrayList<TLRPC.MessageEntity> entities) {
int count = entities.size();
for (int a = 0; a < count; a++) {
TLRPC.MessageEntity entity = entities.get(a);
if (entity.offset > end) {
entity.offset -= 4;
} else if (entity.offset > start) {
entity.offset -= 2;
}
}
}
//---------------- MESSAGES END ----------------
private LongSparseArray<Integer> draftsFolderIds = new LongSparseArray<>();
@ -6950,10 +7014,12 @@ public class MediaDataController extends BaseController {
TLRPC.Document document = premiumPreviewStickers.get(i == 2 ? premiumPreviewStickers.size() - 1 : i);
if (MessageObject.isPremiumSticker(document)) {
ImageReceiver imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(ImageLocation.getForDocument(document), null, null, "webp", null, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
imageReceiver = new ImageReceiver();
imageReceiver.setAllowLoadingOnAttachedOnly(false);
imageReceiver.setImage(ImageLocation.getForDocument(MessageObject.getPremiumStickerAnimation(document), document), null, null, null, "tgs", null, 1);
ImageLoader.getInstance().loadImageForImageReceiver(imageReceiver);
}

View file

@ -3333,7 +3333,11 @@ public class MessageObject {
int i = messageText.toString().indexOf("un2");
if (i != -1) {
SpannableStringBuilder sb = SpannableStringBuilder.valueOf(messageText);
messageText = sb.replace(i, i + 3, BillingController.getInstance().formatCurrency(messageOwner.action.amount, messageOwner.action.currency));
CharSequence price = BillingController.getInstance().formatCurrency(messageOwner.action.amount, messageOwner.action.currency);
if ((messageOwner.action.flags & 1) != 0) {
price = String.format("%.2f", (messageOwner.action.cryptoAmount * Math.pow(10, -9))) + " " + messageOwner.action.cryptoCurrency + " (~ " + price + ")";
}
messageText = sb.replace(i, i + 3, price);
}
} else if (messageOwner.action instanceof TLRPC.TL_messageActionSuggestProfilePhoto) {
if (messageOwner.action.photo != null && messageOwner.action.photo.video_sizes != null && !messageOwner.action.photo.video_sizes.isEmpty()) {

View file

@ -295,6 +295,8 @@ public class MessagesController extends BaseController implements NotificationCe
private String uploadingWallpaper;
private Theme.OverrideWallpaperInfo uploadingWallpaperInfo;
private UserNameResolver userNameResolver;
private boolean loadingAppConfig;
private Fetcher<Integer, TLRPC.TL_help_appConfig> appConfigFetcher = new Fetcher<Integer, TLRPC.TL_help_appConfig>() {
@Override
@ -750,6 +752,13 @@ public class MessagesController extends BaseController implements NotificationCe
return null;
}
public UserNameResolver getUserNameResolver() {
if (userNameResolver == null) {
userNameResolver = new UserNameResolver(currentAccount);
}
return userNameResolver;
}
public class SponsoredMessagesInfo {
public ArrayList<MessageObject> messages;
public Integer posts_between;
@ -4137,6 +4146,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (user.min) {
if (oldUser != null) {
if (!fromCache) {
getUserNameResolver().update(oldUser, user);
if (user.bot) {
if (user.username != null) {
oldUser.username = user.username;
@ -4166,6 +4176,7 @@ public class MessagesController extends BaseController implements NotificationCe
getUserConfig().setCurrentUser(user);
getUserConfig().saveConfig(true);
}
getUserNameResolver().update(oldUser, user);
if (oldUser != null && user.status != null && oldUser.status != null && user.status.expires != oldUser.status.expires) {
return true;
}
@ -4246,6 +4257,7 @@ public class MessagesController extends BaseController implements NotificationCe
if (chat.min) {
if (oldChat != null) {
if (!fromCache) {
getUserNameResolver().update(oldChat, chat);
oldChat.title = chat.title;
oldChat.photo = chat.photo;
oldChat.broadcast = chat.broadcast;
@ -5525,6 +5537,10 @@ public class MessagesController extends BaseController implements NotificationCe
}
public void unblockPeer(long id) {
unblockPeer(id, null);
}
public void unblockPeer(long id, Runnable callback) {
TLRPC.TL_contacts_unblock req = new TLRPC.TL_contacts_unblock();
TLRPC.User user = null;
TLRPC.Chat chat = null;
@ -5547,9 +5563,11 @@ public class MessagesController extends BaseController implements NotificationCe
req.id = getInputPeer(chat);
}
getNotificationCenter().postNotificationName(NotificationCenter.blockedUsersDidLoad);
getConnectionsManager().sendRequest(req, (response, error) -> {
});
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
if (callback != null) {
callback.run();
}
}));
}
public void getBlockedPeers(boolean reset) {
@ -15667,13 +15685,18 @@ public class MessagesController extends BaseController implements NotificationCe
}
TelephonyManager tm = (TelephonyManager) ApplicationLoader.applicationContext.getSystemService(Context.TELEPHONY_SERVICE);
boolean callStateIsIdle = true;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
//TODO check
if (ActivityCompat.checkSelfPermission(ApplicationLoader.applicationContext, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
//TODO check
if (ActivityCompat.checkSelfPermission(ApplicationLoader.applicationContext, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
callStateIsIdle = tm.getCallStateForSubscription() == TelephonyManager.CALL_STATE_IDLE;
}
} else {
callStateIsIdle = tm.getCallState() == TelephonyManager.CALL_STATE_IDLE;
}
} else {
callStateIsIdle = tm.getCallState() == TelephonyManager.CALL_STATE_IDLE;
} catch (Throwable e) {
FileLog.e(e);
}
if (svc != null || VoIPService.callIShouldHavePutIntoIntent != null || !callStateIsIdle) {
if (BuildVars.LOGS_ENABLED) {
@ -17354,10 +17377,8 @@ public class MessagesController extends BaseController implements NotificationCe
AlertDialog[] progressDialog = new AlertDialog[] {
new AlertDialog(fragment.getParentActivity(), AlertDialog.ALERT_TYPE_SPINNER)
};
TLRPC.TL_contacts_resolveUsername req = new TLRPC.TL_contacts_resolveUsername();
req.username = username;
int reqId = getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
boolean[] canceled = new boolean[]{false};
getMessagesController().getUserNameResolver().resolve(username, (peerId) -> {
try {
if (progress != null) {
progress.end();
@ -17367,15 +17388,14 @@ public class MessagesController extends BaseController implements NotificationCe
} catch (Exception ignored) {}
progressDialog[0] = null;
fragment.setVisibleDialog(null);
if (error == null) {
TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response;
putUsers(res.users, false);
putChats(res.chats, false);
getMessagesStorage().putUsersAndChats(res.users, res.chats, false, true);
if (!res.chats.isEmpty()) {
openChatOrProfileWith(null, res.chats.get(0), fragment, 1, false);
} else if (!res.users.isEmpty()) {
openChatOrProfileWith(res.users.get(0), null, fragment, type, false);
if (canceled[0]) {
return;
}
if (peerId != null) {
if (peerId < 0) {
openChatOrProfileWith(null, getChat(-peerId), fragment, 1, false);
} else {
openChatOrProfileWith(getUser(peerId), null, fragment, type, false);
}
} else {
if (fragment.getParentActivity() != null) {
@ -17389,16 +17409,16 @@ public class MessagesController extends BaseController implements NotificationCe
}
}
}
}));
});
if (progress != null) {
progress.onCancel(() -> getConnectionsManager().cancelRequest(reqId, true));
progress.onCancel(() -> canceled[0] = true);
progress.init();
} else {
AndroidUtilities.runOnUIThread(() -> {
if (progressDialog[0] == null) {
return;
}
progressDialog[0].setOnCancelListener(dialog -> getConnectionsManager().cancelRequest(reqId, true));
progressDialog[0].setOnCancelListener(dialog -> canceled[0] = true);
fragment.showDialog(progressDialog[0]);
}, 500);
}

View file

@ -15,7 +15,6 @@ import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseIntArray;
@ -88,6 +87,7 @@ public class MessagesStorage extends BaseController {
private int archiveUnreadCount;
private volatile int pendingMainUnreadCount;
private volatile int pendingArchiveUnreadCount;
private boolean databaseCreated;
private CountDownLatch openSync = new CountDownLatch(1);
@ -99,7 +99,7 @@ public class MessagesStorage extends BaseController {
}
}
public final static int LAST_DB_VERSION = 115;
public final static int LAST_DB_VERSION = 116;
private boolean databaseMigrationInProgress;
public boolean showClearDatabaseAlert;
private LongSparseIntArray dialogIsForum = new LongSparseIntArray();
@ -291,6 +291,7 @@ public class MessagesStorage extends BaseController {
boolean createTable = false;
databaseCreated = false;
if (!cacheFile.exists()) {
createTable = true;
}
@ -357,6 +358,7 @@ public class MessagesStorage extends BaseController {
}
}
}
databaseCreated = true;
} catch (Exception e) {
FileLog.e(e);
if (openTries < 3 && e.getMessage() != null && e.getMessage().contains("malformed")) {
@ -367,6 +369,7 @@ public class MessagesStorage extends BaseController {
cleanupInternal(false);
}
openDatabase(openTries == 1 ? 2 : 3);
return;
}
}
@ -403,6 +406,7 @@ public class MessagesStorage extends BaseController {
private boolean recoverDatabase() {
database.close();
boolean restored = DatabaseMigrationHelper.recoverDatabase(cacheFile, walCacheFile, shmCacheFile, currentAccount);
FileLog.e("Database restored = " + restored);
if (restored) {
try {
database = new SQLiteDatabase(cacheFile.getPath());
@ -416,9 +420,14 @@ public class MessagesStorage extends BaseController {
}
}
if (!restored) {
cleanupInternal(true);
openDatabase(1);
restored = databaseCreated;
FileLog.e("Try create new database = " + restored);
}
if (restored) {
reset();
}
reset();
return restored;
}
@ -505,6 +514,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, send_state, date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_date_idx_scheduled_messages_v2 ON scheduled_messages_v2(uid, date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_scheduled_messages_v2 ON scheduled_messages_v2(mid, reply_to_message_id);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_scheduled_messages_v2 ON scheduled_messages_v2(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("CREATE TABLE messages_v2(mid INTEGER, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER, mention INTEGER, forwards INTEGER, replies_data BLOB, thread_reply_id INTEGER, is_channel INTEGER, reply_to_message_id INTEGER, custom_params BLOB, group_id INTEGER, PRIMARY KEY(mid, uid))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_read_out_idx_messages_v2 ON messages_v2(uid, mid, read_state, out);").stepThis().dispose();
@ -515,6 +525,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages_v2 ON messages_v2(uid, mention, read_state);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS is_channel_idx_messages_v2 ON messages_v2(mid, is_channel);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_v2 ON messages_v2(mid, reply_to_message_id);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_v2 ON messages_v2(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_groupid_messages_v2 ON messages_v2(uid, mid, group_id);").stepThis().dispose();
database.executeFast("CREATE TABLE download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, parent TEXT, PRIMARY KEY (uid, type));").stepThis().dispose();
@ -637,6 +648,7 @@ public class MessagesStorage extends BaseController {
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages_topics ON messages_topics(mid, send_state, date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS is_channel_idx_messages_topics ON messages_topics(mid, is_channel);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS reply_to_idx_messages_topics ON messages_topics(mid, reply_to_message_id);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS idx_to_reply_messages_topics ON messages_topics(reply_to_message_id, mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_uid_messages_topics ON messages_topics(mid, uid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mid_read_out_idx_messages_topics ON messages_topics(uid, topic_id, mid, read_state, out);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS uid_mention_idx_messages_topics ON messages_topics(uid, topic_id, mention, read_state);").stepThis().dispose();
@ -785,6 +797,7 @@ public class MessagesStorage extends BaseController {
private void checkSQLException(Throwable e, boolean logToAppCenter) {
if (e instanceof SQLiteException && e.getMessage() != null && e.getMessage().contains("is malformed") && !tryRecover) {
tryRecover = true;
FileLog.e("disk image malformed detected, try recover");
if (recoverDatabase()) {
tryRecover = false;
clearLoadingDialogsOffsets();
@ -1816,6 +1829,18 @@ public class MessagesStorage extends BaseController {
});
}
public void removeTopics(long dialogId, ArrayList<Integer> topicIds) {
storageQueue.postRunnable(() -> {
try {
String topics = TextUtils.join(", ", topicIds);
database.executeFast(String.format(Locale.US, "DELETE FROM topics WHERE did = %d AND topic_id IN (%s)", dialogId, topics)).stepThis().dispose();
database.executeFast(String.format(Locale.US, "DELETE FROM messages_topics WHERE uid = %d AND topic_id = IN (%s)", dialogId, topics)).stepThis().dispose();
} catch (SQLiteException e) {
e.printStackTrace();
}
});
}
public void updateTopicsWithReadMessages(HashMap<TopicKey, Integer> topicsReadOutbox) {
storageQueue.postRunnable(() -> {
for (TopicKey topicKey : topicsReadOutbox.keySet()) {
@ -2815,6 +2840,293 @@ public class MessagesStorage extends BaseController {
return array;
}
// public void checkLoadedRemoteFilter(TLRPC.DialogFilter newFilter) {
// storageQueue.postRunnable(() -> {
// try {
// SparseArray<MessagesController.DialogFilter> filtersToDelete = new SparseArray<>();
// for (int a = 0, N = dialogFilters.size(); a < N; a++) {
// MessagesController.DialogFilter filter = dialogFilters.get(a);
// filtersToDelete.put(filter.id, filter);
// }
// ArrayList<Integer> filtersOrder = new ArrayList<>();
//
// ArrayList<Long> usersToLoad = new ArrayList<>();
// HashMap<Long, TLRPC.InputPeer> usersToLoadMap = new HashMap<>();
// ArrayList<Long> chatsToLoad = new ArrayList<>();
// HashMap<Long, TLRPC.InputPeer> chatsToLoadMap = new HashMap<>();
// ArrayList<Long> dialogsToLoad = new ArrayList<>();
// HashMap<Long, TLRPC.InputPeer> dialogsToLoadMap = new HashMap<>();
//
// ArrayList<MessagesController.DialogFilter> filtersToSave = new ArrayList<>();
// HashMap<Integer, HashSet<Long>> filterDialogRemovals = new HashMap<>();
// HashSet<Integer> filtersUnreadCounterReset = new HashSet<>();
// for (int a = 0, N = vector.objects.size(); a < N; a++) {
// TLRPC.DialogFilter newFilter = (TLRPC.DialogFilter) vector.objects.get(a);
// filtersOrder.add(newFilter.id);
// int newFlags = 0;
// if (newFilter.contacts) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_CONTACTS;
// }
// if (newFilter.non_contacts) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_NON_CONTACTS;
// }
// if (newFilter.groups) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_GROUPS;
// }
// if (newFilter.broadcasts) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_CHANNELS;
// }
// if (newFilter.bots) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_BOTS;
// }
// if (newFilter.exclude_muted) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_MUTED;
// }
// if (newFilter.exclude_read) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_READ;
// }
// if (newFilter.exclude_archived) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_EXCLUDE_ARCHIVED;
// }
// if (newFilter instanceof TLRPC.TL_dialogFilterCommunity) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_COMMUNITY;
// if (newFilter.community_can_admin) {
// newFlags |= MessagesController.DIALOG_FILTER_FLAG_COMMUNITY_ADMIN;
// }
// }
//
// MessagesController.DialogFilter filter = dialogFiltersMap.get(newFilter.id);
// if (filter != null) {
// filtersToDelete.remove(newFilter.id);
// boolean changed = false;
// boolean unreadChanged = false;
// if (!TextUtils.equals(filter.name, newFilter.title)) {
// changed = true;
// filter.name = newFilter.title;
// }
// if (filter.flags != newFlags) {
// filter.flags = newFlags;
// changed = true;
// unreadChanged = true;
// }
//
// HashSet<Long> existingIds = new HashSet<>(filter.alwaysShow);
// existingIds.addAll(filter.neverShow);
// HashSet<Long> existingDialogsIds = new HashSet<>();
//
// LinkedHashMap<Integer, Long> secretChatsMap = null;
// if (filter.pinnedDialogs.size() != 0) {
// ArrayList<Long> pinArray = new ArrayList<>();
// boolean hasSecret = false;
// for (int c = 0, N2 = filter.pinnedDialogs.size(); c < N2; c++) {
// long did = filter.pinnedDialogs.keyAt(c);
// if (DialogObject.isEncryptedDialog(did)) {
// hasSecret = true;
// }
// pinArray.add(did);
// }
// if (hasSecret) {
// secretChatsMap = new LinkedHashMap<>();
// LongSparseIntArray pinnedDialogs = filter.pinnedDialogs;
// Collections.sort(pinArray, (o1, o2) -> {
// int idx1 = pinnedDialogs.get(o1);
// int idx2 = pinnedDialogs.get(o2);
// if (idx1 > idx2) {
// return 1;
// } else if (idx1 < idx2) {
// return -1;
// }
// return 0;
// });
// for (int c = 0, N2 = pinArray.size(); c < N2; c++) {
// long did = pinArray.get(c);
// if (!DialogObject.isEncryptedDialog(did)) {
// continue;
// }
// secretChatsMap.put(c, did);
// }
// }
// }
// for (int c = 0, N2 = filter.pinnedDialogs.size(); c < N2; c++) {
// long did = filter.pinnedDialogs.keyAt(c);
// if (DialogObject.isEncryptedDialog(did)) {
// continue;
// }
// existingDialogsIds.add(did);
// existingIds.remove(did);
// }
//
// filter.pinnedDialogs.clear();
// for (int b = 0, N2 = newFilter.pinned_peers.size(); b < N2; b++) {
// TLRPC.InputPeer peer = newFilter.pinned_peers.get(b);
// Long id;
// if (peer.user_id != 0) {
// id = peer.user_id;
// } else {
// id = -(peer.chat_id != 0 ? peer.chat_id : peer.channel_id);
// }
// int index = filter.pinnedDialogs.size();
// if (secretChatsMap != null) {
// Long did;
// while ((did = secretChatsMap.remove(index)) != null) {
// filter.pinnedDialogs.put(did, index);
// index++;
// }
// }
// filter.pinnedDialogs.put(id, index);
// existingIds.remove(id);
// if (!existingDialogsIds.remove(id)) {
// changed = true;
// if (!dialogsToLoadMap.containsKey(id)) {
// dialogsToLoad.add(id);
// dialogsToLoadMap.put(id, peer);
// }
// }
// }
// if (secretChatsMap != null) {
// for (LinkedHashMap.Entry<Integer, Long> entry : secretChatsMap.entrySet()) {
// filter.pinnedDialogs.put(entry.getValue(), filter.pinnedDialogs.size());
// }
// }
//
// for (int c = 0; c < 2; c++) {
// ArrayList<Long> fromArray = toPeerIds(c == 0 ? newFilter.include_peers : newFilter.exclude_peers);
// ArrayList<Long> toArray = c == 0 ? filter.alwaysShow : filter.neverShow;
//
// if (c == 0) {
// // put pinned_peers into include_peers (alwaysShow)
// ArrayList<Long> pinnedArray = toPeerIds(newFilter.pinned_peers);
// for (int i = 0; i < pinnedArray.size(); ++i) {
// fromArray.remove(pinnedArray.get(i));
// }
// fromArray.addAll(0, pinnedArray);
// }
//
// final int fromArrayCount = fromArray.size();
// boolean isDifferent = fromArray.size() != toArray.size();
// if (!isDifferent) {
// for (int i = 0; i < fromArrayCount; ++i) {
// if (!toArray.contains(fromArray.get(i))) {
// isDifferent = true;
// break;
// }
// }
// }
//
// if (isDifferent) {
// unreadChanged = true;
// changed = true;
// if (c == 0) {
// filter.alwaysShow = fromArray;
// } else {
// filter.neverShow = fromArray;
// }
// }
// }
// if (!existingDialogsIds.isEmpty()) {
// filterDialogRemovals.put(filter.id, existingDialogsIds);
// changed = true;
// }
// if (changed) {
// filtersToSave.add(filter);
// }
// if (unreadChanged) {
// filtersUnreadCounterReset.add(filter.id);
// }
// } else {
// filter = new MessagesController.DialogFilter();
// filter.id = newFilter.id;
// filter.flags = newFlags;
// filter.name = newFilter.title;
// filter.pendingUnreadCount = -1;
// for (int c = 0; c < 2; c++) {
// if (c == 0) {
// for (int b = 0, N2 = newFilter.pinned_peers.size(); b < N2; b++) {
// TLRPC.InputPeer peer = newFilter.pinned_peers.get(b);
// Long id;
// if (peer.user_id != 0) {
// id = peer.user_id;
// } else {
// id = -(peer.chat_id != 0 ? peer.chat_id : peer.channel_id);
// }
// if (!filter.alwaysShow.contains(id)) {
// filter.alwaysShow.add(id);
// }
// filter.pinnedDialogs.put(id, filter.pinnedDialogs.size() + 1);
// if (!dialogsToLoadMap.containsKey(id)) {
// dialogsToLoad.add(id);
// dialogsToLoadMap.put(id, peer);
// }
// }
// }
// ArrayList<TLRPC.InputPeer> fromArray = c == 0 ? newFilter.include_peers : newFilter.exclude_peers;
// ArrayList<Long> toArray = c == 0 ? filter.alwaysShow : filter.neverShow;
// for (int b = 0, N2 = fromArray.size(); b < N2; b++) {
// TLRPC.InputPeer peer = fromArray.get(b);
// if (peer.user_id != 0) {
// Long uid = peer.user_id;
// if (!toArray.contains(uid)) {
// toArray.add(uid);
// }
// if (!usersToLoadMap.containsKey(uid)) {
// usersToLoad.add(uid);
// usersToLoadMap.put(uid, peer);
// }
// } else {
// Long chatId = peer.chat_id != 0 ? peer.chat_id : peer.channel_id;
// Long dialogId = -chatId;
// if (!toArray.contains(dialogId)) {
// toArray.add(dialogId);
// }
// if (!chatsToLoadMap.containsKey(chatId)) {
// chatsToLoad.add(chatId);
// chatsToLoadMap.put(chatId, peer);
// }
// }
// }
// }
// filtersToSave.add(filter);
// }
// }
//
// TLRPC.messages_Dialogs dialogs;
// if (!dialogsToLoad.isEmpty()) {
// dialogs = loadDialogsByIds(TextUtils.join(",", dialogsToLoad), usersToLoad, chatsToLoad, new ArrayList<>());
// for (int a = 0, N = dialogs.dialogs.size(); a < N; a++) {
// TLRPC.Dialog dialog = dialogs.dialogs.get(a);
// dialogsToLoadMap.remove(dialog.id);
// }
// } else {
// dialogs = new TLRPC.TL_messages_dialogs();
// }
// ArrayList<TLRPC.User> users = new ArrayList<>();
// if (!usersToLoad.isEmpty()) {
// getUsersInternal(TextUtils.join(",", usersToLoad), users);
// for (int a = 0, N = users.size(); a < N; a++) {
// TLRPC.User user = users.get(a);
// usersToLoadMap.remove(user.id);
// }
// }
// ArrayList<TLRPC.Chat> chats = new ArrayList<>();
// if (!chatsToLoad.isEmpty()) {
// getChatsInternal(TextUtils.join(",", chatsToLoad), chats);
// for (int a = 0, N = chats.size(); a < N; a++) {
// TLRPC.Chat chat = chats.get(a);
// chatsToLoadMap.remove(chat.id);
// }
// }
//
// if (usersToLoadMap.isEmpty() && chatsToLoadMap.isEmpty() && dialogsToLoadMap.isEmpty()) {
// processLoadedFilterPeersInternal(dialogs, null, users, chats, filtersToSave, filtersToDelete, filtersOrder, filterDialogRemovals, filtersUnreadCounterReset);
// } else {
// getMessagesController().loadFilterPeers(dialogsToLoadMap, usersToLoadMap, chatsToLoadMap, dialogs, new TLRPC.TL_messages_dialogs(), users, chats, filtersToSave, filtersToDelete, filtersOrder, filterDialogRemovals, filtersUnreadCounterReset);
// }
// } catch (Exception e) {
// checkSQLException(e);
// }
// });
// }
public void checkLoadedRemoteFilters(TLRPC.Vector vector) {
storageQueue.postRunnable(() -> {
try {
@ -13180,6 +13492,7 @@ public class MessagesStorage extends BaseController {
try {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state, custom_params FROM messages_v2 WHERE mid = %d AND uid = %d LIMIT 1", message.id, MessageObject.getDialogId(message)));
if (!cursor.next()) {
cursor.dispose();
return;
}
readState = cursor.intValue(1);

View file

@ -6694,7 +6694,7 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
cursor.moveToFirst();
len = cursor.getLong(sizeIndex);
cursor.close();
} catch (Exception e) {
FileLog.e(e);
}

View file

@ -10,6 +10,7 @@ package org.telegram.messenger;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
@ -38,7 +39,10 @@ import org.telegram.messenger.partisan.UpdateData;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.SerializedData;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.AlertDialog;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.Components.SwipeGestureSettingsView;
import org.telegram.ui.LaunchActivity;
import java.io.File;
import java.io.RandomAccessFile;
@ -72,6 +76,40 @@ public class SharedConfig {
return LiteMode.isEnabled(LiteMode.FLAG_ANIMATED_STICKERS_CHAT);
}
public static boolean readOnlyStorageDirAlertShowed;
public static void checkSdCard(File file) {
if (file == null || SharedConfig.storageCacheDir == null || readOnlyStorageDirAlertShowed) {
return;
}
if (file.getPath().startsWith(SharedConfig.storageCacheDir)) {
AndroidUtilities.runOnUIThread(() -> {
if (readOnlyStorageDirAlertShowed) {
return;
}
BaseFragment fragment = LaunchActivity.getLastFragment();
if (fragment != null && fragment.getParentActivity() != null) {
SharedConfig.storageCacheDir = null;
SharedConfig.saveConfig();
ImageLoader.getInstance().checkMediaPaths(() -> {
});
readOnlyStorageDirAlertShowed = true;
AlertDialog.Builder dialog = new AlertDialog.Builder(fragment.getParentActivity());
dialog.setTitle(LocaleController.getString("SdCardError", R.string.SdCardError));
dialog.setSubtitle(LocaleController.getString("SdCardErrorDescription", R.string.SdCardErrorDescription));
dialog.setPositiveButton(LocaleController.getString("DoNotUseSDCard", R.string.DoNotUseSDCard), (dialog1, which) -> {
});
Dialog dialogFinal = dialog.create();
dialogFinal.setCanceledOnTouchOutside(false);
dialogFinal.show();
}
});
}
}
@Retention(RetentionPolicy.SOURCE)
@IntDef({
PASSCODE_TYPE_PIN,
@ -158,7 +196,7 @@ public class SharedConfig {
public static boolean streamMkv = false;
public static boolean saveStreamMedia = true;
public static boolean pauseMusicOnRecord = false;
public static boolean pauseMusicOnMedia = true;
public static boolean pauseMusicOnMedia = false;
public static boolean noiseSupression;
public static final boolean noStatusBar = true;
public static boolean debugWebView;
@ -684,7 +722,7 @@ public class SharedConfig {
streamMedia = preferences.getBoolean("streamMedia", true);
saveStreamMedia = preferences.getBoolean("saveStreamMedia", true);
pauseMusicOnRecord = preferences.getBoolean("pauseMusicOnRecord", false);
pauseMusicOnMedia = preferences.getBoolean("pauseMusicOnMedia", true);
pauseMusicOnMedia = preferences.getBoolean("pauseMusicOnMedia", false);
forceDisableTabletMode = preferences.getBoolean("forceDisableTabletMode", false);
streamAllVideo = preferences.getBoolean("streamAllVideo", BuildVars.DEBUG_VERSION);
streamMkv = preferences.getBoolean("streamMkv", false);
@ -1422,7 +1460,7 @@ public class SharedConfig {
info.ping = data.readInt64(false);
info.availableCheckTime = data.readInt64(false);
proxyList.add(info);
proxyList.add(0, info);
if (currentProxy == null && !TextUtils.isEmpty(proxyAddress)) {
if (proxyAddress.equals(info.address) && proxyPort == info.port && proxyUsername.equals(info.username) && proxyPassword.equals(info.password)) {
currentProxy = info;
@ -1440,7 +1478,7 @@ public class SharedConfig {
data.readString(false),
data.readString(false),
data.readString(false));
proxyList.add(info);
proxyList.add(0, info);
if (currentProxy == null && !TextUtils.isEmpty(proxyAddress)) {
if (proxyAddress.equals(info.address) && proxyPort == info.port && proxyUsername.equals(info.username) && proxyPassword.equals(info.password)) {
currentProxy = info;
@ -1474,7 +1512,7 @@ public class SharedConfig {
serializedData.writeByte(PROXY_CURRENT_SCHEMA_VERSION);
int count = infoToSerialize.size();
serializedData.writeInt32(count);
for (int a = 0; a < count; a++) {
for (int a = count - 1; a >= 0; a--) {
ProxyInfo info = infoToSerialize.get(a);
serializedData.writeString(info.address != null ? info.address : "");
serializedData.writeInt32(info.port);

View file

@ -11,6 +11,8 @@ package org.telegram.messenger;
import android.content.Context;
import android.content.SharedPreferences;
import org.telegram.messenger.utils.ImmutableByteArrayOutputStream;
import java.io.File;
import java.io.RandomAccessFile;
@ -78,6 +80,7 @@ public class StatsController extends BaseController {
return ((long) bytes[0] & 0xFF) << 56 | ((long) bytes[1] & 0xFF) << 48 | ((long) bytes[2] & 0xFF) << 40 | ((long) bytes[3] & 0xFF) << 32 | ((long) bytes[4] & 0xFF) << 24 | ((long) bytes[5] & 0xFF) << 16 | ((long) bytes[6] & 0xFF) << 8 | ((long) bytes[7] & 0xFF);
}
ImmutableByteArrayOutputStream byteArrayOutputStream = new ImmutableByteArrayOutputStream();
private Runnable saveRunnable = new Runnable() {
@Override
public void run() {
@ -87,25 +90,27 @@ public class StatsController extends BaseController {
}
lastInternalStatsSaveTime = newTime;
try {
statsFile.seek(0);
byteArrayOutputStream.reset();
for (int a = 0; a < 3; a++) {
for (int b = 0; b < OLD_TYPES_COUNT; b++) {
statsFile.write(longToBytes(sentBytes[a][b]), 0, 8);
statsFile.write(longToBytes(receivedBytes[a][b]), 0, 8);
statsFile.write(intToBytes(sentItems[a][b]), 0, 4);
statsFile.write(intToBytes(receivedItems[a][b]), 0, 4);
byteArrayOutputStream.write(longToBytes(sentBytes[a][b]), 0, 8);
byteArrayOutputStream.write(longToBytes(receivedBytes[a][b]), 0, 8);
byteArrayOutputStream.write(intToBytes(sentItems[a][b]), 0, 4);
byteArrayOutputStream.write(intToBytes(receivedItems[a][b]), 0, 4);
}
statsFile.write(intToBytes(callsTotalTime[a]), 0, 4);
statsFile.write(longToBytes(resetStatsDate[a]), 0, 8);
byteArrayOutputStream.write(intToBytes(callsTotalTime[a]), 0, 4);
byteArrayOutputStream.write(longToBytes(resetStatsDate[a]), 0, 8);
}
for (int b = OLD_TYPES_COUNT; b < TYPES_COUNT; ++b) {
for (int a = 0; a < 3; ++a) {
statsFile.write(longToBytes(sentBytes[a][b]), 0, 8);
statsFile.write(longToBytes(receivedBytes[a][b]), 0, 8);
statsFile.write(intToBytes(sentItems[a][b]), 0, 4);
statsFile.write(intToBytes(receivedItems[a][b]), 0, 4);
byteArrayOutputStream.write(longToBytes(sentBytes[a][b]), 0, 8);
byteArrayOutputStream.write(longToBytes(receivedBytes[a][b]), 0, 8);
byteArrayOutputStream.write(intToBytes(sentItems[a][b]), 0, 4);
byteArrayOutputStream.write(intToBytes(receivedItems[a][b]), 0, 4);
}
}
statsFile.seek(0);
statsFile.write(byteArrayOutputStream.buf, 0, byteArrayOutputStream.count());
statsFile.getFD().sync();
} catch (Exception ignore) {
@ -280,6 +285,7 @@ public class StatsController extends BaseController {
long newTime = System.currentTimeMillis();
if (Math.abs(newTime - lastStatsSaveTime.get()) >= 2000) {
lastStatsSaveTime.set(newTime);
statsSaveQueue.cancelRunnable(saveRunnable);
statsSaveQueue.postRunnable(saveRunnable);
}
}

View file

@ -404,6 +404,26 @@ public class SvgHelper {
public void copyCommandFromPosition(int position) {
commands.add(commands.get(position));
}
public SvgDrawable clone() {
SvgDrawable drawable = new SvgDrawable();
for (int i = 0; i < commands.size(); i++) {
drawable.commands.add(commands.get(i));
Paint fromPaint = paints.get(commands.get(i));
if (fromPaint != null) {
Paint toPaint = new Paint();
toPaint.setColor(fromPaint.getColor());
toPaint.setStrokeCap(fromPaint.getStrokeCap());
toPaint.setStrokeJoin(fromPaint.getStrokeJoin());
toPaint.setStrokeWidth(fromPaint.getStrokeWidth());
toPaint.setStyle(fromPaint.getStyle());
drawable.paints.put(commands.get(i), toPaint);
}
}
drawable.width = width;
drawable.height = height;
return drawable;
}
}
public static Bitmap getBitmap(int res, int width, int height, int color) {

View file

@ -149,6 +149,7 @@ public class TopicsController extends BaseController {
}
ArrayList<TLRPC.TL_forumTopic> topics = topicsByChatId.get(chatId);
ArrayList<TLRPC.TL_forumTopic> topicsToReload = null;
ArrayList<Integer> deletedTopics = null;
LongSparseArray<TLRPC.TL_forumTopic> topicsMap = topicsMapByChatId.get(chatId);
if (topics == null) {
@ -165,6 +166,10 @@ public class TopicsController extends BaseController {
for (int i = 0; i < newTopics.size(); i++) {
TLRPC.TL_forumTopic newTopic = newTopics.get(i);
if (newTopic instanceof TLRPC.TL_forumTopicDeleted) {
if (deletedTopics == null) {
deletedTopics = new ArrayList<>();
}
deletedTopics.add(newTopic.id);
continue;
}
if (!topicsMap.containsKey(newTopic.id)) {
@ -206,6 +211,17 @@ public class TopicsController extends BaseController {
}
}
if (deletedTopics != null && loadType == LOAD_TYPE_LOAD_UNKNOWN) {
for (int i = 0; i < deletedTopics.size(); i++) {
for (int j = 0; j < topics.size(); j++) {
if (topics.get(j).id == deletedTopics.get(i)) {
topics.remove(j);
break;
}
}
}
getMessagesStorage().removeTopics(chatId, deletedTopics);
}
if (topicsToReload != null && loadType != LOAD_TYPE_LOAD_UNKNOWN) {
reloadTopics(chatId, topicsToReload, null);
} else if (((loadType == LOAD_TYPE_PRELOAD && !fromCache) || loadType == LOAD_TYPE_LOAD_NEXT) && topics.size() >= totalCount && totalCount >= 0) {

View file

@ -0,0 +1,123 @@
package org.telegram.messenger;
import android.text.TextUtils;
import android.util.LruCache;
import com.google.android.exoplayer2.util.Consumer;
import org.telegram.tgnet.ConnectionsManager;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.Components.BulletinFactory;
import org.telegram.ui.LaunchActivity;
import java.util.ArrayList;
import java.util.HashMap;
public class UserNameResolver {
private final int currentAccount;
private final static long CACHE_TIME = 1000 * 60 * 60; //1 hour
UserNameResolver(int currentAccount) {
this.currentAccount = currentAccount;
}
LruCache<String, CachedPeer> resolvedCache = new LruCache<>(100);
HashMap<String, ArrayList<Consumer<Long>>> resolvingConsumers = new HashMap<>();
public void resolve(String username, Consumer<Long> resolveConsumer) {
CachedPeer cachedPeer = resolvedCache.get(username);
if (cachedPeer != null) {
if (System.currentTimeMillis() - cachedPeer.time < CACHE_TIME) {
resolveConsumer.accept(cachedPeer.peerId);
FileLog.d("resolve username from cache " + username + " " + cachedPeer.peerId);
return;
} else {
resolvedCache.remove(username);
}
}
ArrayList<Consumer<Long>> consumers = resolvingConsumers.get(username);
if (consumers != null) {
consumers.add(resolveConsumer);
return;
}
consumers = new ArrayList<>();
consumers.add(resolveConsumer);
resolvingConsumers.put(username, consumers);
TLObject req;
if (AndroidUtilities.isNumeric(username)) {
TLRPC.TL_contacts_resolvePhone resolvePhone = new TLRPC.TL_contacts_resolvePhone();
resolvePhone.phone = username;
req = resolvePhone;
} else {
TLRPC.TL_contacts_resolveUsername resolveUsername = new TLRPC.TL_contacts_resolveUsername();
resolveUsername.username = username;
req = resolveUsername;
}
ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
ArrayList<Consumer<Long>> finalConsumers = resolvingConsumers.remove(username);
if (finalConsumers == null) {
return;
}
if (error != null) {
for (int i = 0; i < finalConsumers.size(); i++) {
finalConsumers.get(i).accept(null);
}
if (error != null && error.text != null && error.text.contains("FLOOD_WAIT")) {
BaseFragment fragment = LaunchActivity.getLastFragment();
if (fragment != null) {
BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("FloodWait", R.string.FloodWait)).show();
}
}
return;
}
TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response;
MessagesController.getInstance(currentAccount).putUsers(res.users, false);
MessagesController.getInstance(currentAccount).putChats(res.chats, false);
MessagesStorage.getInstance(currentAccount).putUsersAndChats(res.users, res.chats, false, true);
long peerId = MessageObject.getPeerId(res.peer);
resolvedCache.put(username, new CachedPeer(peerId));
for (int i = 0; i < finalConsumers.size(); i++) {
finalConsumers.get(i).accept(peerId);
}
}, ConnectionsManager.RequestFlagFailOnServerErrors));
};
public void update(TLRPC.User oldUser, TLRPC.User user) {
if (oldUser == null || user == null || oldUser.username == null || TextUtils.equals(oldUser.username, user.username)) {
return;
}
resolvedCache.remove(oldUser.username);
if (user.username != null) {
resolvedCache.put(user.username, new CachedPeer(user.id));
}
}
public void update(TLRPC.Chat oldChat, TLRPC.Chat chat) {
if (oldChat == null || chat == null || oldChat.username == null || TextUtils.equals(oldChat.username, chat.username)) {
return;
}
resolvedCache.remove(oldChat.username);
if (chat.username != null) {
resolvedCache.put(chat.username, new CachedPeer(-chat.id));
}
}
private class CachedPeer {
final long peerId;
final long time;
public CachedPeer(long peerId) {
this.peerId = peerId;
time = System.currentTimeMillis();
}
}
}

View file

@ -90,4 +90,7 @@ public class ImmutableByteArrayOutputStream extends OutputStream {
count = 0;
}
public int count() {
return count;
}
}

View file

@ -83,7 +83,9 @@ public class MediaCodecVideoConvertor {
long time = System.currentTimeMillis();
boolean error = false;
boolean repeatWithIncreasedTimeout = false;
boolean isAvatar = avatarStartTime >= 0;
int videoTrackIndex = -5;
String selectedEncoderName = null;
try {
MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
@ -108,7 +110,7 @@ public class MediaCodecVideoConvertor {
boolean decoderDone = false;
int framesCount = 0;
if (avatarStartTime >= 0) {
if (isAvatar) {
if (durationS <= 2000) {
bitrate = 2600000;
} else if (durationS <= 5000) {
@ -144,6 +146,10 @@ public class MediaCodecVideoConvertor {
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
encoder = MediaCodec.createEncoderByType(MediaController.VIDEO_MIME_TYPE);
selectedEncoderName = encoder.getName();
FileLog.d("selected encoder " + selectedEncoderName);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
@ -345,7 +351,7 @@ public class MediaCodecVideoConvertor {
extractor.selectTrack(videoIndex);
MediaFormat videoFormat = extractor.getTrackFormat(videoIndex);
String encoderName = null;
if (avatarStartTime >= 0) {
if (isAvatar) {
if (durationS <= 2000) {
bitrate = 2600000;
} else if (durationS <= 5000) {
@ -392,21 +398,6 @@ public class MediaCodecVideoConvertor {
w = resultWidth;
h = resultHeight;
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create encoder with w = " + w + " h = " + h + " bitrate = " + bitrate);
}
MediaFormat outputFormat = MediaFormat.createVideoFormat(MediaController.VIDEO_MIME_TYPE, w, h);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);
if (Build.VERSION.SDK_INT < 23 && Math.min(h, w) <= 480) {
if (bitrate > 921600) {
bitrate = 921600;
}
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
}
if (encoderName != null) {
try {
@ -418,6 +409,30 @@ public class MediaCodecVideoConvertor {
if (encoder == null) {
encoder = MediaCodec.createEncoderByType(MediaController.VIDEO_MIME_TYPE);
}
if (BuildVars.LOGS_ENABLED) {
FileLog.d("create encoder with w = " + w + " h = " + h + " bitrate = " + bitrate);
}
MediaFormat outputFormat = MediaFormat.createVideoFormat(MediaController.VIDEO_MIME_TYPE, w, h);
outputFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
if (isAvatar && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// prevent case when result video max 2MB
outputFormat.setInteger(MediaFormat.KEY_BITRATE_MODE, MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
}
outputFormat.setInteger( "max-bitrate", bitrate);
outputFormat.setInteger(MediaFormat.KEY_FRAME_RATE, framerate);
outputFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
if (Build.VERSION.SDK_INT < 23 && Math.min(h, w) <= 480 && !isAvatar) {
if (bitrate > 921600) {
bitrate = 921600;
}
outputFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
}
selectedEncoderName = encoder.getName();
FileLog.d("selected encoder " + selectedEncoderName);
encoder.configure(outputFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
inputSurface = new InputSurface(encoder.createInputSurface());
inputSurface.makeCurrent();
@ -825,12 +840,16 @@ public class MediaCodecVideoConvertor {
long timeLeft = System.currentTimeMillis() - time;
if (BuildVars.LOGS_ENABLED) {
FileLog.d("compression completed time=" + timeLeft + " needCompress=" + needCompress + " w=" + resultWidth + " h=" + resultHeight + " bitrate=" + bitrate + " file size=" + cacheFile.length());
FileLog.d("compression completed time=" + timeLeft + " needCompress=" + needCompress + " w=" + resultWidth + " h=" + resultHeight + " bitrate=" + bitrate + " file size=" + AndroidUtilities.formatFileSize(cacheFile.length()) + " encoder_name=" + selectedEncoderName);
}
return error;
}
private boolean isMediatekAvcEncoder(MediaCodec encoder) {
return encoder.getName().equals("c2.mtk.avc.encoder");
}
private long readAndWriteTracks(MediaExtractor extractor, MP4Builder mediaMuxer,
MediaCodec.BufferInfo info, long start, long end, long duration, File file, boolean needAudio) throws Exception {
int videoTrackIndex = MediaController.findTrack(extractor, false);

View file

@ -3109,7 +3109,11 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
if (hasAudioFocus) {
am.abandonAudioFocus(this);
}
Utilities.globalQueue.postRunnable(() -> soundPool.release());
Utilities.globalQueue.postRunnable(() -> {
if (soundPool != null) {
soundPool.release();
}
});
}
if (USE_CONNECTION_SERVICE) {
@ -3559,6 +3563,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
if (!USE_CONNECTION_SERVICE && btAdapter != null && btAdapter.isEnabled()) {
try {
MediaRouter mr = (MediaRouter) getSystemService(Context.MEDIA_ROUTER_SERVICE);
AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (Build.VERSION.SDK_INT < 24) {
int headsetState = btAdapter.getProfileConnectionState(BluetoothProfile.HEADSET);
updateBluetoothHeadsetState(headsetState == BluetoothProfile.STATE_CONNECTED);
@ -3574,7 +3579,7 @@ public class VoIPService extends Service implements SensorEventListener, AudioMa
l.onAudioSettingsChanged();
}
} else {
updateBluetoothHeadsetState(false);
updateBluetoothHeadsetState(am.isBluetoothA2dpOn());
}
}
} catch (Throwable e) {

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

@ -70,7 +70,7 @@ public class TLRPC {
public static final int MESSAGE_FLAG_HAS_BOT_ID = 0x00000800;
public static final int MESSAGE_FLAG_EDITED = 0x00008000;
public static final int LAYER = 156;
public static final int LAYER = 157;
public static class TL_stats_megagroupStats extends TLObject {
public static int constructor = 0xef7ff916;
@ -24362,6 +24362,8 @@ public class TLRPC {
public int score;
public boolean video;
public int months;
public String cryptoCurrency;
public long cryptoAmount;
public static MessageAction TLdeserialize(AbstractSerializedData stream, int constructor, boolean exception) {
MessageAction result = null;
@ -24528,7 +24530,7 @@ public class TLRPC {
case 0x8f31b327:
result = new TL_messageActionPaymentSentMe();
break;
case 0xaba0f5c6:
case 0xc83d6aec:
result = new TL_messageActionGiftPremium();
break;
case 0xfe77345d:
@ -25504,19 +25506,29 @@ public class TLRPC {
}
public static class TL_messageActionGiftPremium extends MessageAction {
public static int constructor = 0xaba0f5c6;
public static int constructor = 0xc83d6aec;
public void readParams(AbstractSerializedData stream, boolean exception) {
flags = stream.readInt32(exception);
currency = stream.readString(exception);
amount = stream.readInt64(exception);
months = stream.readInt32(exception);
if ((flags & 1) != 0) {
cryptoCurrency = stream.readString(exception);
cryptoAmount = stream.readInt64(exception);
}
}
public void serializeToStream(AbstractSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(flags);
stream.writeString(currency);
stream.writeInt64(amount);
stream.writeInt32(months);
if ((flags & 1) != 0) {
stream.writeString(cryptoCurrency);
stream.writeInt64(cryptoAmount);
}
}
}

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

@ -6277,6 +6277,7 @@ public class Theme {
public static Drawable rect(String backgroundColorKey) {
return rect(Theme.getColor(backgroundColorKey));
}
public static Drawable rect(String backgroundColorKey, float ...radii) {
return rect(Theme.getColor(backgroundColorKey), radii);
}
@ -10878,13 +10879,27 @@ public class Theme {
return false;
}
public static void turnOffAutoNight(BaseFragment fragment) {
turnOffAutoNight(fragment != null ? fragment.getLayoutContainer() : null, () -> {
INavigationLayout nav = fragment != null ? fragment.getParentLayout() : null;
if (nav != null) {
nav.presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT));
public static void turnOffAutoNight(@NonNull BaseFragment fragment) {
if (selectedAutoNightType != AUTO_NIGHT_TYPE_NONE) {
if (fragment != null) {
try {
BulletinFactory.of(fragment).createSimpleBulletin(
R.raw.auto_night_off,
selectedAutoNightType == AUTO_NIGHT_TYPE_SYSTEM ?
LocaleController.getString("AutoNightSystemModeOff", R.string.AutoNightSystemModeOff) :
LocaleController.getString("AutoNightModeOff", R.string.AutoNightModeOff),
LocaleController.getString("Settings", R.string.Settings),
Bulletin.DURATION_PROLONG,
() -> fragment.presentFragment(new ThemeActivity(ThemeActivity.THEME_TYPE_NIGHT))
).show();
} catch (Exception e) {
FileLog.e(e);
}
}
});
selectedAutoNightType = AUTO_NIGHT_TYPE_NONE;
saveAutoNightThemeConfig();
cancelAutoNightThemeCallbacks();
}
}
public static void turnOffAutoNight(FrameLayout container, Runnable openSettings) {

View file

@ -22,6 +22,8 @@ import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.exoplayer2.util.Log;
import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.SQLite.SQLiteCursor;
import org.telegram.SQLite.SQLitePreparedStatement;
@ -293,6 +295,9 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
if (reqForumId != 0 && reqId != 0) {
return;
}
if (lastMessagesSearchId != lastSearchId) {
return;
}
if (delegate != null && delegate.getSearchForumDialogId() != 0 && !localMessagesSearchEndReached) {
searchForumMessagesInternal(lastMessagesSearchString, lastMessagesSearchId);
} else {
@ -465,7 +470,7 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
req.filter = new TLRPC.TL_inputMessagesFilterEmpty();
req.flags |= 1;
req.folder_id = folderId;
if (query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty()) {
if (query.equals(lastMessagesSearchString) && !searchResultMessages.isEmpty() && lastMessagesSearchId == lastSearchId) {
MessageObject lastMessage = searchResultMessages.get(searchResultMessages.size() - 1);
req.offset_id = lastMessage.getId();
req.offset_rate = nextSearchRate;
@ -477,7 +482,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
req.offset_peer = new TLRPC.TL_inputPeerEmpty();
}
lastMessagesSearchString = query;
final int currentReqId = ++lastReqId;
lastReqId++;
final int currentReqId = lastReqId;
reqId = ConnectionsManager.getInstance(currentAccount).sendRequest(req, (response, error) -> {
final ArrayList<MessageObject> messageObjects = new ArrayList<>();
if (error == null) {
@ -1046,7 +1052,8 @@ public class DialogsSearchAdapter extends RecyclerListView.SelectionAdapter {
searchResultHashtags.clear();
}
final int searchId = ++lastSearchId;
lastSearchId++;
final int searchId = lastSearchId;
waitingResponseCount = 3;
globalSearchCollapsed = true;
phoneCollapsed = true;

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

View file

@ -82,6 +82,7 @@ import org.telegram.PhoneFormat.PhoneFormat;
import org.telegram.messenger.AccountInstance;
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.ChatObject;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.DialogObject;
@ -182,7 +183,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
public boolean clipToGroupBounds;
public boolean drawForBlur;
private boolean flipImage;
private boolean visibleOnScreen;
private boolean visibleOnScreen = true;
public boolean shouldCheckVisibleOnScreen;
float parentBoundsTop;
int parentBoundsBottom;
@ -374,6 +375,9 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
if (this.visibleOnScreen != visibleOnScreen) {
this.visibleOnScreen = visibleOnScreen;
checkImageReceiversAttachState();
if (visibleOnScreen) {
invalidate();
}
}
}
@ -3887,9 +3891,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
NotificationCenter.getInstance(currentAccount).removeObserver(this, NotificationCenter.userInfoDidLoad);
cancelShakeAnimation();
if (animationRunning) {
return;
}
if (checkBox != null) {
checkBox.onDetachedFromWindow();
}
@ -3946,9 +3947,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.emojiLoaded);
NotificationCenter.getInstance(currentAccount).addObserver(this, NotificationCenter.userInfoDidLoad);
// if (currentMessageObject != null) {
// currentMessageObject.onAttachedWindow(this);
// }
if (currentMessageObject != null) {
currentMessageObject.animateComments = false;
}
@ -4093,26 +4091,30 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
photoImage.onDetachedFromWindow();
blurredPhotoImage.onDetachedFromWindow();
if (currentMessageObject != null && !currentMessageObject.mediaExists && !currentMessageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(currentMessageObject.messageOwner.id)) {
TLRPC.Document document = currentMessageObject.getDocument();
boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document);
if (!loadDocumentFromImageReceiver) {
if (document != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(document);
} else {
TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(currentMessageObject.photoThumbs, AndroidUtilities.getPhotoSize());
if (photo != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(photo);
}
}
}
}
cancelLoading(currentMessageObject);
AnimatedEmojiSpan.release(this, animatedEmojiDescriptionStack);
AnimatedEmojiSpan.release(this, animatedEmojiReplyStack);
AnimatedEmojiSpan.release(this, animatedEmojiStack);
}
}
private void cancelLoading(MessageObject messageObject) {
if (messageObject != null && !messageObject.mediaExists && !messageObject.putInDownloadsStore && !DownloadController.getInstance(currentAccount).isDownloading(messageObject.messageOwner.id) && !PhotoViewer.getInstance().isVisible()) {
TLRPC.Document document = messageObject.getDocument();
boolean loadDocumentFromImageReceiver = MessageObject.isStickerDocument(document) || MessageObject.isAnimatedStickerDocument(document, true) || MessageObject.isGifDocument(document) || MessageObject.isRoundVideoDocument(document);
if (!loadDocumentFromImageReceiver) {
if (document != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(document);
} else {
TLRPC.PhotoSize photo = FileLoader.getClosestPhotoSizeWithSize(messageObject.photoThumbs, AndroidUtilities.getPhotoSize());
if (photo != null) {
FileLoader.getInstance(currentAccount).cancelLoadFile(photo);
}
}
}
}
}
private void setMessageContent(MessageObject messageObject, MessageObject.GroupedMessages groupedMessages, boolean bottomNear, boolean topNear) {
if (messageObject.checkLayout() || currentPosition != null && lastHeight != AndroidUtilities.displaySize.y) {
currentMessageObject = null;
@ -7595,7 +7597,7 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
botButtonsByData.put(key, botButton);
botButtonsByPosition.put(position, botButton);
botButton.x = b * (buttonWidth + AndroidUtilities.dp(5));
botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(5);
botButton.y = a * AndroidUtilities.dp(44 + 4) + AndroidUtilities.dp(2.5f);
botButton.width = buttonWidth;
botButton.height = AndroidUtilities.dp(44);
CharSequence buttonText;
@ -17663,9 +17665,6 @@ public class ChatMessageCell extends BaseCell implements SeekBar.SeekBarDelegate
} else {
this.willRemoved = false;
}
if (getParent() == null && attachedToWindow) {
onDetachedFromWindow();
}
}
@Override

View file

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

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));
Drawable background = new ColorDrawable(backgroundColor);
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
setBackgroundDrawable(combinedDrawable);
size = s;
this.resourcesProvider = resourcesProvider;
this.backgroundColor = backgroundColor;
this.size = s;
updateBackground();
}
public void setTopBottom(boolean top, boolean bottom) {
if (this.top != top || this.bottom != bottom) {
this.top = top;
this.bottom = bottom;
updateBackground();
}
}
private void updateBackground() {
if (backgroundColor == 0) {
if (!top && !bottom) {
setBackground(null);
} else {
setBackground(Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider)));
}
} else {
if (!top && !bottom) {
setBackgroundColor(backgroundColor);
} else {
Drawable shadowDrawable = Theme.getThemedDrawable(getContext(), getBackgroundResId(), Theme.getColor(Theme.key_windowBackgroundGrayShadow, resourcesProvider));
Drawable background = new ColorDrawable(backgroundColor);
CombinedDrawable combinedDrawable = new CombinedDrawable(background, shadowDrawable, 0, 0);
combinedDrawable.setFullsize(true);
setBackground(combinedDrawable);
}
}
}
private int getBackgroundResId() {
if (top && bottom) {
return R.drawable.greydivider;
} else if (top) {
return R.drawable.greydivider_bottom;
} else if (bottom) {
return R.drawable.greydivider_top;
} else {
return R.drawable.transparent;
}
}
@Override

View file

@ -300,6 +300,7 @@ import org.telegram.ui.Components.UndoView;
import org.telegram.ui.Components.UnreadCounterTextView;
import org.telegram.ui.Components.ViewHelper;
import org.telegram.ui.Components.spoilers.SpoilerEffect;
import org.telegram.ui.Components.voip.CellFlickerDrawable;
import org.telegram.ui.Components.voip.VoIPHelper;
import org.telegram.ui.Delegates.ChatActivityMemberRequestsDelegate;
import org.telegram.ui.DialogBuilder.DialogCheckBox;
@ -388,6 +389,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private GridLayoutManagerFixed chatLayoutManager;
private ChatActivityAdapter chatAdapter;
private UnreadCounterTextView bottomOverlayChatText;
private TextView bottomOverlayStartButton;
private ImageView bottomOverlayImage;
private RadialProgressView bottomOverlayProgress;
private AnimatorSet bottomOverlayAnimation;
@ -721,6 +723,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private int loadsCount;
private int last_message_id = 0;
private long mergeDialogId;
private boolean sentBotStart;
private long startMessageAppearTransitionMs;
private List<MessageSkeleton> messageSkeletons = new ArrayList<>();
@ -3434,6 +3437,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (themeDelegate.isThemeChangeAvailable()) {
headerItem.lazilyAddSubItem(change_colors, R.drawable.msg_colors, LocaleController.getString("ChangeColors", R.string.ChangeColors));
}
boolean addedSettings = false;
if (!isTopic) {
if (ChatObject.isChannel(currentChat) && !currentChat.creator) {
if (!ChatObject.isNotInChat(currentChat)) {
@ -3446,6 +3450,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (!ChatObject.isChannel(currentChat)) {
if (currentChat != null) {
headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_leave, LocaleController.getString("DeleteAndExit", R.string.DeleteAndExit));
} else if (currentUser != null && currentUser.bot) {
headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings));
addedSettings = true;
headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_dialogTextRed), getThemedColor(Theme.key_dialogTextRed));
} else {
headerItem.lazilyAddSubItem(delete_chat, R.drawable.msg_delete, LocaleController.getString("DeleteChatUser", R.string.DeleteChatUser));
}
@ -3455,7 +3463,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
headerItem.lazilyAddSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
}
if (currentUser != null && currentEncryptedChat == null && currentUser.bot) {
headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings));
if (!addedSettings) {
headerItem.lazilyAddSubItem(bot_settings, R.drawable.msg_settings_old, LocaleController.getString("BotSettings", R.string.BotSettings));
}
headerItem.lazilyAddSubItem(bot_help, R.drawable.msg_help, LocaleController.getString("BotHelp", R.string.BotHelp));
updateBotButtons();
}
@ -5148,26 +5158,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
@Override
public void onScrolled(int dx, int dy) {
super.onScrolled(dx, dy);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
}
@Override
public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
super.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@ -5178,7 +5168,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
chatListViewAttached = false;
clearMessagesPreloading();
}
};
if (currentEncryptedChat != null && Build.VERSION.SDK_INT >= 19) {
@ -5534,7 +5523,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
scrollingChatListView = false;
checkTextureViewPosition = false;
hideFloatingDateView(true);
checkAutoDownloadMessages(scrollUp);
if (SharedConfig.getDevicePerformanceClass() == SharedConfig.PERFORMANCE_CLASS_LOW) {
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.startAllHeavyOperations, 512);
}
@ -6821,6 +6809,41 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
bottomOverlayChat.setClipChildren(false);
contentView.addView(bottomOverlayChat, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.BOTTOM));
bottomOverlayStartButton = new TextView(context) {
CellFlickerDrawable cellFlickerDrawable;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (cellFlickerDrawable == null) {
cellFlickerDrawable = new CellFlickerDrawable();
cellFlickerDrawable.drawFrame = false;
cellFlickerDrawable.repeatProgress = 2f;
}
cellFlickerDrawable.setParentWidth(getMeasuredWidth());
AndroidUtilities.rectTmp.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
cellFlickerDrawable.draw(canvas, AndroidUtilities.rectTmp, AndroidUtilities.dp(4), null);
invalidate();
}
@Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
ViewGroup.LayoutParams params = bottomOverlayChat.getLayoutParams();
params.height = AndroidUtilities.dp(visibility == VISIBLE ? 51 + 8 * 2 : 51);
}
};
bottomOverlayStartButton.setBackground(Theme.AdaptiveRipple.filledRect(getThemedColor(Theme.key_featuredStickers_addButton), 8));
bottomOverlayStartButton.setTextColor(getThemedColor(Theme.key_featuredStickers_buttonText));
bottomOverlayStartButton.setText(LocaleController.getString(R.string.BotStart));
bottomOverlayStartButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
bottomOverlayStartButton.setGravity(Gravity.CENTER);
bottomOverlayStartButton.setTypeface(AndroidUtilities.getTypeface(AndroidUtilities.TYPEFACE_ROBOTO_MEDIUM));
bottomOverlayStartButton.setVisibility(View.GONE);
bottomOverlayStartButton.setOnClickListener(v -> bottomOverlayChatText.callOnClick());
bottomOverlayChat.addView(bottomOverlayStartButton, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.CENTER, 8, 8, 8, 8));
bottomOverlayChatText = new UnreadCounterTextView(context) {
@Override
protected void updateCounter() {
@ -6875,12 +6898,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentUser.bot) {
String botUserLast = botUser;
botUser = null;
getMessagesController().unblockPeer(currentUser.id);
if (botUserLast != null && botUserLast.length() != 0) {
getMessagesController().sendBotStart(currentUser, botUserLast);
} else {
getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null, false);
}
getMessagesController().unblockPeer(currentUser.id, () -> {
if (botUserLast != null && botUserLast.length() != 0) {
getMessagesController().sendBotStart(currentUser, botUserLast);
} else {
getSendMessagesHelper().sendMessage("/start", dialog_id, null, null, null, false, null, null, null, true, 0, null, false);
}
});
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity(), themeDelegate);
builder.setMessage(LocaleController.getString("AreYouSureUnblockContact", R.string.AreYouSureUnblockContact));
@ -10352,127 +10376,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showDialog(chatAttachAlert);
}
ArrayList<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;
@ -11911,7 +11814,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (bottom <= clipTop - chatListViewPaddingVisibleOffset || top > chatListView.getMeasuredHeight() - blurredViewBottomOffset) {
if (messageCell != null) {
if (!blurEnabled) {
if (blurEnabled) {
messageCell.setVisibleOnScreen(false);
} else {
messageCell.setVisibleOnScreen(true);
@ -13678,6 +13581,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (keyboardSize > AndroidUtilities.dp(20) && getLayoutParams().height < 0) {
h += keyboardSize;
}
if (bottomOverlay != null && bottomOverlay.getVisibility() == View.VISIBLE && bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() != View.GONE) {
h -= AndroidUtilities.dp(16);
}
int contentHeightSpec = View.MeasureSpec.makeMeasureSpec(Math.max(AndroidUtilities.dp(10), h), View.MeasureSpec.EXACTLY);
child.measure(contentWidthSpec, contentHeightSpec);
} else if (child == progressView) {
@ -13927,9 +13833,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
invalidateMessagesVisiblePart();
updateTextureViewPosition(false, false);
if (!scrollingChatListView) {
checkAutoDownloadMessages(false);
}
notifyHeightChanged();
}
@ -16437,6 +16340,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
getNotificationCenter().runDelayedNotifications();
});
}
if (did == dialog_id && !messages.isEmpty() && currentUser != null && (bottomOverlayStartButton != null && bottomOverlayStartButton.getVisibility() == View.VISIBLE)) {
if (!TextUtils.isEmpty(botUser) && !sentBotStart) {
sentBotStart = true;
getMessagesController().sendBotStart(currentUser, botUser);
bottomOverlayChat.setVisibility(View.GONE);
chatActivityEnterView.setVisibility(View.VISIBLE);
}
}
} else if (id == NotificationCenter.invalidateMotionBackground) {
if (chatListView != null) {
chatListView.invalidateViews();
@ -16484,9 +16397,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else if (id == NotificationCenter.didUpdateConnectionState) {
int state = ConnectionsManager.getInstance(account).getConnectionState();
if (state == ConnectionsManager.ConnectionStateConnected) {
checkAutoDownloadMessages(false);
}
} else if (id == NotificationCenter.chatOnlineCountDidLoad) {
Long chatId = (Long) args[0];
if (chatInfo == null || currentChat == null || currentChat.id != chatId) {
@ -20815,11 +20725,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
showBottomOverlayProgress(false, true);
} else if (botUser != null && currentUser.bot) {
bottomOverlayChatText.setText(LocaleController.getString("BotStart", R.string.BotStart));
// bottomOverlayStartButton.setText(LocaleController.getString("BotStart", R.string.BotStart));
bottomOverlayStartButton.setVisibility(View.VISIBLE);
bottomOverlayChatText.setVisibility(View.GONE);
chatActivityEnterView.hidePopup(false);
if (getParentActivity() != null) {
AndroidUtilities.hideKeyboard(getParentActivity().getCurrentFocus());
}
if (dialog_id == dialog_id && !messages.isEmpty() && currentUser != null) {
if (botUser.length() != 0 && !sentBotStart) {
sentBotStart = true;
}
}
} else {
bottomOverlayChatText.setText(LocaleController.getString("DeleteThisChat", R.string.DeleteThisChat));
}
@ -20839,6 +20757,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatActivityEnterView.setVisibility(View.INVISIBLE);
} else if (searchItem != null && searchItemVisible) {
createSearchContainer();
if (searchContainer == null) {
return;
}
searchContainer.animate().setListener(null).cancel();
if (searchContainer.getVisibility() != View.VISIBLE) {
searchContainer.setVisibility(View.VISIBLE);
@ -20986,6 +20907,12 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
topViewWasVisible = 0;
}
}
if (sentBotStart) {
getMessagesController().sendBotStart(currentUser, botUser);
bottomOverlayChat.setVisibility(View.GONE);
chatActivityEnterView.setVisibility(View.VISIBLE);
}
checkRaiseSensors();
}

View file

@ -1509,7 +1509,19 @@ public class AlertsCreator {
lastMessageIsJoined = true;
}
if (!second && (secret && !clear || canDeleteInbox) && !UserObject.isDeleted(user) && !lastMessageIsJoined || (deleteChatForAll = checkDeleteForAll && !clear && chat != null && chat.creator)) {
if (user != null && user.bot) {
cell[0] = new CheckBoxCell(context, 1, resourcesProvider);
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
cell[0].setText(LocaleController.getString(R.string.BlockBot), "", false, false);
cell[0].setPadding(LocaleController.isRTL ? AndroidUtilities.dp(16) : AndroidUtilities.dp(8), 0, LocaleController.isRTL ? AndroidUtilities.dp(8) : AndroidUtilities.dp(16), 0);
cell[0].setChecked(deleteForAll[0] = true, false);
frameLayout.addView(cell[0], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 0));
cell[0].setOnClickListener(v -> {
CheckBoxCell cell1 = (CheckBoxCell) v;
deleteForAll[0] = !deleteForAll[0];
cell1.setChecked(deleteForAll[0], true);
});
} else if (!second && (secret && !clear || canDeleteInbox) && !UserObject.isDeleted(user) && !lastMessageIsJoined || (deleteChatForAll = checkDeleteForAll && !clear && chat != null && chat.creator)) {
cell[0] = new CheckBoxCell(context, 1, resourcesProvider);
cell[0].setBackgroundDrawable(Theme.getSelectorDrawable(false));
if (deleteChatForAll) {
@ -1603,7 +1615,7 @@ public class AlertsCreator {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.getString("AreYouSureDeleteThisChatSavedMessages", R.string.AreYouSureDeleteThisChatSavedMessages)));
} else {
if (user.bot && !user.support) {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithBot", R.string.AreYouSureDeleteThisChatWithBot, UserObject.getUserName(user, account))));
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString(R.string.AreYouSureDeleteThisChatWithBotWithCheckmark, UserObject.getUserName(user, account))));
} else {
messageTextView.setText(AndroidUtilities.replaceTags(LocaleController.formatString("AreYouSureDeleteThisChatWithUser", R.string.AreYouSureDeleteThisChatWithUser, UserObject.getUserName(user, account))));
}

View file

@ -462,6 +462,7 @@ public class AnimatedEmojiDrawable extends Drawable {
return super.setImageBitmapByKey(drawable, key, type, memCache, guid);
}
};
imageReceiver.setAllowLoadingOnAttachedOnly(true);
};
if (cacheType == CACHE_TYPE_RENDERING_VIDEO) {
imageReceiver.ignoreNotifications = true;

View file

@ -93,7 +93,7 @@ public class Bulletin {
@SuppressLint("RtlHardcoded")
public static Bulletin make(@NonNull BaseFragment fragment, @NonNull Layout contentLayout, int duration) {
if (fragment instanceof ChatActivity) {
contentLayout.setWideScreenParams(ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.RIGHT);
contentLayout.setWideScreenParams(ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);
} else if (fragment instanceof DialogsActivity) {
contentLayout.setWideScreenParams(ViewGroup.LayoutParams.MATCH_PARENT, Gravity.NO_GRAVITY);
}

View file

@ -29,7 +29,7 @@ public class CanvasButton {
ArrayList<RectF> drawingRects = new ArrayList<>();
int usingRectCount;
boolean buttonPressed;
RippleDrawable selectorDrawable;
Drawable selectorDrawable;
private final static int[] pressedState = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed};
private final View parent;
@ -256,7 +256,9 @@ public class CanvasButton {
public void setRoundRadius(int radius) {
roundRadius = radius;
pathEffect = new CornerPathEffect(radius);
maskPaint.setPathEffect(new CornerPathEffect(radius));
if (maskPaint != null) {
maskPaint.setPathEffect(new CornerPathEffect(radius));
}
}
public void cancelRipple() {

View file

@ -730,7 +730,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
delegate.needStartRecordAudio(1);
startedDraggingX = -1;
MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid);
MediaController.getInstance().startRecording(currentAccount, dialog_id, replyingMessageObject, getThreadMessage(), recordingGuid, true);
recordingAudioVideo = true;
updateRecordInterface(RECORD_STATE_ENTER);
if (recordTimerView != null) {
@ -2022,55 +2022,84 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
sendButtonContainer.setClipToPadding(false);
textFieldContainer.addView(sendButtonContainer, LayoutHelper.createFrame(48, 48, Gravity.BOTTOM | Gravity.RIGHT));
audioVideoButtonContainer = new FrameLayout(context);
audioVideoButtonContainer.setSoundEffectsEnabled(false);
sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48));
audioVideoButtonContainer.setFocusable(true);
audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> {
createRecordCircle();
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (recordCircle.isSendButtonVisible()) {
if (!hasRecordVideo || calledRecordRunnable) {
startedDraggingX = -1;
if (hasRecordVideo && isInVideoMode()) {
delegate.needStartRecordVideo(1, true, 0);
} else {
if (recordingAudioVideo && isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
audioVideoButtonContainer = new FrameLayout(context) {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
@Override
public boolean onTouchEvent(MotionEvent motionEvent) {
createRecordCircle();
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
if (recordCircle.isSendButtonVisible()) {
if (!hasRecordVideo || calledRecordRunnable) {
startedDraggingX = -1;
if (hasRecordVideo && isInVideoMode()) {
delegate.needStartRecordVideo(1, true, 0);
} else {
if (recordingAudioVideo && isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
}
MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
delegate.needStartRecordAudio(0);
}
MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
delegate.needStartRecordAudio(0);
recordingAudioVideo = false;
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
}, 200);
}
recordingAudioVideo = false;
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
}, 200);
}
getParent().requestDisallowInterceptTouchEvent(true);
return true;
}
if (parentFragment != null) {
TLRPC.Chat chat = parentFragment.getCurrentChat();
TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo();
if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) {
delegate.needShowMediaBanHint();
getParent().requestDisallowInterceptTouchEvent(true);
return true;
}
}
if (hasRecordVideo) {
calledRecordRunnable = false;
recordAudioVideoRunnableStarted = true;
AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150);
} else {
recordAudioVideoRunnable.run();
}
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL && recordingAudioVideo) {
if (recordCircle.slideToCancelProgress < 0.7f) {
if (parentFragment != null) {
TLRPC.Chat chat = parentFragment.getCurrentChat();
TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo();
if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) {
delegate.needShowMediaBanHint();
return true;
}
}
if (hasRecordVideo) {
calledRecordRunnable = false;
recordAudioVideoRunnableStarted = true;
AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150);
} else {
recordAudioVideoRunnable.run();
}
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL && recordingAudioVideo) {
if (recordCircle.slideToCancelProgress < 0.7f) {
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(2, true, 0);
} else {
delegate.needStartRecordAudio(0);
MediaController.getInstance().stopRecording(0, false, 0);
}
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
} else {
recordCircle.sendButtonVisible = true;
startLockTransition();
}
return false;
}
if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) {
if (recordAudioVideoRunnableStarted) {
AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
}
return false;
}
float x = motionEvent.getX() + audioVideoButtonContainer.getX();
float dist = (x - startedDraggingX);
float alpha = 1.0f + dist / distCanMove;
if (alpha < 0.45) {
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(2, true, 0);
@ -2081,119 +2110,264 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
} else {
recordCircle.sendButtonVisible = true;
startLockTransition();
}
return false;
}
if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) {
if (recordAudioVideoRunnableStarted) {
AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
}
return false;
}
float x = motionEvent.getX() + audioVideoButtonContainer.getX();
float dist = (x - startedDraggingX);
float alpha = 1.0f + dist / distCanMove;
if (alpha < 0.45) {
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(2, true, 0);
} else {
delegate.needStartRecordAudio(0);
MediaController.getInstance().stopRecording(0, false, 0);
}
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
} else {
if (recordAudioVideoRunnableStarted) {
AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
if (sendVoiceEnabled && sendRoundEnabled) {
delegate.onSwitchRecordMode(!isInVideoMode());
setRecordVideoButtonVisible(!isInVideoMode(), true);
} else {
delegate.needShowMediaBanHint();
if (recordAudioVideoRunnableStarted) {
AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
if (sendVoiceEnabled && sendRoundEnabled) {
delegate.onSwitchRecordMode(!isInVideoMode());
setRecordVideoButtonVisible(!isInVideoMode(), true);
} else {
delegate.needShowMediaBanHint();
}
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
} else if (!hasRecordVideo || calledRecordRunnable) {
startedDraggingX = -1;
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(1, true, 0);
} else if (!sendVoiceEnabled) {
delegate.needShowMediaBanHint();
} else {
if (recordingAudioVideo && isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
}
delegate.needStartRecordAudio(0);
MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
}
recordingAudioVideo = false;
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
}, 500);
}
performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
} else if (!hasRecordVideo || calledRecordRunnable) {
startedDraggingX = -1;
}
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) {
float x = motionEvent.getX();
float y = motionEvent.getY();
if (recordCircle.isSendButtonVisible()) {
return false;
}
if (recordCircle.setLockTranslation(y) == 2) {
startLockTransition();
return false;
} else {
recordCircle.setMovingCords(x, y);
}
if (startedDraggingX == -1) {
startedDraggingX = x;
distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35);
if (distCanMove > AndroidUtilities.dp(140)) {
distCanMove = AndroidUtilities.dp(140);
}
}
x = x + audioVideoButtonContainer.getX();
float dist = (x - startedDraggingX);
float alpha = 1.0f + dist / distCanMove;
if (startedDraggingX != -1) {
if (alpha > 1) {
alpha = 1;
} else if (alpha < 0) {
alpha = 0;
}
if (slideText != null) {
slideText.setSlideX(alpha);
}
if (recordCircle != null) {
recordCircle.setSlideToCancelProgress(alpha);
}
}
if (alpha == 0) {
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(1, true, 0);
} else if (!sendVoiceEnabled) {
delegate.needShowMediaBanHint();
delegate.needStartRecordVideo(2, true, 0);
} else {
if (recordingAudioVideo && isInScheduleMode()) {
AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
}
delegate.needStartRecordAudio(0);
MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
MediaController.getInstance().stopRecording(0, false, 0);
}
recordingAudioVideo = false;
messageTransitionIsRunning = false;
AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
moveToSendStateRunnable = null;
updateRecordInterface(RECORD_STATE_SENDING);
}, 500);
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
}
}
return true;
} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) {
float x = motionEvent.getX();
float y = motionEvent.getY();
if (recordCircle.isSendButtonVisible()) {
return false;
}
if (recordCircle.setLockTranslation(y) == 2) {
startLockTransition();
return false;
} else {
recordCircle.setMovingCords(x, y);
}
if (startedDraggingX == -1) {
startedDraggingX = x;
distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35);
if (distCanMove > AndroidUtilities.dp(140)) {
distCanMove = AndroidUtilities.dp(140);
}
}
x = x + audioVideoButtonContainer.getX();
float dist = (x - startedDraggingX);
float alpha = 1.0f + dist / distCanMove;
if (startedDraggingX != -1) {
if (alpha > 1) {
alpha = 1;
} else if (alpha < 0) {
alpha = 0;
}
if (slideText != null) {
slideText.setSlideX(alpha);
}
if (recordCircle != null) {
recordCircle.setSlideToCancelProgress(alpha);
}
}
if (alpha == 0) {
if (hasRecordVideo && isInVideoMode()) {
CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
delegate.needStartRecordVideo(2, true, 0);
} else {
delegate.needStartRecordAudio(0);
MediaController.getInstance().stopRecording(0, false, 0);
}
recordingAudioVideo = false;
updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
return true;
}
return true;
}
view.onTouchEvent(motionEvent);
return true;
});
};
audioVideoButtonContainer.setSoundEffectsEnabled(false);
sendButtonContainer.addView(audioVideoButtonContainer, LayoutHelper.createFrame(48, 48));
audioVideoButtonContainer.setFocusable(true);
audioVideoButtonContainer.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
// audioVideoButtonContainer.setOnTouchListener((view, motionEvent) -> {
// createRecordCircle();
// if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
// if (recordCircle.isSendButtonVisible()) {
// if (!hasRecordVideo || calledRecordRunnable) {
// startedDraggingX = -1;
// if (hasRecordVideo && isInVideoMode()) {
// delegate.needStartRecordVideo(1, true, 0);
// } else {
// if (recordingAudioVideo && isInScheduleMode()) {
// AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
// }
// MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
// delegate.needStartRecordAudio(0);
// }
// recordingAudioVideo = false;
// messageTransitionIsRunning = false;
// AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
// moveToSendStateRunnable = null;
// updateRecordInterface(RECORD_STATE_SENDING);
// }, 200);
// }
// getParent().requestDisallowInterceptTouchEvent(true);
// return true;
// }
// if (parentFragment != null) {
// TLRPC.Chat chat = parentFragment.getCurrentChat();
// TLRPC.UserFull userFull = parentFragment.getCurrentUserInfo();
// if (chat != null && !(ChatObject.canSendVoice(chat) || (ChatObject.canSendRoundVideo(chat) && hasRecordVideo)) || userFull != null && userFull.voice_messages_forbidden) {
// delegate.needShowMediaBanHint();
// return true;
// }
// }
// if (hasRecordVideo) {
// calledRecordRunnable = false;
// recordAudioVideoRunnableStarted = true;
// AndroidUtilities.runOnUIThread(recordAudioVideoRunnable, 150);
// } else {
// recordAudioVideoRunnable.run();
// }
// return true;
// } else if (motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL) {
// if (motionEvent.getAction() == MotionEvent.ACTION_CANCEL && recordingAudioVideo) {
// if (recordCircle.slideToCancelProgress < 0.7f) {
// if (hasRecordVideo && isInVideoMode()) {
// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
// delegate.needStartRecordVideo(2, true, 0);
// } else {
// delegate.needStartRecordAudio(0);
// MediaController.getInstance().stopRecording(0, false, 0);
// }
// recordingAudioVideo = false;
// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
// } else {
// recordCircle.sendButtonVisible = true;
// startLockTransition();
// }
// return false;
// }
// if (recordCircle != null && recordCircle.isSendButtonVisible() || recordedAudioPanel != null && recordedAudioPanel.getVisibility() == VISIBLE) {
// if (recordAudioVideoRunnableStarted) {
// AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
// }
// return false;
// }
//
// float x = motionEvent.getX() + audioVideoButtonContainer.getX();
// float dist = (x - startedDraggingX);
// float alpha = 1.0f + dist / distCanMove;
// if (alpha < 0.45) {
// if (hasRecordVideo && isInVideoMode()) {
// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
// delegate.needStartRecordVideo(2, true, 0);
// } else {
// delegate.needStartRecordAudio(0);
// MediaController.getInstance().stopRecording(0, false, 0);
// }
// recordingAudioVideo = false;
// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
// } else {
// if (recordAudioVideoRunnableStarted) {
// AndroidUtilities.cancelRunOnUIThread(recordAudioVideoRunnable);
// if (sendVoiceEnabled && sendRoundEnabled) {
// delegate.onSwitchRecordMode(!isInVideoMode());
// setRecordVideoButtonVisible(!isInVideoMode(), true);
// } else {
// delegate.needShowMediaBanHint();
// }
// performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP);
// sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
// } else if (!hasRecordVideo || calledRecordRunnable) {
// startedDraggingX = -1;
// if (hasRecordVideo && isInVideoMode()) {
// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
// delegate.needStartRecordVideo(1, true, 0);
// } else if (!sendVoiceEnabled) {
// delegate.needShowMediaBanHint();
// } else {
// if (recordingAudioVideo && isInScheduleMode()) {
// AlertsCreator.createScheduleDatePickerDialog(parentActivity, parentFragment.getDialogId(), (notify, scheduleDate) -> MediaController.getInstance().stopRecording(1, notify, scheduleDate), () -> MediaController.getInstance().stopRecording(0, false, 0), resourcesProvider);
// }
// delegate.needStartRecordAudio(0);
// MediaController.getInstance().stopRecording(isInScheduleMode() ? 3 : 1, true, 0);
// }
// recordingAudioVideo = false;
// messageTransitionIsRunning = false;
// AndroidUtilities.runOnUIThread(moveToSendStateRunnable = () -> {
// moveToSendStateRunnable = null;
// updateRecordInterface(RECORD_STATE_SENDING);
// }, 500);
// }
// }
// return true;
// } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE && recordingAudioVideo) {
// float x = motionEvent.getX();
// float y = motionEvent.getY();
// if (recordCircle.isSendButtonVisible()) {
// return false;
// }
// if (recordCircle.setLockTranslation(y) == 2) {
// startLockTransition();
// return false;
// } else {
// recordCircle.setMovingCords(x, y);
// }
//
// if (startedDraggingX == -1) {
// startedDraggingX = x;
// distCanMove = (float) (sizeNotifierLayout.getMeasuredWidth() * 0.35);
// if (distCanMove > AndroidUtilities.dp(140)) {
// distCanMove = AndroidUtilities.dp(140);
// }
// }
//
// x = x + audioVideoButtonContainer.getX();
// float dist = (x - startedDraggingX);
// float alpha = 1.0f + dist / distCanMove;
// if (startedDraggingX != -1) {
// if (alpha > 1) {
// alpha = 1;
// } else if (alpha < 0) {
// alpha = 0;
// }
// if (slideText != null) {
// slideText.setSlideX(alpha);
// }
// if (recordCircle != null) {
// recordCircle.setSlideToCancelProgress(alpha);
// }
// }
//
// if (alpha == 0) {
// if (hasRecordVideo && isInVideoMode()) {
// CameraController.getInstance().cancelOnInitRunnable(onFinishInitCameraRunnable);
// delegate.needStartRecordVideo(2, true, 0);
// } else {
// delegate.needStartRecordAudio(0);
// MediaController.getInstance().stopRecording(0, false, 0);
// }
// recordingAudioVideo = false;
// updateRecordInterface(RECORD_STATE_CANCEL_BY_GESTURE);
// }
// return true;
// }
// view.onTouchEvent(motionEvent);
// return true;
// });
audioVideoSendButton = new ChatActivityEnterViewAnimatedIconView(context);
audioVideoSendButton.setFocusable(true);
@ -7388,7 +7562,7 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
return;
}
if (focus) {
if (searchingType == 0 && !messageEditText.isFocused()) {
if (searchingType == 0 && !messageEditText.isFocused() && (botWebViewMenuContainer == null || botWebViewMenuContainer.getVisibility() == View.GONE)) {
AndroidUtilities.runOnUIThread(focusRunnable = () -> {
focusRunnable = null;
boolean allowFocus;

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.messenger.fakepasscode.RemoveAfterReadingMessages;
@ -283,7 +281,7 @@ public class ChatAttachAlert extends BottomSheet implements NotificationCenter.N
@Override
public void onSetupMainButton(boolean isVisible, boolean isActive, String text, int color, int textColor, boolean isProgressVisible) {
if (currentAttachLayout != webViewLayout || !webViewLayout.isBotButtonAvailable()) {
if (currentAttachLayout != webViewLayout || !webViewLayout.isBotButtonAvailable() && startCommand == null) {
return;
}
botMainButtonTextView.setClickable(isActive);

View file

@ -1080,7 +1080,6 @@ public class ChatAvatarContainer extends FrameLayout implements NotificationCent
sb.append("\n");
sb.append(subtitleTextView.getText());
info.setContentDescription(sb);
setContentDescription(sb);
if (info.isClickable() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
info.addAction(new AccessibilityNodeInfo.AccessibilityAction(AccessibilityNodeInfo.ACTION_CLICK, LocaleController.getString("OpenProfile", R.string.OpenProfile)));
}

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

@ -57,6 +57,7 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.RecyclerListView;
import org.telegram.ui.Components.SeekBarView;
import org.telegram.ui.LaunchActivity;
import org.telegram.ui.ProfileActivity;
import java.util.ArrayList;
import java.util.List;
@ -520,6 +521,7 @@ public class FloatingDebugView extends FrameLayout implements NotificationCenter
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.needSetDayNightTheme, finalThemeInfo, true, null, -1);
}, 200);
}));
items.add(new FloatingDebugController.DebugItem(LocaleController.getString(R.string.DebugSendLogs), () -> ProfileActivity.sendLogs((Activity) getContext(), false)));
return items;
}

View file

@ -35,6 +35,7 @@ public class ForumBubbleDrawable extends Drawable {
private final Paint strokePaint;
private final Paint topPaint;
private static SvgHelper.SvgDrawable mainDrawable;
private int currentColors[];
@ -60,7 +61,10 @@ public class ForumBubbleDrawable extends Drawable {
public ForumBubbleDrawable(int color) {
svgDrawable = SvgHelper.getDrawable(R.raw.topic_bubble, Color.WHITE);
if (mainDrawable == null) {
mainDrawable = SvgHelper.getDrawable(R.raw.topic_bubble, Color.WHITE);
}
svgDrawable = mainDrawable.clone();
svgDrawable.copyCommandFromPosition(0);
topPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

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

@ -357,6 +357,9 @@ public class PremiumPreviewBottomSheet extends BottomSheetWithRecyclerListView i
if (isOutboundGift) {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle, user != null ? user.first_name : ""), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
} else if (user != null && user.id == 777000) {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPluralSomeone, LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));
} else {
titleView[0].setText(AndroidUtilities.replaceSingleTag(LocaleController.formatString(R.string.TelegramPremiumUserGiftedPremiumDialogTitleWithPlural, user != null ? user.first_name : "", LocaleController.formatPluralString("GiftMonths", giftTier.getMonths())), Theme.key_windowBackgroundWhiteBlueButton, AndroidUtilities.REPLACING_TAG_TYPE_LINK, null));
subtitleView.setText(AndroidUtilities.replaceTags(LocaleController.getString(R.string.TelegramPremiumUserGiftedPremiumDialogSubtitle)));

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();
builder.getDismissRunnable().run();
rebind(storageNumRow);
ImageLoader.getInstance().checkMediaPaths(() -> {
CacheControlActivity.resetCalculatedTotalSIze();
loadCacheSize();
});
if (!TextUtils.equals(SharedConfig.storageCacheDir, storageDir)) {
if (!isInternal) {
AlertDialog.Builder confirAlert = new AlertDialog.Builder(getContext());
confirAlert.setTitle(LocaleController.getString("DecreaseSpeed", R.string.DecreaseSpeed));
confirAlert.setMessage(LocaleController.getString("SdCardAlert", R.string.SdCardAlert));
confirAlert.setPositiveButton(LocaleController.getString("Proceed", R.string.Proceed), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setStorageDirectory(storageDir);
builder.getDismissRunnable().run();
}
});
confirAlert.setNegativeButton(LocaleController.getString("Back", R.string.Back), null);
confirAlert.show();
} else {
setStorageDirectory(storageDir);
builder.getDismissRunnable().run();
}
}
});
}
builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null);
@ -534,10 +590,29 @@ public class DataSettingsActivity extends BaseFragment {
}
}
});
DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
itemAnimator.setDurations(350);
itemAnimator.setInterpolator(CubicBezierInterpolator.EASE_OUT_QUINT);
itemAnimator.setDelayAnimations(false);
itemAnimator.setSupportsChangeAnimations(false);
listView.setItemAnimator(itemAnimator);
return fragmentView;
}
private void setStorageDirectory(String storageDir) {
SharedConfig.storageCacheDir = storageDir;
SharedConfig.saveConfig();
if (storageDir != null) {
SharedConfig.readOnlyStorageDirAlertShowed = false;
}
rebind(storageNumRow);
ImageLoader.getInstance().checkMediaPaths(() -> {
CacheControlActivity.resetCalculatedTotalSIze();
loadCacheSize();
});
}
@Override
protected void onDialogDismiss(Dialog dialog) {
DownloadController.getInstance(currentAccount).checkAutodownloadSettings();
@ -548,6 +623,7 @@ public class DataSettingsActivity extends BaseFragment {
super.onResume();
loadCacheSize();
rebindAll();
updateRows(false);
}
private class ListAdapter extends RecyclerListView.SelectionAdapter {
@ -702,7 +778,7 @@ public class DataSettingsActivity extends BaseFragment {
String text;
CharSequence description = null;
DownloadController.Preset preset = null;
boolean enabled;
boolean enabled, divider = true;
if (position == saveToGalleryPeerRow) {
text = LocaleController.getString("SaveToGalleryPrivate", R.string.SaveToGalleryPrivate);
description = SaveToGallerySettingsHelper.user.createDescription(currentAccount);
@ -715,6 +791,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("SaveToGalleryChannels", R.string.SaveToGalleryChannels);
description = SaveToGallerySettingsHelper.channels.createDescription(currentAccount);
enabled = SaveToGallerySettingsHelper.channels.enabled();
divider = false;
} else if (position == mobileRow) {
text = LocaleController.getString("WhenUsingMobileData", R.string.WhenUsingMobileData);
enabled = DownloadController.getInstance(currentAccount).mobilePreset.enabled;
@ -727,6 +804,7 @@ public class DataSettingsActivity extends BaseFragment {
text = LocaleController.getString("WhenRoaming", R.string.WhenRoaming);
enabled = DownloadController.getInstance(currentAccount).roamingPreset.enabled;
preset = DownloadController.getInstance(currentAccount).getCurrentRoamingPreset();
divider = resetDownloadRow >= 0;
}
boolean checked;
if (preset != null) {
@ -776,7 +854,7 @@ public class DataSettingsActivity extends BaseFragment {
checked = enabled;
}
checkCell.setAnimationsEnabled(true);
checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, true);
checkCell.setTextAndValueAndCheck(text, description, checked, 0, true, divider);
break;
}
}
@ -805,15 +883,9 @@ public class DataSettingsActivity extends BaseFragment {
}
public boolean isRowEnabled(int position) {
if (position == resetDownloadRow) {
DownloadController controller = DownloadController.getInstance(currentAccount);
return !controller.lowPreset.equals(controller.getCurrentRoamingPreset()) || controller.lowPreset.isEnabled() != controller.roamingPreset.enabled ||
!controller.mediumPreset.equals(controller.getCurrentMobilePreset()) || controller.mediumPreset.isEnabled() != controller.mobilePreset.enabled ||
!controller.highPreset.equals(controller.getCurrentWiFiPreset()) || controller.highPreset.isEnabled() != controller.wifiPreset.enabled;
}
return position == mobileRow || position == roamingRow || position == wifiRow || position == storageUsageRow || position == useLessDataForCallsRow || position == dataUsageRow || position == proxyRow || position == clearDraftsRow ||
position == enableCacheStreamRow || position == enableStreamRow || position == enableAllStreamRow || position == enableMkvRow || position == quickRepliesRow || position == autoplayVideoRow || position == autoplayGifsRow ||
position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow;
position == storageNumRow || position == saveToGalleryGroupsRow || position == saveToGalleryPeerRow || position == saveToGalleryChannelsRow || position == resetDownloadRow;
}
@Override

View file

@ -3280,6 +3280,14 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
viewPage.listView.setInstantClick(true);
viewPage.layoutManager = new LinearLayoutManager(context) {
@Override
protected int firstPosition() {
if (viewPage.dialogsType == DIALOGS_TYPE_DEFAULT && hasHiddenArchive() && viewPage.archivePullViewState == ARCHIVE_ITEM_STATE_HIDDEN) {
return 1;
}
return 0;
}
private boolean fixOffset;
@Override
@ -6793,6 +6801,11 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
chatActivity.setPreloadedSticker(sticker, true);
}
}
if (AndroidUtilities.isTablet()) {
if (rightSlidingDialogContainer.currentFragment != null) {
rightSlidingDialogContainer.finishPreview();
}
}
presentFragment(chatActivity);
}
}
@ -7259,6 +7272,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
ActionBarMenuSubItem deleteItem = new ActionBarMenuSubItem(getParentActivity(), false, true);
deleteItem.setIconColor(getThemedColor(Theme.key_dialogRedIcon));
deleteItem.setTextColor(getThemedColor(Theme.key_dialogTextRed));
deleteItem.setSelectorColor(Theme.multAlpha(getThemedColor(Theme.key_dialogTextRed), .12f));
deleteItem.setTextAndIcon(LocaleController.getString("Delete", R.string.Delete), R.drawable.msg_delete);
deleteItem.setMinimumWidth(160);
deleteItem.setOnClickListener(e -> {
@ -8835,7 +8849,17 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
} else if (id == NotificationCenter.dialogsUnreadReactionsCounterChanged) {
updateVisibleRows(0);
} else if (id == NotificationCenter.emojiLoaded) {
updateVisibleRows(0);
for (int i = 0; i < viewPages.length; ++i) {
final RecyclerListView listView = viewPages[i].listView;
if (listView != null) {
for (int a = 0; a < listView.getChildCount(); ++a) {
View child = listView.getChildAt(a);
if (child != null) {
child.invalidate();
}
}
}
}
if (filterTabsView != null) {
filterTabsView.getTabsContainer().invalidateViews();
}
@ -8961,7 +8985,16 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
long dialogId = (Long) args[0];
TLRPC.User user = (TLRPC.User) args[1];
TLRPC.Chat chat = (TLRPC.Chat) args[2];
boolean revoke = (Boolean) args[3];
boolean revoke;
boolean botBlock;
if (user != null && user.bot) {
revoke = false;
botBlock = (Boolean) args[3];
} else {
revoke = (Boolean) args[3];
botBlock = false;
}
Runnable deleteRunnable = () -> {
if (chat != null) {
if (ChatObject.isNotInChat(chat)) {
@ -8971,7 +9004,7 @@ public class DialogsActivity extends BaseFragment implements NotificationCenter.
}
} else {
getMessagesController().deleteDialog(dialogId, 0, revoke);
if (user != null && user.bot) {
if (user != null && user.bot && botBlock) {
getMessagesController().blockPeer(user.id);
}
}

View file

@ -161,8 +161,13 @@ public class DownloadProgressIcon extends View implements NotificationCenter.Not
}
}
if (currentListeners.size() == 0 && (getVisibility() != View.VISIBLE || getAlpha() != 1f)) {
progress = 0;
currentProgress = 0;
if (DownloadController.getInstance(currentAccount).hasUnviewedDownloads()) {
progress = 1f;
currentProgress = 1f;
} else {
progress = 0;
currentProgress = 0;
}
}
}

View file

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

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();
updateLanguage();
});
});
}
LocaleController.getInstance().checkForcePatchLangpack(currentAccount, () -> {
if (!isPaused) {
updateLanguage();
}
});
}
@Override

View file

@ -3594,27 +3594,12 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}));
} else if (username != null) {
TLObject req;
if (AndroidUtilities.isNumeric(username)) {
TLRPC.TL_contacts_resolvePhone resolvePhone = new TLRPC.TL_contacts_resolvePhone();
resolvePhone.phone = username;
req = resolvePhone;
} else {
TLRPC.TL_contacts_resolveUsername resolveUsername = new TLRPC.TL_contacts_resolveUsername();
resolveUsername.username = username;
req = resolveUsername;
}
requestId[0] = ConnectionsManager.getInstance(intentAccount).sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
MessagesController.getInstance(intentAccount).getUserNameResolver().resolve(username, (peerId) -> {
if (!LaunchActivity.this.isFinishing()) {
boolean hideProgressDialog = true;
TLRPC.TL_contacts_resolvedPeer res = (TLRPC.TL_contacts_resolvedPeer) response;
if (error == null && actionBarLayout != null && (game == null && voicechat == null || game != null && !res.users.isEmpty() || voicechat != null && !res.chats.isEmpty() || livestream != null && !res.chats.isEmpty())) {
MessagesController.getInstance(intentAccount).putUsers(res.users, false);
MessagesController.getInstance(intentAccount).putChats(res.chats, false);
MessagesStorage.getInstance(intentAccount).putUsersAndChats(res.users, res.chats, false, true);
if (peerId != null && actionBarLayout != null && (game == null && voicechat == null || game != null && peerId > 0 || voicechat != null && peerId > 0 || livestream != null && peerId < 0)) {
if (!TextUtils.isEmpty(botAppMaybe)) {
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(res.peer.user_id);
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
if (user != null && user.bot) {
TLRPC.TL_messages_getBotApp getBotApp = new TLRPC.TL_messages_getBotApp();
TLRPC.TL_inputBotAppShortName app = new TLRPC.TL_inputBotAppShortName();
@ -3673,11 +3658,11 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
if (setAsAttachBot != null && attachMenuBotToOpen == null) {
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(res.peer.user_id);
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
if (user != null && user.bot) {
if (user.bot_attach_menu) {
TLRPC.TL_messages_getAttachMenuBot getAttachMenuBot = new TLRPC.TL_messages_getAttachMenuBot();
getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(res.peer.user_id);
getAttachMenuBot.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
ConnectionsManager.getInstance(intentAccount).sendRequest(getAttachMenuBot, (response1, error1) -> AndroidUtilities.runOnUIThread(() -> {
if (response1 instanceof TLRPC.TL_attachMenuBotsBot) {
TLRPC.TL_attachMenuBotsBot attachMenuBotsBot = (TLRPC.TL_attachMenuBotsBot) response1;
@ -3757,7 +3742,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
.setMessage(AndroidUtilities.replaceTags(LocaleController.formatString("BotRequestAttachPermission", R.string.BotRequestAttachPermission, UserObject.getUserName(user, currentAccount))))
.setPositiveButton(LocaleController.getString(R.string.BotAddToMenu), (dialog, which) -> {
TLRPC.TL_messages_toggleBotInAttachMenu botRequest = new TLRPC.TL_messages_toggleBotInAttachMenu();
botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(res.peer.user_id);
botRequest.bot = MessagesController.getInstance(intentAccount).getInputUser(peerId);
botRequest.enabled = true;
botRequest.write_allowed = allowWrite.get();
@ -3803,8 +3788,9 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
} else {
BulletinFactory.of(mainFragmentsStack.get(mainFragmentsStack.size() - 1)).createErrorBulletin(LocaleController.getString(R.string.BotSetAttachLinkNotBot)).show();
}
} else if (messageId != null && (commentId != null || threadId != null) && !res.chats.isEmpty()) {
requestId[0] = runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, res.chats.get(0));
} else if (messageId != null && (commentId != null || threadId != null) && peerId < 0) {
TLRPC.Chat chat = MessagesController.getInstance(intentAccount).getChat(-peerId);
requestId[0] = runCommentRequest(intentAccount, dismissLoading, messageId, commentId, threadId, chat);
if (requestId[0] != 0) {
hideProgressDialog = false;
}
@ -3816,12 +3802,13 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
args.putString("selectAlertString", LocaleController.getString("SendGameToText", R.string.SendGameToText));
args.putString("selectAlertStringGroup", LocaleController.getString("SendGameToGroupText", R.string.SendGameToGroupText));
DialogsActivity fragment = new DialogsActivity(args);
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
fragment.setDelegate((fragment1, dids, message1, param, topicsFragment) -> {
long did = dids.get(0).dialogId;
TLRPC.TL_inputMediaGame inputMediaGame = new TLRPC.TL_inputMediaGame();
inputMediaGame.id = new TLRPC.TL_inputGameShortName();
inputMediaGame.id.short_name = game;
inputMediaGame.id.bot_id = MessagesController.getInstance(intentAccount).getInputUser(res.users.get(0));
inputMediaGame.id.bot_id = MessagesController.getInstance(intentAccount).getInputUser(user);
SendMessagesHelper.getInstance(intentAccount).sendGame(MessagesController.getInstance(intentAccount).getInputPeer(did), inputMediaGame, 0, 0);
Bundle args1 = new Bundle();
@ -3864,7 +3851,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
drawerLayoutContainer.setAllowOpenDrawer(true, false);
}
} else if (botChat != null || botChannel != null) {
final TLRPC.User user = !res.users.isEmpty() ? res.users.get(0) : null;
final TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
if (user == null || user.bot && user.bot_nochats) {
try {
if (!mainFragmentsStack.isEmpty()) {
@ -4016,14 +4003,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
long dialog_id;
boolean isBot = false;
Bundle args = new Bundle();
if (!res.chats.isEmpty()) {
args.putLong("chat_id", res.chats.get(0).id);
dialog_id = -res.chats.get(0).id;
TLRPC.User user = MessagesController.getInstance(intentAccount).getUser(peerId);
if (peerId < 0) {
args.putLong("chat_id", -peerId);
dialog_id = peerId;
} else {
args.putLong("user_id", res.users.get(0).id);
dialog_id = res.users.get(0).id;
args.putLong("user_id", peerId);
dialog_id = peerId;
}
if (botUser != null && res.users.size() > 0 && res.users.get(0).bot) {
if (botUser != null && user != null && user.bot) {
args.putString("botUser", botUser);
isBot = true;
}
@ -4160,17 +4148,15 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
} else {
try {
if (!mainFragmentsStack.isEmpty()) {
BaseFragment fragment = mainFragmentsStack.get(mainFragmentsStack.size() - 1);
if (fragment instanceof ChatActivity) {
((ChatActivity) fragment).shakeContent();
BaseFragment lastFragment = LaunchActivity.getLastFragment();
if (lastFragment != null) {
if (lastFragment instanceof ChatActivity) {
((ChatActivity) lastFragment).shakeContent();
}
if (error != null && error.text != null && error.text.startsWith("FLOOD_WAIT")) {
BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("FloodWait", R.string.FloodWait)).show();
} else if (AndroidUtilities.isNumeric(username)) {
BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("NoPhoneFound", R.string.NoPhoneFound)).show();
if (AndroidUtilities.isNumeric(username)) {
BulletinFactory.of(lastFragment).createErrorBulletin(LocaleController.getString("NoPhoneFound", R.string.NoPhoneFound)).show();
} else {
BulletinFactory.of(fragment).createErrorBulletin(LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound)).show();
BulletinFactory.of(lastFragment).createErrorBulletin(LocaleController.getString("NoUsernameFound", R.string.NoUsernameFound)).show();
}
}
} catch (Exception e) {
@ -4186,7 +4172,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
}
}
}
}, ConnectionsManager.RequestFlagFailOnServerErrors));
});
} else if (group != null) {
if (state == 0) {
final TLRPC.TL_messages_checkChatInvite req = new TLRPC.TL_messages_checkChatInvite();
@ -5065,12 +5051,20 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
visibleDialog.setOnDismissListener(dialog -> {
if (visibleDialog != null) {
if (visibleDialog == localeDialog) {
BaseFragment fragment = actionBarLayout == null ? null : actionBarLayout.getLastFragment();
try {
String shorname = LocaleController.getInstance().getCurrentLocaleInfo().shortName;
BulletinFactory.of(Bulletin.BulletinWindow.make(LaunchActivity.this), null).createSimpleBulletin(
R.raw.msg_translate,
getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater)
).setDuration(Bulletin.DURATION_PROLONG).show();
if (fragment != null) {
BulletinFactory.of(fragment).createSimpleBulletin(
R.raw.msg_translate,
getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater)
).setDuration(Bulletin.DURATION_PROLONG).show();
} else {
BulletinFactory.of(Bulletin.BulletinWindow.make(LaunchActivity.this), null).createSimpleBulletin(
R.raw.msg_translate,
getStringForLanguageAlert(shorname.equals("en") ? englishLocaleStrings : systemLocaleStrings, "ChangeLanguageLater", R.string.ChangeLanguageLater)
).setDuration(Bulletin.DURATION_PROLONG).show();
}
} catch (Exception e) {
FileLog.e(e);
}

View file

@ -78,6 +78,8 @@ public class LiteModeSettingsActivity extends BaseFragment {
Bulletin restrictBulletin;
private int FLAGS_CHAT;
@Override
public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@ -142,6 +144,7 @@ public class LiteModeSettingsActivity extends BaseFragment {
});
fragmentView = contentView;
FLAGS_CHAT = AndroidUtilities.isTablet() ? (LiteMode.FLAGS_CHAT & ~LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN) : LiteMode.FLAGS_CHAT;
updateItems();
@ -168,7 +171,7 @@ public class LiteModeSettingsActivity extends BaseFragment {
return 0;
} else if (flags == LiteMode.FLAGS_ANIMATED_EMOJI) {
return 1;
} else if (flags == LiteMode.FLAGS_CHAT) {
} else if (flags == FLAGS_CHAT) {
return 2;
}
return -1;
@ -206,10 +209,12 @@ public class LiteModeSettingsActivity extends BaseFragment {
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsAutoplayReactions"), LiteMode.FLAG_ANIMATED_EMOJI_REACTIONS));
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsAutoplayChat"), LiteMode.FLAG_ANIMATED_EMOJI_CHAT));
}
items.add(Item.asSwitch(R.drawable.msg2_ask_question, LocaleController.getString("LiteOptionsChat"), LiteMode.FLAGS_CHAT));
items.add(Item.asSwitch(R.drawable.msg2_ask_question, LocaleController.getString("LiteOptionsChat"), FLAGS_CHAT));
if (expanded[2]) {
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsBackground"), LiteMode.FLAG_CHAT_BACKGROUND));
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsTopics"), LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN));
if (!AndroidUtilities.isTablet()) {
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsTopics"), LiteMode.FLAG_CHAT_FORUM_TWOCOLUMN));
}
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsSpoiler"), LiteMode.FLAG_CHAT_SPOILER));
if (SharedConfig.getDevicePerformanceClass() >= SharedConfig.PERFORMANCE_CLASS_AVERAGE) {
items.add(Item.asCheckbox(LocaleController.getString("LiteOptionsBlur"), LiteMode.FLAG_CHAT_BLUR));

View file

@ -3863,6 +3863,8 @@ public class LoginActivity extends BaseFragment {
if (currentType == AUTH_TYPE_MESSAGE) {
if (nextType == AUTH_TYPE_FLASH_CALL || nextType == AUTH_TYPE_CALL || nextType == AUTH_TYPE_MISSED_CALL) {
problemText.setText(LocaleController.getString("DidNotGetTheCodePhone", R.string.DidNotGetTheCodePhone));
} else if (nextType == 0) {
problemText.setText(LocaleController.getString("DidNotGetTheCode", R.string.DidNotGetTheCode));
} else {
problemText.setText(LocaleController.getString("DidNotGetTheCodeSms", R.string.DidNotGetTheCodeSms));
}
@ -4112,9 +4114,11 @@ public class LoginActivity extends BaseFragment {
} else if (currentType == AUTH_TYPE_FLASH_CALL) {
AndroidUtilities.setWaitingForCall(true);
NotificationCenter.getGlobalInstance().addObserver(this, NotificationCenter.didReceiveCall);
AndroidUtilities.runOnUIThread(() -> {
CallReceiver.checkLastReceivedCall();
});
if (restore) {
AndroidUtilities.runOnUIThread(() -> {
CallReceiver.checkLastReceivedCall();
});
}
}
currentParams = params;
@ -4443,7 +4447,6 @@ public class LoginActivity extends BaseFragment {
AndroidUtilities.setWaitingForSms(false);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveSmsCode);
} else if (currentType == AUTH_TYPE_FLASH_CALL) {
AndroidUtilities.setWaitingForCall(false);
NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didReceiveCall);
}
waitingForEvent = false;
@ -4674,6 +4677,9 @@ public class LoginActivity extends BaseFragment {
} else if (currentType == AUTH_TYPE_FLASH_CALL) {
AndroidUtilities.setWaitingForCall(true);
NotificationCenter.getGlobalInstance().addObserver(LoginActivitySmsView.this, NotificationCenter.didReceiveCall);
AndroidUtilities.runOnUIThread(() -> {
CallReceiver.checkLastReceivedCall();
});
}
waitingForEvent = true;
if (currentType != AUTH_TYPE_FLASH_CALL) {
@ -4707,6 +4713,7 @@ public class LoginActivity extends BaseFragment {
if (ok) {
if (currentType == AUTH_TYPE_FLASH_CALL) {
AndroidUtilities.endIncomingCall();
AndroidUtilities.setWaitingForCall(false);
}
}
}), ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagWithoutLogin);
@ -4718,6 +4725,10 @@ public class LoginActivity extends BaseFragment {
}
private void animateSuccess(Runnable callback) {
if (currentType == AUTH_TYPE_FLASH_CALL) {
callback.run();
return;
}
for (int i = 0; i < codeFieldContainer.codeField.length; i++) {
int finalI = i;
codeFieldContainer.postDelayed(()-> codeFieldContainer.codeField[finalI].animateSuccessProgress(1f), i * 75L);
@ -6290,6 +6301,10 @@ public class LoginActivity extends BaseFragment {
int minutes = ((timeRemaining % 86400) % 3600) / 60;
int seconds = ((timeRemaining % 86400) % 3600) % 60;
if (hours >= 16) {
days++;
}
String time;
if (days != 0) {
time = LocaleController.formatString(R.string.LoginEmailResetInSinglePattern, LocaleController.formatPluralString("Days", days));

View file

@ -664,10 +664,13 @@ public class PremiumPreviewFragment extends BaseFragment implements Notification
if (tier == null) {
forcePremium = true;
for (TLRPC.TL_premiumSubscriptionOption option : fragment.getAccountInstance().getMediaDataController().getPremiumPromo().period_options) {
if (option.months == 1) {
tier = new SubscriptionTier(option);
break;
TLRPC.TL_help_premiumPromo promo = fragment.getAccountInstance().getMediaDataController().getPremiumPromo();
if (promo != null) {
for (TLRPC.TL_premiumSubscriptionOption option : promo.period_options) {
if (option.months == 1) {
tier = new SubscriptionTier(option);
break;
}
}
}
}

View file

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

View file

@ -1821,10 +1821,15 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
} else {
if (!userBlocked) {
getMessagesController().blockPeer(userId);
AlertsCreator.createClearOrDeleteDialogAlert(ProfileActivity.this, false, currentChat, user, currentEncryptedChat != null, true, true, (param) -> {
if (getParentLayout().getFragmentStack().get(getParentLayout().getFragmentStack().size() - 2) instanceof ChatActivity) {
getParentLayout().removeFragmentFromStack(getParentLayout().getFragmentStack().size() - 2);
}
finishFragment();
getNotificationCenter().postNotificationName(NotificationCenter.needDeleteDialog, dialogId, user, currentChat, param);
}, getResourceProvider());
} else {
getMessagesController().unblockPeer(userId);
getSendMessagesHelper().sendMessage("/start", userId, null, null, null, false, null, null, null, true, 0, null, false);
getMessagesController().unblockPeer(userId, ()-> getSendMessagesHelper().sendMessage("/start", userId, null, null, null, false, null, null, null, true, 0, null, false));
finishFragment();
}
}
@ -1891,7 +1896,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
finishFragment();
BulletinFactory.of(Bulletin.BulletinWindow.make(getContext()), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show();
Context context = getContext();
if (context != null) {
BulletinFactory.of(Bulletin.BulletinWindow.make(context), resourcesProvider).createSimpleBulletin(R.raw.ic_delete, LocaleController.getPluralString("TopicsDeleted", 1)).show();
}
dialog.dismiss();
}
});
@ -2208,6 +2216,18 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
setForegroundImage(true);
}
if (photo == null || avatarsViewPager.getRealPosition() == 0) {
TLRPC.Photo nextPhoto = avatarsViewPager.getPhoto(1);
if (nextPhoto != null) {
getUserConfig().getCurrentUser().photo =new TLRPC.TL_userProfilePhoto();
TLRPC.PhotoSize smallSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 90);
TLRPC.PhotoSize bigSize = FileLoader.getClosestPhotoSizeWithSize(nextPhoto.sizes, 1000);
if (smallSize != null && bigSize != null) {
getUserConfig().getCurrentUser().photo.photo_small = smallSize.location;
getUserConfig().getCurrentUser().photo.photo_big = bigSize.location;
}
} else {
getUserConfig().getCurrentUser().photo = new TLRPC.TL_userProfilePhotoEmpty();
}
getMessagesController().deleteUserPhoto(null);
} else {
TLRPC.TL_inputPhoto inputPhoto = new TLRPC.TL_inputPhoto();
@ -8034,10 +8054,12 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (userBlocked) {
otherItem.addSubItem(block_contact, R.drawable.msg_block, LocaleController.getString("Unblock", R.string.Unblock));
}
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
} else {
if (currentEncryptedChat == null) {
createAutoDeleteItem(context);
}
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
if (isBot) {
otherItem.addSubItem(share, R.drawable.msg_share, LocaleController.getString("BotShare", R.string.BotShare));
} else {
@ -8047,7 +8069,11 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
otherItem.addSubItem(share_contact, R.drawable.msg_share, LocaleController.getString("ShareContact", R.string.ShareContact));
}
if (isBot) {
otherItem.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_retry, !userBlocked ? LocaleController.getString("BotStop", R.string.BotStop) : LocaleController.getString("BotRestart", R.string.BotRestart));
if (!userBlocked) {
otherItem.addSubItem(block_contact, R.drawable.msg_block2, LocaleController.getString(R.string.DeleteAndBlock)).setColors(getThemedColor(Theme.key_dialogTextRed), getThemedColor(Theme.key_dialogTextRed));
} else {
otherItem.addSubItem(block_contact, R.drawable.msg_retry, LocaleController.getString("BotRestart", R.string.BotRestart));
}
} else {
otherItem.addSubItem(block_contact, !userBlocked ? R.drawable.msg_block : R.drawable.msg_block, !userBlocked ? LocaleController.getString("BlockContact", R.string.BlockContact) : LocaleController.getString("Unblock", R.string.Unblock));
}
@ -8070,6 +8096,9 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
otherItem.addSubItem(start_secret_chat, R.drawable.msg_secret, LocaleController.getString("StartEncryptedChat", R.string.StartEncryptedChat));
}
if (!isBot && getContactsController().contactsDict.get(userId) != null) {
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
}
if (SharedConfig.fakePasscodeActivatedIndex == -1) {
if (isBot && SharedConfig.allowRenameChat) {
otherItem.addSubItem(edit_chat_name, R.drawable.floating_pencil, LocaleController.getString("EditChatName", R.string.EditChatName));
@ -8091,7 +8120,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
}
}
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
otherItem.addSubItem(add_shortcut, R.drawable.msg_home, LocaleController.getString("AddShortcut", R.string.AddShortcut));
}
}
} else if (chatId != 0) {
TLRPC.Chat chat = getMessagesController().getChat(chatId);
@ -8795,6 +8825,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
try {
File dir = AndroidUtilities.getLogsDir();
if (dir == null) {
AndroidUtilities.runOnUIThread(progressDialog::dismiss);
return;
}

Some files were not shown because too many files have changed in this diff Show more